java left logo
java middle logo
java right logo
 

Home arrow Java EE Tips
 
 
Main Menu
Home
Java Tutorials
Book Reviews
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Java Network
Java Forums
Java Blog




Most Visited Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews
Top Rated Tips
Java SE Tips
Java ME Tips
Java EE Tips
Other API Tips
Java Applications
Java Libraries
Java Games
Book Reviews


Statistics
Registered Users: 4095
Java SE Tips: 614
Java ME Tips: 202
Java EE Tips: 183
Other API Tips: 779
Java Applications: 298
Java Libraries: 209
Java Games: 16
Book Reviews:
 
 
 
J2EE Connector Architecture 1.5 E-mail
User Rating: / 25
PoorBest 

This Tech Tip reprinted with permission by java.sun.com

If you've ever tried to integrate legacy systems with a J2EE application server, you know that it can be quite a challenge. Managing connections, converting between different data types, and even sending messages between an application server and an Enterprise Information System (EIS) can leave an enterprise Java programmer with quite a headache. Thankfully, there's the J2EE Connector Architecture, now in version 1.5 in J2EE 1.4, which defines a standard architecture for connecting the J2EE platform to heterogeneous EISs.

Using the J2EE Connector Architecture, EIS vendors do not have to create custom connection software for multiple application servers. Neither do application server vendors have to customize their code to support various EIS packages. Instead, these vendors can package "in-between" code that conforms to the J2EE Connector Architecture specifications. The code implements or extends a set of standardized contract interfaces and classes that adapt data and messages for communication between the application server and the EIS resource. This in-between code plugs into the application server, and is called a resource adapter.

A resource adapter module, typically called a Resource Adapter Archive (RAR), is simply a JAR file. A RAR typically includes the following:

  • Java classes and interfaces that implement the resource adapter contracts and client APIs.
  • Any native libraries that are required to communicate with the EIS.
  • A deployment descriptor file, ra.xml, that the application server uses to configure the resource adapter. The file is located in the META-INF directory.

Here is an illustration that shows where the resource adapter fits in with an application server and an EIS.

Image

Note how each element communicates with one other.

There are three important communication bridges that comprise the J2EE Connector Architecture. Let's look at each of them.

Client APIs and the Common Client Interface

Application components that plug into the application server must have a way of communicating with the resource adapter. The Common Client Interface (CCI) is the recommended API to do this. The CCI is an API that is implemented in the javax.resource.cci package. The API is recommended because it's easy to use, but it's not mandatory. Resource adapter implementers are free to create their own specialized client APIs to communicate with application components if the CCI does not satisfy their needs.

Container-Component Contracts

This is a standardized communication method between the application server and the application components. There's not much here in terms of JCA. For example, if a Web application uses Enterprise JavaBeans (EJB) components, then the EJB specification is the container-component contract that governs how each EJB component communicates with the application server.

System Contracts

This is a major part of the J2EE Connector Architecture. The architecture specifies several system contracts that a resource adapter must conform to in order to communicate clearly with the application server. The APIs for the system contracts are implemented in the javax.resource.spi package. The 1.0 version of the J2EE Connector Architecture introduced three such contracts:

  • Connection Management Contract: Provides interfaces and classes that allow for connections between the EIS and the application server. It also allows the application server to pool these connections as it deems necessary.
  • ransaction Management Contract: Brings atomic transaction capabilities to the EIS. The EIS can then be managed either by the resource adapter or a transaction manager. This only works one way, however. Transactions must be initiated outside the EIS and passed to it, not the reverse.
  • Security Contract: Ensures that there is proper authentication between the application server and the EIS.

With version 1.5 of the architecture, four new contracts were created that allow greater functionality inside of a resource adapter. The new contracts are:

  • Lifecycle Management Contract: Provides a way for the application server to cleanly start and shutdown the resource adapter.
  • Work Management Contract: Provides interfaces and classes that allow resource adapters to submit work for execution by the application server.
  • Transaction Inflow Contract: Allows transactions to be passed from the EIS to the application server (the reverse of the Transaction Management Contract). It also assists with transaction recovery in the event that the EIS crashes.
  • Message Inflow Contract: Allows the resource adapter to send synchronous or asynchronous messages to endpoints within the application server.

Let's examine these four new contracts in more detail.

Lifecycle Management and Work Management Contracts

The ResourceAdapter interface in the javax.resource.spi package represents a resource adapter. There are two methods in the ResourceAdapter interface that allow for lifecycle management: start() and stop(). The start() method is called when an application server wants to start a resource adapter (for example, to deploy it). The stop() method is called when the application server wants to release a resource adapter (for example, to undeploy it).

