JBoss.org Community Documentation
To conclude our discussion of the JBoss JCA framework we will create and deploy a single non-transacted resource adaptor that simply provides a skeleton implementation that stubs out the required interfaces and logs all method calls. We will not discuss the details of the requirements of a resource adaptor provider as these are discussed in detail in the JCA specification. The purpose of the adaptor is to demonstrate the steps required to create and deploy a RAR in JBoss, and to see how JBoss interacts with the adaptor.
The adaptor we will create could be used as the starting point for a non-transacted file system adaptor. The source to the example adaptor can be found in the src/main/org/jboss/book/jca/ex1
directory of the book examples. A class diagram that shows the mapping from the required javax.resource.spi
interfaces to the resource adaptor implementation is given in Figure 5.3, “The file system RAR class diagram”.
We will build the adaptor, deploy it to the JBoss server and then run an example client against an EJB that uses the resource adaptor to demonstrate the basic steps in a complete context. We'll then take a look at the JBoss server log to see how the JBoss JCA framework interacts with the resource adaptor to help you better understand the components in the JCA system level contract.
To build the example and deploy the RAR to the JBoss server deploy/lib
directory, execute the following Ant command in the book examples directory.
[examples]$ ant -Dchap=jca build-chap
The deployed files include a jca-ex1.sar
and a notxfs-service.xml
service descriptor. The example resource adaptor deployment descriptor is shown in Example 5.1, “The nontransactional file system resource adaptor deployment descriptor.”.
<?xml version="1.0" encoding="UTF-8"?> <connector xmlns="http://java.sun.com/xml/ns/"Whats_new_in_JBoss_4-J2EE_Certification_and_Standards_Compliance" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd" version="1.5"> <display-name>File System Adapter</display-name> <vendor-name>JBoss</vendor-name> <eis-type>FileSystem</eis-type> <resourceadapter-version>1.0</resourceadapter-version> <license> <description>LGPL</description> <license-required>false</license-required> </license> <resourceadapter> <resourceadapter-class> org.jboss.resource.deployment.DummyResourceAdapter </resourceadapter-class> <outbound-resourceadapter> <connection-definition> <managedconnectionfactory-class> org.jboss.book.jca.ex1.ra.FSManagedConnectionFactory </managedconnectionfactory-class> <config-property> <config-property-name>FileSystemRootDir</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value>/tmp/db/fs_store</config-property-value> </config-property> <config-property> <config-property-name>UserName</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value/> </config-property> <config-property> <config-property-name>Password</config-property-name> <config-property-type>java.lang.String</config-property-type> <config-property-value/> </config-property> <connectionfactory-interface> org.jboss.book.jca.ex1.ra.DirContextFactory </connectionfactory-interface> <connectionfactory-impl-class> org.jboss.book.jca.ex1.ra.DirContextFactoryImpl </connectionfactory-impl-class> <connection-interface> javax.naming.directory.DirContext </connection-interface> <connection-impl-class> org.jboss.book.jca.ex1.ra.FSDirContext </connection-impl-class> </connection-definition> <transaction-support>NoTransaction</transaction-support> <authentication-mechanism> <authentication-mechanism-type>BasicPassword</authentication-mechanism-type> <credential-interface> javax.resource.spi.security.PasswordCredential </credential-interface> </authentication-mechanism> <reauthentication-support>true</reauthentication-support> </outbound-resourceadapter> <security-permission> <description> Read/Write access is required to the contents of the FileSystemRootDir </description> <security-permission-spec> permission java.io.FilePermission "/tmp/db/fs_store/*", "read,write"; </security-permission-spec> </security-permission> </resourceadapter> </connector>
Example 5.1. The nontransactional file system resource adaptor deployment descriptor.
The key items in the resource adaptor deployment descriptor are highlighted in bold. These define the classes of the resource adaptor, and the elements are:
managedconnectionfactory-class
: The implementation of the ManagedConnectionFactory
interface, org.jboss.book.jca.ex1.ra.FSManagedConnectionFactory
connectionfactory-interface
: This is the interface that clients will obtain when they lookup the connection factory instance from JNDI, here a proprietary resource adaptor value, org.jboss.book.jca.ex1.ra.DirContextFactory
. This value will be needed when we create the JBoss ds.xml
to use the resource.
connectionfactory-impl-class
: This is the class that provides the implementation of the connectionfactory-interface
, org.jboss.book.jca.ex1.ra.DirContextFactoryImpl
.
connection-interface
: This is the interface for the connections returned by the resource adaptor connection factory, here the JNDI javax.naming.directory.DirContext
interface.
connection-impl-class
: This is he class that provides the connection-interface
implementation, org.jboss.book.jca.ex1.ra.FSDirContext
.
transaction-support
: The level of transaction support, here defined as NoTransaction
, meaning the file system resource adaptor does not do transactional work.
The RAR classes and deployment descriptor only define a resource adaptor. To use the resource adaptor it must be integrated into the JBoss application server using a ds.xml
descriptor file. An example of this for the file system adaptor is shown in Example 5.2, “The notxfs-ds.xml resource adaptor MBeans service descriptor.”.
<!DOCTYPE connection-factories PUBLIC "-//JBoss//DTD JBOSS JCA Config 1.5//EN" "http://www.jboss.org/j2ee/dtd/jboss-ds_1_5.dtd"> <!-- The non-transaction FileSystem resource adaptor service configuration --> <connection-factories> <no-tx-connection-factory> <jndi-name>NoTransFS</jndi-name> <rar-name>jca-ex1.rar</rar-name> <connection-definition> org.jboss.book.jca.ex1.ra.DirContextFactory </connection-definition> <config-property name="FileSystemRootDir" type="java.lang.String">/tmp/db/fs_store</config-property> </no-tx-connection-factory> </connection-factories>
Example 5.2. The notxfs-ds.xml resource adaptor MBeans service descriptor.
The main attributes are:
jndi-name
: This specifies where the connection factory will be bound into JNDI. For this deployment that binding will be java:/NoTransFS
.
rar-name
: This is the name of the RAR file that contains the definition for the resource we want to provide. For nested RAR files, the name would look like myapplication.ear#my.rar
. In this example, it is simply jca-ex1.rar
.
connection-definition
: This is the connection factory interface class. It should match the connectionfactory-interface
in the ra.xml
file. Here our connection factory interface is org.jboss.book.jca.ex1.ra.DirContextFactory
.
config-property
: This can be used to provide non-default settings to the resource adaptor connection factory. Here the FileSystemRootDir
is being set to /tmp/db/fs_store
. This overrides the default value in the ra.xml
file.
To deploy the RAR and connection manager configuration to the JBoss server, run the following:
[examples]$ ant -Dchap=jca config
The server console will display some logging output indicating that the resource adaptor has been deployed.
Now we want to test access of the resource adaptor by a J2EE component. To do this we have created a trivial stateless session bean that has a single method called echo
. Inside of the echo
method the EJB accesses the resource adaptor connection factory, creates a connection, and then immediately closes the connection. The echo
method code is shown below.
public String echo(String arg) { log.info("echo, arg="+arg); try { InitialContext ctx = new InitialContext(); Object ref = ctx.lookup("java:comp/env/ra/DirContextFactory"); log.info("echo, ra/DirContextFactory=" + ref); DirContextFactory dcf = (DirContextFactory) ref; log.info("echo, found dcf=" + dcf); DirContext dc = dcf.getConnection(); log.info("echo, lookup dc=" + dc); dc.close(); } catch(NamingException e) { log.error("Failed during JNDI access", e); } return arg; }
Example 5.3. The stateless session bean echo method code that shows the access of the resource adaptor connection factory.
The EJB is not using the CCI interface to access the resource adaptor. Rather, it is using the resource adaptor specific API based on the proprietary DirContextFactory
interface that returns a JNDI DirContext
object as the connection object. The example EJB is simply exercising the system contract layer by looking up the resource adaptor connection factory, creating a connection to the resource and closing the connection. The EJB does not actually do anything with the connection, as this would only exercise the resource adaptor implementation since this is a non-transactional resource.
Run the test client which calls the EchoBean.echo
method by running Ant as follows from the examples directory:
[examples]$ ant -Dchap=jca -Dex=1 run-example
You'll see some output from the bean in the system console, but much more detailed logging output can be found in the server/production/log/server.log
file. Don't worry if you see exceptions. They are just stack traces to highlight the call path into parts of the adaptor. To help understand the interaction between the adaptor and the JBoss JCA layer, we'll summarize the events seen in the log using a sequence diagram. Figure 5.4, “A sequence diagram illustrating the key interactions between the JBossCX framework and the example resource adaptor that result when the EchoBean accesses the resource adaptor connection factory.” is a sequence diagram that summarizes the events that occur when the EchoBean
accesses the resource adaptor connection factory from JNDI and creates a connection.
Figure 5.4. A sequence diagram illustrating the key interactions between the JBossCX framework and the example resource adaptor that result when the EchoBean accesses the resource adaptor connection factory.
The starting point is the client's invocation of the EchoBean.echo
method. For the sake of conciseness of the diagram, the client is shown directly invoking the EchoBean.echo method when in reality the JBoss EJB container handles the invocation. There are three distinct interactions between the EchoBean
and the resource adaptor; the lookup of the connection factory, the creation of a connection, and the close of the connection.
The lookup of the resource adaptor connection factory is illustrated by the 1.1 sequences of events. The events are:
1, the echo method invokes the getConnection
method on the resource adaptor connection factory obtained from the JNDI lookup on the java:comp/env/ra/DirContextFactory
name which is a link to the java:/NoTransFS
location.
1.1, the DirContextFactoryImpl
class asks its associated ConnectionManager
to allocate a connection. It passes in the ManagedConnectionFactory
and FSRequestInfo
that were associated with the DirContextFactoryImpl
during its construction.
1.1.1, the ConnectionManager
invokes its getManagedConnection
method with the current Subject
and FSRequestInfo
.
1.1.1.1, the ConnectionManager
asks its object pool for a connection object. The JBossManagedConnectionPool$BasePool
is get the key for the connection and then asks the matching InternalPool
for a connection.
1.1.1.1.1, Since no connections have been created the pool must create a new connection. This is done by requesting a new managed connection from the ManagedConnectionFactory
. The Subject
associated with the pool as well as the FSRequestInfo
data are passed as arguments to the createManagedConnection
method invocation.
1.1.1.1.1.1, the ConnectionFactory
creates a new FSManagedConnection
instance and passes in the Subject
and FSRequestInfo
data.
1.1.1.2, a javax.resource.spi.ConnectionListener
instance is created. The type of listener created is based on the type of ConnectionManager
. In this case it is an org.jboss.resource.connectionmgr.BaseConnectionManager2$NoTransactionListener
instance.
1.1.1.2.1, the listener registers as a javax.resource.spi.ConnectionEventListener
with the ManagedConnection
instance created in 1.2.1.1.
1.1.2, the ManagedConnection
is asked for the underlying resource manager connection. The Subject
and FSRequestInfo
data are passed as arguments to the getConnection
method invocation.
The resulting connection object is cast to a javax.naming.directory.DirContext
instance since this is the public interface defined by the resource adaptor.
After the EchoBean
has obtained the DirContext
for the resource adaptor, it simply closes the connection to indicate its interaction with the resource manager is complete.
This concludes the resource adaptor example. Our investigation into the interaction between the JBossCX layer and a trivial resource adaptor should give you sufficient understanding of the steps required to configure any resource adaptor. The example adaptor can also serve as a starting point for the creation of your own custom resource adaptors if you need to integrate non-JDBC resources into the JBoss server environment.