BEA Logo BEA Application Integration Adapter Development Kit Release 2.0

  BEA Home  |  Events  |  Solutions  |  Partners  |  Products  |  Services  |  Download  |  Developer Center  |  WebSUPPORT

 

   Application Integration Documentation   |   Application Integration Development Guide   |   Previous Topic   |   Next Topic   |   Contents   |   Index

Developing a Service Adapter

 

Service adapters receive an XML request document from a client and invoke the associated function in the underlying EIS. They are consumers of messages and may or may not provide a response. Service adapters perform the following four functions:

This section contains information on the following subjects:

J2EE-Compliant Adapters Not Specific to WebLogic Integration

The steps outlined in this chapter are directed primarily at developing adapters for use with WebLogic Integration. You can also use the ADK to develop adapters that can be used outside of the WebLogic Integration environment by following the steps herein, but modifying them as described in Creating an Adapter Not Specific to WebLogic Integration.

 


Service Adapters in the Runtime Environment

Figure 6-1 and Figure 6-2 show the processes executed when a service adapter is used in the runtime environment. Figure 6-1shows an asynchronous service adapter while Figure 6-2 shows a synchronous adapter.

Figure 6-1 An Asynchronous Service Adapter in the Runtime Environment


 
 

Figure 6-2 A Synchronous Service Adapter in the Runtime Environment


 
 

 


The Flow of Events

Figure 6-3 outlines the steps required to develop a Service Adapter.

Figure 6-3 Service Adapter Flow of Events


 
 

 


Step 1: Development Considerations

You will need to consider the items listed below before commencing with service adapter development. The Adapter Setup Worksheet will provide much of this information. See Adapter Setup Worksheet.

 


Step 2: Configuring the Development Environment

This step describes the processes you must complete to prepare your computer for adapter development.

Step 2a: Set Up the File Structure

Installing the Application Integration creates the file structure necessary not only to run an adapter, but also to use the ADK. The ADK files appear under <WLAI_HOME>\dev\, where <WLAI_HOME> is the directory where you installed the Application Integration distribution. You need to verify that, upon installation, the necessary directories and files appear in your <WLAI_HOME> directory. The file structure that follows under <WLAI_HOME>/ is described in Table 6-1:

Table 6-1 ADK File Structure


 

File Path/Filename

Description

dev

This directory contains the ADK.

dev/adk/src/war

All files under this directory should be included in the .war file for an adapter. This directory contains .jsp files, .html files, images, etc.

dev/bin

This directory contains a file used by the build process to timestamp .jar files.

dev/dbms

This directory contains a sample J2EE-compliant adapter built with the ADK.

dev/email

This directory contains a sample J2EE-compliant adapter built with the ADK.

dev/doc

This directory should contain the user guide, release notes, and installation guide for an adapter.

dev/doc/api

This directory contains Javadoc for an adapter, the ADK, and related classes.

dev/project

This directory contains the primary make file (Makefile) for the ADK make process and its related MakeOptions files. You should consult MakeOptions.mak for instructions on using the make process.

dev/sample

This directory contains a sample adapter that you can use to start developing their own adapter.

dev/sample/docs

This directory should contain the user guide, release notes, and installation guide for a the sample adapter.

dev/sample/docs/api

This directory contains Javadoc for the sample adapter, the ADK, and related classes.

dev/sample/docs/api_internal

A directory for internal API documentation.

dev/sample/lib

This directory contains adapter related .jar, .rar, and .war files.

dev/sample/project

This directory contains the Apache Jakarta Ant build file build.xml. This file contains build information for compiling the source code, generating the .jar, .rar, and .war files, and generating Javadoc information. See Step 2c: Setting Up the Build Process for details on how to build the adapter.

dev/sample/src

This directory contains all the source code for an adapter. It is up to you to decide to provide source code with your adapter.

dev/sample/src/BEA_WLS_SAMPLE_ ADK.properties

This file contains messages used by the adapter for internationalization and localization.

dev/sample/src/BEA_WLS_ SAMPLE_ADK.xml

This file provides a basic configuration file for the logging framework. You should use this file to develop their own adapter logging configuration file.

dev/sample/src/ eventrouter/WEB-INF/ web.xml

This is the configuration file for the event router web application.

dev/sample/src/rar/META- INF/ra.xml

This file contains configuration information about a J2EE-compliant adapter. You should use this file as a guide on which parameters needed by the ADK's runtime framework.

dev/sample/src/rar/META- INF/weblogic-ra.xml

This file contains configuration information about a J2EE-compliant adapter that is specific to the WebLogic 6.0 J2EE engine. You should use this file as an example for setting up the weblogic-ra.xml file for their adapter. It is required for WebLogic 6.0

dev/sample/src/sample

This directory contains the source code for the adapter.

dev/sample/src/war

All files under this directory should be included in the web application archive (.war) file for an adapter. This directory contains .jsp files, .html files, images, etc. For more information on web applications for WebLogic 6.0, look here

dev/sample/src/war/WEB- INF/web.xml

The web application descriptor

dev/sample/src/war/WEB-INF/ weblogic.xml

The weblogic.xml file contains WebLogic-specific attributes for a Web Application.

Modifying the Directory Structure

When you clone a development tree by using GenerateAdapterTemplate, the file paths and files under dev/sample are automatically cloned and updated to reflect the new development environment. The changes are reflected in the file dev/<CLONE>/api/index.html (where <CLONE> is the name of the new development directory). This file also contains code that you can copy and paste into the config.xml file and the <DEPLOYMENT_HOME>/wlai.properties files for the new adapter that will setup Application Integration to host the adapter.

Step 2b: Assign the Adapter Logical Name

Next, you need to assign the adapter's logical name. By convention, this name is comprised of the vendor name, the type of EIS connected to the adapter, and the version number of the EIS and is expressed as vendor_EIS-type_EIS version. For example:

BEA_WLS_SAMPLE_ADK

Step 2c: Setting Up the Build Process

The ADK employs a build process based upon Ant, a 100% pure Java-based build tool. For more information on Ant, please see Ant-Based Build Process. For more information on using Ant, see http://jakarta.apache.org/ant/index.html.

The sample adapter shipped with the ADK (located in <WLAI_HOME>\dev\bin\ sample) contains the file build.xml. This is the Ant build file for the sample adapter. It contains the tasks needed to build a J2EE-compliant adapter. Running the GenerateAdapterTemplate utility to clone a development tree for your adapter creates a build.xml file specifically for that adapter. This will free you from having to customize the sample build.xml and will ensure that the code is correct. For information on using the GenerateAdapterTemplate utility, see Creating a Custom Development Environment.

build.xml Components

If you edit build.xml and review its components, you will better understand how this file works. This section describes the prominent elements of build.xml.

Note: The following examples are taken from the sample adapter, not a cloned version thereof.

  1. The first line you encounter:
     <project name='BEA_WLS_SAMPLE_ADK' default='all' basedir='.'>

    sets the name attribute of the root project element.

  2. Listing 6-1sets the archive file (.jar, .war, and .rar) names.

    Listing 6-1 Setting Archive File Names

    <property name='JAR_FILE' value='BEA_WLS_SAMPLE_ADK.jar'/> <property name='RAR_FILE' value='BEA_WLS_SAMPLE_ADK.rar'/> <property name='WLS_RAR_FILE' value='BEA_WLS_SAMPLE_ADK_ WLSRAR.rar'/><property name='WAR_FILE' value='BEA_WLS_SAMPLE_ ADK_Web.war'/>

  3. Listing 6-2 shows a list of standard properties for the ADK. You shouldn't need to alter them.

    Listing 6-2 Standard ADK Properties

    <property name='PROJECT_DIR' value='.'/>
    <property name='ROOT' value='${PROJECT_DIR}/../..'/>
    <property name='SRC_DIR' value='${PROJECT_DIR}/../src'/>
    <property name='LIB_DIR' value='${PROJECT_DIR}/../lib'/>
    <property name='DOC_DIR' value='${PROJECT_DIR}/../docs/api'/>
    <property name='RESOURCE_DIR' value='${ROOT}/../resources'/>
    <property name='XALAN_JAR' value='${RESOURCE_DIR}/xml/xalan.jar'/>
    <property name='XERCES_JAR' value='${RESOURCE_DIR}/xml/xerces_dp1.jar'/>
    <property name='METAMATA_JAR' value='${RESOURCE_DIR}/metamata/metamata.jar'/>
    <property name='OROMATCHER_JAR' value='${RESOURCE_DIR}/OROMatcher-1.1.0a/oromatcher.jar'/>
    <property name='JAAS_JAR' value='${RESOURCE_DIR}/jaas1.0/jaas.jar'/>
    <property name='J2EECA_DIR' value='${RESOURCE_DIR}/j2eeca1.0'/>
    <property name='J2EECA_JAR' value='${J2EECA_DIR}/connector.jar'/>
    <property name='JDK13_JAR' value='${RESOURCE_DIR}/jre1.3/rt.jar'/>
    <property name='J2EE_JAR' value='${RESOURCE_DIR}/j2eesdk1.2/j2ee.jar'/>
    <property name='LICENSE_JAR' value='${RESOURCE_DIR}/license/license.jar'/>
    <property name='LOG4J_JAR' value='${RESOURCE_DIR}/ log4j/log4j.jar'/>
    <property name='WLAI_LIB_DIR' value='${ROOT}/../lib'/>
    <property name='ADK' value='${WLAI_LIB_DIR}/adk.jar'/>
    <property name='ADK_WEB' value='${WLAI_LIB_DIR}/adk-web.jar'/>
    <property name='ADK_EVENTGENERATOR' value='${WLAI_LIB_DIR}/adk-eventgenerator.jar'/>
    <property name='BEA' value='${WLAI_LIB_DIR}/bea.jar'/>
    <property name='LOGTOOLKIT' value='${WLAI_LIB_DIR}/logtoolkit.jar'/>
    <property name='WEBTOOLKIT' value='${WLAI_LIB_DIR}/webtoolkit.jar'/>
    <property name='WLAI_CLIENT' value='${WLAI_LIB_DIR}/wlaiclient.jar'/>
    <property name='WLAI_CLIENT_EJB' value='${WLAI_LIB_DIR}/wlaiclient-ejb.jar'/>
    <property name='WLAI_COMMON' value='${WLAI_LIB_DIR}/wlai-common.jar'/>
    <property name='WLAI_EJB' value='${WLAI_LIB_DIR}/wlai-ejb.jar'/>
    <property name='WLAI_EJB_CLIENT' value='${WLAI_LIB_DIR}/wlai-ejb-client.jar'/>
    <property name='WLAI_EVENTROUTER' value='${WLAI_LIB_DIR}/wlai-eventrouter.jar'/>
    <property name='WLAI_EVENTROUTER_CLIENT' value='${WLAI_LIB_DIR}/wlai-eventrouter-client.jar'/>
    <property name='WLAI_SERVLET_CLIENT' value='${WLAI_LIB_DIR}/wlai-servlet-client.jar'/>
    <property name='XMLTOOLKIT' value='${WLAI_LIB_DIR}/xmltoolkit.jar'/>
    <property name='XCCI' value='${WLAI_LIB_DIR}/xcci.jar'/>

    To the list in Listing 6-2, you can add any additional .jar files and/or classes that are specific to your adapter.

  4. Listing 6-3 sets up the classpath for compiling:

    Listing 6-3 Sample for Setting the Classpath

    <path id='CLASSPATH'>
       <pathelement location='${SRC_DIR}'/>
       <pathelement path='${ADK}:${ADK_WEB}:${BEA}:${LOGTOOLKIT}: ${WEBTOOLKIT}:${WLAI_COMMON}:${XCCI}:${XMLTOOLKIT}'/>
       <pathelement path='${J2EECA_JAR}:${JAAS_JAR}:${J2EE_JAR}'/>
       <pathelement path='${XERCES_JAR}:${XALAN_JAR}'/>
       <pathelement path='${LOG4J_JAR}'/>
    </path>

    To this information, you can add code that will produce the following:

  5. Listing 6-5 produce the .jar file for the adapter. This fileset element specifies what is included into the .jar file. Run-time aspects of the adapter are included in the main jar, while additional classes, such as the design-time GUI support classes, are included in the .war or other jar files.

    Listing 6-5 Sample Setting .jar File Contents

    <target name='jar' depends='packages,version_info'>
    <delete file='${LIB_DIR}/${JAR_FILE}'/>
    <jar jarfile='${LIB_DIR}/${JAR_FILE}'>

  6. Listing 6-6 includes the "includes" list from the adapter's source directory. For the adapter described in these code samples, all the classes in the sample/cci and sample/spi packages are included, as well as the logging configuration file and message bundles.

    Listing 6-6 Sample Code for Including the "Includes" List

    <fileset dir='${SRC_DIR}'  
    includes='sample/cci/*.class,sample/ spi/*.class,*.xml,*. properties'/>

  7. Listing 6-7 includes version information about the .jar file:

    Listing 6-7 Setting .jar File Version Information

    <fileset dir='${PROJECT_DIR}'
    includes='version_info.xml'/>
    </jar>
    </target>

  8. Listing 6-8 produces the J2EE adapter archive (.rar) file. The .rar file should contain all classes and JARs that the adapter needs. This .rar can be deployed into any J2EE-compliant application server that the adapter depends upon. This example includes the following targets:

  9. Listing 6-9 produces the .rar file specific for the WebLogic 6.0 platform. This file contains the weblogic-ra.xml file for the adapter. Otherwise, the fileset is the same for the standard .rar.

    Listing 6-9 Creating the WebLogic 6.0-Specific .rar File

    <target name='weblogic_rar' depends='jar'>
    <delete file='${LIB_DIR}/${WLS_RAR_FILE}'/>
      <jar jarfile='${LIB_DIR}/${WLS_RAR_FILE}'>
         <fileset dir='${LIB_DIR}' includes='${JAR_FILE}'/>
         <fileset dir='${PROJECT_DIR}' includes='version_info. xml'/>
         <fileset dir='${SRC_DIR}/rar' includes='META-INF/ ra.xml,META-INF/weblogic-ra.xml'/>
         <fileset dir='${WLAI_LIB_DIR}' includes='adk.jar,bea. jar,logtoolkit.jar,xcci.jar, xmltoolkit.jar'/>
         <fileset dir='${RESOURCE_DIR}/log4j' includes='log4j. jar'/>
    </jar>
    </target>

  10. Listing 6-10 produces the J2EE web application archive (.war) file. It also includes code that cleans up the existing environment:

    Listing 6-10 Sample Code Producing the .war File

     <target name='war' depends='jar'>
        <!-- Clean-up existing environment -->
        <delete file='${LIB_DIR}/${WAR_FILE}'/>
        <delete dir='${SRC_DIR}/war/WEB-INF/lib'/>
        <delete dir='${SRC_DIR}/war/WEB-INF/classes'/>
        <war warfile='${LIB_DIR}/${WAR_FILE}' webxml='${SRC_DIR}/war/WEB-INF/web.xml'>
          <fileset dir='${PROJECT_DIR}' includes='version_info.xml'/>
          <!-- 
          IMPORTANT! Exclude the WEB-INF/web.xml file from the WAR 
          as it already gets included via the webxml attribute above
          -->
          <fileset dir='${SRC_DIR}/war' excludes='WEB-INF/web.xml'/>
         <!--
          IMPORTANT! Include the ADK design time framework into the 
         adapter's design time Web application.
         -->
          <fileset dir='${ROOT}/adk/src/war'/>
          <!-- Include classes from the adapter that support the design time UI -->
          <classes dir='${SRC_DIR}' includes='sample/web/*.class'/>
          <!-- 
          Include all JARs required by the Web application under the
         WEB-INF/lib directory of the WAR file
          -->
          <lib dir='${LIB_DIR}' includes='${JAR_FILE}'/>
          <lib dir='${WLAI_LIB_DIR}' includes='adk.jar,adk-web.jar,bea.jar,logtoolkit.jar,webtoolkit.jar,wlai-common.jar,wlai-ejb-client.jar,xcci.jar,xmltoolkit.jar'/>
          <lib dir='${RESOURCE_DIR}/log4j' includes='log4j.jar'/>
          <lib dir='${RESOURCE_DIR}/OROMatcher-1.1.0a' includes='oromatcher.jar'/>
        </war>

  11. Listing 6-11 includes all .jar files required by the web application under the WEB-INF/lib directory of the .war file.

    Listing 6-11 Sample Code to Include JARs Required by Web Application

    <lib dir='${LIB_DIR}' includes='${JAR_FILE}'/>
         <lib dir='${WLAI_LIB_DIR}' includes='adk.jar,adk-web.jar,bea.jar,logtoolkit.jar,webtoolkit.jar,wlai-common.jar,wlai-ejb-client.jar,xcci.jar,xmltoolkit.jar'/>
         <lib dir='${RESOURCE_DIR}/log4j' includes='log4j.jar'/>
         <lib dir='${RESOURCE_DIR}/OROMatcher-1.1.0a' includes='oromatcher.jar'/>
         <lib dir='${RESOURCE_DIR}/xml' includes='xerces_dp1.jar'/>
         <lib dir='${RESOURCE_DIR}/xml' includes='xalan.jar'/>
       </war>
    </target>

  12. Listing 6-12 compiles all the Java source files for this project:

    Listing 6-12 Sample Code for Compiling Java Source

    <target name='packages'>
       <javac srcdir='${SRC_DIR}'>
         <classpath refid='CLASSPATH'/>
       </javac>
    </target>

  13. Listing 6-13 generates the Javadoc.

    Listing 6-13 Sample Code for Generating Javadocs

    <target name='apidoc'>
    <mkdir dir='${DOC_DIR}'/>
       <javadoc sourcepath='${SRC_DIR}'
         destdir='${DOC_DIR}'
         packagenames='sample.*'
         author='true'
         version='true'
         use='true'
         windowtitle='WebLogic Sample Adapter API Documentation'
         doctitle='WebLogic Sample Adapter API Documentation'
         header='WebLogic Sample Adapter'
         bottom='Built using the WebLogic Adapter Development Kit (ADK)'>
         <classpath refid='CLASSPATH'/>
       </javadoc>
    </target>

  14. Listing 6-14 shows the targets that clean the files created by their counterparts:

    Listing 6-14 Sample Code for Including Clean-Up Code

    <target name='clean_release' depends='clean_all,clean_apidoc'/>
      <target name='clean_all' depends='clean_rar,clean_weblogic_rar, clean_war'/>
      <target name='clean_rar' depends='clean_jar'>
         <delete file='${LIB_DIR}/${RAR_FILE}'/>
      </target>
      <target name='clean_weblogic_rar' depends='clean_jar'>
         <delete file='${LIB_DIR}/${WLS_RAR_FILE}'/>
      </target>
      <target name='clean_war' depends='clean_jar'>
         <delete file='${LIB_DIR}/${WAR_FILE}'/>
      </target>
      <target name='clean_jar' depends='clean_packages, clean_version_info'>
         <delete file='${LIB_DIR}/${JAR_FILE}'/>
      </target>
      <target name='clean_version_info'>
         <delete file='${PROJECT_DIR}/version_info.xml'/>
      </target>
      <target name='clean_packages'>
         <delete>
           <fileset dir='${SRC_DIR}' includes='**/*.class'/>
         </delete>
      </target>
      <target name='clean_apidoc'>
         <delete dir='${DOC_DIR}'/>
      </target>
    </project>