The Work Management contract allows the resource adapter to submit work to the application server. It does this by creating an object that extends the Work interface in the javax.resource.spi.work package. The Work interface is an extension of the Runnable interface. In addition to the run() method that it inherits from Runnable and which executes in its own thread, the Work interface contains a release() method. The application server can use release() to request that the thread complete, and release its resources as soon as possible.

Here is part of an example implementation of the ResourceAdapter interface that illustrates the lifecycle management and work management contracts:

   public class NexesResourceAdapterImpl implements 
           ResourceAdapter {

      // Ten seconds
      public static final long WORK_START_TIMEOUT = 10000L;
      
      public NexesResourceAdapterImpl() {    }
      public void start(BootstrapContext ctx)
      throws ResourceAdapterInternalException
      {
 
          WorkManager workManager = ctx.getWorkManager();
          Work nexesWorkJob = new NexesWorkImpl();
          WorkListener workListener = 
                  new NexesWorkListenerImpl();

          try {

              // Unlike scheduleWork() or doWork(), this call 
              // blocks until the work has started. If it takes 
              // longer than 10 seconds for the work to start, 
              // the call throws a WorkRejectedException.

              workManager.startWork
                      (nexesWorkJob, WORK_START_TIMEOUT, 
                      new ExecutionContext(), workListener);

          catch (WorkException e) {
              //  Handle the exception
          }
        }

       public void stop()
       {
          //  Do whatever you need to do here to close down the
          //  resource adapter.
       }  
       
          // Transaction Inflow contract methods omitted. 
          // See the section "Message Inflow and Transaction 
          // Inflow Contracts"

      }

Notice that there is an object passed in with the start() method that implements the BootstrapContext interface. This is an important object that allows the EIS to pass transaction information to the application server, as well as the ability to pass work to the application server. See the section "Message Inflow and Transaction Inflow Contracts" for more details about the BootstrapContext interface.

Also notice the reference to the WorkListener interface:

   WorkListener workListener = 
           new NexesWorkListenerImpl();

and the startWork method:

   workManager.startWork
           (nexesWorkJob, WORK_START_TIMEOUT, 
           new ExecutionContext(), workListener);

If you want the application server to notify you about the progress of any work that is submitted, you can create an object that implements the javax.resource.spi.WorkListener interface. You can then register this object using the startWork() method of the WorkManager object on the application server. The WorkManager interface provides a facility to submit Work instances for execution. Registering the object allows the server to notify the resource adapter if the work was rejected or accepted, and if accepted, when the work was started and completed. You can also extend the WorkAdapter class, which implements the WorkListener interface and provides empty methods for each of these. Here is skeleton code for a class that implements WorkListener:

   public class NexesWorkListenerImpl implements WorkListener {

      public void workAccepted(WorkEvent e) {
          //  myAppServerLog.log("Work instance " + e + 
          //      " has been accepted."); 
      }

      public void workRejected(WorkEvent e) {
          //  myAppServerLog.log("Work instance " + e + 
          //      " has been rejected."); 
      }

      public void workStarted(WorkEvent e) {
          //  myAppServerLog.log("Work instance " + e + 
          //      " has been started."); 
      }

      public void workCompleted(WorkEvent e) {
          //  myAppServerLog.log("Work instance " + e + 
          //      " has been completed."); 
      }

}

Message Inflow and Transaction Inflow Contracts

The Message Inflow contract allows the resource adapter to react to calls made by the application server to activate and deactivate message endpoints. The endpointActivation() method in the ResourceAdapter interface is called during endpoint activation. This causes the resource adapter to do the necessary setup for message delivery to the message endpoint. The endpointDeactivation() method of ResourceAdapter is called when a message endpoint is deactivated. This stops the resource adapter from delivering messages to the message endpoint. A MessageEndpointFactory object in the javax.resource.spi.endpoint package is passed in to the endpointActivation method. The object is used by the resource adapter to create a number of message endpoints. Any information about these endpoints should be removed from the resource adapter when the endpointDeactivation() method is called. Finally, the getXAResources() method of ResourceAdapter can be used to retrieve transaction resources in the event of a system crash. The endpointActivation(), endpointDeactivation(), and getXAResources() methods are mandated by the ResourceAdapter interface.

   public class NexesResourceAdapterImpl implements 
          ResourceAdapter {

      //  Lifecycle Contract methods from earlier omitted.

      public XAResource[] getXAResources(ActivationSpec[] specs)
      throws ResourceException
      {
          // This method should either return an array of 
          // XAResource objects that uniquely correspond to the 
          // resource manager given the ActivationSpecs passed 
          // in, or null if it does  not support this par 
          // of the Message Inflow contract.
        
          return null;
      }

      public void endpointActivation(MessageEndpointFactory mef, 
          ActivationSpec as
      throws NotSupportedException
      {
          // This is also part of the Message Inflow contract.
          // The idea here is to create a message endpoint 
          // using the MEF's createEndpoint() method, which is 
          // then stored in the ActivationSpec class. This binds 
          // the EIS and the application server together so that 
          // the two can communicate independently of the 
          // messaging style of the EIS.
      }

      public void endpointDeactivation(MessageEndpointFactory mef, 
          ActivationSpec as)
      {
          //  This removes any resources that were created by the 
          //  endpointActivation() method above for the specified
          //  messaging endpoint. The resource adapter must notify
          //  any message providers that the endpoint is no longer
          //  valid
      }

   }

The ActivationSpec class that is passed in to the ResourceAdapter methods is a JavaBean that implements a number of get and set methods for various properties. In addition to providing these get and set methods, an implementation must also provide a validate() method to ensure that all of the properties have been legally set. If a property has not been set properly, the method must throw an InvalidPropertyException. Note that an ActivationSpec object cannot override equals().

   public class MyActivationSpec implements ActivationSpec, 
           Serializable {

      public void setMyProperty(MyProperty s) { }
      public MyProperty getMyProperty() { }

      public void validate() throws InvalidPropertyException { }

   }

In version 1.0 of the J2EE Connector Architecture, a resource adapter could only pass transaction information to the EIS, either from itself or from an external transaction manager. However with the Transaction Inflow contract in version 1.5 of the architecture, the resource adapter can pass EIS transaction requests to the application server as well as use the BootstrapContext object that is passed in with the start() method of the Lifecycle Contract. The BootStrapContext interface was mentioned briefly in the discussion of the Lifecycle Management contract. Here are the methods in the BootstrapContext interface:

   public class NexesBootstrapContextImpl implements 
           BootstrapContext {

      public WorkManager getWorkManager() {
          //  Get the work manager from the application server
      }

      public XATerminator getXATerminator() {
          return new NexesXATerminatorImpl();
      }

      public Timer createTimer() {
          return new Timer();
      }

}

Let's also take a closer look at the XATerminator interface. Notice that it's the return type of the getXATerminator() method in the BootStrapContext interface. The XATerminator interface contains five simple methods that handle transactions:

   public class NexesXATerminatorImpl implements XATerminator {

      public void commit(Xid xid, boolean onePhase)
              throws XAException { }
      public void forget(Xid xidthrows XAException { }
      public int prepare(Xid xidthrows XAException { }
      public Xid[] recover(int flagthrows XAException { }
      public void rollback(Xid xidthrows XAException { }

   }

The Resource Adapter File

The resource adapter descriptor file, ra.xml, is fairly easy to create. You simply need to point in the file to the class that implements the ResourceAdapter interface. The application server will then access that class. See the J2EE Connector Architecture 1.5 specifications for more information on resource adapter deployment descriptors, including how to tie incoming message classes to ActivationSpec classes. Like all deployment descriptors, the ra.xml file needs to be in the WEB-INF directory of the WAR file.

   <?xml version="1.0" encoding="UTF-8"?>
   <connector xmlns="http://java.sun.com/xml/ns/j2ee"
     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>Skeleton Resource Adapter</display-name>
     <vendor-name>Sun Microsystems, Inc.</vendor-name>
     <eis-type>Unknown</eis-type>
     <resourceadapter-version>1.0</resourceadapter-version>

     <resourceadapter>
       <resourceadapter-class>
         com.nexes.ra.NexesResourceAdapterImpl
       </resourceadapter-class>
     </resourceadapter>

   </connector>

For more information about the J2EE Connector Architecture, see the J2EE Connector Architecture page.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.


 Related Tips

 
< Prev   Next >

Page 1 of 0 ( 0 comments )

You can share your information about this topic using the form below!

Please do not post your questions with this form! Thanks.


Name (required)


E-Mail (required)

Your email will not be displayed on the site - only to our administrator
Homepage(optional)



Comment Enable HTML code : Yes No



 
       
         
     
 
 
 
   
 
 
java bottom left
java bottom middle
java bottom right
RSS 0.91 FeedRSS 1.0 FeedRSS 2.0 FeedATOM FeedOPML Feed

Home - About Us - Privacy Policy
Copyright 2005 - 2008 www.java-tips.org
Java is a trademark of Sun Microsystems, Inc.