1156 lines
50 KiB
XML
1156 lines
50 KiB
XML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<chapter id="cci">
|
|
<title>JCA CCI</title>
|
|
|
|
<section id="cci-introduction">
|
|
<title>Introduction</title>
|
|
|
|
<para>J2EE provides a specification to standardize access to enterprise information systems (EIS):
|
|
the JCA (Java Connector Architecture). This specification is divided into several different parts:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>SPI (Service provider interfaces) that the connector provider
|
|
must implement. These interfaces constitute a resource adapter which
|
|
can be deployed on a J2EE application server. In such a scenario, the
|
|
server manages connection pooling, transaction and security (managed
|
|
mode). The application server is also responsible for managing the
|
|
configuration, which is held outside the client application. A connector
|
|
can be used without an application server as well; in this case, the
|
|
application must configure it directly (non-managed mode).</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>CCI (Common Client Interface) that an application can use to
|
|
interact with the connector and thus communicate with an EIS. An API
|
|
for local transaction demarcation is provided as well.</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>The aim of the Spring CCI support is to provide classes to access
|
|
a CCI connector in typical Spring style, leveraging the Spring Framework's general
|
|
resource and transaction management facilities.</para>
|
|
|
|
<note>
|
|
<para>The client side of connectors doesn't alway use CCI. Some
|
|
connectors expose their own APIs, only providing JCA resource adapter to
|
|
use the system contracts of a J2EE container (connection pooling, global
|
|
transactions, security). Spring does not offer special support for such
|
|
connector-specific APIs.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="cci-config">
|
|
<title>Configuring CCI</title>
|
|
|
|
<section id="cci-config-connector">
|
|
<title>Connector configuration</title>
|
|
|
|
<para>The base resource to use JCA CCI is the
|
|
<interfacename>ConnectionFactory</interfacename> interface. The connector used
|
|
must provide an implementation of this interface.</para>
|
|
|
|
<para>To use your connector, you can deploy it on your application
|
|
server and fetch the <interfacename>ConnectionFactory</interfacename> from the
|
|
server's JNDI environment (managed mode). The connector must be
|
|
packaged as a RAR file (resource adapter archive) and contain a
|
|
<filename>ra.xml</filename> file to describe its deployment
|
|
characteristics. The actual name of the resource is specified when
|
|
you deploy it. To access it within Spring, simply use Spring's
|
|
<classname>JndiObjectFactoryBean</classname> to fetch the factory
|
|
by its JNDI name.</para>
|
|
|
|
<para>Another way to use a connector is to embed it in your application
|
|
(non-managed mode), not using an application server to deploy and
|
|
configure it. Spring offers the possibility to configure a connector
|
|
as a bean, through a provided <literal>FactoryBean</literal>
|
|
(<classname>LocalConnectionFactoryBean</classname>). In this manner,
|
|
you only need the connector library in the classpath (no RAR file and
|
|
no <filename>ra.xml</filename> descriptor needed). The library must
|
|
be extracted from the connector's RAR file, if necessary.</para>
|
|
|
|
<para>Once you have got access to your <interfacename>ConnectionFactory</interfacename>
|
|
instance, you can inject it into your components. These components can
|
|
either be coded against the plain CCI API or leverage Spring's support
|
|
classes for CCI access (e.g. <classname>CciTemplate</classname>).</para>
|
|
|
|
<note>
|
|
<para>When you use a connector in
|
|
non-managed mode, you can't use global transactions because the resource
|
|
is never enlisted / delisted in the current global transaction of the
|
|
current thread. The resource is simply not aware of any global J2EE
|
|
transactions that might be running.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="cci-config-connectionfactory">
|
|
<title><interfacename>ConnectionFactory</interfacename> configuration in Spring</title>
|
|
|
|
<para>In order to make connections to the EIS, you need to obtain a
|
|
<interfacename>ConnectionFactory</interfacename> from the application server if
|
|
you are in a managed mode, or directly from Spring if you are in a
|
|
non-managed mode.</para>
|
|
|
|
<para>In a managed mode, you access a <interfacename>ConnectionFactory</interfacename>
|
|
from JNDI; its properties will be configured in the application server.</para>
|
|
|
|
<programlisting><![CDATA[<bean id="eciConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
|
|
<property name="jndiName" value="eis/cicseci"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<para>In non-managed mode, you must configure the <interfacename>ConnectionFactory</interfacename>
|
|
you want to use in the configuration of Spring as a JavaBean. The
|
|
<classname>LocalConnectionFactoryBean</classname> class offers this
|
|
setup style, passing in the <classname>ManagedConnectionFactory</classname>
|
|
implementation of your connector, exposing the application-level
|
|
CCI <interfacename>ConnectionFactory</interfacename>.</para>
|
|
|
|
<programlisting><![CDATA[<bean id="eciManagedConnectionFactory" class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
|
|
<property name="serverName" value="TXSERIES"/>
|
|
<property name="connectionURL" value="tcp://localhost/"/>
|
|
<property name="portNumber" value="2006"/>
|
|
</bean>
|
|
|
|
<bean id="eciConnectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
|
|
<property name="managedConnectionFactory" ref="eciManagedConnectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<note>
|
|
<para>You can't directly instantiate a specific
|
|
<interfacename>ConnectionFactory</interfacename>. You need to go through
|
|
the corresponding implementation of the
|
|
<classname>ManagedConnectionFactory</classname> interface for your
|
|
connector. This interface is part of the JCA SPI specification.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="cci-config-cci-connections">
|
|
<title>Configuring CCI connections</title>
|
|
|
|
<para>JCA CCI allow the developer to configure the connections to the
|
|
EIS using the <interfacename>ConnectionSpec</interfacename> implementation of your
|
|
connector. In order to configure its properties, you need to wrap the
|
|
target connection factory with a dedicated adapter,
|
|
<classname>ConnectionSpecConnectionFactoryAdapter</classname>. So, the
|
|
dedicated <interfacename>ConnectionSpec</interfacename> can be configured with the
|
|
property <literal>connectionSpec</literal> (as an inner bean).</para>
|
|
|
|
<para>This property is not mandatory because the CCI
|
|
<interfacename>ConnectionFactory</interfacename> interface defines two different
|
|
methods to obtain a CCI connection. Some of the
|
|
<interfacename>ConnectionSpec</interfacename> properties can often be configured
|
|
in the application server (in managed mode) or on the corresponding local
|
|
<classname>ManagedConnectionFactory</classname> implementation.</para>
|
|
|
|
<programlisting><![CDATA[public interface ConnectionFactory implements Serializable, Referenceable {
|
|
...
|
|
Connection getConnection() throws ResourceException;
|
|
Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException;
|
|
...
|
|
}]]></programlisting>
|
|
|
|
<para>Spring provides a <classname>ConnectionSpecConnectionFactoryAdapter</classname>
|
|
that allows for specifying a <interfacename>ConnectionSpec</interfacename> instance
|
|
to use for all operations on a given factory. If the adapter's
|
|
<literal>connectionSpec</literal> property is specified, the adapter
|
|
uses the <literal>getConnection</literal> variant without argument,
|
|
else the one with the <interfacename>ConnectionSpec</interfacename> argument.</para>
|
|
|
|
<programlisting><![CDATA[<bean id="managedConnectionFactory"
|
|
class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">
|
|
<property name="connectionURL" value="jdbc:hsqldb:hsql://localhost:9001"/>
|
|
<property name="driverName" value="org.hsqldb.jdbcDriver"/>
|
|
</bean>
|
|
|
|
<bean id="targetConnectionFactory"
|
|
class="org.springframework.jca.support.LocalConnectionFactoryBean">
|
|
<property name="managedConnectionFactory" ref="managedConnectionFactory"/>
|
|
</bean>
|
|
|
|
<bean id="connectionFactory"
|
|
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
|
|
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
|
|
<property name="connectionSpec">
|
|
<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">
|
|
<property name="user" value="sa"/>
|
|
<property name="password" value=""/>
|
|
</bean>
|
|
</property>
|
|
</bean>]]></programlisting>
|
|
</section>
|
|
|
|
<section id="cci-config-single-connection">
|
|
<title>Using a single CCI connection</title>
|
|
|
|
<para>If you want to use a single CCI connection, Spring provides a further
|
|
<interfacename>ConnectionFactory</interfacename> adapter to manage this. The
|
|
<classname>SingleConnectionFactory</classname> adapter class will open a single
|
|
connection lazily and close it when this bean is destroyed at application
|
|
shutdown. This class will expose special <interfacename>Connection</interfacename>
|
|
proxies that behave accordingly, all sharing the same underlying physical
|
|
connection.</para>
|
|
|
|
<programlisting><![CDATA[<bean id="eciManagedConnectionFactory"
|
|
class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
|
|
<property name="serverName" value="TEST"/>
|
|
<property name="connectionURL" value="tcp://localhost/"/>
|
|
<property name="portNumber" value="2006"/>
|
|
</bean>
|
|
|
|
<bean id="targetEciConnectionFactory"
|
|
class="org.springframework.jca.support.LocalConnectionFactoryBean">
|
|
<property name="managedConnectionFactory" ref="eciManagedConnectionFactory"/>
|
|
</bean>
|
|
|
|
<bean id="eciConnectionFactory"
|
|
class="org.springframework.jca.cci.connection.SingleConnectionFactory">
|
|
<property name="targetConnectionFactory" ref="targetEciConnectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<note>
|
|
<para>This <interfacename>ConnectionFactory</interfacename> adapter cannot directly be
|
|
configured with a <interfacename>ConnectionSpec</interfacename>. Use an
|
|
intermediary <classname>ConnectionSpecConnectionFactoryAdapter</classname>
|
|
that the <classname>SingleConnectionFactory</classname> talks to
|
|
if you require a single connection for a specific
|
|
<interfacename>ConnectionSpec</interfacename>.</para>
|
|
</note>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="cci-using">
|
|
<title>Using Spring's CCI access support</title>
|
|
|
|
<section id="cci-record-creator">
|
|
<title>Record conversion</title>
|
|
|
|
<para>One of the aims of the JCA CCI support is to provide convenient
|
|
facilities for manipulating CCI records. The developer can specify the
|
|
strategy to create records and extract datas from records, for use
|
|
with Spring's <classname>CciTemplate</classname>. The following interfaces will configure the
|
|
strategy to use input and output records if you don't want to work
|
|
with records directly in your application.</para>
|
|
|
|
<para>In order to create an input <interfacename>Record</interfacename>, the
|
|
developer can use a dedicated implementation of the
|
|
<interfacename>RecordCreator</interfacename> interface.</para>
|
|
|
|
<programlisting><![CDATA[public interface RecordCreator {
|
|
|
|
Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException;
|
|
}]]></programlisting>
|
|
|
|
<para>As you can see, the <literal>createRecord(..)</literal> method
|
|
receives a <interfacename>RecordFactory</interfacename> instance as parameter,
|
|
which corresponds to the <interfacename>RecordFactory</interfacename> of the
|
|
<interfacename>ConnectionFactory</interfacename> used. This reference can be
|
|
used to create <interfacename>IndexedRecord</interfacename> or
|
|
<interfacename>MappedRecord</interfacename> instances. The following sample
|
|
shows how to use the <interfacename>RecordCreator</interfacename> interface
|
|
and indexed/mapped records.</para>
|
|
|
|
<programlisting><![CDATA[public class MyRecordCreator implements RecordCreator {
|
|
|
|
public Record createRecord(RecordFactory recordFactory) throws ResourceException {
|
|
IndexedRecord input = recordFactory.createIndexedRecord("input");
|
|
input.add(new Integer(id));
|
|
return input;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>An output <interfacename>Record</interfacename> can be used to receive
|
|
data back from the EIS. Hence, a specific implementation of the
|
|
<interfacename>RecordExtractor</interfacename> interface can be passed to
|
|
Spring's <classname>CciTemplate</classname> for extracting data from the output
|
|
<interfacename>Record</interfacename>.</para>
|
|
|
|
<programlisting><![CDATA[public interface RecordExtractor {
|
|
|
|
Object extractData(Record record) throws ResourceException, SQLException, DataAccessException;
|
|
}]]></programlisting>
|
|
|
|
<para>The following sample shows how to use the <interfacename>RecordExtractor</interfacename> interface.</para>
|
|
|
|
<programlisting><![CDATA[public class MyRecordExtractor implements RecordExtractor {
|
|
|
|
public Object extractData(Record record) throws ResourceException {
|
|
CommAreaRecord commAreaRecord = (CommAreaRecord) record;
|
|
String str = new String(commAreaRecord.toByteArray());
|
|
String field1 = string.substring(0,6);
|
|
String field2 = string.substring(6,1);
|
|
return new OutputObject(Long.parseLong(field1), field2);
|
|
}
|
|
}]]></programlisting>
|
|
</section>
|
|
|
|
<section id="cci-using-template">
|
|
<title>The <classname>CciTemplate</classname></title>
|
|
|
|
<para>The <classname>CciTemplate</classname> is the central class of the core CCI support package
|
|
(<literal>org.springframework.jca.cci.core</literal>). It simplifies
|
|
the use of CCI since it handles the creation and release of resources.
|
|
This helps to avoid common errors like forgetting to always close the
|
|
connection. It cares for the lifecycle of connection and interaction
|
|
objects, letting application code focus on generating input records
|
|
from application data and extracting application data from output
|
|
records.</para>
|
|
|
|
<para>The JCA CCI specification defines two distinct methods to call
|
|
operations on an EIS. The CCI <interfacename>Interaction</interfacename>
|
|
interface provides two execute method signatures:</para>
|
|
|
|
<programlisting><![CDATA[public interface javax.resource.cci.Interaction {
|
|
...
|
|
boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException;
|
|
|
|
Record execute(InteractionSpec spec, Record input) throws ResourceException;
|
|
...
|
|
}]]></programlisting>
|
|
|
|
<para>Depending on the template method called, <classname>CciTemplate</classname>
|
|
will know which <literal>execute</literal> method to call on the interaction.
|
|
In any case, a correctly initialized <interfacename>InteractionSpec</interfacename>
|
|
instance is mandatory.</para>
|
|
|
|
<para><literal>CciTemplate.execute(..)</literal> can be used in two ways:</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>With direct <interfacename>Record</interfacename> arguments. In this case,
|
|
you simply need to pass the CCI input record in, and the returned object
|
|
be the corresponding CCI output record.</para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para>With application objects, using record mapping. In this case,
|
|
you need to provide corresponding <interfacename>RecordCreator</interfacename>
|
|
and <interfacename>RecordExtractor</interfacename> instances.
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>With the first approach, the following methods of the template
|
|
will be used. These methods directly correspond to those on the
|
|
<interfacename>Interaction</interfacename> interface.</para>
|
|
|
|
<programlisting><![CDATA[public class CciTemplate implements CciOperations {
|
|
|
|
public Record execute(InteractionSpec spec, Record inputRecord)
|
|
throws DataAccessException { ... }
|
|
|
|
public void execute(InteractionSpec spec, Record inputRecord, Record outputRecord)
|
|
throws DataAccessException { ... }
|
|
|
|
}]]></programlisting>
|
|
|
|
<para>With the second approach, we need to specify the record creation
|
|
and record extraction strategies as arguments. The interfaces used
|
|
are those describe in the previous section on record conversion.
|
|
The corresponding <classname>CciTemplate</classname> methods are the
|
|
following:</para>
|
|
|
|
<programlisting><![CDATA[public class CciTemplate implements CciOperations {
|
|
|
|
public Record execute(InteractionSpec spec, RecordCreator inputCreator)
|
|
throws DataAccessException { ... }
|
|
|
|
public Object execute(InteractionSpec spec, Record inputRecord, RecordExtractor outputExtractor)
|
|
throws DataAccessException { ... }
|
|
|
|
public Object execute(InteractionSpec spec, RecordCreator creator, RecordExtractor extractor)
|
|
throws DataAccessException { ... }
|
|
|
|
}]]></programlisting>
|
|
|
|
<para>Unless the <literal>outputRecordCreator</literal> property is
|
|
set on the template (see the following section), every method will call
|
|
the corresponding <literal>execute</literal> method of the CCI
|
|
<interfacename>Interaction</interfacename> with two parameters:
|
|
<interfacename>InteractionSpec</interfacename> and input <interfacename>Record</interfacename>,
|
|
receiving an output <interfacename>Record</interfacename> as return value.
|
|
</para>
|
|
|
|
<para><classname>CciTemplate</classname> also provides methods to create
|
|
<literal>IndexRecord</literal> and <literal>MappedRecord</literal>
|
|
outside a <interfacename>RecordCreator</interfacename> implementation, through
|
|
its <literal>createIndexRecord(..)</literal> and
|
|
<literal>createMappedRecord(..)</literal> methods. This can be used
|
|
within DAO implementations to create <interfacename>Record</interfacename>
|
|
instances to pass into corresponding
|
|
<literal>CciTemplate.execute(..)</literal> methods.</para>
|
|
|
|
<programlisting><![CDATA[public class CciTemplate implements CciOperations {
|
|
|
|
public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... }
|
|
|
|
public MappedRecord createMappedRecord(String name) throws DataAccessException { ... }
|
|
|
|
}]]></programlisting>
|
|
</section>
|
|
|
|
<section id="cci-using-dao">
|
|
<title>DAO support</title>
|
|
|
|
<para>Spring's CCI support provides a abstract class for DAOs,
|
|
supporting injection of a <interfacename>ConnectionFactory</interfacename>
|
|
or a <classname>CciTemplate</classname> instances. The name of the
|
|
class is <classname>CciDaoSupport</classname>: It provides simple
|
|
<literal>setConnectionFactory</literal> and
|
|
<literal>setCciTemplate</literal> methods. Internally, this
|
|
class will create a <classname>CciTemplate</classname> instance
|
|
for a passed-in <interfacename>ConnectionFactory</interfacename>, exposing
|
|
it to concrete data access implementations in subclasses.</para>
|
|
|
|
<programlisting><![CDATA[public abstract class CciDaoSupport {
|
|
|
|
public void setConnectionFactory(ConnectionFactory connectionFactory) { ... }
|
|
public ConnectionFactory getConnectionFactory() { ... }
|
|
|
|
public void setCciTemplate(CciTemplate cciTemplate) { ... }
|
|
public CciTemplate getCciTemplate() { ... }
|
|
|
|
}]]></programlisting>
|
|
</section>
|
|
|
|
<section id="automatic-output-generation">
|
|
<title>Automatic output record generation</title>
|
|
|
|
<para>If the connector used only supports the
|
|
<methodname>Interaction.execute(..)</methodname> method with input and output
|
|
records as parameters (that is, it requires the desired output record
|
|
to be passed in instead of returning an appropriate output record),
|
|
you can set the <literal>outputRecordCreator</literal> property of the
|
|
<classname>CciTemplate</classname> to automatically generate an output
|
|
record to be filled by the JCA connector when the response is received.
|
|
This record will be then returned to the caller of the template.</para>
|
|
|
|
<para>This property simply holds an implementation of the
|
|
<interfacename>RecordCreator</interfacename> interface, used for that purpose.
|
|
The <interfacename>RecordCreator</interfacename> interface has already been
|
|
discussed in the section entitled <xref linkend="cci-record-creator"/>.
|
|
The <literal>outputRecordCreator</literal>
|
|
property must be directly specified on the <classname>CciTemplate</classname>.
|
|
This could be done in the application code like so:</para>
|
|
|
|
<programlisting><![CDATA[cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator());]]></programlisting>
|
|
|
|
<para>Or (recommended) in the Spring configuration, if the <classname>CciTemplate</classname>
|
|
is configured as a dedicated bean instance:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="eciOutputRecordCreator" class="eci.EciOutputRecordCreator"/>
|
|
|
|
<bean id="cciTemplate" class="org.springframework.jca.cci.core.CciTemplate">
|
|
<property name="connectionFactory" ref="eciConnectionFactory"/>
|
|
<property name="outputRecordCreator" ref="eciOutputRecordCreator"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<note>
|
|
<para>As the <classname>CciTemplate</classname> class is thread-safe, it will
|
|
usually be configured as a shared instance.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="template-summary">
|
|
<title>Summary</title>
|
|
|
|
<para>The following table summarizes the mechanisms of the
|
|
<classname>CciTemplate</classname> class and the corresponding methods
|
|
called on the CCI <interfacename>Interaction</interfacename> interface:<table
|
|
frame="all" id="cci-interaction-execute-methods">
|
|
<title>Usage of <interfacename>Interaction</interfacename> execute methods</title>
|
|
|
|
<tgroup cols="3">
|
|
<thead>
|
|
<row>
|
|
<entry align="center">CciTemplate method signature</entry>
|
|
|
|
<entry align="center">CciTemplate outputRecordCreator
|
|
property</entry>
|
|
|
|
<entry align="center">execute method called on the CCI
|
|
Interaction</entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
|
|
<entry align="center">not set</entry>
|
|
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
|
|
<entry align="center">set</entry>
|
|
|
|
<entry align="center">boolean execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
|
|
<entry align="center">not set</entry>
|
|
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
|
|
<entry align="center">set</entry>
|
|
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
RecordCreator)</entry>
|
|
|
|
<entry align="center">not set</entry>
|
|
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
RecordCreator)</entry>
|
|
|
|
<entry align="center">set</entry>
|
|
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec, Record,
|
|
RecordExtractor)</entry>
|
|
|
|
<entry align="center">not set</entry>
|
|
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec, Record,
|
|
RecordExtractor)</entry>
|
|
|
|
<entry align="center">set</entry>
|
|
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
RecordCreator, RecordExtractor)</entry>
|
|
|
|
<entry align="center">not set</entry>
|
|
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
RecordCreator, RecordExtractor)</entry>
|
|
|
|
<entry align="center">set</entry>
|
|
|
|
<entry align="center">void execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table></para>
|
|
</section>
|
|
|
|
<section id="cci-straight">
|
|
<title>Using a CCI <interfacename>Connection</interfacename> and <interfacename>Interaction</interfacename> directly</title>
|
|
|
|
<para><classname>CciTemplate</classname> also offers the possibility to
|
|
work directly with CCI connections and interactions, in the same manner
|
|
as <classname>JdbcTemplate</classname> and <classname>JmsTemplate</classname>.
|
|
This is useful when you want to perform multiple operations on a CCI
|
|
connection or interaction, for example.</para>
|
|
|
|
<para>The interface <interfacename>ConnectionCallback</interfacename> provides a
|
|
CCI <interfacename>Connection</interfacename> as argument, in order to perform
|
|
custom operations on it, plus the CCI <interfacename>ConnectionFactory</interfacename>
|
|
which the <interfacename>Connection</interfacename> was created with. The latter
|
|
can be useful for example to get an associated <interfacename>RecordFactory</interfacename>
|
|
instance and create indexed/mapped records, for example.</para>
|
|
|
|
<programlisting><![CDATA[public interface ConnectionCallback {
|
|
|
|
Object doInConnection(Connection connection, ConnectionFactory connectionFactory)
|
|
throws ResourceException, SQLException, DataAccessException;
|
|
}]]></programlisting>
|
|
|
|
<para>The interface <interfacename>InteractionCallback</interfacename> provides
|
|
the CCI <interfacename>Interaction</interfacename>, in order to perform custom
|
|
operations on it, plus the corresponding CCI <interfacename>ConnectionFactory</interfacename>.
|
|
</para>
|
|
|
|
<programlisting><![CDATA[public interface InteractionCallback {
|
|
|
|
Object doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
|
|
throws ResourceException, SQLException, DataAccessException;
|
|
}]]></programlisting>
|
|
|
|
<note>
|
|
<para><interfacename>InteractionSpec</interfacename> objects
|
|
can either be shared across multiple template calls or newly created
|
|
inside every callback method. This is completely up to the DAO implementation.</para>
|
|
</note>
|
|
</section>
|
|
|
|
<section id="cci-template-example">
|
|
<title>Example for <classname>CciTemplate</classname> usage</title>
|
|
|
|
<para>In this section, the usage of the <classname>CciTemplate</classname>
|
|
will be shown to acces to a CICS with ECI mode, with the IBM CICS ECI
|
|
connector.</para>
|
|
|
|
<para>Firstly, some initializations on the CCI
|
|
<interfacename>InteractionSpec</interfacename> must be done to specify which CICS
|
|
program to access and how to interact with it.</para>
|
|
|
|
<programlisting><![CDATA[ECIInteractionSpec interactionSpec = new ECIInteractionSpec();
|
|
interactionSpec.setFunctionName("MYPROG");
|
|
interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);]]></programlisting>
|
|
|
|
<para>Then the program can use CCI via Spring's template and specify
|
|
mappings between custom objects and CCI <literal>Records</literal>.</para>
|
|
|
|
<programlisting><![CDATA[public class MyDaoImpl extends CciDaoSupport implements MyDao {
|
|
|
|
public OutputObject getData(InputObject input) {
|
|
ECIInteractionSpec interactionSpec = ...;
|
|
|
|
OutputObject output = (ObjectOutput) getCciTemplate().execute(interactionSpec,
|
|
new RecordCreator() {
|
|
public Record createRecord(RecordFactory recordFactory) throws ResourceException {
|
|
return new CommAreaRecord(input.toString().getBytes());
|
|
}
|
|
},
|
|
new RecordExtractor() {
|
|
public Object extractData(Record record) throws ResourceException {
|
|
CommAreaRecord commAreaRecord = (CommAreaRecord)record;
|
|
String str = new String(commAreaRecord.toByteArray());
|
|
String field1 = string.substring(0,6);
|
|
String field2 = string.substring(6,1);
|
|
return new OutputObject(Long.parseLong(field1), field2);
|
|
}
|
|
});
|
|
|
|
return output;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>As discussed previously, callbacks can be used to work
|
|
directly on CCI connections or interactions.</para>
|
|
|
|
<programlisting><![CDATA[public class MyDaoImpl extends CciDaoSupport implements MyDao {
|
|
|
|
public OutputObject getData(InputObject input) {
|
|
ObjectOutput output = (ObjectOutput) getCciTemplate().execute(
|
|
new ConnectionCallback() {
|
|
public Object doInConnection(Connection connection, ConnectionFactory factory)
|
|
throws ResourceException {
|
|
|
|
]]><lineannotation>// do something...</lineannotation><![CDATA[
|
|
}
|
|
});
|
|
}
|
|
return output;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<note>
|
|
<para>With a <interfacename>ConnectionCallback</interfacename>,
|
|
the <interfacename>Connection</interfacename> used will be managed and closed by
|
|
the <classname>CciTemplate</classname>, but any interactions created
|
|
on the connection must be managed by the callback implementation.</para>
|
|
</note>
|
|
|
|
<para>For a more specific callback, you can implement an
|
|
<interfacename>InteractionCallback</interfacename>. The passed-in
|
|
<interfacename>Interaction</interfacename> will be managed and closed by the
|
|
<classname>CciTemplate</classname> in this case.</para>
|
|
|
|
<programlisting><![CDATA[public class MyDaoImpl extends CciDaoSupport implements MyDao {
|
|
|
|
public String getData(String input) {
|
|
ECIInteractionSpec interactionSpec = ...;
|
|
|
|
String output = (String) getCciTemplate().execute(interactionSpec,
|
|
new InteractionCallback() {
|
|
public Object doInInteraction(Interaction interaction, ConnectionFactory factory)
|
|
throws ResourceException {
|
|
Record input = new CommAreaRecord(inputString.getBytes());
|
|
Record output = new CommAreaRecord();
|
|
interaction.execute(holder.getInteractionSpec(), input, output);
|
|
return new String(output.toByteArray());
|
|
}
|
|
});
|
|
|
|
return output;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>For the examples above, the corresponding configuration of the
|
|
involved Spring beans could look like this in non-managed mode:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="managedConnectionFactory" class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
|
|
<property name="serverName" value="TXSERIES"/>
|
|
<property name="connectionURL" value="local:"/>
|
|
<property name="userName" value="CICSUSER"/>
|
|
<property name="password" value="CICS"/>
|
|
</bean>
|
|
|
|
<bean id="connectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
|
|
<property name="managedConnectionFactory" ref="managedConnectionFactory"/>
|
|
</bean>
|
|
|
|
<bean id="component" class="mypackage.MyDaoImpl">
|
|
<property name="connectionFactory" ref="connectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<para>In managed mode (that is, in a J2EE environment), the configuration
|
|
could look as follows:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
|
|
<property name="jndiName" value="eis/cicseci"/>
|
|
</bean>
|
|
|
|
<bean id="component" class="MyDaoImpl">
|
|
<property name="connectionFactory" ref="connectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="cci-object">
|
|
<title>Modeling CCI access as operation objects</title>
|
|
|
|
<para>The <literal>org.springframework.jca.cci.object</literal> package
|
|
contains support classes that allow you to access the EIS in a different
|
|
style: through reusable operation objects, analogous to Spring's JDBC
|
|
operation objects (see JDBC chapter). This will usually encapsulate the
|
|
CCI API: an application-level input object will be passed to the operation
|
|
object, so it can construct the input record and then convert the received
|
|
record data to an application-level output object and return it.</para>
|
|
|
|
<para><emphasis>Note</emphasis>: This approach is internally based on the
|
|
<classname>CciTemplate</classname> class and the <interfacename>RecordCreator</interfacename>
|
|
/ <interfacename>RecordExtractor</interfacename> interfaces, reusing the machinery of
|
|
Spring's core CCI support.</para>
|
|
|
|
<section id="cci-object-mapping-record">
|
|
<title><classname>MappingRecordOperation</classname></title>
|
|
|
|
<para><classname>MappingRecordOperation</classname> essentially performs the
|
|
same work as <classname>CciTemplate</classname>, but represents a specific,
|
|
pre-configured operation as an object. It provides two template methods
|
|
to specify how to convert an input object to a input record, and how to
|
|
convert an output record to an output object (record mapping):</para>
|
|
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para><literal>createInputRecord(..)</literal> to specify how to
|
|
convert an input object to an input <interfacename>Record</interfacename></para>
|
|
</listitem>
|
|
|
|
<listitem>
|
|
<para><literal>extractOutputData(..)</literal> to specify how to
|
|
extract an output object from an output <interfacename>Record</interfacename></para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
|
|
<para>Here are the signatures of these methods:</para>
|
|
|
|
<programlisting><![CDATA[public abstract class MappingRecordOperation extends EisOperation {
|
|
...
|
|
protected abstract Record createInputRecord(RecordFactory recordFactory, Object inputObject)
|
|
throws ResourceException, DataAccessException { ... }
|
|
|
|
protected abstract Object extractOutputData(Record outputRecord)
|
|
throws ResourceException, SQLException, DataAccessException { ... }
|
|
...
|
|
}]]></programlisting>
|
|
|
|
<para>Thereafter, in order to execute an EIS operation, you need to use
|
|
a single execute method, passing in an application-level input object
|
|
and receiving an application-level output object as result:</para>
|
|
|
|
<programlisting><![CDATA[public abstract class MappingRecordOperation extends EisOperation {
|
|
...
|
|
public Object execute(Object inputObject) throws DataAccessException {
|
|
...
|
|
}]]></programlisting>
|
|
|
|
<para>As you can see, contrary to the <classname>CciTemplate</classname> class,
|
|
this <methodname>execute(..)</methodname> method does not have an
|
|
<interfacename>InteractionSpec</interfacename> as argument. Instead, the
|
|
<interfacename>InteractionSpec</interfacename> is global to the operation.
|
|
The following constructor must be used to instantiate an operation
|
|
object with a specific <interfacename>InteractionSpec</interfacename>:</para>
|
|
|
|
<programlisting><![CDATA[InteractionSpec spec = ...;
|
|
MyMappingRecordOperation eisOperation = new MyMappingRecordOperation(getConnectionFactory(), spec);
|
|
...]]></programlisting>
|
|
</section>
|
|
|
|
<section id="cci-object-mapping-comm-area">
|
|
<title><classname>MappingCommAreaOperation</classname></title>
|
|
|
|
<para>Some connectors use records based on a COMMAREA which represents
|
|
an array of bytes containing parameters to send to the EIS and data
|
|
returned by it. Spring provides a special operation class for working
|
|
directly on COMMAREA rather than on records. The
|
|
<classname>MappingCommAreaOperation</classname> class extends the
|
|
<classname>MappingRecordOperation</classname> class to provide such special
|
|
COMMAREA support. It implicitly uses the <classname>CommAreaRecord</classname>
|
|
class as input and output record type, and provides two new methods to
|
|
convert an input object into an input COMMAREA and the output COMMAREA
|
|
into an output object.</para>
|
|
|
|
<programlisting><![CDATA[public abstract class MappingCommAreaOperation extends MappingRecordOperation {
|
|
...
|
|
protected abstract byte[] objectToBytes(Object inObject)
|
|
throws IOException, DataAccessException;
|
|
|
|
protected abstract Object bytesToObject(byte[] bytes)
|
|
throws IOException, DataAccessException;
|
|
...
|
|
}]]></programlisting>
|
|
</section>
|
|
|
|
<section id="cci-automatic-record-gen">
|
|
<title>Automatic output record generation</title>
|
|
|
|
<para>As every <classname>MappingRecordOperation</classname> subclass is
|
|
based on CciTemplate internally, the same way to automatically generate
|
|
output records as with <classname>CciTemplate</classname> is available.
|
|
Every operation object provides a corresponding
|
|
<literal>setOutputRecordCreator(..)</literal> method. For further information,
|
|
see the section entitled <xref linkend="automatic-output-generation"/>.</para>
|
|
</section>
|
|
|
|
<section id="cci-object-summary">
|
|
<title>Summary</title>
|
|
|
|
<para>The operation object approach uses records in the same manner
|
|
as the <classname>CciTemplate</classname> class.</para>
|
|
|
|
<table frame="all" id="cci-interaction-methods">
|
|
<title>Usage of Interaction execute methods</title>
|
|
|
|
<tgroup cols="3">
|
|
<thead>
|
|
<row>
|
|
<entry align="center"><classname>MappingRecordOperation</classname> method
|
|
signature</entry>
|
|
|
|
<entry align="center"><classname>MappingRecordOperation</classname>
|
|
<literal>outputRecordCreator</literal> property</entry>
|
|
|
|
<entry align="center">execute method called on the CCI
|
|
<interfacename>Interaction</interfacename></entry>
|
|
</row>
|
|
</thead>
|
|
|
|
<tbody>
|
|
<row>
|
|
<entry align="center">Object execute(Object)</entry>
|
|
|
|
<entry align="center">not set</entry>
|
|
|
|
<entry align="center">Record execute(InteractionSpec,
|
|
Record)</entry>
|
|
</row>
|
|
|
|
<row>
|
|
<entry align="center">Object execute(Object)</entry>
|
|
|
|
<entry align="center">set</entry>
|
|
|
|
<entry align="center">boolean execute(InteractionSpec, Record,
|
|
Record)</entry>
|
|
</row>
|
|
</tbody>
|
|
</tgroup>
|
|
</table>
|
|
</section>
|
|
|
|
<section id="cci-objects-mappring-record-example">
|
|
<title>Example for <classname>MappingRecordOperation</classname> usage</title>
|
|
|
|
<para>In this section, the usage of the
|
|
<classname>MappingRecordOperation</classname> will be shown to access a
|
|
database with the Blackbox CCI connector.</para>
|
|
|
|
<note>
|
|
<para>The original version of this connector is provided by the J2EE SDK
|
|
(version 1.3), available from Sun.</para>
|
|
</note>
|
|
|
|
<para>Firstly, some initializations on the CCI
|
|
<interfacename>InteractionSpec</interfacename> must be done to specify which SQL
|
|
request to execute. In this sample, we directly define the way to
|
|
convert the parameters of the request to a CCI record and the way to
|
|
convert the CCI result record to an instance of the
|
|
<classname>Person</classname> class.</para>
|
|
|
|
<programlisting><![CDATA[public class PersonMappingOperation extends MappingRecordOperation {
|
|
|
|
public PersonMappingOperation(ConnectionFactory connectionFactory) {
|
|
setConnectionFactory(connectionFactory);
|
|
CciInteractionSpec interactionSpec = new CciConnectionSpec();
|
|
interactionSpec.setSql("select * from person where person_id=?");
|
|
setInteractionSpec(interactionSpec);
|
|
}
|
|
|
|
protected Record createInputRecord(RecordFactory recordFactory, Object inputObject)
|
|
throws ResourceException {
|
|
Integer id = (Integer) inputObject;
|
|
IndexedRecord input = recordFactory.createIndexedRecord("input");
|
|
input.add(new Integer(id));
|
|
return input;
|
|
}
|
|
|
|
protected Object extractOutputData(Record outputRecord)
|
|
throws ResourceException, SQLException {
|
|
ResultSet rs = (ResultSet) outputRecord;
|
|
Person person = null;
|
|
if (rs.next()) {
|
|
Person person = new Person();
|
|
person.setId(rs.getInt("person_id"));
|
|
person.setLastName(rs.getString("person_last_name"));
|
|
person.setFirstName(rs.getString("person_first_name"));
|
|
}
|
|
return person;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>Then the application can execute the operation object, with the
|
|
person identifier as argument. Note that operation object could be
|
|
set up as shared instance, as it is thread-safe.</para>
|
|
|
|
<programlisting><![CDATA[public class MyDaoImpl extends CciDaoSupport implements MyDao {
|
|
|
|
public Person getPerson(int id) {
|
|
PersonMappingOperation query = new PersonMappingOperation(getConnectionFactory());
|
|
Person person = (Person) query.execute(new Integer(id));
|
|
return person;
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>The corresponding configuration of Spring beans could look
|
|
as follows in non-managed mode:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="managedConnectionFactory"
|
|
class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">
|
|
<property name="connectionURL" value="jdbc:hsqldb:hsql://localhost:9001"/>
|
|
<property name="driverName" value="org.hsqldb.jdbcDriver"/>
|
|
</bean>
|
|
|
|
<bean id="targetConnectionFactory"
|
|
class="org.springframework.jca.support.LocalConnectionFactoryBean">
|
|
<property name="managedConnectionFactory" ref="managedConnectionFactory"/>
|
|
</bean>
|
|
|
|
<bean id="connectionFactory"
|
|
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
|
|
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
|
|
<property name="connectionSpec">
|
|
<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">
|
|
<property name="user" value="sa"/>
|
|
<property name="password" value=""/>
|
|
</bean>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="component" class="MyDaoImpl">
|
|
<property name="connectionFactory" ref="connectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<para>In managed mode (that is, in a J2EE environment), the configuration
|
|
could look as follows:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="targetConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
|
|
<property name="jndiName" value="eis/blackbox"/>
|
|
</bean>
|
|
|
|
<bean id="connectionFactory"
|
|
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
|
|
<property name="targetConnectionFactory" ref="targetConnectionFactory"/>
|
|
<property name="connectionSpec">
|
|
<bean class="com.sun.connector.cciblackbox.CciConnectionSpec">
|
|
<property name="user" value="sa"/>
|
|
<property name="password" value=""/>
|
|
</bean>
|
|
</property>
|
|
</bean>
|
|
|
|
<bean id="component" class="MyDaoImpl">
|
|
<property name="connectionFactory" ref="connectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
</section>
|
|
|
|
<section id="cci-objects-mapping-comm-area-example">
|
|
<title>Example for <classname>MappingCommAreaOperation</classname> usage</title>
|
|
|
|
<para>In this section, the usage of the
|
|
<classname>MappingCommAreaOperation</classname> will be shown: accessing
|
|
a CICS with ECI mode with the IBM CICS ECI connector.</para>
|
|
|
|
<para>Firstly, the CCI <interfacename>InteractionSpec</interfacename> needs to be
|
|
initialized to specify which CICS program to access and how to interact
|
|
with it.</para>
|
|
|
|
<programlisting><![CDATA[public abstract class EciMappingOperation extends MappingCommAreaOperation {
|
|
|
|
public EciMappingOperation(ConnectionFactory connectionFactory, String programName) {
|
|
setConnectionFactory(connectionFactory);
|
|
ECIInteractionSpec interactionSpec = new ECIInteractionSpec(),
|
|
interactionSpec.setFunctionName(programName);
|
|
interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
|
|
interactionSpec.setCommareaLength(30);
|
|
setInteractionSpec(interactionSpec);
|
|
setOutputRecordCreator(new EciOutputRecordCreator());
|
|
}
|
|
|
|
private static class EciOutputRecordCreator implements RecordCreator {
|
|
public Record createRecord(RecordFactory recordFactory) throws ResourceException {
|
|
return new CommAreaRecord();
|
|
}
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>The abstract <classname>EciMappingOperation</classname> class can
|
|
then be subclassed to specify mappings between custom objects and
|
|
<literal>Records</literal>.</para>
|
|
|
|
<programlisting><![CDATA[public class MyDaoImpl extends CciDaoSupport implements MyDao {
|
|
|
|
public OutputObject getData(Integer id) {
|
|
EciMappingOperation query = new EciMappingOperation(getConnectionFactory(), "MYPROG") {
|
|
protected abstract byte[] objectToBytes(Object inObject) throws IOException {
|
|
Integer id = (Integer) inObject;
|
|
return String.valueOf(id);
|
|
}
|
|
protected abstract Object bytesToObject(byte[] bytes) throws IOException;
|
|
String str = new String(bytes);
|
|
String field1 = str.substring(0,6);
|
|
String field2 = str.substring(6,1);
|
|
String field3 = str.substring(7,1);
|
|
return new OutputObject(field1, field2, field3);
|
|
}
|
|
});
|
|
|
|
return (OutputObject) query.execute(new Integer(id));
|
|
}
|
|
}]]></programlisting>
|
|
|
|
<para>The corresponding configuration of Spring beans could look
|
|
as follows in non-managed mode:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="managedConnectionFactory" class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
|
|
<property name="serverName" value="TXSERIES"/>
|
|
<property name="connectionURL" value="local:"/>
|
|
<property name="userName" value="CICSUSER"/>
|
|
<property name="password" value="CICS"/>
|
|
</bean>
|
|
|
|
<bean id="connectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
|
|
<property name="managedConnectionFactory" ref="managedConnectionFactory"/>
|
|
</bean>
|
|
|
|
<bean id="component" class="MyDaoImpl">
|
|
<property name="connectionFactory" ref="connectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<para>In managed mode (that is, in a J2EE environment), the configuration
|
|
could look as follows:</para>
|
|
|
|
<programlisting><![CDATA[<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
|
|
<property name="jndiName" value="eis/cicseci"/>
|
|
</bean>
|
|
|
|
<bean id="component" class="MyDaoImpl">
|
|
<property name="connectionFactory" ref="connectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
</section>
|
|
</section>
|
|
|
|
<section id="cci-tx">
|
|
<title>Transactions</title>
|
|
|
|
<para>JCA specifies several levels of transaction support for resource adapters.
|
|
The kind of transactions that your resource adapter supports is specified
|
|
in its <filename>ra.xml</filename> file. There are essentially three options:
|
|
none (for example with CICS EPI connector), local transactions (for
|
|
example with a CICS ECI connector), global transactions (for example with an
|
|
IMS connector).</para>
|
|
|
|
<programlisting><![CDATA[<connector>
|
|
|
|
<resourceadapter>
|
|
|
|
]]><lineannotation><!-- <transaction-support>NoTransaction</transaction-support> --></lineannotation><![CDATA[
|
|
]]><lineannotation><!-- <transaction-support>LocalTransaction</transaction-support> --></lineannotation><![CDATA[
|
|
<transaction-support>XATransaction</transaction-support>
|
|
|
|
<resourceadapter>
|
|
|
|
<connector>]]></programlisting>
|
|
|
|
<para>For global transactions, you can use Spring's generic transaction
|
|
infrastructure to demarcate transactions, with <classname>JtaTransactionManager</classname> as
|
|
backend (delegating to the J2EE server's distributed transaction coordinator
|
|
underneath).</para>
|
|
|
|
<para>For local transactions on a single CCI <interfacename>ConnectionFactory</interfacename>,
|
|
Spring provides a specific transaction management strategy for CCI, analogous
|
|
to the <classname>DataSourceTransactionManager</classname> for JDBC. The CCI API
|
|
defines a local transaction object and corresponding local transaction
|
|
demarcation methods. Spring's <classname>CciLocalTransactionManager</classname>
|
|
executes such local CCI transactions, fully compliant with Spring's generic
|
|
<interfacename>PlatformTransactionManager</interfacename> abstraction.</para>
|
|
|
|
<programlisting><![CDATA[<bean id="eciConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
|
|
<property name="jndiName" value="eis/cicseci"/>
|
|
</bean>
|
|
|
|
<bean id="eciTransactionManager"
|
|
class="org.springframework.jca.cci.connection.CciLocalTransactionManager">
|
|
<property name="connectionFactory" ref="eciConnectionFactory"/>
|
|
</bean>]]></programlisting>
|
|
|
|
<para>Both transaction strategies can be used with any of Spring's
|
|
transaction demarcation facilities, be it declarative or programmatic.
|
|
This is a consequence of Spring's generic
|
|
<interfacename>PlatformTransactionManager</interfacename> abstraction, which
|
|
decouples transaction demarcation from the actual execution strategy.
|
|
Simply switch between <classname>JtaTransactionManager</classname> and
|
|
<classname>CciLocalTransactionManager</classname> as needed, keeping
|
|
your transaction demarcation as-is.</para>
|
|
|
|
<para>For more information on Spring's transaction facilities, see the
|
|
chapter entitled <xref linkend="transaction"/>.</para>
|
|
</section>
|
|
</chapter>
|