org.modeshape.graph.connector
Interface RepositoryConnection

All Known Implementing Classes:
Connection, JcrRepositoryConnection, MapRepositoryConnection, PathRepositoryConnection, RepositoryConnectionPool.ConnectionWrapper, SearchableRepositorySource.AbstractConnection, SearchableRepositorySource.ParallelConnection, SearchableRepositorySource.SynchronousConnection, SimpleJpaConnection

@NotThreadSafe
public interface RepositoryConnection

A connection to a repository source.

These connections need not support concurrent operations by multiple threads.

Implementing a connector

While most of these methods are straightforward, a few warrant additional information. The ping(long, TimeUnit) method allows ModeShape to check the connection to see if it is alive. This method can be used in a variety of situations, ranging from verifying that a RepositorySource's JavaBean properties are correct to ensuring that a connection is still alive before returning the connection from a connection pool.

The most important method on this interface, though, is the execute(ExecutionContext, Request) method, which serves as the mechanism by which the component using the connector access and manipulates the content exposed by the connector. The first parameter to this method is the ExecutionContext, which contains the information about environment as well as the subject performing the request.

The second parameter, however, represents a request that is to be processed by the connector. Request objects can take many different forms, as there are different classes for each kind of request (see the {org.modeshape.graph.request} package for more detail). Each request contains the information a connector needs to do the processing, and it also is the place where the connector places the results (or the error, if one occurs).

Although there are over a dozen different kinds of requests, we do anticipate adding more in future releases. For example, ModeShape will likely support searching repository content in sources through an additional subclass of Request. Getting the version history for a node will likely be another kind of request added in an upcoming release.

A connector is technically free to implement the execute(ExecutionContext, Request) method in any way, as long as the semantics are maintained. But ModeShape provides a RequestProcessor class that can simplify writing your own connector and at the same time help insulate your connector from new kinds of requests that may be added in the future. The RequestProcessor is an abstract class that defines a process(...) method for each concrete Request subclass. In other words, there is a RequestProcessor.process(org.modeshape.graph.request.CompositeRequest) method, a RequestProcessor.process(org.modeshape.graph.request.ReadNodeRequest) method, and so on.

To use a request processor in your connector, simply subclass RequestProcessor and override all of the abstract methods and optionally override any of the other methods that have a default implementation. In many cases, the default implementations of the process(...) methods are sufficient but probably not efficient or optimum. If that is the case, simply provide your own methods that perform the request in a manner that is efficient for your source. However, if performance is not a big issue, all of the concrete methods will provide the correct behavior. And remember, you can always provide better implementations later, so it's often best to keep things simple at first.

Then, in your connector's execute(ExecutionContext, Request) method, instantiate your RequestProcessor subclass and pass the execute(...) method's Request parameter directly into the the request processor's RequestProcessor.process(Request) method, which will determine the appropriate method given the actual Request object and will then invoke that method. For example:

 public void execute( ExecutionContext context,
                      Request request ) throws RepositorySourceException {
     RequestProcessor processor = new RequestProcessor(context);
     try {
         proc.process(request);
     } finally {
         proc.close();
     }
 }
 
If you do this, the bulk of your connector implementation will be in the RequestProcessor implementation methods. This not only is more maintainable, it also lends itself to easier testing. And should any new request types be added in the future, your connector may work just fine without any changes. In fact, if the RequestProcessor class can implement meaningful methods for those new request types, your connector may "just work". Or, at least your connector will still be binary compatible, even if your connector won't support any of the new features.

Finally, how should the connector handle exceptions? As mentioned above, each Request object has a slot where the connector can set any exception encountered during processing. This not only handles the exception, but in the case of a CompositeRequest it also correctly associates the problem with the request. However, it is perfectly acceptable to throw an exception if the connection becomes invalid (e.g., there is a communication failure) or if a fatal error would prevent subsequent requests from being processed.


Method Summary
 void close()
          Close this connection to signal that it is no longer needed and that any accumulated resources are to be released.
 void execute(ExecutionContext context, Request request)
          Execute the supplied commands against this repository source.
 CachePolicy getDefaultCachePolicy()
          Get the default cache policy for this repository.
 String getSourceName()
          Get the name for this repository source.
 XAResource getXAResource()
          Return the transactional resource associated with this connection.
 boolean ping(long time, TimeUnit unit)
          Ping the underlying system to determine if the connection is still valid and alive.
 

Method Detail

getSourceName

String getSourceName()
Get the name for this repository source. This value should be the same as that returned by the same RepositorySource that created this connection.

Returns:
the identifier; never null or empty

getXAResource

XAResource getXAResource()
Return the transactional resource associated with this connection. The transaction manager will use this resource to manage the participation of this connection in a distributed transaction.

Returns:
the XA resource, or null if this connection is not aware of distributed transactions

ping

boolean ping(long time,
             TimeUnit unit)
             throws InterruptedException
Ping the underlying system to determine if the connection is still valid and alive.

Parameters:
time - the length of time to wait before timing out
unit - the time unit to use; may not be null
Returns:
true if this connection is still valid and can still be used, or false otherwise
Throws:
InterruptedException - if the thread has been interrupted during the operation

getDefaultCachePolicy

CachePolicy getDefaultCachePolicy()
Get the default cache policy for this repository. If none is provided, a global cache policy will be used.

Returns:
the default cache policy

execute

void execute(ExecutionContext context,
             Request request)
             throws RepositorySourceException
Execute the supplied commands against this repository source.

Parameters:
context - the environment in which the commands are being executed; never null
request - the request to be executed; never null
Throws:
PathNotFoundException - if the request(s) contain paths to nodes that do not exist
ReferentialIntegrityException - if the request is or contains a delete operation, where the delete could not be performed because some references to deleted nodes would have remained after the delete operation completed
RepositorySourceException - if there is a problem loading the node data

close

void close()
Close this connection to signal that it is no longer needed and that any accumulated resources are to be released.



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