32. JCA CCI

32.1 简介

Java EE提供了一个规范来标准化对企业信息系统(EIS)的访问:JCA(Java EE连接器体系结构)。该规范分为几个不同的部分:

  • 连接器提供程序必须实现的SPI(服务提供程序接口)。这些接口构成可以部署在Java EE应用程序服务器上的资源适配器。在这种情况下,服务器管理连接池,事务和安全性(托管模式)。应用程序服务器还负责管理客户端应用程序外部的配置。连接器也可以在没有应用服务器的情况下使用;在这种情况下,应用程序必须直接配置它(非托管模式)。

  • CCI(通用客户端接口),应用程序可以使用它与连接器进行交互,从而与EIS进行通信。还提供了用于本地事务划分的API。

Spring CCI支持的目的是提供以典型Spring风格访问CCI连接器的类,利用Spring Framework的一般资源和事务管理工具。

连接器的客户端一直不使用CCI。有些连接器公开自己的API,只提供JCA资源适配器来使用Java EE容器的系统 Contract (连接池,全局事务,安全性)。 Spring不为这种特定于连接器的API提供特殊支持。

32.2 配置CCI

32.2.1 连接器配置

使用JCA CCI的基本资源是 ConnectionFactory 接口。使用的连接器必须提供此接口的实现。

要使用连接器,可以将其部署在应用程序服务器上,并从服务器的JNDI环境(托管模式)获取 ConnectionFactory 。必须将连接器打包为RAR文件(资源适配器归档文件)并包含 ra.xml 文件以描述其部署特征。部署资源时指定资源的实际名称。要在Spring中访问它,只需使用Spring的 JndiObjectFactoryBean / <jee:jndi-lookup> 按其JNDI名称获取工厂。

使用连接器的另一种方法是将其嵌入应用程序(非托管模式),而不是使用应用程序服务器来部署和配置它。 Spring提供了通过提供的 FactoryBeanLocalConnectionFactoryBean )将连接器配置为bean的可能性。通过这种方式,您只需要类路径中的连接器库(不需要RAR文件,也不需要 ra.xml 描述符)。必要时,必须从连接器的RAR文件中提取库。

一旦有权访问 ConnectionFactory 实例,就可以将其注入组件中。这些组件可以针对普通CCI API进行编码,也可以利用Spring的支持类进行CCI访问(例如 CciTemplate )。

在非托管模式下使用连接器时,不能使用全局事务,因为资源在当前线程的当前全局事务中永远不会登记/退出。资源根本不知道可能正在运行的任何全局Java EE事务。

32.2.2 Spring中的ConnectionFactory配置

为了 Build 与EIS的连接,如果您处于托管模式,则需要从应用程序服务器获取 ConnectionFactory ,如果您处于非托管模式,则需要直接从Spring获取。

在托管模式下,您可以从JNDI访问 ConnectionFactory ;其属性将在应用程序服务器中配置。

<jee:jndi-lookup id="eciConnectionFactory" jndi-name="eis/cicseci"/>

在非托管模式下,必须将要在Spring配置中使用的 ConnectionFactory 配置为JavaBean。 LocalConnectionFactoryBean 类提供此设置样式,传递连接器的 ManagedConnectionFactory 实现,公开应用程序级CCI ConnectionFactory

<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>

您无法直接实例化特定的ConnectionFactory。您需要为连接器完成ManagedConnectionFactory接口的相应实现。该接口是JCA SPI规范的一部分。

32.2.3 配置CCI连接

JCA CCI允许开发人员使用连接器的 ConnectionSpec 实现配置与EIS的连接。要配置其属性,需要使用专用适配器 ConnectionSpecConnectionFactoryAdapter 包装目标连接工厂。因此,专用 ConnectionSpec 可以使用属性 connectionSpec (作为内部bean)进行配置。

此属性不是必需的,因为CCI ConnectionFactory 接口定义了两种不同的方法来获取CCI连接。某些 ConnectionSpec 属性通常可以在应用程序服务器(在托管模式下)或相应的本地 ManagedConnectionFactory 实现中进行配置。

public interface ConnectionFactory implements Serializable, Referenceable {
    ...
    Connection getConnection() throws ResourceException;
    Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException;
    ...
}

Spring提供了 ConnectionSpecConnectionFactoryAdapter ,允许指定 ConnectionSpec 实例以用于给定工厂的所有操作。如果指定了适配器的 connectionSpec 属性,则适配器将 getConnection 变量与 ConnectionSpec 参数一起使用,否则使用不带参数的变量。

<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>

32.2.4 使用单个CCI连接

如果您想使用单个CCI连接,Spring会提供另一个 ConnectionFactory 适配器来管理它。 SingleConnectionFactory 适配器类将懒惰地打开一个连接,并在应用程序关闭时销毁此bean时将其关闭。此类将公开相应行为的特殊 Connection 代理,它们共享相同的底层物理连接。

<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>

此ConnectionFactory适配器无法直接配置ConnectionSpec。如果您需要针对特定ConnectionSpec的单个连接,请使用SingleConnectionFactory与之对话的中间ConnectionSpecConnectionFactoryAdapter。

32.3 使用Spring的CCI访问支持

32.3.1 记录转换

JCA CCI支持的目标之一是为操作CCI记录提供便利的设施。开发人员可以指定策略来创建记录并从记录中提取数据,以便与Spring的 CciTemplate 一起使用。如果您不想直接在应用程序中使用记录,以下接口将配置策略以使用输入和输出记录。

为了创建输入 Record ,开发人员可以使用 RecordCreator 接口的专用实现。

public interface RecordCreator {

    Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException;

}

如你所见, createRecord(..) 接收 RecordFactory 实例作为参数,该参数对应于 ConnectionFactory 使用的 RecordFactory 。此引用可用于创建 IndexedRecordMappedRecord 实例。以下示例显示如何使用 RecordCreator 接口和索引/映射记录。

public class MyRecordCreator implements RecordCreator {

    public Record createRecord(RecordFactory recordFactory) throws ResourceException {
        IndexedRecord input = recordFactory.createIndexedRecord("input");
        input.add(new Integer(id));
        return input;
    }

}

输出 Record 可用于从EIS接收数据。因此,可以将 RecordExtractor 接口的特定实现传递给Spring的 CciTemplate ,以便从输出 Record 中提取数据。

public interface RecordExtractor {

    Object extractData(Record record) throws ResourceException, SQLException, DataAccessException;

}

以下示例显示如何使用 RecordExtractor 接口。

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);
    }

}

32.3.2 CciTemplate

CciTemplate 是核心CCI支持包的中心类( org.springframework.jca.cci.core )。它简化了CCI的使用,因为它处理资源的创建和释放。这有助于避免常见错误,例如忘记始终关闭连接。它关注连接和交互对象的生命周期,让应用程序代码专注于从应用程序数据生成输入记录并从输出记录中提取应用程序数据。

JCA CCI规范定义了两种不同的方法来调用EIS上的操作。 CCI Interaction 接口提供两个执行方法签名:

public interface javax.resource.cci.Interaction {

    ...

    boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException;

    Record execute(InteractionSpec spec, Record input) throws ResourceException;

    ...

}

根据调用的模板方法, CciTemplate 将知道在交互时调用哪个 execute 方法。无论如何,正确初始化的 InteractionSpec 实例是必需的。

CciTemplate.execute(..) 可以通过两种方式使用:

  • 使用直接的 Record 参数。在这种情况下,您只需要传入CCI输入记录,返回的对象就是相应的CCI输出记录。

  • 使用应用程序对象,使用记录映射。在这种情况下,您需要提供相应的 RecordCreatorRecordExtractor 实例。

使用第一种方法,将使用模板的以下方法。这些方法直接对应于 Interaction 接口上的方法。

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 { ... }

}

使用第二种方法,我们需要将记录创建和记录提取策略指定为参数。使用的接口是上一节中关于记录转换的描述。相应的 CciTemplate 方法如下:

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 {
        // ...
    }

}

除非在模板上设置 outputRecordCreator 属性(请参阅下一节),否则每个方法都将使用两个参数调用CCI Interaction 的相应 execute 方法: InteractionSpec 并输入 Record ,接收输出 Record 作为返回值。

CciTemplate 还提供了通过 createIndexRecord(..)createMappedRecord(..) 方法在 RecordCreator 实现之外创建 IndexRecordMappedRecord 的方法。这可以在DAO实现中用于创建 Record 实例以传递到相应的 CciTemplate.execute(..) 方法。

