Finding a Connector

Once you've decided to use JCA to connect to an external system from J2EE, the next step is to locate an appropriate Connector.

While it's certainly possible to write your own Connector, it's almost always cheaper and easier to use an existing implementation. Fortunately, J2EE is well enough established that EIS vendors now offer prepackaged J2EE Connectors for the most popular products and platforms. Thus, the first place to look is always the vendor who supplied the original system.

If that company is unable or unwilling to provide J2EE support, you may able to find a third-party provider that supports your configuration. Many enterprise integration companies offer large catalogs of adapters for everything from SAP and PeopleSoft. Also, most integration server platforms offer dozens of built-in Connectors for the most common types of systems. Finally, it's worth checking out SourceForge .net (see http://sourceforge.net/index.php ), and other free distribution sites.

Of course, if you need to talk to a homegrown or highly customized system, it's time to start writing code. First, you'll need to define a client API that your J2EE components will use to interact with this resource. Next, you'll actually implement that API along with a number of system interfaces for connection management, transactions, and security. Finally, you'll package your new resource adapter in a RAR with an ra.xml deployment descriptor. None of these steps are specific to OC4J, and Sun provides a complete walk-through in the online J2EE Connector tutorial.

Writing a Connector

Let's take a look at a very simple implementation of a J2EE Connector. It will not actually do anything, but it will serve as a good starting point for writing your own Connectors.

Before examining the code, let's take a look at the directory structure of the Connector, as shown in Figure 12-2.

image from book
Figure 12-2: Directory structure of the Resource Adapter project

The web/src/java and util/src/java directories contain Java source code for the web application and the resource adapter. These Java source codes aren't very important right now, but what is important is the location of descriptor files. The EAR descriptors are located in ear/src/META-INF and the resource adapter descriptors are in rar/src/META-INF . A resource adapter RAR file must contain a correctly formatted deployment descriptor (/META-INF/ra.xml ). We've included the generic ra.xml deployment descriptor as well as the OC4J-specifc oc4jra.xml descriptor.

The descriptors in ear/src/META-INF are pretty standard EAR descriptors; you simply identify modules that make up the application, in this case a web module and a Connector. The oc4j-connectors.xml file is an OC4J-specific configuration file that specifies the JNDI location for the adapter, as shown here:

 <?xml version="1.0"?> <!DOCTYPE oc4j-connectors PUBLIC "-//Oracle//DTD Connectors configuration"   "http://xmlns.oracle.com/ias/dtds/oc4j-connectors.dtd"> <oc4j-connectors>     <connector name="embedded" path="embedded_ra.rar"/> </oc4j-connectors> 

Next, let's examine the ra.xml descriptor, as shown in the following sample, and then we'll move on to describe the crucial points of the actual implementation.

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE connector PUBLIC '-//Sun Microsystems, Inc.//DTD Connector 1.0//EN'     'http://java.sun.com/dtd/connector_1_0.dtd'> <connector>     <display-name>Sample Resource Adapter</display-name>     <description>Testing adapter</description>     <vendor-name>Apress</vendor-name>     <spec-version>1.0</spec-version>     <eis-type>ConnectionFactory</eis-type>     <version>1.0</version>     <resourceadapter>         <managedconnectionfactory-class>  com.apress.oc4j.connectors.SampleManagedConnectionFactory  </managedconnectionfactory-class>         <connectionfactory-interface>             javax.resource.cci.ConnectionFactory         </connectionfactory-interface>         <connectionfactory-impl-class>  com.apress.oc4j.connectors.SampleConnectionFactory  </connectionfactory-impl-class>         <connection-interface>javax.resource.cci.Connection</connection-interface>         <connection-impl-class>  com.apress.oc4j.connectors.SampleConnection  </connection-impl-class>         <transaction-support>NoTransaction</transaction-support>         <reauthentication-support>false</reauthentication-support>     </resourceadapter> </connector> 

You need to implement the three classes shown in bold. You'll start with the simplest class: SampleConnection . The purpose of this class is to manage connections to the resource, as shown in the following sample:

SampleConnection source

 package com.apress.oc4j.connectors; import javax.resource.NotSupportedException; import javax.resource.ResourceException; import javax.resource.cci.Connection; import javax.resource.cci.ConnectionMetaData; import javax.resource.cci.Interaction; import javax.resource.cci.LocalTransaction; import javax.resource.cci.ResultSetInfo; public class SampleConnection implements Connection, LocalTransaction {     public Interaction createInteraction() throws ResourceException {         SampleInteraction interaction = new SampleInteraction();         interaction.setConnection(this);         return interaction;     }     public LocalTransaction getLocalTransaction() throws ResourceException {         return this;     }     public ConnectionMetaData getMetaData() throws ResourceException {         return new SampleConnectionMetadata();     }     public ResultSetInfo getResultSetInfo() throws ResourceException {         throw new NotSupportedException("Result Set support not implemented");     }     public void close() throws ResourceException {          // noop     }     public void begin() throws ResourceException {          // noop     }     public void commit() throws ResourceException {         // noop     }     public void rollback() throws ResourceException {         // noop     } } 

As you can see, we've implemented the Connection and LocalTransaction interfaces. The Connection interface allows the application to use the Connector; the LocalTransaction interface manages transactions. It's important to keep in mind that transactions need to be managed by the Connector; we aren't actually implementing any transaction management code.

Next, you have to implement SampleConnectionFactory , which is a class that is responsible for creating SampleConnection objects, as shown in the following sample:

SampleConnectionFactory implementation

 package com.apress.oc4j.connectors; import javax.naming.NamingException; import javax.naming.Reference; import javax.resource.ResourceException; import javax.resource.cci.Connection; import javax.resource.cci.ConnectionFactory; import javax.resource.cci.ConnectionSpec; import javax.resource.cci.RecordFactory; import javax.resource.cci.ResourceAdapterMetaData; import javax.resource.spi.ConnectionManager; import javax.resource.spi.ManagedConnectionFactory; public class SampleConnectionFactory implements ConnectionFactory {     private SampleRecordFactory recordFactory = new SampleRecordFactory();     private Reference reference;     private ConnectionManager connectionManager = new SampleDefaultConnectionManager();     private ManagedConnectionFactory managedConnectionFactory;     public Connection getConnection() throws ResourceException {         return getConnection(new SampleConnectionData());     }     public Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException {         SampleConnectionData info;         if (connectionSpec instanceof SampleConnectionData) {             SampleConnectionData sd = (SampleConnectionData)connectionSpec;             info = sd;         } else {             throw new ResourceException("ConnectionSpec object is of type " + connectionSpec.getClass().getName() + " not SampleConnectionData");         }         return (Connection)connectionManager.allocateConnection(managedConnectionFactory, info);     }     public RecordFactory getRecordFactory() throws ResourceException {         return recordFactory;     }     public ResourceAdapterMetaData getMetaData() throws ResourceException {         return new SampleResourceAdapterMetadata();     }     public void setReference(Reference reference) {         this.reference = reference;     }     public Reference getReference() throws NamingException {         return reference;     }     public ConnectionManager getConnectionManager() {         return connectionManager;     }     public void setConnectionManager(ConnectionManager connectionManager) {         this.connectionManager = connectionManager;     }     public ManagedConnectionFactory getManagedConnectionFactory() {         return managedConnectionFactory;     }     public void setManagedConnectionFactory(ManagedConnectionFactory managedConnectionFactory) {         this.managedConnectionFactory = managedConnectionFactory;     } } 

Again, we've taken a minimalist approach; you simply return the SampleConnection class without checking the ConnectionSpec data. A full-blown Connector would check that ConnectionSpec is of the correct type and that it contains valid data. The data passed in ConnectionSpec can include login information, data source names , filenames, and so on.

Finally, you need to implement ManagedConnectionFactory . This class is used to return the appropriate ConnectionFactory implementation. The Connector is a very simple one, so you'll only return one implementation of ConnectorFactory , as shown here:

 package com.apress.oc4j.connectors; import java.io.PrintWriter; import java.util.Set; import javax.resource.ResourceException; import javax.resource.spi.ConnectionManager; import javax.resource.spi.ConnectionRequestInfo; import javax.resource.spi.ManagedConnection; import javax.resource.spi.ManagedConnectionFactory; import javax.security.auth.Subject; public class SampleManagedConnectionFactory implements ManagedConnectionFactory {     private PrintWriter logWriter;     public Object createConnectionFactory(ConnectionManager connectionManager) throws ResourceException {         return new SampleConnectionFactory();     }     public Object createConnectionFactory() throws ResourceException {         return new SampleConnectionFactory();     }     public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException {         return new SampleConnectionFactory().getManagedConnectionFactory().createManagedConnection (subject, connectionRequestInfo);     }     public ManagedConnection matchManagedConnections(Set connections,  Subject subject, ConnectionRequestInfo connectionRequestInfo) throws ResourceException {         return new SampleConnectionFactory().getManagedConnectionFactory().createManagedConnection (subject, connectionRequestInfo);     }     public void setLogWriter(PrintWriter logWriter) throws ResourceException {         this.logWriter = logWriter;     }     public PrintWriter getLogWriter() throws ResourceException {         return logWriter;     } } 

This provides the basic skeleton of a resource adapter. We've implemented Connection and LocalTransaction interfaces in the SampleConnection class; we've implemented ConnectionFactory to return appropriate Connection instances, and we've also implemented Managed-ConnectionFactory to return implementations of ConnectionFactory .

Next, you need to package the Connector into a RAR file. This is simply a JAR file with a different extension. The build script for the entire application looks like this:

The build.xml script

 <project name="sample" basedir="." default="dist-ear">     <!-- etc -->  <target name="dist-rar" depends="init, compile-util">   <jar destfile="${dir.rar.dist}/embedded_ra.rar">   <fileset dir="${dir.rar.src}">   <include name="**/*"/>   </fileset>   <fileset dir="${dir.util.dist}">   <include name="**/*"/>   </fileset>  <  /jar>   </target>  <!-- etc --> </project> 

As you can see, the build script is very basic and the RAR file is simply a glorified JAR file.

The rest of the implementation is quite straightforward, and all is explained in the source code. It's important to keep in mind that this Connector doesn't actually do anything. It's merely a skeleton that you can extend.

You can now have a look at how to configure a Connector.



Oracle Application Server 10g. J2EE Deployment and Administration
Oracle Application Server 10g: J2EE Deployment and Administration
ISBN: 1590592352
EAN: 2147483647
Year: 2004
Pages: 150

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net