?
本文檔使用 PHP中文網(wǎng)手冊 發(fā)布
對JCA CCI支持的一個目標(biāo)是提供方便的機制來操作CCI記錄。
開發(fā)人員可以通過使用Spring的 CciTemplate
來指定創(chuàng)建記錄并從記錄中提取數(shù)據(jù)的策略。
如果你不想在應(yīng)用程序中直接操作記錄,可以使用下面的接口來配置用于輸入輸出記錄的策略。
為了創(chuàng)建一個輸入 Record
,開發(fā)人員可以使用 RecordCreator
接口的一個特定實現(xiàn)。
public interface RecordCreator { Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException; }
正如你所看到的一樣, createRecord(..)
方法接收一個 RecordFactory
實例作為參數(shù),
該參數(shù)對應(yīng)于所使用的 ConnectionFactory
的 RecordFactory
接口。
它能被用于創(chuàng)建 IndexedRecord
或者 MappedRecord
的實例。
下面的例子展示了如何使用 RecordFactory
接口和索引(indexed)/映射(mapped)記錄。
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收回數(shù)據(jù)。
因此,一個 RecordExtractor
接口的特定實現(xiàn)可以被傳給Spring的 CciTemplate
,
用來從輸出 Record
接口中提取數(shù)據(jù)。
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); } }
CciTemplate
類是 CCI 核心支持包(org.springframework.jca.cci.core
)中主要的類。
它簡化了CCI的使用,因為它會處理資源的創(chuàng)建和釋放。這有助于避免常見的錯誤,比如總是忘記關(guān)閉連接。
它關(guān)注連接和交互對象的生命周期,從而使應(yīng)用程序的代碼可以專注于處理從應(yīng)用程序數(shù)據(jù)中生成輸入記錄和從輸出記錄中提取應(yīng)用程序數(shù)據(jù)。
JCA CCI規(guī)范定義了兩個不同的方法來在EIS上調(diào)用操作。CCI Interaction
接口提供兩個 execute
方法的簽名:
public interface javax.resource.cci.Interaction { ... boolean execute(InteractionSpec spec, Record input, Record output) throws ResourceException; Record execute(InteractionSpec spec, Record input) throws ResourceException; ... }
依賴于模板方法的調(diào)用,CciTemplate
類可以知道 interaction上的哪個 execute
方法被調(diào)用。
在任何情況下,都必須有一個正確初始化過的 InteractionSpec
實例。
CciTemplate.execute(..)
可以以下列兩種方式使用:
在提供直接的 Record
參數(shù)的情況下,只需要傳遞輸入記錄給 CCI ,
而返回的對象就是對應(yīng)的 CCI 輸出記錄。
在提供使用記錄映射的應(yīng)用對象的情況下,你需要提供相應(yīng)的 RecordCreator
和 RecordExtractor
實例。
第一種方法將使用下面的模板方法。這些模板方法將直接對應(yīng)到 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 { ... } }
第二種方法需要我們以參數(shù)的方式指定創(chuàng)建記錄和記錄提取的策略。
使用前面記錄轉(zhuǎn)化一節(jié)中描述的接口。對應(yīng)的 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 { ... } }
除非在模板上設(shè)置 outputRecordCreator
屬性(參見下一部分),
不然每個方法都將調(diào)用CCI Interaction
中相應(yīng)的含有兩個參數(shù):
InteractionSpec
和輸入 Record
的 execute
方法,
并接收一個輸出 Record
作為返回值。
通過 createIndexRecord(..)
和 createMappedRecord(..)
方法,
CciTemplate
在 RecordCreator
實現(xiàn)類外部也提供了創(chuàng)建
IndexRecord
和 MappedRecord
。
還可以用來在DAO實現(xiàn)內(nèi)創(chuàng)建記錄實例并傳入到相應(yīng)的 CciTemplate.execute(..)
方法。
public class CciTemplate implements CciOperations { public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... } public MappedRecord createMappedRecord(String name) throws DataAccessException { ... } }
Spring的 CCI 支持為 DAO 提供了一個抽象類,支持 ConnectionFactory
或 CciTemplate
實例的注入。這個類的名字是 CciDaoSupport
:
它提供了簡單的 setConnectionFactory
和 setCciTemplate
方法。
在內(nèi)部,該類將為傳入的 ConnectionFactory
創(chuàng)建一個 CciTemplate
實例,
并把它暴露給子類中具體的數(shù)據(jù)訪問實現(xiàn)使用。
public abstract class CciDaoSupport { public void setConnectionFactory(ConnectionFactory connectionFactory) { ... } public ConnectionFactory getConnectionFactory() { ... } public void setCciTemplate(CciTemplate cciTemplate) { ... } public CciTemplate getCciTemplate() { ... } }
如果所用的連接器只支持以輸入輸出記錄作為參數(shù)的 Interaction.execute(..)
方法
(就是說,它要求傳入期望的輸出記錄而不是返回適當(dāng)?shù)妮敵鲇涗洠? 你可以設(shè)定 CciTemplate
類的 outputRecordCreator
屬性來自動生成一個輸出記錄,
當(dāng)接收到響應(yīng)時JCA連接器(JCA connector)將填充該記錄并返回給模板的調(diào)用者。
因為這個目的,這個屬性只持有 RecordCreator
接口的一個實現(xiàn)。
RecordCreator
接口已經(jīng)在 第?21.3.1?節(jié) “記錄轉(zhuǎn)換” 進行了討論。
outputRecordCreator
屬性必須直接在 CciTemplate
中指定,可以在應(yīng)用代碼中做到這一點。
cciTemplate.setOutputRecordCreator(new EciOutputRecordCreator());
或者如果 CciTemplate
被配置為一個專門的bean實例,那么outputRecordCreator還可以在Spring文件中配置(推薦的做法):
<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
類是線程安全的,所以它通常被配置為一個共享實例。
下表總結(jié)了 CciTemplate
類和在 CCI Interaction
接口上調(diào)用相應(yīng)方法的機制:
表?21.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) |
類似于 JdbcTemplate
類和 JmsTemplate
類的操作方式,
CciTemplate
類同樣提供直接操作CCI 連接和交互的可能性。
比如說如果你想對一個CCI連接執(zhí)行多種操作,這就會很有用。
ConnectionCallback
接口提供以CCI Connection
作為參數(shù),
為了在它上面執(zhí)行自定義動作,添加了創(chuàng)建 Connection
的CCI ConnectionFactory
。
后者在獲取相關(guān) RecordFactory
實例和創(chuàng)建indexed/mapped records時很有用。例如:
public interface ConnectionCallback { Object doInConnection(Connection connection, ConnectionFactory connectionFactory) throws ResourceException, SQLException, DataAccessException; }
InteractionCallback
接口提供 CCI Interaction
接口,
為了在它上面執(zhí)行自定義動作,請?zhí)砑酉鄳?yīng)的CCI ConnectionFactory
。
public interface InteractionCallback { Object doInInteraction(Interaction interaction, ConnectionFactory connectionFactory) throws ResourceException, SQLException, DataAccessException; }
InteractionSpec
對象還可以在多個template調(diào)用之間被共享或者在每個回調(diào)方法內(nèi)重新創(chuàng)建,
這完全取決于 DAO 的實現(xiàn)。
在本章節(jié)中,我們將展示如何使用 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; } }
正如之前討論的那樣,callbacks 可以被用來直接在 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;
}
}
當(dāng)getCciTemplate().execute參數(shù)是 ConnectionCallback
時,
所用的 Connection
將被 CciTemplate
管理和關(guān)閉,
但是任何在連接上建立的交互都必須被callback實現(xiàn)類所管理。
對于一個更特殊的callback,你可以實現(xiàn)一個 InteractionCallback
。
這樣傳入的 Interaction
將會被 CciTemplate
管理和關(guān)閉。
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; } }
在上面的例子中,非托管模式(non-managed)下對應(yīng)的spring beans的配置會像下面這樣:
<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>
在托管模式(managed mode)(也就是說,在一個J2EE環(huán)境)下,配置可能如下所示:
<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>