public class CciTemplate implements CciOperations {

    public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... }

    public MappedRecord createMappedRecord(String name) throws DataAccessException { ... }

}

32.3.3 DAO支持

Spring的CCI支持为DAO提供了一个抽象类,支持注入 ConnectionFactoryCciTemplate 实例。该类的名称是 CciDaoSupport :它提供简单的 setConnectionFactorysetCciTemplate 方法。在内部,此类将为传入的 ConnectionFactory 创建 CciTemplate 实例,将其公开给子类中的具体数据访问实现。

public abstract class CciDaoSupport {

    public void setConnectionFactory(ConnectionFactory connectionFactory) {
        // ...
    }

    public ConnectionFactory getConnectionFactory() {
        // ...
    }

    public void setCciTemplate(CciTemplate cciTemplate) {
        // ...
    }

    public CciTemplate getCciTemplate() {
        // ...
    }

}

32.3.4 自动输出记录生成

如果使用的连接器仅支持带有输入和输出记录作为参数的 Interaction.execute(..) 方法(也就是说,它需要传入所需的输出记录而不是返回适当的输出记录),则可以将 CciTemplateoutputRecordCreator 属性设置为自动生成一个输出记录,在收到响应时由JCA连接器填充。然后该记录将返回给模板的调用者。

此属性只保存 RecordCreator 接口的实现,用于此目的。 RecordCreator 接口已在 Section 32.3.1, “Record conversion” 中讨论过。必须在 CciTemplate 上直接指定 outputRecordCreator 属性。这可以在应用程序代码中完成,如下所示:

cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator());

或者(推荐)在Spring配置中,如果将 CciTemplate 配置为专用bean实例:

<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>

由于CciTemplate类是线程安全的,因此通常将其配置为共享实例。

32.3.5 摘要

下表总结了 CciTemplate 类的机制以及在CCI Interaction 接口上调用的相应方法:

Table 32.1. Usage of Interaction execute methods

CciTemplate方法签名CciTemplate outputRecordCreator属性在CCI交互上调用的执行方法
记录执行(InteractionSpec,记录)未设置记录执行(InteractionSpec,记录)
记录执行(InteractionSpec,Record)setboolean execute(InteractionSpec,Record,Record)
void execute(InteractionSpec,Record,Record)not setvoid execute(InteractionSpec,Record,Record)
void execute(InteractionSpec,Record,Record)setvoid执行(InteractionSpec,记录,记录)
记录执行(InteractionSpec,RecordCreator)未设置记录执行(InteractionSpec,记录)
记录执行(InteractionSpec,RecordCreator)setvoid execute(InteractionSpec,Record,Record)
记录执行(InteractionSpec,Record,RecordExtractor)未设置记录执行(InteractionSpec,记录)
记录执行(InteractionSpec,Record,RecordExtractor)setvoid execute(InteractionSpec,Record,Record)
记录执行(InteractionSpec,RecordCreator,RecordExtractor)未设置记录执行(InteractionSpec,记录)
记录执行(InteractionSpec,RecordCreator,RecordExtractor)setvoid execute(InteractionSpec,Record,Record)

32.3.6 直接使用CCI连接和交互

CciTemplate 也提供了直接使用CCI连接和交互的可能性,方法与 JdbcTemplateJmsTemplate 相同。例如,当您想要在CCI连接或交互上执行多个操作时,这非常有用。

接口 ConnectionCallback 提供CCI Connection 作为参数,以便对其执行自定义操作,以及创建 Connection 的CCI ConnectionFactory 。例如,后者可用于获取关联的 RecordFactory 实例并创建索引/映射记录。

public interface ConnectionCallback {

    Object doInConnection(Connection connection, ConnectionFactory connectionFactory)
            throws ResourceException, SQLException, DataAccessException;

}

接口 InteractionCallback 提供CCI Interaction ,以便对其执行自定义操作,以及相应的CCI ConnectionFactory

public interface InteractionCallback {

    Object doInInteraction(Interaction interaction, ConnectionFactory connectionFactory)
        throws ResourceException, SQLException, DataAccessException;

}

