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 CciTemplate. 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.
In order to create an input Record,
the developer can use a dedicated implementation of the
RecordCreator interface.
public interface RecordCreator { Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException; }
As you can see, the createRecord(..) method
receives a RecordFactory instance as
parameter, which corresponds to the
RecordFactory of the
ConnectionFactory used. This reference
can be used to create IndexedRecord or
MappedRecord instances. The following
sample shows how to use the RecordCreator
interface and indexed/mapped records.
public class MyRecordCreator implements RecordCreator { public Record createRecord(RecordFactory recordFactory) throws ResourceException { IndexedRecord input = recordFactory.createIndexedRecord("input"); input.add(new Integer(id)); return input; } }
An output Record can be used to
receive data back from the EIS. Hence, a specific implementation of the
RecordExtractor interface can be passed
to Spring's CciTemplate for extracting data from
the output Record.
public interface RecordExtractor { Object extractData(Record record) throws ResourceException, SQLException, DataAccessException; }
The following sample shows how to use the
RecordExtractor interface.
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); } }
The CciTemplate is the central class of the
core CCI support package
(org.springframework.jca.cci.core). 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.
The JCA CCI specification defines two distinct methods to call
operations on an EIS. The CCI Interaction
interface provides two execute method signatures:
public interface javax.resource.cci.Interaction { ... boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException; Record execute(InteractionSpec spec, Record input) throws ResourceException; ... }
Depending on the template method called,
CciTemplate will know which
execute method to call on the interaction. In any
case, a correctly initialized
InteractionSpec instance is
mandatory.
CciTemplate.execute(..) can be used in two
ways:
With direct Record arguments.
In this case, you simply need to pass the CCI input record in, and
the returned object be the corresponding CCI output record.
With application objects, using record mapping. In this case,
you need to provide corresponding
RecordCreator and
RecordExtractor instances.
With the first approach, the following methods of the template
will be used. These methods directly correspond to those on the
Interaction interface.
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 { ... } }
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 CciTemplate methods are the
following:
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 { ... } }
Unless the outputRecordCreator property is set
on the template (see the following section), every method will call the
corresponding execute method of the CCI
Interaction with two parameters:
InteractionSpec and input
Record, receiving an output
Record as return value.
CciTemplate also provides methods to create
IndexRecord and MappedRecord
outside a RecordCreator implementation,
through its createIndexRecord(..) and
createMappedRecord(..) methods. This can be used
within DAO implementations to create
Record instances to pass into
corresponding CciTemplate.execute(..) methods.
public class CciTemplate implements CciOperations { public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... } public MappedRecord createMappedRecord(String name) throws DataAccessException { ... } }
Spring's CCI support provides a abstract class for DAOs,
supporting injection of a
ConnectionFactory or a
CciTemplate instances. The name of the class is
CciDaoSupport: It provides simple
setConnectionFactory and
setCciTemplate methods. Internally, this class will
create a CciTemplate instance for a passed-in
ConnectionFactory, exposing it to
concrete data access implementations in subclasses.
public abstract class CciDaoSupport { public void setConnectionFactory(ConnectionFactory connectionFactory) { ... } public ConnectionFactory getConnectionFactory() { ... } public void setCciTemplate(CciTemplate cciTemplate) { ... } public CciTemplate getCciTemplate() { ... } }
If the connector used only supports the
Interaction.execute(..) 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 outputRecordCreator property
of the CciTemplate 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.
This property simply holds an implementation of the
RecordCreator interface, used for that
purpose. The RecordCreator interface has
already been discussed in Section 23.3.1, “Record conversion”. The
outputRecordCreator property must be directly
specified on the CciTemplate. This could be done
in the application code like so:
cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator());Or (recommended) in the Spring configuration, if the
CciTemplate is configured as a dedicated bean
instance:
<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>
![]() | Note |
|---|---|
As the |
The following table summarizes the mechanisms of the
CciTemplate class and the corresponding methods
called on the CCI Interaction
interface:
Table 23.1. Usage of Interaction execute
methods
| CciTemplate method signature | CciTemplate outputRecordCreator property | execute method called on the CCI Interaction |
|---|---|---|
| Record execute(InteractionSpec, Record) | not set | Record execute(InteractionSpec, Record) |
| Record execute(InteractionSpec, Record) | set | boolean execute(InteractionSpec, Record, Record) |
| void execute(InteractionSpec, Record, Record) | not set | void execute(InteractionSpec, Record, Record) |
| void execute(InteractionSpec, Record, Record) | set | void execute(InteractionSpec, Record, Record) |
| Record execute(InteractionSpec, RecordCreator) | not set | Record execute(InteractionSpec, Record) |
| Record execute(InteractionSpec, RecordCreator) | set | void execute(InteractionSpec, Record, Record) |
| Record execute(InteractionSpec, Record, RecordExtractor) | not set | Record execute(InteractionSpec, Record) |
| Record execute(InteractionSpec, Record, RecordExtractor) | set | void execute(InteractionSpec, Record, Record) |
| Record execute(InteractionSpec, RecordCreator, RecordExtractor) | not set | Record execute(InteractionSpec, Record) |
| Record execute(InteractionSpec, RecordCreator, RecordExtractor) | set | void execute(InteractionSpec, Record, Record) |
CciTemplate also offers the possibility to
work directly with CCI connections and interactions, in the same manner
as JdbcTemplate and
JmsTemplate. This is useful when you want to
perform multiple operations on a CCI connection or interaction, for
example.
The interface ConnectionCallback
provides a CCI Connection as argument, in
order to perform custom operations on it, plus the CCI
ConnectionFactory which the
Connection was created with. The latter
can be useful for example to get an associated
RecordFactory instance and create
indexed/mapped records, for example.
public interface ConnectionCallback { Object doInConnection(Connection connection, ConnectionFactory connectionFactory) throws ResourceException, SQLException, DataAccessException; }
The interface InteractionCallback
provides the CCI Interaction, in order to
perform custom operations on it, plus the corresponding CCI
ConnectionFactory.
public interface InteractionCallback { Object doInInteraction(Interaction interaction, ConnectionFactory connectionFactory) throws ResourceException, SQLException, DataAccessException; }
![]() | Note |
|---|---|
|
In this section, the usage of the
CciTemplate will be shown to acces to a CICS with
ECI mode, with the IBM CICS ECI connector.
Firstly, some initializations on the CCI
InteractionSpec must be done to specify
which CICS program to access and how to interact with it.
ECIInteractionSpec interactionSpec = new ECIInteractionSpec(); interactionSpec.setFunctionName("MYPROG"); interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
Then the program can use CCI via Spring's template and specify
mappings between custom objects and CCI
Records.
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; } }
As discussed previously, callbacks can be used to work directly on CCI connections or interactions.
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 { // do something... } }); } return output; } }
![]() | Note |
|---|---|
With a |
For a more specific callback, you can implement an
InteractionCallback. The passed-in
Interaction will be managed and closed by
the CciTemplate in this case.
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; } }
For the examples above, the corresponding configuration of the involved Spring beans could look like this in non-managed mode:
<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>
In managed mode (that is, in a Java EE environment), the configuration could look as follows:
<jee:jndi-lookup id="connectionFactory" jndi-name="eis/cicseci"/> <bean id="component" class="MyDaoImpl"> <property name="connectionFactory" ref="connectionFactory"/> </bean>