Package org.jboss.dna.graph.connector

JBoss DNA uses connectors to access information from external systems (such as databases, other repositories, services, applications, etc.) and create graph representations of that information.

See:
          Description


Interface Summary
RepositoryConnection A connection to a repository source.
RepositoryConnectionFactory An interface for a factory of RepositoryConnections using the names of the RepositorySource from which the connections are to be obtained.
RepositoryContext The context for a repository.
RepositorySource A repository source is a description of a resource that can be used to access or store repository information.
 

Class Summary
RepositoryConnectionPool A reusable implementation of a managed pool of connections that is optimized for safe concurrent operations.
RepositorySourceCapabilities The capabilities of a RepositorySource.
 

Exception Summary
LockFailedException Exception that indicates that a lock request failed at the repository level.
RepositorySourceException A runtime exception signalling an error within a RepositorySource.
UuidAlreadyExistsException Exception that indicates that a copy request failed because one of the UUIDs in the source branch already exists in the target workspace and the UUID conflict behavior is set to throw an exception instead of removing the existing nodes.
 

Package org.jboss.dna.graph.connector Description

JBoss DNA uses connectors to access information from external systems (such as databases, other repositories, services, applications, etc.) and create graph representations of that information. This package defines the interfaces that a connector must implement.

Concepts

A connector is the runnable code packaged in one or more JAR files that contains implementations of several interfaces (described below). A Java developer writes a connector to a type of source, such as a particular database management system, LDAP directory, source code management system, etc. It is then packaged into one or more JAR files (including dependent JARs) and deployed for use in applications that use JBoss DNA repositories.

The description of a particular source system (e.g., the "Customer" database, or the company LDAP system) is called a repository source. JBoss DNA defines a RepositorySource interface that defines methods describing the behavior and supported features and a method for establishing connections. A connector will have a class that implements this interface and that has JavaBean properties for all of the connector-specific properties required to fully describe an instance of the system. Use of JavaBean properties is not required, but it is highly recommended, as it enables reflective configuration and administration. Applications that use JBoss DNA create an instance of the connector's RepositorySource implementation and set the properties for the external source that the application wants to access with that connector.

A repository source instance is then used to establish connections to that source. A connector provides an implementation of the RepositoryConnection interface, which defines methods for interacting with the external system. In particular, the execute(...) method takes an ExecutionContext instance and a Request object. The object defines the environment in which the processing is occurring, including information about the JAAS Subject and LoginContext. The Request object describes the requested operations on the content, with different concrete subclasses representing each type of activity. Examples of commands include (but not limited to) getting a node, moving a node, creating a node, changing a node, and deleting a node. And, if the repository source is able to participate in JTA/JTS distributed transactions, then the RepositoryConnection must implement the RepositoryConnection#getXAResource() method by returning a valid XAResource object that can be used by the transaction monitor.

Example connector

As an example, consider that we want JBoss DNA to give us access through JCR to the schema information contained in a relational databases. We first have to develop a connector that allows us to interact with relational databases using JDBC. That connector would contain a JdbcRepositorySource Java class that implements RepositorySource, and that has all of the various JavaBean properties for setting the name of the driver class, URL, username, password, and other properties. (Or we might have a JavaBean property that defines the JNDI name where we can find a JDBC DataSource instance pointing to our JDBC database.)

Our new connector would also have a JdbcRepositoryConnection Java class that implements the RepositoryConnection interface. This class would probably wrap a JDBC database connection, and would implement the RepositoryConnection#execute(org.jboss.dna.graph.ExecutionContext, org.jboss.dna.graph.request.Request) method such that the nodes exposed by the connector describe the database schema of the database. For example, the connector might represent each database table as a node with the table's name, with properties that describe the table (e.g., the description, whether it's a temporary table), and with child nodes that represent each of the columns, keys and constraints.

To use our connector in an application that uses JBoss DNA, we need to create an instance of the JdbcRepositorySource for each database instance that we want to access. If we have 3 MySQL databases, 9 Oracle databases, and 4 PostgreSQL databases, then we'd need to create a total of 16 JdbcRepositorySource instances, each with the properties describing a single database instance. Those sources are then available for use by JBoss DNA components, including the JCR implementation.

Implementing a connector

As mentioned earlier, a connector consists of the Java code that is used to access content from a system. Perhaps the most important class that makes up a connector is the implementation of the RepositorySource. This class is analogous to JDBC's DataSource in that it is instantiated to represent a single instance of a system that will be accessed, and it contains enough information (in the form of JavaBean properties) so that it can create connections to the source.

Why is the RepositorySource implementation a JavaBean? Well, this is the class that is instantiated, usually reflectively, and so a no-arg constructor is required. Using JavaBean properties makes it possible to reflect upon the object's class to determine the properties that can be set (using setters) and read (using getters). This means that an administrative application can instantiate, configure, and manage the objects that represent the actual sources, without having to know anything about the actual implementation.

Testing a connector implementation

Testing connectors is not really that much different than testing other classes. Using mocks may help to isolate your instances so you can create more unit tests that don't require the underlying source system.

JBoss DNA does provide a set of unit tests that you can use to verify that your connector "behaves correctly". These are useful because you only have to set up the test case classes (by extending one of the provided test case classes and overriding the appropriate set up methods), but you don't have to write any test methods (since they're all inherited).

However, there may be times when you have to use the underlying source system in your tests. If this is the case, we recommend using Maven integration tests, which run at a different point in the Maven lifecycle. The benefit of using integration tests is that by convention they're able to rely upon external systems. Plus, your unit tests don't become polluted with slow-running tests that break if the external system is not available.



Copyright © 2008-2010 JBoss, a division of Red Hat. All Rights Reserved.