InteractionSpec对象可以在多个模板调用之间共享,也可以在每个回调方法中新创建。这完全取决于DAO的实现。

32.3.7 CciTemplate用法示例

在本节中,将显示 CciTemplate 的使用情况,以使用IBM CICS ECI连接器访问具有ECI模式的CICS。

首先,必须对CCI InteractionSpec 进行一些初始化,以指定要访问的CICS程序以及如何与之交互。

ECIInteractionSpec interactionSpec = new ECIInteractionSpec();
interactionSpec.setFunctionName("MYPROG");
interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);

然后程序可以通过Spring的模板使用CCI并指定自定义对象和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;
    }
}

如前所述,回调可用于直接在CCI连接或交互上工作。

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;
    }

}

使用ConnectionCallback,所使用的连接将由CciTemplate管理和关闭,但在连接上创建的任何交互都必须由回调实现进行管理。

对于更具体的回调,您可以实现 InteractionCallback 。在这种情况下,传入的 Interaction 将由 CciTemplate 管理和关闭。

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;
    }

}

对于上面的示例,所涉及的Spring bean的相应配置在非托管模式下可能如下所示:

<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>

在托管模式下(即在Java EE环境中),配置可能如下所示:

<jee:jndi-lookup id="connectionFactory" jndi-name="eis/cicseci"/>

<bean id="component" class="MyDaoImpl">
    <property name="connectionFactory" ref="connectionFactory"/>
</bean>

32.4 将CCI访问建模为操作对象

org.springframework.jca.cci.object 包中包含支持类,允许您以不同的方式访问EIS:通过可重用的操作对象,类似于Spring的JDBC操作对象(请参阅JDBC章节)。这通常会封装CCI API:应用程序级输入对象将传递给操作对象,因此它可以构造输入记录,然后将接收到的记录数据转换为应用程序级输出对象并返回它。

这种方法在内部基于CciTemplate类和RecordCreator / RecordExtractor接口,重用了Spring的核心CCI支持。

32.4.1 MappingRecordOperation

MappingRecordOperation 本质上执行与 CciTemplate 相同的工作,但将特定的预配置操作表示为对象。它提供了两种模板方法来指定如何将输入对象转换为输入记录,以及如何将输出记录转换为输出对象(记录映射):

  • createInputRecord(..) 指定如何将输入对象转换为输入 Record

  • extractOutputData(..) 指定如何从输出中提取输出对象 Record

以下是这些方法的签名:

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 {
        // ...
    }

    ...

}

此后,为了执行EIS操作,您需要使用单个execute方法,传入应用程序级输入对象并接收应用程序级输出对象,结果如下:

public abstract class MappingRecordOperation extends EisOperation {

    ...

    public Object execute(Object inputObject) throws DataAccessException {
    }

    ...
}

正如您所看到的,与 CciTemplate 类相反,此 execute(..) 方法没有 InteractionSpec 作为参数。相反, InteractionSpec 是操作的全局。必须使用以下构造函数来实例化具有特定 InteractionSpec 的操作对象:

InteractionSpec spec = ...;
MyMappingRecordOperation eisOperation = new MyMappingRecordOperation(getConnectionFactory(), spec);
...

32.4.2 MappingCommAreaOperation

某些连接器使用基于COMMAREA的记录,该记录表示包含要发送到EIS的参数和由其返回的数据的字节数组。 Spring提供了一个特殊的操作类,用于直接在COMMAREA而不是on上工作记录。 MappingCommAreaOperation 类扩展了 MappingRecordOperation 类以提供这种特殊的COMMAREA支持。它隐式使用 CommAreaRecord 类作为输入和输出记录类型,并提供两种新方法将输入对象转换为输入COMMAREA,将输出COMMAREA转换为输出对象。

public abstract class MappingCommAreaOperation extends MappingRecordOperation {

    ...

    protected abstract byte[] objectToBytes(Object inObject)
            throws IOException, DataAccessException;

    protected abstract Object bytesToObject(byte[] bytes)
        throws IOException, DataAccessException;

    ...

}

32.4.3 自动输出记录生成

由于每个 MappingRecordOperation 子类都在内部基于CciTemplate,因此可以使用与 CciTemplate 一样自动生成输出记录的相同方法。每个操作对象都提供相应的 setOutputRecordCreator(..) 方法。有关详细信息,请参阅 Section 32.3.4, “Automatic output record generation”