Step 2d: Create the Message Bundle

Any message destined for the end-user should be placed in a message bundle. The message bundle is simply a .properties text file that contains key=value pairs that allow you to internationalize messages. When a locale and national language are specified at runtime, the contents of the message is interpreted, based upon the key=value pair, and the message is presented to the user in the correct language for his or her locale.

For instructions on creating a message bundle, please refer to the JavaSoft tutorial on internationalization at:

http://java.sun.com/docs/books/tutorial/i18n/index.html

 


Step 3: Implementing the SPI

The Service Provider Interface (SPI) contains the objects that provide and manage connectivity to the EIS, establish transaction demarcation, and provide a framework for service invocation. All J2EE-compliant adapters must provide an implementation for these interfaces in the javax.resource.spi package.

How to Use this Section

Step 3: Implementing the SPI contains descriptions of the interfaces you can use to implement the SPI. A minimum of three interfaces are necessary to complete the task (see "Basic SPI Implementation"). Each of these are described in detail, followed by a discussion of how they were extended in the sample adapter included with the ADK.

Following the three required interfaces, the additional interfaces are described in detail, including information regarding why you might use them and what benefit they are to an adapter.

Basic SPI Implementation

To implement the SPI for your adapter, you need to extend at least these three interfaces:

Ideally, you will implement these interfaces in the order specified above.

In addition to these three interfaces, you can implement any of the other interfaces described in this step, as your adapter needs dictate.

ManagedConnectionFactory

javax.resource.spi.ManagedConnectionFactory

ManagedConnectionFactory instance is a factory of both ManagedConnection and EIS-specific connection factory instances. This interface supports connection pooling by providing methods for matching and creating a ManagedConnection instance.

Transaction Demarcation

