bea.com | products | dev2dev | support | askBEA |
![]() |
![]() |
|
![]() |
e-docs > WebLogic Platform > WebLogic Integration > AI Topics > Developing Adapters > Developing a Service Adapter |
Developing Adapters
|
Developing a Service Adapter
A service adapter receives an XML request document from a client and invokes the associated function in the underlying EIS. Service adapters are consumers of messages; they may or may not provide responses. They perform the following four functions:
This section contains information about the following subjects:
J2EE-Compliant Adapters Not Specific to WebLogic Integration
The steps outlined in this section are directed primarily at developing adapters for use with WebLogic Integration. You can also use the ADK to develop adapters for use outside the WebLogic Integration environment, however, by following the same steps with certain modifications. For instructions, see Creating an Adapter Not Specific to WebLogic Integration.
Service Adapters in a Run-Time Environment
Figure 6-1 and Figure 6-2 show the processes that are executed when a service adapter is used in a run-time environment. Figure 6-1 shows an asynchronous service adapter; Figure 6-2, a synchronous adapter.
Figure 6-1 Asynchronous Service Adapter in a Run-Time Environment
Figure 6-2 Synchronous Service Adapter in a Run-Time Environment
Flow of Events
Figure 6-3 outlines the steps required to develop a service adapter.
Figure 6-3 Flow of Events in Service Adapter Development Process
Step 1: Research Your Environment Requirements
Before you start developing your service adapter, you must identify the resources needed in your environment to support it. This section provides a high-level description of the prerequisites for a development environment. For a complete list of required resources, see Adapter Setup Worksheet.
Based on your knowledge of the EIS, identify the interface to the back-end functionality.
An expensive connection object is an object required to invoke a function within the EIS. This function, in turn, is required for communicating with the EIS.
An expensive connection object requires an allocation of system resources, such as a socket connection or DBMS connection. A valuable benefit of using the J2EE Connector Architecture is that the application server pools these objects. Because the object for your adapter will be pooled by the application server, you need to identify it.
To pass connection authentication across the connection request path, your adapter must implement a ConnectionRequestInfo class. To facilitate such an implementation, the ADK provides the class ConnectionRequestInfoMap. You can use this class to map authorization information, such as username and password, to the connection.
The ADK conforms to the J2EE Connector Architecture Specification 1.0. For more information about connection architecture security, see the "Security" section of that document. You can download the specification in PDF format (for easy printing) from the following URL:
Decide which of the following types of transaction demarcation support to implement with your adapter:
Note: For more information about transaction demarcation support, see Transaction Demarcation, or see:
http://java.sun.com/blueprints/guidelines/designing_enterprise_applications/transaction_management/platform/index.html
Step 2: Configure the Development Environment
This section provides a four-step procedure (steps 2a-2d) for configuring your environment.
Note: A simple way of completing this procedure is by running the GenerateAdapterTemplate utility. For more information, see Creating a Custom Development Environment.
Step 2a: Set Up the Directory Structure
When you install WebLogic Integration, you also create the directory structure necessary not only to run an adapter, but also to use the ADK. The ADK files reside under WLI_HOME/adapters/, where WLI_HOME is the directory in which you installed WebLogic Integration. Be sure to verify that your WLI_HOME directory is populated with the necessary directories and files at installation time.
The following table describes the directory structure under WLI_HOME.
Modifying the Directory Structure When you clone a development tree by using GenerateAdapterTemplate, the contents of all the directories under adapters/sample are automatically cloned and updated to reflect the new development environment. The changes are also reflected in the file WLI_HOME/adapters/ADAPTER/docs/api/index.html, where the value of ADAPTER is the name of the new development directory. This file also contains code that you can copy and paste into the config.xml file for the new adapter that sets up WebLogic Integration to host the adapter. Step 2b: Assign the Adapter Logical Name Assign a logical name to the adapter. By convention, this name is made up of three items—the vendor name, the type of EIS connected to the adapter, and the version number of the EIS—separated by underscores, as follows: vendor_EIS-type_EIS-version For example: BEA_WLS_SAMPLE_ADK For more information about the logical name of an adapter, see Adapter Logical Name. Step 2c: Set Up the Build Process The ADK employs a build process based on Ant, a 100% pure Java-based build tool. For more information about Ant, see Ant-Based Build Process. For more information about using Ant, see:
The sample adapter provided with the ADK (in WLI_HOME/adapters/sample/project) contains build.xml, the Ant build file for the sample adapter. It contains the tasks needed to build a J2EE-compliant adapter. When you run the GenerateAdapterTemplate utility to clone a development tree for your adapter, a build.xml file is created specifically for that adapter. This automatic file generation frees you from having to customize the sample build.xml and ensures that the code is correct. For information about using the GenerateAdapterTemplate utility, see Creating a Custom Development Environment.
Manifest File
Among the files created by GenerateAdapterTemplate is MANIFEST.MF, the manifest file. This file contains classloading instructions for each component that uses the file. A manifest file is created for each /META-INF directory except ear/META-INF.
Listing 6-1 shows an example of the manifest file included with the sample adapter.
Listing 6-1 Manifest File Example
Manifest-Version: 1.0
Created-By: BEA Systems, Inc.
Class-Path: BEA_WLS_SAMPLE_ADK.jar adk.jar wlai-core.jar
wlai-client.jar
The first two lines of the file contain version and vendor information. The third line contains the relevant classpath or classloading instructions. The Class-Path property contains references to resources required by the component and a list of shared JAR files. (Filenames in the list are separated by spaces.) Make sure the JAR files are included in the shared area of the EAR file. (For details, see Enterprise Archive (EAR) Files.)
The JAR tool imposes a 72-character limit on the length of the Class-Path: line. Lines longer than 72 characters should carry over to the next line and begin with a preceeding space, as in the following:
Class-Path: .....72 chars of classpath
<space>more classpath
In the sample ADK adapters, all shared JAR files are combined into a single JAR file (shared.jar) using the following Ant commands:
Listing 6-2
<jar jarfile='${LIB_DIR}/shared.jar'>
<zipfileset src='${LIB_DIR}/${JAR_FILE}'>
<exclude name='META-INF/MANIFEST.MF'/>
</zipfileset>
<zipfileset src='${WLI_LIB_DIR}/adk.jar'>
<exclude name='META-INF/MANIFEST.MF'/>
</zipfileset>
<zipfileset src='${WLI_LIB_DIR}/wlai-core.jar'>
<exclude name='META-INF/MANIFEST.MF'/>
</zipfileset>
<zipfileset src='${WLI_LIB_DIR}/wlai-client.jar'>
<exclude name='META-INF/MANIFEST.MF'/>
</zipfileset>
</jar>
<jar jarfile='${LIB_DIR}/${EAR_FILE}'>
<fileset dir='${basedir}' includes='version_info.xml'/>
<fileset dir='${SRC_DIR}/ear' includes='META-INF/application.xml'/>
<fileset dir='${LIB_DIR}' includes='shared.jar,${RAR_FILE},${WAR_FILE},
${EVENTROUTER_WAR_FILE}'/>
</jar>
Note: When it is included in a WAR file, the filename MANIFEST.MF must be spelled in all uppercase letters. If it is spelled otherwise, it is not recognized on a UNIX system and an error occurs.
build.xml Components
To learn how build.xml works, open it and review its components. This section provides descriptions of the main file elements. Refer to these descriptions as you review the contents of build.xml.
Note: The examples in this section are taken from the sample adapter itself, not from a cloned version of it.
<project name='BEA_WLS_SAMPLE_ADK' default='all' basedir='.'>
Listing 6-3 Setting Archive Filenames
<property name='JAR_FILE' value='BEA_WLS_SAMPLE_ADK.jar'/>
<property name='RAR_FILE' value='BEA_WLS_SAMPLE_ADK.rar'/>
<property name='WAR_FILE' value='BEA_WLS_SAMPLE_ADK_Web.war'/>
<property name='EVENTROUTER_JAR_FILE'
value='BEA_WLS_SAMPLE_ADK_EventRouter.jar'/>
<property name='EVENTROUTER_WAR_FILE'
value='BEA_WLS_SAMPLE_ADK_EventRouter.war'/>
<property name='EAR_FILE' value='BEA_WLS_SAMPLE_ADK.ear'/>
Listing 6-4 Standard ADK Properties
<property name='ADK' value='${WLI_LIB_DIR}/adk.jar'/>
<property name='ADK_WEB' value='${WLI_LIB_DIR}/adk-web.jar'/>
<property name='ADK_TEST' value='${WLI_LIB_DIR}/adk-test.jar'/>
<property name='ADK_EVENTGENERATOR' value='${WLI_LIB_DIR}/
adk-eventgenerator.jar'/>
<property name='BEA' value='${WLI_LIB_DIR}/bea.jar'/>
<property name='LOGTOOLKIT' value='${WLI_LIB_DIR}/
logtoolkit.jar'/>
<property name='WEBTOOLKIT' value='${WLI_LIB_DIR}/
webtoolkit.jar'/>
<property name='WLAI_CORE' value='${WLI_LIB_DIR}/
wlai-core.jar'/>
<property name='WLAI_CLIENT' value='${WLI_LIB_DIR}/
wlai-client.jar'/>
<property name='WLAI_COMMON' value='${WLI_LIB_DIR}/
wlai-common.jar'/>
<property name='WLAI_EVENTROUTER' value='${WLI_LIB_DIR}/
wlai-eventrouter.jar'/>
<property name='XMLTOOLKIT' value='${WLI_LIB_DIR}/
xmltoolkit.jar'/>
<property name='XCCI' value='${WLI_LIB_DIR}/xcci.jar'/>
You should not need to alter these properties. After them, however, you can add any other JAR files and/or classes needed by your adapter.
Listing 6-5 Setting the Classpath
<path id='CLASSPATH'>
<pathelement location='${SRC_DIR}'/>
<pathelement path='${ADK}:${ADK_EVENTGENERATOR}:
${ADK_WEB}:${ADK_TEST}:${WEBTOOLKIT}:${WLAI_CORE}:
${WLAI_EVENTROUTER}:${WLAI_CLIENT}'/>
<pathelement path='${WEBLOGIC_JAR}:${env.BEA_HOME}'/>
<pathelement path='${JUNIT}:${HTTPUNIT}:${TIDY}'/>
</path>
After this information, you have the option of calling any of the following three combinations of files:
Listing 6-6 Sample of Calling All Binaries and Archives
<!-- This target produces all the binaries and archives
for the adapter -->
<target name='all' depends='ear'/>
<target name='release' depends='all,apidoc'/>
Listing 6-7 Sample version_info File
<!-- This target produces a version_info file for inclusion into
archives -->
<target name='version_info'>
<java classname='GenerateVersionInfo'>
<arg line='-d${basedir}'/>
<classpath>
<pathelement path='${WLI_HOME}/adapters/utils:
${WEBLOGIC_JAR}'/>
</classpath>
</java>
</target>
Listing 6-8 Sample Code for Setting Values in a JAR File
<target name='jar' depends='packages,version_info'>
<delete file='${LIB_DIR}/${JAR_FILE}'/>
<mkdir dir='${LIB_DIR}'/>
<jar jarfile='${LIB_DIR}/${JAR_FILE}'>
Listing 6-9 Sample Code for Including the Includes List
<fileset dir='${SRC_DIR}'
includes='sample/cci/*.class,sample/spi/*.class,
sample/eis/*. class,*.xml,*.properties'/>
Listing 6-10 Setting JAR File Version Information
<!-- Include version information about the JAR file -->
<fileset dir='${basedir}'
includes='version_info.xml'/>
</jar>
Listing 6-11 Sample Code for Creating the Connection Architecture RAR File
<target name='rar' depends='jar'>
<delete file='${LIB_DIR}/${RAR_FILE}'/>
<mkdir dir='${LIB_DIR}'/>
<jar jarfile='${LIB_DIR}/${RAR_FILE}'
manifest='${SRC_DIR}/rar/META-INF/MANIFEST.MF'>
<fileset dir='${SRC_DIR}/rar'includes='META-INF/ra.xml,
META-INF/weblogic-ra.xml' excludes=
'META-INF/MANIFEST.MF'/>
</jar>
</target>
Listing 6-12 Sample Code for Producing the WAR File
<target name='war' depends='jar'>
<!-- Clean-up existing environment -->
<delete file='${LIB_DIR}/${WAR_FILE}'/>
<copy file='${WLI_HOME}/adapters/src/war/WEB-INF/taglibs/
adk.tld' todir='${SRC_DIR}/war/WEB-INF/taglibs'/>
<java classname='weblogic.jspc' fork='yes'>
<arg line='-d ${SRC_DIR}/war -webapp ${SRC_DIR}/
war -compileAll -depend'/>
<classpath refid='CLASSPATH'/>
</java>
<!-- The first adapter should compile the common ADK JSPs -->
<java classname='weblogic.jspc' fork='yes'>
<arg line='-d ${WLI_HOME}/adapters/src/war -webapp
${WLI_HOME}/adapters/src/war -compileAll
-depend'/>
<classpath refid='CLASSPATH'/>
</java>
<war warfile='${LIB_DIR}/${WAR_FILE}'
webxml='${SRC_DIR}/war/WEB-INF/web.xml'
manifest='${SRC_DIR}/war/META-INF/MANIFEST.MF'>
<!--
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" >
<patternset >
<include name="WEB-INF/weblogic.xml"/>
<include name="**/*.html"/>
<include name="**/*.gif"/>
</patternset>
</fileset>
<!--
IMPORTANT! Include the ADK design time framework into the
adapter's design time Web application.
-->
<fileset dir="${WLI_HOME}/adapters/src/war" >
<patternset >
<include name="**/*.css"/>
<include name="**/*.html"/>
<include name="**/*.gif"/>
<include name="**/*.js"/>
</patternset>
</fileset>
<!-- Include classes from the adapter that support the design
time UI -->
<classes dir='${SRC_DIR}' includes='sample/web/*.class'/>
<classes dir='${SRC_DIR}/war'includes='**/*.class'/>
<classes dir='${WLI_HOME}/adapters/src/war' includes=
'**/*.class'/>
<!--
Include all JARs required by the Web application under the
WEB-INF/lib directory of the WAR file that are not shared in the
EAR
-->
Listing 6-13 Including JAR Files Needed by Web Application
<lib dir='${WLI_LIB_DIR}' includes='adk-web.jar,
webtoolkit.jar,wlai-client.jar'/>
Listing 6-14 Including the EAR File
<target name='ear' depends='rar,eventrouter_jar,war'>
<delete file='${LIB_DIR}/${EAR_FILE}'/>
<!-- include an eventrouter that shares the jars
rather than includes them-->
<delete file='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'/>
<delete dir='${SRC_DIR}/eventrouter/WEB-INF/lib'/>
<war warfile='${LIB_DIR}/${EVENTROUTER_WAR_FILE}
'webxml='${SRC_DIR}/eventrouter/WEB-INF/web.xml
'manifest='${SRC_DIR}/eventrouter/META-INF/
MANIFEST.MF'>
<fileset dir='${basedir}' includes='version_info.xml'/>
<fileset dir="${SRC_DIR}/eventrouter" >
<patternset>
<exclude name="WEB-INF/web.xml"/>
<exclude name="META-INF/*.mf"/>
</patternset>
</fileset>
<lib dir='${LIB_DIR}' includes='${EVENTROUTER_JAR_
FILE}'/>
<lib dir='${WLI_LIB_DIR}'includes=
'adk-eventgenerator.jar,wlai-eventrouter.jar'/>
</war>
<jar jarfile='${LIB_DIR}/${EAR_FILE}'>
<fileset dir='${basedir}' includes='version_info.xml'/>
<fileset dir='${SRC_DIR}/ear' includes=
'application.xml'/>
<fileset dir='${LIB_DIR}'includes='${JAR_FILE},
${RAR_FILE}, ${WAR_FILE},${EVENTROUTER_WAR_FILE}'/>
<fileset dir='${WLI_LIB_DIR}'includes='adk.jar,
wlai-core.jar,wlai-client.jar'/>
</jar>
<delete file='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'/>
<delete file='${LIB_DIR}/${EVENTROUTER_JAR_FILE}'/>
<delete file='${LIB_DIR}/${WAR_FILE}'/>
<delete file='${LIB_DIR}/${RAR_FILE}'/>
<delete file='${LIB_DIR}/${JAR_FILE}'/>
</target>
Because an event router specific to the EAR deployment cannot be deployed by itself, it is called from within the EAR target, as shown in the following listing.
Listing 6-15 Including EAR-specific EventRouter
<delete file='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'/>
<delete dir='${SRC_DIR}/eventrouter/WEB-INF/lib'/>
<war warfile='${LIB_DIR}/${EVENTROUTER_WAR_FILE}
'webxml='${SRC_DIR}/eventrouter/WEB-INF/web.xml
'manifest='${SRC_DIR}/eventrouter/META-INF/
MANIFEST.MF'>
<fileset dir='${basedir}' includes='version_info.xml'/>
<fileset dir="${SRC_DIR}/eventrouter" >
<patternset >
<exclude name="WEB-INF/web.xml"/>
<exclude name="META-INF/*.mf"/>
</patternset>
</fileset>
<lib dir='${LIB_DIR}' includes='${EVENTROUTER_
JAR_FILE}'/>
<libdir='${WLI_LIB_DIR}'
includes='adk-eventgenerator.jar,
wlai-eventrouter.jar'/>
</war>
Within the EAR target shown in the previous listing you can also find all common or shared JAR files, as shown in the following listing.
Listing 6-16 Including Common or Shared JAR Files
<jar jarfile='${LIB_DIR}/${EAR_FILE}'>
<fileset dir='${basedir}' includes='version_info.xml'/>
<fileset dir='${SRC_DIR}/ear' includes='application.xml'/>
<fileset dir='${LIB_DIR}'includes='${JAR_FILE},${RAR_FILE},
${WAR_FILE},${EVENTROUTER_WAR_FILE}'/>
<fileset dir='${WLI_LIB_DIR}' includes='adk.jar,
wlai-core.jar,wlai-client.jar'/>
</jar>
Listing 6-17 Compiling Java Source
<target name='packages'>
<echo message='Building ${ant.project.name}...'/>
<javac srcdir='${SRC_DIR}'
excludes='war/jsp_servlet/**'
deprecation='true' debug='true'>
<classpath refid='CLASSPATH'/>
</javac>
</target>
Listing 6-18 Constructing the EventRouter JAR File
<target name='eventrouter_jar' depends='packages,version_info'>
<delete file='${LIB_DIR}/${EVENTROUTER_JAR_FILE}'/>
<jar jarfile='${LIB_DIR}/${EVENTROUTER_JAR_FILE}'>
<fileset dir='${SRC_DIR}'
includes='sample/event/*.class'/>
<fileset dir='${basedir}'
includes='version_info.xml'/>
</jar>
</target>
Listing 6-19 Producing the EventRouter Target for Stand-Alone Deployment
<target name='eventrouter_war' depends='jar,eventrouter_jar'>
<delete file='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'/>
<delete dir='${SRC_DIR}/eventrouter/WEB-INF/lib'/>
<war warfile='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'webxml=
'${SRC_DIR}/eventrouter/WEB-INF/web.xml'>
<fileset dir='${basedir}' includes='version_info.xml'/>
<fileset dir='${SRC_DIR}/eventrouter' excludes=
'WEB-INF/web.xml'/>
<lib dir='${LIB_DIR}' includes='${JAR_FILE},
${EVENTROUTER_JAR_FILE}'/>
<lib dir='${WLI_LIB_DIR}'includes='adk.jar,
adk-eventgenerator.jar,wlai-core.jar,
wlai-eventrouter.jar,wlai-client.jar''/>
</war>
</target>
Listing 6-20 Generating Javadoc
<target name='apidoc'>
<mkdir dir='${DOC_DIR}'/>
<javadoc sourcepath='${SRC_DIR}'
destdir='${DOC_DIR}'
packagenames='sample.*'
author='true'
version='true'
use='true'
overview='${SRC_DIR}/overview.html'
windowtitle='WebLogic BEA_WLS_SAMPLE_ADK Adapter
API Documentation'
doctitle='WebLogic BEA_WLS_SAMPLE_ADK Adapter
API Documentation'
header='WebLogic BEA_WLS_SAMPLE_ADK Adapter'
bottom='Built using the WebLogic Adapter
Development Kit (ADK)'>
<classpath refid='CLASSPATH'/>
</javadoc>
</target>
Listing 6-21 Including Cleanup Code
<target name='clean' depends='clean_release'/>
<target name='clean_release' depends='clean_all,clean_apidoc'/>
<target name='clean_all'depends='clean_ear,clean_rar,clean_war,
clean_eventrouter_war,clean_test'/>
<target name='clean_test'>
<delete file='${basedir}/BEA_WLS_SAMPLE_ADK.log'/>
<delete file='${basedir}/mcf.ser'/>
</target>
<target name='clean_ear' depends='clean_jar'>
<delete file='${LIB_DIR}/${EAR_FILE}'/>
</target>
<target name='clean_rar' depends='clean_jar'>
<delete file='${LIB_DIR}/${RAR_FILE}'/>
</target>
<target name='clean_war' depends='clean_jar'>
<delete file='${LIB_DIR}/${WAR_FILE}'/>
<delete dir='${SRC_DIR}/war/jsp_servlet'/>
</target>
<target name='clean_jar' depends='clean_packages,clean_version_
info'>
<delete file='${LIB_DIR}/${JAR_FILE}'/>
</target>
<target name='clean_eventrouter_jar'>
<delete file='${LIB_DIR}/${EVENTROUTER_JAR_FILE}'/>
</target>
<target name='clean_eventrouter_war' depends='clean_
eventrouter_jar'>
<delete file='${LIB_DIR}/${EVENTROUTER_WAR_FILE}'/>
</target>
<target name='clean_version_info'>
<delete file='${basedir}/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 an end-user should be placed in a message bundle: a .properties text file containing key=value pairs that allow you to generate messages in more than one natural language. When a locale and a language are specified at run time, the contents of a message are interpreted in accordance with the relevant key=value pairs, and the message is presented to the user in the language appropriate for his or her locale.
For instructions on creating a message bundle, see the JavaSoft tutorial on internationalization at:
http://java.sun.com/docs/books/tutorial/i18n/index.html
Step 3: Implement 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.
This section 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 interface is described in detail, followed by a discussion of how it is extended in the sample adapter included with the ADK.
First, we describe the three required interfaces. Then we describe the additional interfaces in detail, and discuss why you might use them and how they can be beneficial when used in an adapter.
Basic SPI Implementation
To implement the SPI for your adapter, you must extend at least the following three interfaces:
Ideally, these interfaces are implemented in the order specified here.
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
The ManagedConnectionFactory interface 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 interface is transaction demarcation. You must be able 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. The contract differs, depending on the type of transaction for which it is used. There are two types of transactions:
XA-Compliant Transaction
In a distributed transaction processing (DTP) environment, a javax.transaction.xa.XAResource-based contract is established between a transaction manager and a resource manager. A JDBC driver or a JMS provider implements this interface to support the 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 in which transactions are controlled by an external transaction manager.
An example of such a resource is a database management system set up in such a way that 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 with all work performed on its data between invocations of the start() and end() methods.
At transaction commit time, the resource managers are instructed, by the transaction manager, to prepare, commit, or roll back a transaction, according to the two-phase commit protocol.
Local Transaction
When an adapter implements the javax.resource.spi.LocalTransaction interface to support local transactions that are performed on the underlying resource manager, a local transaction management contract is established. This contract enables an application server to provide the infrastructure and run-time environment for transaction management. Application components rely on this transaction infrastructure to support the component-level transaction model that they use.
For more information about transaction demarcation support, enter the following URL:
http://java.sun.com/blueprints/guidelines/
designing_enterprise_applications/transaction_management/
platform/index.html
ADK Implementations
The ADK provides an abstract foundation for an adapter called the AbstractManagedConnectionFactory. This foundation provides the following features:
You must provide your own implementations for the following key methods:
The following sections describe these methods.
createConnectionFactory()
createConnectionFactory() is 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, we recommend 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-22 createConnectionFactory() Example
protected Object
createConnectionFactory(ConnectionManager connectionManager,
String strAdapterName,
String strAdapterDescription,
String strAdapterVersion,
String strVendorName)
throws ResourceException
createManagedConnection()
createManagedConnection() is used to construct a ManagedConnection instance for your adapter. The following listing shows an example of this method.
Listing 6-23 createManagedConnection() Example
public ManagedConnection
createManagedConnection(Subject subject, ConnectionRequestInfo
info)
throws ResourceException
The ManagedConnection instance encapsulates the expensive resources needed to communicate with the EIS. This method is called by the ConnectionManager when it determines that a new ManagedConnection is required to satisfy a client's request. A common design pattern used in 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.
checkState()
The checkState() method is called by the AbstractManagedConnectionFactory before it attempts to perform any 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 follows:
protected boolean checkState()
equals()
The equals() method tests the object argument for equality. It is important to implement this method correctly because 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 follows:
public boolean equals(Object obj)
hashCode()
The hashCode() method 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 on properties that determine the uniqueness of the object.
Implement this method as follows:
public int hashCode()
matchManagedConnections()
The ManagedConnectionFactory must supply an implementation of the matchManagedConnections() method. The AbstractManagedConnectionFactory provides an implementation of the matchManagedConnections() method that relies on the compareCredentials() method of AbstractManagedConnection.
To provide logic that can match managed connections, you must override the compareCredentials() method provided by the AbstractManagedConnection class. This method is invoked when the ManagedConnectionFactory attempts to match a connection with a connection request for the ConnectionManager.
Currently, the AbstractManagedConnectionFactory implementation extracts a PasswordCredential from the Subject/ConnectionRequestInfo parameters that are supplied. If both parameters are null, this method returns true because it has already been established that the ManagedConnectionFactory for this instance is correct. This implementation is shown in the following listing.
Listing 6-24 compareCredentials() Implementation
public boolean compareCredentials(Subject subject,
ConnectionRequestInfo info)
throws ResourceException
{
ILogger logger = getLogger();
Next, you must extract a PasswordCredential from either the JAAS Subject or the SPI ConnectionRequestInfo using the ADK's ManagedConnectionFactory. An example is shown in the following listing.
Listing 6-25 Extracting a PasswordCredential
PasswordCredential pc = getFactory().
getPasswordCredential(subject, info);
if (pc == null)
{
logger.debug(this.toString() + ": compareCredentials
In the previous listing, JAAS Subject and ConnectionRequestInfo are null, which means that a match is assumed. This method is not 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. The following listing shows how to ping the connection programmatically.
Listing 6-26 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 check whether the user specified in either the Subject or ConnectionRequestInfo is the same as our user. We do not support reauthentication in this adapter, so if the usernames do not match, this instance cannot satisfy the request. The following code satisfies the request:
bUserNameMatch = m_strUserName.equals(strPcUserName);
If the usernames match, ping the connection to determine whether it is still good. If the names do not match, there is no reason to ping.
To ping the connection, use the following code:
return bUserNameMatch ? ping() : false;
Explanation of the Implementation
In 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 whether it can satisfy the request.
matchManagedConnections() is called by the ConnectionManager (as shown in Listing 6-27) to search for a valid connection in the pool it is managing. If this method returns null, then the ConnectionManager allocates a new connection to the EIS via a call to createManagedConnection().
Listing 6-27 matchManagedConnections() Method Implementation
public ManagedConnection
matchManagedConnections(Set connectionSet,
Subject subject,
ConnectionRequestInfo info)
throws ResourceException
This class uses the following approach to match a connection:
AbstractManagedConnectionFactory Properties Required at Deployment
To use the base implementation of AbstractManagedConnectionFactory, you must, at deployment time, provide the properties described in the following table.
Other Key ManagedConnectionFactory Features in the ADK The ADK sample adapter provides a class called sample.spi.ManagedConnectionFactoryImpl that extends AbstractManagedConnectionFactory. Use this class as an example of how to extend the ADK's base class. For a complete code listing of an implementation of the sample adapter called ManagedConnectionFactory, see: WLI_HOME/adapters/sample/src/sample/spi/ ManagedConnection javax.resource.spi.ManagedConnection The ManagedConnection object is responsible for encapsulating all the 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 ManagedConnection. The base class provides logic for managing connection event listeners and multiple application-level connection handles for each instance of ManagedConnection. When implementing the ManagedConnection interface, you need to determine the transaction demarcation support provided by the underlying EIS. For more information about transaction demarcation, see Transaction Demarcation. The ADK provides AbstractManagedConnection, an abstract implementation for the javax.resource.spi.ManagedConnection interface that:
ManagedConnectionFactoryImpl.java
The sample adapter provided with the ADK includes ManagedConnectionImpl, which extends AbstractManagedConnection. For a complete code listing for a sample adapter called ManagedConnection, see:
WLI_HOME/adapters/sample/src/sample/spi/
ManagedConnectionFactoryImpl.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 run-time 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 provided with the ADK includes ConnectionMetaDataImpl, which extends AbstractManagedConnectionMetaData. For the complete code listing for the adapter, see:
WLI_HOME/adapters/sample/src/sample/spi/ConnectionMetaDataImpl.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 ConnectionEventListener:
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 that can be used by 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 an unmanaged 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 unmanaged 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 a 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 the javax.resource.spi.ConnectionRequestInfo interface. This interface is called ConnectionRequestInfoMap. It provides a java.util.Map interface to information requested when a connection is being established, such as username and password.
LocalTransaction
javax.resource.spi.LocalTransaction
The LocalTransaction interface provides support for transactions that are managed within 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, thus allowing you to focus on implementing the EIS-specific aspects of a LocalTransaction. Specifically, it:
Step 4: Implement the CCI
The client interface allows a J2EE-compliant application to access back-end systems. The client interface manages the flow of data between the client application and the back-end system; it 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 both the request records and the response records for a given interaction with the EIS.
First, you must determine whether your adapter must support the J2EE-compliant Common Client Interface (CCI). Although not required by the current J2EE specification, the CCI is likely to be required in a later version. Consequently, the ADK focuses on helping you implement a CCI interface for your adapter.
How to Use This Section
This section (Step 4: Implement the CCI) describes some of the interfaces you can use to implement the CCI. At a minimum, two interfaces are necessary to complete the task. (See Basic CCI Implementation.) Each interface is described in detail, followed by a discussion of how it is extended in the sample adapter included with the ADK.
Following the description of the two required interfaces, detailed descriptions of the additional interfaces are provided, along with a discussion of reasons why you might use these interfaces and the benefits they provide.
Basic CCI Implementation
To implement the CCI for your adapter, you need to extend at least the following two interfaces:
If possible, implement these interfaces in the order specified here.
In addition, you can implement any of the following interfaces needed for your adapter:
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 implementation provides the following functionality:
You must 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 the association between the Interaction and the Connection instances. The close() method releases all resources maintained by the adapter for the interaction. The close of an Interaction instance should not trigger the close of the associated Connection instance.
ADK Implementation
The ADK provides an implementation of this interface called AbstractInteraction. This implementation:
You must supply a concrete extension to AbstractInteraction that implements execute(). Two versions of execute() are available. They are described in the following sections.
execute() Version 1
The execute() method declared in Listing 6-28 shows an interaction represented by InteractionSpec.
Listing 6-28 Example of execute() Version 1
public boolean execute(InteractionSpec ispec,
Record input,
Record output)
throws ResourceException
When invoked in this way, execute() takes an input record and updates the output record. It returns the following:
The parameters for execute() version 1 are described in the following table.
execute() Version 2 The execute() method declared in Listing 6-29 also executes an Interaction represented by InteractionSpec. Listing 6-29 Example of execute() Version 2 When invoked in this way, execute() takes an input Record and, if the execution of Interaction is successful, it returns an output Record. This method:
public Record execute(InteractionSpec ispec,
Record input)
throws ResourceException
If an exception occurs, this method notifies its Connection, which takes the appropriate action, including closing itself.
The parameters for execute() version 2 are listed in the following table.
Using XCCI to Implement the CCI XML-CCI is a dialect of the Client Connector Interface, in which XML-based record formats are used to represent data. These formats are supported by a framework and tools. XML-CCI is usually referred to by its abbreviation: XCCI. XCCI is made up of two components: Services and DocumentRecords. Services A service represents functionality available in an EIS. It includes four components:
Every service has a unique business name that indicates its role in an integration solution. For example, in an integration solution involving a Customer Relationship Management (CRM) system, you may have a service named CreateNewCustomer. It is important to give a service a name that reflects the business purpose of the service; it is an abstraction of the name of the functions invoked by your service in the EIS.
The request document definition describes the input requirements for a service. The com.bea.document.IDocumentDefinition interface embodies all the metadata about a document type. It includes the document schema (structure and usage), and the root element name for all documents of this type. The root element name is needed because an XML schema can define more than one root element.
A response document definition describes the output of a service.
A service is a higher-order component in an integration solution that hides most of the complexity involved in executing functionality in an EIS. In other words, a service does not expose many of the details required to interact with the EIS in its public interface. As a result, some of the information required to invoke a function in an EIS is not provided by the client in the request. Consequently, most services need to store additional metadata. In WebLogic Integration, this additional metadata is encapsulated by an adapter's javax.resource.cci.InteractionSpec implementation class.
To indicate that a given service does not require request or response data, create an empty or null IDocumentDefinition for the request or response in your DesignTimeRequestHandler. You may also set the IDocumentDescriptor for the request or response on the IServiceDescriptor for the service with an empty or null IDocumentDescriptor instance. Create empty or null IDocumentDefinition instances using the static DocumentFactory.createNullDocumentDefinition() method, and empty or null IDocumentDescriptor instances by using the static DescriptorFactory.createNullDocumentDescriptor() method.
If you choose to use empty or null document definitions or descriptors in the generated IServiceDescriptor or IApplicationViewDescriptor generated by the adapter at design-time, you must ensure that the null request or response documents for these services are handled at runtime. In other words, an adapter that uses empty or null document descriptors must not assume a request or response document is non-null at runtime.
The Application View runtime engine ensures that services requiring a request or response receive non-null request or response documents, and ensures that services not requiring a request or response receive null request or response documents.
DocumentRecord
com.bea.connector.DocumentRecord
At run time, 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. For a description of the Record interface, see Record.
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 most important value added by the IDocument interface is an XPath interface to elements in an XML document. In other words, IDocument objects can be queried and updated using XPath strings. For example, the XML document shown in Listing 6-30 shows how XML is used to record details about a person named Bob.
Listing 6-30 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 XPath code shown in Listing 6-31.
Listing 6-31 Sample Code for Retrieving IDocument Data
System.out.println("Jimmy's hair color: " +
person.getStringFrom("//Person[@name=\"Bob\"]/Family/Child
[@name=\"Jimmy\"]/Stats/@hair");
On the other hand, if DOM is used, you must use the code shown in Listing 6-32 to submit a query.
Listing 6-32 Sample Code for Retrieving DOM Data
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, IDocument enables you to simplify your code.
ADK-Supplied XCCI Classes
To help you implement XCCI for your adapters, the ADK provides the following classes and interfaces:
This section describes those classes and interfaces.
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 that 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 are not invoked on the concrete implementation until it has been verified that the output records 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.
DocumentInteractionSpecImpl
com.bea.adapter.cci.DocumentInteractionSpecImpl
This class allows you to save a request document definition and response document definition for a service in the InteractionSpec provided to the execute method at run time. This capability is useful when the Interaction for an adapter needs access to the XML schemas for a service at run time.
IProxiedMarker and IProxiedConnection Interfaces
com.bea.connector.IProxiedConnection
com.bea.connector.IProxiedMarker
The IProxiedMarker interface is implemented by the com.bea.adapter.cci.ConnectionFactoryImpl class. The marker is used to determine whether the associated connection is a proxy object. The IProxiedConnection interface is implemented by the com.bea.adapter.cci.AbstractConnection class and is used to return the real connection associated with the proxy. The IProxiedConnection interface has one method, getAdapterConnection(). The getAdapterConnection method is defined in the AbstractConnection class returning the pointer. The IProxedConnection interface is required because a proxy can return only those Interfaces that it implements. A proxy cannot distinguish class objects in its derivation tree.
XCCI Design Pattern
A design pattern that is frequently used with the XCCI is support for the definition of services in the Interaction implementation. When this design pattern is used, the javax.resource.cci.Interaction implementation for an adapter allows a client program to retrieve metadata from the underlying EIS in order to define a WebLogic Integration service. As a result, the interaction must be able to generate the request and response XML schemas and additional metadata for a service. The Interaction may 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.DesignTimeInteraction- SpecImpl class to help you implement this design pattern. The sample.cci.InteractionImpl class demonstrates how to implement this design pattern using the DesignTimeInteractionSpecImpl class.
Using NonXML J2EE-Compliant Adapters
The ADK provides a plug-in mechanism for using nonXML adapters with WebLogic Integration. Not all prebuilt adapters use XML as the javax.resource.cci.Record data type. For example, XML may not be used in the following circumstances:
To facilitate implementation of these types of adapters, the ADK provides the com.bea.connector.IRecordTranslator interface. At run time, the application integration engine uses an adapter's IRecordTranslator implementation to translate request and response records before executing the adapter's service.
Because the application integration engine supports only javax.resource.cci.Record of type com.bea.connector.DocumentRecord, you must translate this proprietary format to a document record for request and response records. You do not need to rewrite the adapter's CCI interaction layer. By including a class in your adapter's EAR file that implements the IRecordTranslator interface, the application integration engine can execute the translation methods in your translator class on each record for request and response.
There is a one-to-one correlation between an InteractionSpec implementation class and an IRecordTranslator implementation class. An adapter with more than one type of InteractionSpec implementation requires an IRecordTranslator implementation class for each. The plug-in architecture loads the translator class by name, using the full class name of the adapter's InteractionSpec, plus the phrase RecordTranslator. For example, if the name of the adapter's InteractionSpec class is com.bea.adapter.dbms.cci.InteractionSpecImpl, then the engine loads the com.bea.adapter.dbms.cci.InteractionSpecImplRecordTranslator class (if the latter class is available).
For a description of the methods that must be implemented, see the Javadoc for com.bea.connector.IRecordTranslator in the following directory:
WLI_HOME/docs/apidocs/com/bea/connector/IRecordTranslator.html
ConnectionFactory
javax.resource.cci.ConnectionFactory
ConnectionFactory provides an interface for getting a connection to an EIS instance. An implementation of the ConnectionFactory interface must be provided by an adapter.
The application looks up a ConnectionFactory instance from JNDI namespace and uses it to get EIS connections.
To support JNDI registration, java.io.Serializable and javax.resource.Referenceableinterfaces must be implemented. For this purpose, an implementation class for ConnectionFactory is required.
ADK Implementation
The ADK provides ConnectionFactoryImpl, a concrete implementation of the javax.resource.cci.ConnectionFactory interface that provides the following functionality:
Usually you can use this class as is, without extending it.
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 must 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.
We recommend that you implement the ConnectionSpec interface as a JavaBean so that it can support tools. Define the properties of the ConnectionSpec implementation class through the getter and setter methods pattern.
The CCI specification defines a set of standard properties for a ConnectionSpec. The properties are defined on either 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
Because 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. Specifically, 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 the 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 the InteractionSpec interface is required to implement the java.io.Serializable interface.
The InteractionSpec contains information that is not in Record but that helps to determine which EIS function to invoke.
The standard properties are described in the following table.
The following standard properties are used to give hints to an interaction instance about the ResultSet requirements:
A CCI implementation can provide properties other than the one described in the InteractionSpec interface.
Note: The format and type of any additional properties are specific to an EIS; they are 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 that you can 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 managing local transactions.
A local transaction is managed within a resource manager. No external transaction manager is 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 about local transactions, see Transaction Demarcation.
Record
javax.resource.cci.Record
The javax.resource.cci.Record interface is the base interface for representing an input to or output from the execute() methods defined for an Interaction. For more information about 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 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 the following table.
If the adapter implements a CCI interface, the next question to consider is which record format to use for a service. For each service, a format must be specified for the request records (which provide input to the service) and response records (which provide the EIS responses). 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 the name and description of a record. For an adapter provider who 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 the 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 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 an interface that encapsulates adapter metadata and provides getters and setters for all properties: ResourceAdapterMetaDataImpl.
Step 5: Test the Adapter
To help you test your adapter, the ADK provides com.bea.adapter.test.TestHarness, a test harness that leverages JUnit, an open-source tool for unit testing. The com.bea.adapter.test.TestHarness performs the following functions:
You can find more information about JUnit at:
Using the Test Harness
To use the test harness in the ADK, complete the following steps:
Listing 6-33 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>
This target invokes the JVM with the following main class: com.bea.adapter.test.TestHarness. This class uses the classpath established for the sample adapter and passes the following command-line argument:
-DCONFIG_FILE=test.properties
Test Case Extensions Provided by the ADK
The sample adapter provides two basic TestCase extensions:
sample.spi.NonManagedScenarioTestCase
NonManagedScenarioTestCase allows you to test your SPI and CCI classes in a nonmanaged 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 WebLogic Server. Specifically, this class tests the following for the event generator:
sample.client.ApplicationViewClient
The sample.client.ApplicationViewClient class offers an additional way to 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. An Ant build.xml file provides the client target so you can use the ApplicationViewClient program. When you execute ant client, the default configuration is to display the usage for the program. You can change the input parameters for the client program by editing the build.xml file.
To see an example of sample.client.ApplicationViewClient.java, go to WLI_HOME/adapters/ sample/src/sample/client.
Note: sample.client.ApplicationViewClient is not integrated with the test harness.
Step 6: Deploy the Adapter
After implementing the SPI and CCI interfaces for an adapter, and then testing the adapter, you can deploy the adapter in a WebLogic Integration environment, either manually or from the WebLogic Server Administration Console. For complete information, see Deploying Adapters.
![]() |
![]() |
![]() |
![]() |
||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |