The aim of this tutorial is to establish a good understanding of the term "artifact", the structure of an artifact URI, an the role of the Transit system concerning resource retrieval, hosts, and resource caching.
An artifact is any streamable resource locatable using the artifact
URL protocol. Examples of resources include - jar files, property files, XML
files, files containing meta data, serialized objects, images, etc. Resources
can be viewed as artifacts if they can be located using the artifact
protocol. The protocol structure is as follows:
artifact:[type]:[group]/[name]#[version]
To locate a resource Transit maps the [type], [group],
[name],
and [version]
fields of the artifact URI to a URL
using a layout assigned to a particular host defintion. The most common layout
strategy (refered to as the classic layout) maps the artifact specifications
according to the following rule:
[host-address]/[group]/[type]s/[name]-[version].[type]
The eclipse layout maps artifacts in accordance with the following scheme:
[host-address]/[group]-[version]/[name].[type]
The following testcase demonstrates the use of an artifact to retrieve a property
file from a remote location and supply it as an input stream to a Properties object.
The initial setUp()
method handles the declaration of the Artifact protocol handler
to the JVM. This is Transit's hook into the JVM's URL Hander object model. Within the
testPropertyLoading()
we construct a new URL using an artifact specification
that declares a resource type of "properties", a group named "dpml/test", the name
"example-property-file" and a version equal to "2.2". We then pass the URLs resource
stream to a new Property instance and print out the value of a property declared in the
properties resource.
Source: trunk/validation/resources/src/test/net/osm/tutorial/TransitTestCase.java
public class TransitTestCase extends TestCase { protected void setUp() throws Exception { System.setProperty( "java.protocol.handler.pkgs", "net.dpml.transit" ); } public void testPropertyLoading() throws Exception { URL url = new URL( "artifact:properties:dpml/test/example-property-file#2.2" ); InputStream input = url.openStream(); Properties properties = new Properties(); properties.load( input ); String message = properties.getProperty( "tutorial.message" ); System.out.println( message ); } }
Testcase output:
[x:junit] Executing forked test. [x:junit] Running net.osm.tutorial.TransitTestCase [x:junit] Welcome to the world of Transit! [x:junit] Tests run: 1, Failures: 0, Errors: 0, Time elapsed: 0.344 sec
When the new URL constructor is invoked the JVM checks available URLStreamHandlers using a number of mechanisms - one of which is to check the value of the "java.protocol.handler.pkgs" system property. The JVM will look for a protocol handler named "dpml.transit" + [protocol].Handler. The Transit's artifact Handler class is primarily responsible for the establishment of a ArtifactURLConnection. The ArtifactURLConnection holds a reference to the Transit system. When the openStream operation is invoked the Artifact URL connection will use a cache handler to resolve the URL to a local cached resource. The cache handler will check prioritized hosts for the resource (converting the artifact to the appropriate URL for the host as it evaluates potential multiple candidates). When a host is located a network service downloads the resource to the local cache (itself equivalent to a local files based repository). The openStream() request is then delegated to the local resource.
- Removal of "location" concerns from the codebase.
- Notion of transport protocol is abstracted out.
- Potential redundancy when a resource exists on multiple hosts.
- Configuration concerns are separted from usage.
- Artifact structure encorages consistent naming patterns and resource versioning.
- Functionlity is encapsulated with the URL and URLConnection object model.
The machinery underlying the artifact uri is designed around the availability of local or remote hosts which serve as the resource source repository. This is apropriate when dealing with general integration of multiple projects, however - it is not suitable for the management of local configuration data. The next tutorial introduces the local protocol which provides support for the resolution of preference information local to the application runtime environment. In general terms it follows the same patterns as the artifact protocol but the underlying machining resolves resources relative to a local system wide preference root directory.