A critical component of the ManagedConnectionFactory is transaction demarcation. You will need to determine which statements in your program are included in a single transaction. J2EE defines a transaction management contract between an application server and an adapter (and its underlying resource manager). The transaction management contract has two parts, depending of the type of transaction:

XA-compliant Transaction

A javax.transaction.xa.XAResource-based contract occurs between a transaction manager and a resource manager in a distributed transaction processing (DTP) environment. A JDBC driver or a JMS provider implements this interface to support association between a global transaction and a database or message service connection.

The XAResource interface can be supported by any transactional resource that is intended for use by application programs in an environment where transactions are controlled by an external transaction manager; for example a database management system where an application accesses data through multiple database connections. Each database connection is enlisted with the transaction manager as a transactional resource. The transaction manager obtains an XAResource for each connection participating in a global transaction. The transaction manager uses the start() method to associate the global transaction with the resource; it uses the end() method to disassociate the transaction from the resource. The resource manager associates the global transaction to all work performed on its data between the start() and end() method invocation.

At transaction commit time, the resource managers are informed by the transaction manager to prepare, commit, or rollback a transaction according to the two-phase commit protocol.

Local Transaction

A local transaction management contract occurs when an adapter implements the javax.resource.spi.LocalTransaction interface to provide support for local transactions that are performed on the underlying resource manager. These contracts enable an application server to provide the infrastructure and runtime environment for transaction management. Application components rely on this transaction infrastructure to support their component-level transaction model.

For more information on transaction demarcation support, please refer to:

http://java.sun.com/j2ee/blueprints/transaction_management/ platform/index.html

ADK Implementations

The ADK provides an abstract foundation for an adapter, the AbstractManagedConnectionFactory. This foundation provides the following feature:

There are several key methods that you must supply implementations for. The following paragraphs describe these methods.

createConnectionFactory()

createConnectionFactory(), shown in Listing 6-15, is responsible for constructing the factory for application-level connection handles for the adapter. In other words, clients of your adapter will use the object returned by this method to obtain a connection handle to the EIS.

If the adapter supports a CCI interface, it is recommended that you return an instance of com.bea.adapter.cci.ConnectionFactoryImpl or an extension of this class. The key to implementing this method correctly is to propagate the ConnectionManager, LogContext, and ResourceAdapterMetaData into the client API.

Listing 6-15 createConnectionFactory() Example

protected Object 
    createConnectionFactory(ConnectionManager connectionManager,
                            String strAdapterName,
                            String strAdapterDescription,
                            String strAdapterVersion,
                            String strVendorName)
    throws ResourceException

createManagedConnection()

createManagedConnection(), shown in Listing 6-16, is responsible for constructing a ManagedConnection instance for your adapter. The ManagedConnection instance encapsulates the expensive resources needed to communicate with the EIS. This method is called by the ConnectionManager when it determines a new ManagedConnection is required to satisfy a client's request. A common design pattern with adapters is to open the resources needed to communicate with the EIS in this method and then pass the resources into a new ManagedConnection instance.

Listing 6-16 createManagedConnection() Example

public ManagedConnection

createManagedConnection(Subject subject, ConnectionRequestInfo info)

throws ResourceException

checkState()

checkState() gets called by the AbstractManagedConnectionFactory before it attempts to perform any of its factory responsibilities. Use this method to verify that all members that need to be initialized before the ManagedConnectionFactory can perform its SPI responsibilities have been initialized correctly. Implement this method as shown here:

protected boolean checkState()

equals()

equals() tests the object argument for equality. It is important to implement this method correctly as it is used by the ConnectionManager for managing the connection pools. This method should include all important members in its equality comparison. Implement this method as shown here:

public boolean equals(Object obj)

hashCode()

hashCode() provides a hash code for the factory. It is also used by the ConnectionManager for managing the connection pools. Consequently, this method should generate a hashCode based upon properties that determine the uniqueness of the object. Implement this method as shown here:

public int hashCode()

matchManagedConnections()

Lastly, the ManagedConnectionFactory must supply an implementation of the matchManagedConnections() method. The AbstractManagedConnectionFactory provides an implementation of the matchManagedConnections() method that relies upon the compareCredentials method on AbstractManagedConnection.

In order to provide logic that will match managed connections, you will need to override AbstractManagedConnection's compareCredentials() method. This method is invoked when the ManagedConnectionFactory attempts to match a connection with a connection request for the ConnectionManager.

Currently, AbstractManagedConnectionFactory's implementation extracts a PasswordCredential from the supplied Subject/ConnectionRequestInfo parameters. If both parameters are null, this method returns true because it has already been established that the ManagedConnectionFactory for this instance is correct. Listing 6-17 shows this implementation:

Listing 6-17 compareCredentials() Implementation

