In "Connect the Enterprise with the JCA, Part 1," I introduced JCA (J2EE Connector Architecture), explained how it compares to EAI (enterprise application integration) products, and offered details on JCA interfaces.
JCA, an important new Java standard addressing enterprise integration, provides a framework, much like JDBC (Java Database Connectivity), to read and write data to different enterprise systems such as SAP, PeopleSoft, or Siebel. Reflecting its importance, the latest releases of most J2EE (Java 2 Platform, Enterprise Edition) application servers support JCA.
Read the whole series on the JCA:
In this article, the second of two, I demonstrate how to implement a JCA adapter -- a set of classes with which a J2EE application server targets a particular enterprise system. A JCA adapter functions similarly to how a JDBC driver connects to databases. However, because developing a full-featured JCA adapter is a complex task, I can only scratch the surface in this article. Nevertheless, by the end, you will understand a basic JCA adapter's construction, and grasp the effort required to build your own.
To accomplish those goals, I first describe the sample adapter's capabilities, as well as how to deploy and run it. I then introduce the implementation classes, followed by what occurs when the adapter executes in the container. Finally, I discuss the lessons learned from creating the sample adapter.
Note: To download the myjca.rar source code that accompanies this article, see Resources.
First, it's important to frame the sample-adapter discussion by describing its functionality. This article's sample adapter doesn't actually hook up to an enterprise system; it merely implements the interfaces required to deploy the adapter and look up a connection.
Moreover, the sample adapter implements only those classes required for the JCA specification's connection management section. Further, most of the adapter's method implementations contain print statements that let you see the method calls' order, without hooking up a debugger. The sample adapter does not, however, address transaction and security contacts.
This article's sample adapter does not use the CCI (Common Client Interface) interfaces. It strictly demonstrates the classes necessary to connect to an enterprise system.
To use the adapter (or any JCA adapter for that matter), you need a J2EE application server with JCA 1.0 specification support. I used BEA's WebLogic 6.1 server to test the sample adapter; however, other application servers should work.
To deploy the sample adapter with BEA's WebLogic 6.1, you must:
myjca.rar file, then upload it
In a later section, you'll find instructions on how to compile and build myjca.rar.
Next, let's delve into the Java classes required to implement the sample JCA adapter. The adapter includes two class categories:
With the MyManagedConnectionFactory class, which implements the ManagedConnectionFacytory interface, you create the MyConnectionFactory and MyManagedConnection classes. The MyManagedConnectionFactory class acts as the main entry point for the application server to call into the adapter:
package myjca;
import java.io.PrintWriter;
import java.io.Serializable;
import java.sql.DriverManager;
import java.util.Iterator;
import java.util.Set;
import javax.resource.ResourceException;
import javax.resource.spi.*;
import javax.security.auth.Subject;
public class MyManagedConnectionFactory
implements ManagedConnectionFactory, Serializable
{
public MyManagedConnectionFactory() {
System.out.println("In MyManagedConnectionFactory.constructor");
}
public Object createConnectionFactory(ConnectionManager cxManager) throws ResourceException {
System.out.println("In MyManagedConnectionFactory.createConnectionFactory,1");
return new MyDataSource(this, cxManager);
}
public Object createConnectionFactory() throws ResourceException {
System.out.println("In MyManagedConnectionFactory.createManagedFactory,2");
return new MyDataSource(this, null);
}
public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo info) {
System.out.println("In MyManagedConnectionFactory.createManagedConnection");
return new MyManagedConnection(this, "test");
}
public ManagedConnection matchManagedConnections(Set connectionSet, Subject subject, ConnectionRequestInfo info)
throws ResourceException
{
System.out.println("In MyManagedConnectionFactory.matchManagedConnections");
return null;
}
public void setLogWriter(PrintWriter out) throws ResourceException {
System.out.println("In MyManagedConnectionFactory.setLogWriter");
}
public PrintWriter getLogWriter() throws ResourceException {
System.out.println("In MyManagedConnectionFactory.getLogWriter");
return DriverManager.getLogWriter();
}
public boolean equals(Object obj) {
if(obj == null)
return false;
if(obj instanceof MyManagedConnectionFactory)
{
int hash1 = ((MyManagedConnectionFactory)obj).hashCode();
int hash2 = hashCode();
return hash1 == hash2;
}
else
{
return false;
}
}
public int hashCode()
{
return 1;
}
}
The MyManagedConnection class implements the ManagedConnection interface. MyManagedConnection encapsulates the adapter's physical connection, in this case the MyConnection class:
package myjca;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import javax.resource.NotSupportedException;
import javax.resource.ResourceException;
import javax.resource.spi.*;
import javax.security.auth.Subject;
import javax.transaction.xa.XAResource;
public class MyManagedConnection
implements ManagedConnection
{
private MyConnectionEventListener myListener;
private String user;
private ManagedConnectionFactory mcf;
private PrintWriter logWriter;
private boolean destroyed;
private Set connectionSet;
MyManagedConnection(ManagedConnectionFactory mcf, String user)
{
System.out.println("In MyManagedConnection");
this.mcf = mcf;
this.user = user;
connectionSet = new HashSet();
myListener = new MyConnectionEventListener(this);
}
private void throwResourceException(SQLException ex)
throws ResourceException
{
ResourceException re = new ResourceException("SQLException: " +
ex.getMessage());
re.setLinkedException(ex);
throw re;
}
public Object getConnection(Subject subject, ConnectionRequestInfo
connectionRequestInfo)
throws ResourceException
{
System.out.println("In MyManagedConnection.getConnection");
MyConnection myCon = new MyConnection(this);
addMyConnection(myCon);
return myCon;
}
public void destroy()
{
System.out.println("In MyManagedConnection.destroy");
destroyed = true;
}
public void cleanup()
{
System.out.println("In MyManagedConnection.cleanup");
}
public void associateConnection(Object connection)
{
System.out.println("In MyManagedConnection.associateConnection");
}
public void addConnectionEventListener(ConnectionEventListener listener)
{
System.out.println("In MyManagedConnection.addConnectionEventListener");
myListener.addConnectorListener(listener);
}
public void removeConnectionEventListener(ConnectionEventListener listener)
{
System.out.println("In MyManagedConnection.removeConnectionEventListener");
myListener.removeConnectorListener(listener);
}
public XAResource getXAResource()
throws ResourceException
{
System.out.println("In MyManagedConnection.getXAResource");
return null;
}
public LocalTransaction getLocalTransaction()
{
System.out.println("In MyManagedConnection.getLocalTransaction");
return null;
}
public ManagedConnectionMetaData getMetaData()
throws ResourceException
{
System.out.println("In MyManagedConnection.getMetaData");
return new MyConnectionMetaData(this);
}
public void setLogWriter(PrintWriter out)
throws ResourceException
{
System.out.println("In MyManagedConnection.setLogWriter");
logWriter = out;
}
public PrintWriter getLogWriter()
throws ResourceException
{
System.out.println("In MyManagedConnection.getLogWriter");
return logWriter;
}
Connection getMyConnection()
throws ResourceException
{
System.out.println("In MyManagedConnection.getMyConnection");
return null;
}
boolean isDestroyed()
{
System.out.println("In MyManagedConnection.isDestroyed");
return destroyed;
}
String getUserName()
{
System.out.println("In MyManagedConnection.getUserName");
return user;
}
void sendEvent(int eventType, Exception ex)
{
System.out.println("In MyManagedConnection.sendEvent,1");
myListener.sendEvent(eventType, ex, null);
}
void sendEvent(int eventType, Exception ex, Object connectionHandle)
{
System.out.println("In MyManagedConnection.sendEvent,2 ");
myListener.sendEvent(eventType, ex, connectionHandle);
}
void removeMyConnection(MyConnection myCon)
{
System.out.println("In MyManagedConnection.removeMyConnection");
connectionSet.remove(myCon);
}
void addMyConnection(MyConnection myCon)
{
System.out.println("In MyManagedConnection.addMyConnection");
connectionSet.add(myCon);
}
ManagedConnectionFactory getManagedConnectionFactory()
{
System.out.println("In MyManagedConnection.getManagedConnectionFactory");
return mcf;
}
}
For its part, the MyConnectionEventListener class allows the application server to register callbacks for the adapter. The application server can then perform operations,
connection-pool maintenance, for example, based on the connection state:
Good ArticleBy Anonymous on January 28, 2010, 9:18 amgives the basic understanding of jca architecture. nice article
Reply | Read entire comment
askBy Anonymous on December 16, 2009, 8:34 pmI am very interested with this article. But after I compile that java file, there is a lot of error,it said many objects that are not identificated.why? if I may...
Reply | Read entire comment
Very useful. Thanks.By Anonymous on October 6, 2009, 5:00 pmVery useful. Thanks.
Reply | Read entire comment
Nice article..By Anonymous on March 9, 2009, 3:56 pmNice article..
Reply | Read entire comment
View all comments