32.4.4 摘要

操作对象方法以与 CciTemplate 类相同的方式使用记录。

Table 32.2. Usage of Interaction execute methods

MappingRecordOperation方法签名MappingRecordOperation outputRecordCreator属性在CCI交互上调用的执行方法
对象执行(对象)未设置记录执行(InteractionSpec,记录)
对象执行(对象)set布尔执行(InteractionSpec,记录,记录)

32.4.5 MappingRecordOperation用法示例

在本节中,将显示 MappingRecordOperation 的使用情况,以使用Blackbox CCI连接器访问数据库。

此连接器的原始版本由Oracle提供的Java EE SDK(版本1.3)提供。

首先,必须对CCI InteractionSpec 进行一些初始化以指定要执行的SQL请求。在此示例中,我们直接定义将请求的参数转换为CCI记录的方式以及将CCI结果记录转换为 Person 类的实例的方式。

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;
    }
}

然后应用程序可以执行操作对象,并将人员标识符作为参数。请注意,操作对象可以设置为共享实例,因为它是线程安全的。

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;
    }
}

在非托管模式下,Spring bean的相应配置可能如下所示:

<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>

在托管模式下(即在Java EE环境中),配置可能如下所示:

<jee:jndi-lookup id="targetConnectionFactory" jndi-name="eis/blackbox"/>

<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>

32.4.6 MappingCommAreaOperation用法示例

在本节中,将显示 MappingCommAreaOperation 的用法:使用IBM CICS ECI连接器以ECI模式访问CICS。

首先,需要初始化CCI InteractionSpec 以指定要访问的CICS程序以及如何与之交互。

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();
        }
    }

}

然后可以将抽象 EciMappingOperation 类子类化以指定自定义对象和 Records 之间的映射。

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));
    }

}

在非托管模式下,Spring bean的相应配置可能如下所示:

<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>

在托管模式下(即在Java EE环境中),配置可能如下所示:

<jee:jndi-lookup id="connectionFactory" jndi-name="eis/cicseci"/>

<bean id="component" class="MyDaoImpl">
    <property name="connectionFactory" ref="connectionFactory"/>
</bean>

32.5 Transaction

JCA为资源适配器指定了几个级别的事务支持。资源适配器支持的事务类型在 ra.xml 文件中指定。基本上有三个选项:none(例如使用CICS EPI连接器),本地事务(例如使用CICS ECI连接器),全局事务(例如使用IMS连接器)。

<connector>
    <resourceadapter>
        <!-- <transaction-support>NoTransaction</transaction-support> -->
        <!-- <transaction-support>LocalTransaction</transaction-support> -->
        <transaction-support>XATransaction</transaction-support>
    <resourceadapter>
<connector>

对于全局事务,您可以使用Spring的通用事务基础结构来划分事务,使用 JtaTransactionManager 作为后端(委托给下面的Java EE服务器的分布式事务协调器)。

对于单个CCI ConnectionFactory 上的本地事务,Spring为CCI提供了一个特定的事务管理策略,类似于JDBC的 DataSourceTransactionManager 。 CCI API定义了本地事务对象和相应的本地事务划分方法。 Spring的 CciLocalTransactionManager 执行这样的本地CCI事务,完全符合Spring的通用 PlatformTransactionManager 抽象。

<jee:jndi-lookup id="eciConnectionFactory" jndi-name="eis/cicseci"/>

<bean id="eciTransactionManager"
        class="org.springframework.jca.cci.connection.CciLocalTransactionManager">
    <property name="connectionFactory" ref="eciConnectionFactory"/>
</bean>

两种事务策略都可以与Spring的任何事务划分工具一起使用,无论是声明性的还是编程式的。这是Spring的通用 PlatformTransactionManager 抽象的结果,它将事务划分与实际执行策略分离。只需根据需要在 JtaTransactionManagerCciLocalTransactionManager 之间切换,保持您的事务划分按原样。

有关Spring的事务工具的更多信息,请参阅 Headers 为 Chapter 17, Transaction Management 的章节。

Updated at: 5 months ago
31.8. 更多资源Table of content33. 电子邮件
Comment
You are not logged in.

There are no comments.