public boolean compareCredentials(Subject subject,
                         ConnectionRequestInfo info) 
           throws ResourceException
     {
       ILogger logger = getLogger();

Next, you need to extract a PasswordCredential from either the JAAS Subject or the SPI ConnectionRequestInfo using the ADK's ManagedConnectionFactory. An example is shown in Listing 6-18:

Listing 6-18 Extracting a PasswordCredential

PasswordCredential pc = getFactory(). getPasswordCredential(subject, info);
     if (pc == null)
     {
       logger.debug(this.toString() + ": compareCredentials

In the example shown in Listing 6-18, JAAS Subject and ConnectionRequestInfo are null, which assumes a match. This method will not get invoked unless it has already been established that the factory for this instance is correct. Consequently, if the Subject and ConnectionRequestInfo are both null, then the credentials match by default; therefore, the result of pinging this connection determines the outcome of the comparison. Listing 6-19 shows how to programmatically ping the connection.

Listing 6-19 Pinging a Connection

      return ping();
    }
    boolean bUserNameMatch = true;
    String strPcUserName = pc.getUserName();
    if (m_strUserName != null)
    {
      logger.debug(this.toString() + ": compareCredentials >>> comparing my username ["+m_strUserName+"] with client username ["+strPcUserName+"]");

Next, you need to see if the user supplied in either the Subject or the ConnectionRequestInfo is the same as our user. We do not support re-authentication in this adapter, so if they do not match, this instance cannot satisfy the request. The following line of code does that:

bUserNameMatch = m_strUserName.equals(strPcUserName);

If usernames match, ping the connection to determine if this is still a good connection. Otherwise, there is no match and no reason to ping. The following line of code does that:

return bUserNameMatch ? ping() : false;

Explanation of the Implementation

Under a managed scenario, the application server invokes the matchManagedConnections() method on the ManagedConnectionFactory for an adapter. The specification does not indicate how the application server determines which ManagedConnectionFactory to use to satisfy a connection request. The ADK's AbstractManagedConnectionFactory implements matchManagedConnections(). The first step in this implementation is to compare "this" (that is, the ManagedConnectionFactory instance on which the ConnectionManager invoked matchManagedConnections) to the ManagedConnectionFactory on each ManagedConnection in the set supplied by the application server. For each ManagedConnection in the set that has the same ManagedConnectionFactory, the implementation invokes the compareCredentials() method. This method allows each ManagedConnection object to determine if it can satisfy the request.

matchManagedConnections() gets called by the ConnectionManager (as shown in Listing 6-20) to try to find a valid connection in the pool it is managing. If this method returns null, then the ConnectionManager will allocate a new connection to the EIS via a call to createManagedConnection().

Listing 6-20 matchManagedConnections() Method Implementation

public ManagedConnection
matchManagedConnections(Set connectionSet,
                            Subject subject,
                            ConnectionRequestInfo info) 
      throws ResourceException

This class uses the following approach to matching a connection:

  1. It iterates over the <code>connectionSet</code>, for each object in the set (until a match is found) it determines whether to not it's an AbstractManagedConnection.

  2. If it is, then this is compared to the ManagedConnectionFactory for the AbstractManagedConnection from the set.

  3. If the factories are equal, then the compareCredentials() method is invoked on the AbstractManagedConnection.

  4. If this method returns true, then the instance is returned.

AbstractManagedConnectionFactory Properties Required at Deployment

To use the base implementation of AbstractManagedConnectionFactory, you need to provide the following properties at deployment time:

Table 6-2 AbstractManagedConnectionFactory Properties


 

Property Name

Property Type

Applicable Values

Description

Default

LogLevel

java.lang.String

ERROR, WARN, INFO, DEBUG

Logs verbosity level.

WARN

LanguageCode

java.lang.String

valid ISO Language Code, see http://www.ics.uci. edu/pub/ietf/http/ related/iso639.txt

Determines the desired locale for log messages

en

CountryCode

java.lang. String

valid ISO Country Code, see http://www.chemie. fu-berlin.de/ diverse/doc/ISO_3166.html

Determines the desired locale for log messages

US

MessageBundleBase

java.lang. String

Any valid Java Class name or file name

Determines the message bundle for log messages

none, required

LogConfigFile

java.lang.String

Any valid file name

Configures the LOG4J system

none, required

RootLogContext

java.lang.String

Any valid Java String

Categorizes log messages from this connection factory.

none, required

AdditionalLog Context

java.lang.String

Any valid Java String

Adds additional information to uniquely identify messages from this factory.

none, optional

Other Key ManagedConnectionFactory Features in the ADK

In the ADK sample adapter, the class sample.spi.ManagedConnectionFactoryImpl is provided. This class extends AbstractManagedConnectionFactory. Use this class as an example of how to extend the ADK's base class.

For the complete sample adapter ManagedConnectionFactory implementation code listing, see:

<WLAI_HOME>\dev\sample\src\sample\spi\ManagedConnectionFactory Impl.java

ManagedConnection

javax.resource.spi.ManagedConnection

The ManagedConnection object is responsible for encapsulating all expensive resources needed to establish connectivity to the EIS. A ManagedConnection instance represents a physical connection to the underlying EIS. ManagedConnection objects are pooled by the application server in a managed environment.

ADK Implementation

The ADK provides an abstract implementation of this interface. The base class provides logic for managing connection event listeners and multiple application-level connection handles per ManagedConnection instance.

When implementing the ManagedConnection interface, you need to determine the transaction demarcation support provided by the underlying EIS. For more information on transaction demarcation, see Transaction Demarcation.

The ADK provides AbstractManagedConnection, an abstract implementation for the javax.resource.spi.ManagedConnection interface that:

The sample adapter that comes with the ADK includes ManagedConnectionImpl, which extends AbstractManagedConnection. For the complete sample adapter ManagedConnection implementation code listing, see:

<WLAI_HOME>\dev\sample\src\sample\spi\ManagedConnectionFactory Impl.java

ManagedConnectionMetaData

javax.resource.spi.ManagedConnectionMetaData

The ManagedConnectionMetaData interface provides information about the underlying EIS instance associated with a ManagedConnection instance. An application server uses this information to get runtime information about a connected EIS instance.

ADK Implementation

The ADK provides AbstractManagedConnectionMetaData, an abstract implementation of the javax.resource.spi.ManagedConnectionMetaData and javax.resource.cci.ConnectionMetaData interfaces that:

The sample adapter that comes with the ADK includes ManagedConnectionMetaDataImpl, which extends AbstractManagedConnectionMetaData. For the complete code listing, see:

<WLAI_HOME>\dev\sample\src\sample\spi\ManagedConnectionMetaDataImpl. java 

ConnectionEventListener

javax.resource.spi.ConnectionEventListener

The ConnectionEventListener interface provides an event callback mechanism that enables an application server to receive notifications from a ManagedConnection instance.

ADK Implementation

The ADK provides two concrete implementations of this interface:

In most cases, the implementations provided by the ADK are sufficient; you should not need to provide your own implementation of this interface.

ConnectionManager

javax.resource.spi.ConnectionManager

The ConnectionManager interface provides a hook for the adapter to pass a connection request to the application server.

ADK Implementation

The ADK provides a concrete implementation of this interface, com.bea.adapter.spi.NonManagedConnectionManager. This implementation provides a basic connection manager for adapters running in a non-managed environment. In a managed environment, this interface is provided by the application server. In most cases, you can use the implementation provided by the ADK.

NonManagedConnectionManager is a concrete implementation of the javax.resource.spi.ConnectionManager interface. It serves as the ConnectionManager in the non-managed scenario for an adapter; it does not provide any connection pooling or any other quality of service.

ConnectionRequestInfo

javax.resource.spi.ConnectionRequestInfo

The ConnectionRequestInfo interface enables an adapter to pass its own request specific data structure across the connection request flow. An adapter extends the empty interface to support its own data structures for a connection request.

ADK Implementation

The ADK provides a concrete implementation of this interface called ConnectionRequestInfoMap. This is a concrete implementation of the javax.resource.spi.ConnectionRequestInfo interface and provides a java.util.Map interface to such connection request information as username and password.

LocalTransaction

javax.resource.spi.LocalTransaction

The LocalTransaction interface provides support for transactions that are managed internal to an EIS resource manager, and do not require an external transaction manager.

ADK Implementation

The ADK provides an abstract implementation of this interface called AbstractLocalTransaction. This implementation allows you to focus on implementing the EIS-specific aspects of a LocalTransaction. This implementation:

 


Step 4: Implementing the CCI

The client interface allows a J2EE-compliant application to connect to and access back-end systems. The client interface manages the flow of data between the client application and the back-end system and does not have any visibility into what either the container or the application server are doing with the adapter. The client interface specifies the format of the request and response records for a given interaction with the EIS.

First, you must determine if your adapter must support the J2EE-compliant Common Client Interface (CCI). Although not a requirement in the 1.0 J2EE specification, it is likely to be a requirement in the next version. Consequently, the ADK focuses on helping you implement a CCI interface for your adapter.

How to Use this Section

Step 4: Implementing the CCI describes some of the interfaces you can use to implement the CCI. A minimum of two interfaces are necessary to complete the task (see "Basic CCI Implementation"). Each of these is described in detail, followed by a discussion of how they were extended in the sample adapter included with the ADK.

Following the two required interfaces, the additional interfaces are described in detail, including information regarding why you might use them and what benefit they provide to an adapter.

Basic CCI Implementation

To implement the CCI for your adapter, you need to extend at least these two interfaces:

Ideally, you will implement these interfaces in the order specified above.

In addition to these interfaces, you can implement any of the other interfaces described in this step, as your adapter needs dictate. These interfaces are:

Connection

javax.resource.cci.Connection

A Connection represents an application-level handle that is used by a client to access the underlying physical connection. The actual physical connection associated with a Connection instance is represented by a ManagedConnection instance.

A client gets a Connection instance by using the getConnection method on a ConnectionFactory instance. A connection can be associated with zero or more Interaction instances.

ADK Implementation

The ADK provides an abstract implementation of this interface called AbstractConnection. This interface provides the following functionality:

You will need to extend this class by providing an implementation for:

public Interaction createInteraction()
throws ResourceException

This method creates an interaction associated with this connection. An interaction enables an application to execute EIS functions. This method:

Interaction

javax.resource.cci.Interaction

The javax.resource.cci.Interaction enables a component to execute EIS functions. An Interaction instance supports the following ways of interacting with an EIS instance:

An interaction instance is created from a connection and is required to maintain its association with the Connection instance. The close() method releases all resources maintained by the adapter for the interaction. The close of an interaction instance should not close the associated connection instance.

ADK Implementation

The ADK provides an implementation of this interface called AbstractInteraction. This interface:

You must supply a concrete extension to AbstractInteraction that implements execute(). Use at least one of the following versions of execute():

execute() Version 1

The execute() method declared in Listing 6-21 shows an interaction represented by the InteractionSpec. This form of invocation takes an input record and updates the output record.

This method:

The parameters for execute() version 1 are:

Table 6-3 execute() Version 1 Parameters


 

Parameters

Description

ispec

InteractionSpec representing a target EIS data/function module

input

Input Record

output

Output Record

execute() Version 2

The execute() method declared in Listing 6-22 also executes an interaction represented by the InteractionSpec. This form of invocation takes an input Record and returns an output record if the execution of the Interaction has been successful.

This method:

If an exception occurs, this method will notify its connection, which will take the appropriate action, including closing itself.

Listing 6-22 execute() Version 2 Code Example

public Record execute(InteractionSpec ispec,
                      Record input)
              throws ResourceException

The parameters for execute() version 2 are:

Table 6-4 execute() Version 2 Parameters


 

Parameter

Description

ispec

InteractionSpec representing a target EIS data/function module

input

Input Record

Using XCCI to Implement the CCI

XCCI (XML-CCI) It is a dialect of CCI that uses XML-based record formats to represent data. It provides the tools and framework for supporting this record format. There are two primary components of XCCI: Services and DocumentRecords.

A service represents functionality available in an EIS and is comprised of four components:

DocumentRecord

com.bea.connector.DocumentRecord

At runtime, the XCCI layer expects DocumentRecord objects as input to a service and returns DocumentRecord objects as output from a service. DocumentRecord implements the javax.resource.cci.Record and the com.bea.document.IDocument interfaces. See Record for a description of that interface. IDocument, which facilitates XML input and output from the CCI layer in an adapter, is described in the following section.

IDocument

com.bea.document.IDocument

An IDocument is a higher-order wrapper around the W3C Document Object Model (DOM). The primary value-add of the IDocument interface is it provides an XPath interface to elements in an XML document. In other words, IDocument objects are queryable and updatable using XPath strings. For example, The XML document shown in Listing 6-23 describes a person named "Bob" and some of the details about "Bob."

Listing 6-23 XML Example

<Person name="Bob">
   <Home squareFeet="2000"/>
   <Family>
     <Child name="Jimmy">
       <Stats sex="male" hair="brown" eyes="blue"/>
     </Child>
     <Child name="Susie">
       <Stats sex="female" hair="blonde" eyes="brown"/>
     </Child>
   </Family>
</Person>

By using IDocument, you can retrieve Jimmy's hair color using the code shown in Listing 6-24:

Listing 6-24 IDocument Data Retrieval Code Sample

System.out.println("Jimmy's hair color: " + person.getStringFrom("//Person[@name=\"Bob\"]/Family/Child[@name=\"Jimmy\"]/Stats/@hair");

On the other hand, if you used DOM, you would need to enter the code shown in Listing 6-25:

Listing 6-25 DOM Data Retrieval Code Sample

String strJimmysHairColor = null;
org.w3c.dom.Element root = doc.getDocumentElement();
if (root.getTagName().equals("Person") && 
    root.getAttribute("name").equals("Bob") {
  org.w3c.dom.NodeList list = root.getElementsByTagName("Family");
  if (list.getLength() > 0) {
    org.w3c.dom.Element family = (org.w3c.dom.Element)list.item(0);
    org.w3c.dom.NodeList childList = family.getElementsByTagName("Child");
    for (int i=0; i < childList.getLength(); i++) {
      org.w3c.dom.Element child = childList.item(i);
      if (child.getAttribute("name").equals("Jimmy")) {
        org.w3c.dom.NodeList statsList = child.getElementsByTagName("Stats");
        if (statsList.getLength() > 0) {
          org.w3c.dom.Element stats = statsList.item(0);
          strJimmysHairColor = stats.getAttribute("hair");
        }
      }
    }
  }
}

As you can see, by using IDocument, you can simplify your code.

ADK-Supplied XCCI Classes

The ADK provides several classes that will help you implement XCCI for your adapters. This section describes those classes.

AbstractDocumentRecordInteraction

com.bea.adapter.cci.AbstractDocumentRecordInteraction

This class extends the ADK's abstract base Interaction, com.bea.adapter.cci.AbstractInteraction. The purpose of this class is to provide convenience methods for manipulating DocumentRecords and to reduce the amount of error handling the you need to implement. Specifically, this class declares:

protected abstract boolean execute(InteractionSpec ixSpec, DocumentRecord inputDoc, DocumentRecord outputDoc) throws ResourceException

and

protected abstract DocumentRecord execute(InteractionSpec ixSpec, DocumentRecord inputDoc) throws ResourceException

These methods will not be invoked on the concrete implementation until the parameters have been verified that they are DocumentRecord objects.

DocumentDefinitionRecord

com.bea.adapter.cci.DocumentDefinitionRecord

This class allows the adapter to return an IDocumentDefinition from its DocumentRecordInteraction implementation. This class is useful for satisfying design-time requests to create the request and/or response document definitions for a service.

ServiceInteractionSpecImpl

com.bea.adapter.cci.ServiceInteractionSpecImpl

This class allows you to save the request document definition and response document definition for a service into the InteractionSpec provided to the execute method at runtime. This is useful when the Interaction for an adapter needs access to the XML schemas for a service at runtime.

XCCI Design Pattern

A common design pattern that emerges when using the XCCI approach is to support the definition of services in the Interaction implementation. In other words, the javax.resource.cci.Interaction implementation for an adapter allows a client program to retrieve metadata from the underlying EIS in order to define an Application Integration service. Specifically, this means that the interaction must be able to generate the request and response XML schemas and additional metadata for a service. Additionally, the Interaction could also allow a client program to browse a catalog of functions provided by the EIS. This approach facilitates a thin client architecture for your adapter.

The ADK provides the com.bea.adapter.cci.DesignTimeInteractionSpecImpl class to help you implement this design pattern. The sample.cci.InteractionImpl class demonstrates how to implement this design pattern using the DesignTimeInteractionSpecImpl class.

ConnectionFactory

javax.resource.cci.ConnectionFactory

ConnectionFactory provides an interface for getting connection to an EIS instance. An implementation of ConnectionFactory interface is provided by an adapter.

The application code looks up a ConnectionFactory instance from JNDI namespace and uses it to get EIS connections.

An implementation class for ConnectionFactory is required to implement java.io.Serializable and javax.resource.Referenceableinterfaces to support JNDI registration.

ADK Implementation

The ADK provides ConnectionFactoryImpl, a concrete implementation of the javax.resource.cci.ConnectionFactory interface that provides the following functionality:

Typically, you will not need to extend this class and can use it outright.

ConnectionMetaData

javax.resource.cci.ConnectionMetaData

ConnectionMetaData provides information about an EIS instance connected through a Connection instance. A component calls the method Connection.getMetaData to get a ConnectionMetaData instance.

ADK Implementation

By default, the ADK provides an implementation of this class via the com.bea.adapter.spi.AbstractConnectionMetaData class. You will need to extend this abstract class and implement its four abstract methods for your adapter.

ConnectionSpec

javax.resource.cci.ConnectionSpec

ConnectionSpec is used by an application component to pass connection request-specific properties to the ConnectionFactory.getConnection() method.

It is recommended that you implement the ConnectionSpec interface as a JavaBean so that it can support tools. The properties on the ConnectionSpec implementation class must be defined through the getter and setter methods pattern.

The CCI specification defines a set of standard properties for an ConnectionSpec. The properties are defined either on a derived interface or an implementation class of an empty ConnectionSpec interface. In addition, an adapter may define additional properties specific to its underlying EIS.

ADK Implementation

Since the ConnectionSpec implementation must be a JavaBean, the ADK does not supply an implementation for this class.

InteractionSpec

javax.resource.cci.InteractionSpec

An InteractionSpec holds properties for driving an interaction with an EIS instance. It is used by an interaction to execute the specified function on an underlying EIS.

The CCI specification defines a set of standard properties for an InteractionSpec. An InteractionSpec implementation is not required to support a standard property if that property does not apply to its underlying EIS.

The InteractionSpec implementation class must provide getter and setter methods for each of its supported properties. The getter and setter methods convention should be based on the JavaBeans design pattern.

The InteractionSpec interface must be implemented as a JavaBean in order to support tools. An implementation class for InteractionSpec interface is required to implement the java.io.Serializable interface.

The Interaction spec contains information that is not in Record but helps determine what EIS function to invoke.

The standard properties are described in Table 6-5:

Table 6-5 Standard InteractionSpec Properties


 

Property

Description

FunctionName

Name of an EIS function

InteractionVerb

Mode of interaction with an EIS instance: SYNC_SEND, SYNC_SEND_RECEIVE, SYNC_RECEIVE

ExecutionTimeout

The number of milliseconds an Interaction will wait for an EIS to execute the specified function

The following standard properties are used to give hints to an interaction instance about the ResultSet requirements:

A CCI implementation can provide additional properties beyond that described in the InteractionSpec interface.

Note: The format and type of the additional properties is specific to an EIS and is outside the scope of the CCI specification.

ADK Implementation

The ADK contains a concrete implementation of javax.resource.cci.InteractionSpec called InteractionSpecImpl. This interface provides a base implementation for you to extend by using getter and setter methods for the standard interaction properties described in Table 6-5.

LocalTransaction

javax.resource.cci.LocalTransaction

The LocalTransaction interface is used for application-level local transaction demarcation. It defines a transaction demarcation interface for resource manager local transactions. The system contract level LocalTransaction interface (as defined in the javax.resource.spi package) is used by the container for local transaction management.

A local transaction is managed internal to a resource manager. There is no external transaction manager involved in the coordination of such transactions.

A CCI implementation can (but is not required to) implement the LocalTransaction interface. If the LocalTransaction interface is supported by a CCI implementation, then the method Connection.getLocalTransaction should return a LocalTransaction instance. A component can then use the returned LocalTransaction to demarcate a resource manager local transaction (associated with the Connection instance) on the underlying EIS instance.

The com.bea.adapter.spi.AbstractLocalTransaction class also implements this interface.

For more information on local transactions, see Transaction Demarcation.

Record

javax.resource.cci.Record

The javax.resource.cci.Record interface is the base interface for representing an input or output to the execute() methods defined on an Interaction. For more information on the execute() methods, see execute() Version 1 and execute() Version 2.

A MappedRecord or IndexedRecord can contain another Record. This means that you can use MappedRecord and IndexedRecord to create a hierarchical structure of any arbitrary depth. A basic Java type is used as the leaf element of a hierarchical structure represented by a MappedRecord or IndexedRecord.

The Record interface can be extended to form one of the representations shown in Table 6-6:

Table 6-6 Record Interface Representations


 

Representation

Description

MappedRecord

A key-value pair based collection representing a record. This interface is based on the java.util.Map

IndexedRecord

An ordered and indexed collection representing a record. This interface is based on the java.util.List.

JavaBean based representation of an EIS abstraction

An example is a custom record generated to represent a purchase order in an ERP system.

javax.resource.cci. ResultSet

This interface extends both java.sql.ResultSet and javax.resource.cci.Record. A ResultSet represents tabular data.

Assuming the adapter implements a CCI interface, the next consideration is the record format for a service. A service has a request record format and a response record format. The request record provides input to the service and the response record provides the EIS response.

ADK Implementation

The ADK focuses on helping you implement an XML-based record format in the CCI layer. To this end, the ADK provides the DocumentRecord class. In addition, you can use BEA's schema toolkit to develop schemas to describe the request and response documents for a service.

The ADK provides RecordImpl, a concrete implementation of the javax.resource.cci.Record interface that provides getter and setter methods for record name and description.

If an adapter provider wants to use an XML-based record format (which is highly recommended), the ADK also provides the com.bea.adapter.cci.Abstract DocumentRecordInteraction class. This class ensures that the client passes DocumentRecord objects. In addition, this class provides convenience methods for accessing content in a DocumentRecord.

ResourceAdapterMetaData

javax.resource.cci.ResourceAdapterMetaData

The interface javax.resource.cci.ResourceAdapterMetaData provides information about capabilities of an adapter implementation. A CCI client uses a ConnectionFactory.getMetaData to get metadata information about the adapter. The getMetaData() method does not require establishment of an active connection to an EIS instance. The ResourceAdapterMetaData interface can be extended to provide more information specific to an adapter implementation.

Note: This interface does not provide information about an EIS instance that is connected through the adapter.

ADK Implementation

The ADK provides ResourceAdapterMetaDataImpl that encapsulates adapter metadata and provides getters and setters for all properties.

 


Step 5: Deploying the Adapter

After implementing the SPI and CCI interfaces for an adapter, you deploy it. To deploy your adapter, you need to complete these tasks:

This section describes these tasks.

Step 5a: Update the ra.xml File

To deploy an adapter, you first must supply an adapter descriptor file. This file must be included in the adapter's .rar file as META-INF/ra.xml. The ADK provides a base implementation for this file with the sample adapter. If the adapter provider extends AbstractManagedConnectionFactory, you will need to supply the following properties in the ra.xml file:

Table 6-7 RA.XML Properties


 

Property

Example

LogLevel

This property specifies the log verbosity for this connection factory. Possible values are: DEBUG, INFO, WARN, ERROR, and AUDIT; for example:

<config-property>
     <config-property-name>LogLevel</config- property-name>
     <config-property-type>java.lang.String   </config-property-type>
     <config-property-value>WARN</config- property-value>
</config-property>	

LanguageCode

This property specifies the desired language code for log messages. This property is used with the CountryCode property to identify the correct message bundle from which to retrieve messages.

<config-property>
     <config-property-name>LanguageCode</config-property- name>
     <config-property-type>java.lang.String    </config-property-type>
     <config-property-value>en</config-property-value>
</config-property>		

CountryCode

This property specifies the desired country code for log messages.

<config-property>
     <config-property-name>CountryCode</config- property-name>
     <config-property-type>java.lang.String  </config-property-type>
     <config-property-value>US</config-property- value>
</config-property>

MessageBundleBase

This property specifies the base name for all message bundles supplied with an adapter. The ADK always uses the adapter logical name for its sample adapters. However, you are free to chose your own naming convention for message bundles.

<config-property>
     <config-property-name>MessageBundleBase</config- property-name>
     <config-property-type>java.lang.String </config-property-type>
     <config-property-value>sample</config-property-value>
</config-property>

LogConfigFile

This property specifies the log configuration file for the adapter.

<config-property>
     <config-property-name>LogConfigFile</config-property- name>
     <config-property-type>java.lang.String</config- property-type>
     <config-property-value>sample.xml</config-property- value>
</config-property>

RootLogContext

This property specifies the root log context. Log context helps categorize log messages according to modules in a program. The ADK uses the adapter logical name for the root log context so that all messages from a specific adapter will be categorized accordingly.

<config-property>
     <config-property-name>RootLogContext </config-property-name>
     <config-property-type>java.lang.String</config-    property-type>
     <config-property-value>sample</config-property-value>
</config-property>

AdditionalLogContext

This property allows the user to add additional log context information to help categorize messages. Typically, this is the name of the associated application view.

<config-property>
     <config-property-name>AdditionalLogContext</config- property- name>
     <config-property-type>java.lang.String</config- property-type>
</config-property>

You can see an example of a functioning ra.xml file for either a DBMS adapter or an e-mail adapter in one of the following locations:

Or, you can see an example for the cloned sample adapter at:

<WLAI_HOME>\dev\sample\src\rar\META-INF\

Step 5b: Create the weblogic-ra.xml File

The weblogic-ra.xml file is a deployment descriptor that contains essentially the same information as the ConnectionFactory descriptor, but in the form expected by the WebLogic J2EE engine. This file also contains a reference back to the "base" .rar deployment for the adapter. This reference allows the new .rar to use the code and other resources deployed in the base deployment, and frees it from containing itself. The reference to the base deployment also allows the new .rar to inherit any pool or connection parameters specified for base deployment.

When a user defines and starts to deploy an application view, a ConnectionFactory descriptor is created that contains the EIS connection parameters and connection pools parameters that the user entered. The ConnectionFactory descriptor also contains the JNDI name to which the new connection factory will be bound. This name is automatically generated based on the application view's qualified name. This ConnectionFactory descriptor is then deployed to the Application Integration engine, which, in turn, creates a new .rar file containing only a weblogic-ra.xml file.

A version of the weblogic-ra.xml file is included with the sample adapter at

<WLAI_HOME>\dev\sample\src\rar\META-INF\

When you run the GenerateAdapterTemplate utility, a version of this file tailored for you new adapter will be created.

You can see an example of a weblogic-ra.xml file for a DBMS adapter at:

<WLAI_HOME>\dev\dbms\src\rar\META-INF\

Step 5c: Create and Deploy the .rar File

Class files, logging configuration, and message bundle(s) should be bundled into a .jar file. This .jar file and META-INF/ra.xml should then be bundled into .rar file. The Ant build.xml file demonstrates how to properly construct the .rar file. See "Step 2c: Setting Up the Build Process." Listing 6-26 shows an example of a .rar file:

Listing 6-26

<Application Deployed="true" Name="BEA_WLS_SAMPLE_ADK_WLSRAR.rarPath="d:\wlai\dev\sample\lib">
     <ResourceAdapterComponent
      Description="__BEA_Sample_Description__"
      Name="BEA_WLS_SAMPLE_ADK_WLSRAR" Targets="myserver" URI="BEA_WLS_SAMPLE_ADK_WLSRAR.rar"/>
</Application>

Deploy the .rar file into the J2EE-compliant container in the application server. The deployment procedure will be different on every server.

 


Step 6: Testing the Adapter

The ADK provides a test harness that leverages JUnit, an open-source tool for unit testing. You can find more information on JUnit at http://www.junit.org.

com.bea.adapter.test.TestHarness does the following:

Using the Test Harness

To use the test harness in the ADK, complete the following steps:

  1. Create a class that extends junit.framework.TestCase. The class must provide a static method named suite that returns a new junit.framework.TestSuite. See the sample adapter for details.

  2. Implement test methods; name of methods should begin with "test"

  3. Create/alter the test.properties in the project directory (if you clone the sample adapter, then your adapter will already have a base test.properties in the project directory). The properties file should contain any configuration properties needed for your test case.

  4. Invoke the test using Ant. Your Ant build.xml file will need a test target that invokes the com.bea.adapter.test.TestHarness class with the properties file for your adapter. For example, the sample adapter uses the Ant target shown in Listing 6-27:

    Listing 6-27 Ant Target Specified in the Sample Adapter

    <target name='test' depends='packages'>
      <java classname='com.bea.adapter.test.TestHarness'>
         <arg value='-DCONFIG_FILE=test.properties'/<classpath refid='CLASSPATH'/>
      </java>
    </target>

    This target invokes the JVM with main class com.bea.adapter.test.TestHarness using the classpath established for the sample adapter and passes the command-line argument:

    -DCONFIG_FILE=test.properties

Test Case Extensions Provided by the ADK

The sample adapter ships with two basic TestCase extensions:

sample.spi.NonManagedScenarioTestCase

NonManagedScenarioTestCase allows you to test your SPI and CCI classes in a non-managed scenario. Specifically, this class tests the following:

sample.event.OfflineEventGeneratorTestCase

sample.event.OfflineEventGeneratorTestCase allows you to test the inner workings of your event generator outside of the WebLogic Server. Specifically, this class tests the following for the event generator:

sample.client.ApplicationViewClient

sample.client.ApplicationViewClient offers an additional way of test your adapter. This class is a Java program that demonstrates how to invoke a service and listen for an event on an application view. The Ant build.xml provides the "client" target to allow you to use the ApplicationViewClient program. Executing ant client will provide the usage for the program. To see an example of sample.client.ApplicationViewClient, go to <WLAI_HOME>/dev/sample/ src/sample/client.

Note: sample.client.ApplicationViewClient is not integrated with the test harness.

 

back to top previous page next page