javascript
Spring 中JCA CCI分析--转载
轉載地址:http://blog.csdn.net/a154832918/article/details/6790612
J2EE提供JCA(Java Connector Architecture)規范來標準化對EIS(Enterprise Information System)的訪問。這個規范被分為幾個不同的部分:?
SPI(Service provider interfaces)是連接器提供者(connector provider)必須實現的接口。 這些接口組成了一個能被部署在J2EE應用服務器上的資源適配器(resource adapter)。 在這種情況下,由服務器來管理連接池(connection pooling)、事務和安全(托管模式(managed mode))。 應用服務器還負責管理客戶端應用程序之外所擁有的配置。連接器(connector)同樣能在脫離應用服務器的情況下使用;在這種情況下,應用程序必須直接對它進行配置(非托管模式(non-managed mode))。?
CCI (Common Client Interface)是應用程序用來與連接器交互并與EIS通信的接口。同樣還為本地事務劃界提供了API。?
Spring對CCI的支持,目的是為了提供以典型的Spring方式來訪問CCI連接器的類,并有效地使用Spring的通用資源和事務管理工具。?
Note?
連接器的客戶端不必總是使用CCI。 某些連接器暴露它們自己的API,只提供JCA資源適配器(resource adapter) 以使用J2EE容器的某些系統契約(system contracts)(連接池(connection pooling),全局事務(global transactions),安全(security))。 Spring并沒有為這類連接器特有(connector-specific)的API提供特殊的支持。?
21.2. 配置CCI?
21.2.1. 連接器配置?
使用JCA CCI的基礎資源是 ConnectionFactory 接口。 所用的連接器必須提供這個接口的一個實現。?
為了使用連接器,可以把它部署到你的應用服務器上,并從服務器的JNDI環境(托管模式)取回 ConnectionFactory。 連接器必須打包為一個RAR文件(resource adapte archive)并包含一個部署描述符文件 ra.xml 。 部署時需要指定資源的實際名字。如果想通過Spring訪問它,只要簡單地使用Spring的 JndiObjectFactoryBean 來通過JNDI名字獲取工廠。?
使用連接器的另一種方法是把它嵌入到應用程序中(非托管模式(non-managed mode)),而不用在應用服務器中部署并配置它。 Spring提供了通過已提供的 FactoryBean(LocalConnectionFactoryBean))來將連接器配置成一個bean的可能。 在這種方式中,只需要把連接器類庫放到classpath目錄下(不需要RAR文件和 ra.xml 描述符)。 如果有必要的話,必須從連接器的RAR文件解壓得到那個類庫。?
一旦訪問 ConnectionFactory 實例, 就可以將它注入到組件。這些組件既可以用簡單的CCI API編碼,也可以利用Spring支持CCI訪問的類(比如,CciTemplate)。?
Note?
當在非托管模式(non-managed mode)下使用連接器時,將無法使用全局事務, 因為該資源從不會被加入或刪除到當前線程的當前全局事務中。該資源根本不知道任何可能正在運行的全局的J2EE事務。?
21.2.2. 在Spring中配置ConnectionFactory?
為了創建到 EIS 的連接,如果處于托管模式(managed mode),你需要從應用服務器獲取一個 ConnectionFactory , 或者當你在非托管模式(non-managed mode)時直接從Spring去獲取。?
在托管模式(managed mode)下,你可以從JNDI訪問 ConnectionFactory, 它的屬性將被配置在應用服務器中。?
<bean id="eciConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">?
<property name="jndiName" value="eis/cicseci"/>?
</bean>?
在非托管模式(non-managed mode)下,你必須在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>?
Note?
你不能直接實例化一個指定的 ConnectionFactory 接口。 你需要為連接器實現相應的 ManagedConnectionFactory 接口,這個接口是JCA SPI規范的一部分。?
21.2.3. 配置CCI連接?
JCA CCI允許開發者使用自己的連接器的 ConnectionSpec 接口實現來配置到 EIS 的連接。 為了配置該連接的屬性,需要用一個指定的 ConnectionSpecConnectionFactoryAdapter 適配器來封裝目標連接工廠。 因此,特定的 ConnectionSpec 接口可以用 connectionSpec 屬性來配置(作為一個內部bean)。?
這個屬性不是必需的,因為CCI ConnectionFactory 接口定義了兩個不同的方法來獲取 CCI 連接。 ConnectionSpec 的一些屬性常常可以被配置在應用服務器中(托管模式(managed mode)) 或相關的本地 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>?
21.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>?
Note?
這個 ConnectionFactory 適配器不能直接用 ConnectionSpec 配置。 如果需要特定 ConnectionSpec 的單一連接,那么可以用 SingleConnectionFactory 與之通信的中間 ConnectionSpecConnectionFactoryAdapter 適配器。?
21.3. 使用Spring的 CCI訪問支持?
21.3.1. 記錄轉換?
對JCA CCI支持的一個目標是提供方便的機制來操作CCI記錄。 開發人員可以通過使用Spring的 CciTemplate 來指定創建記錄并從記錄中提取數據的策略。 如果你不想在應用程序中直接操作記錄,可以使用下面的接口來配置用于輸入輸出記錄的策略。?
為了創建一個輸入 Record,開發人員可以使用 RecordCreator 接口的一個特定實現。?
public interface RecordCreator {?
Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException;?
}?
正如你所看到的一樣, createRecord(..) 方法接收一個 RecordFactory 實例作為參數, 該參數對應于所使用的 ConnectionFactory 的 RecordFactory 接口。 它能被用于創建 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收回數據。 因此,一個 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);?
}?
}?
21.3.2. CciTemplate類?
CciTemplate 類是 CCI 核心支持包(org.springframework.jca.cci.core)中主要的類。 它簡化了CCI的使用,因為它會處理資源的創建和釋放。這有助于避免常見的錯誤,比如總是忘記關閉連接。 它關注連接和交互對象的生命周期,從而使應用程序的代碼可以專注于處理從應用程序數據中生成輸入記錄和從輸出記錄中提取應用程序數據。?
JCA CCI規范定義了兩個不同的方法來在EIS上調用操作。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;?
...?
}?
依賴于模板方法的調用,CciTemplate 類可以知道 interaction上的哪個 execute 方法被調用。 在任何情況下,都必須有一個正確初始化過的 InteractionSpec 實例。?
CciTemplate.execute(..)可以以下列兩種方式使用:?
在提供直接的 Record 參數的情況下,只需要傳遞輸入記錄給 CCI , 而返回的對象就是對應的 CCI 輸出記錄。?
在提供使用記錄映射的應用對象的情況下,你需要提供相應的 RecordCreator 和 RecordExtractor 實例。?
第一種方法將使用下面的模板方法。這些模板方法將直接對應到 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 中相應的含有兩個參數: InteractionSpec 和輸入 Record的 execute 方法, 并接收一個輸出 Record 作為返回值。?
通過 createIndexRecord(..) 和 createMappedRecord(..) 方法, CciTemplate 在 RecordCreator 實現類外部也提供了創建 IndexRecord 和 MappedRecord。 還可以用來在DAO實現內創建記錄實例并傳入到相應的 CciTemplate.execute(..) 方法。?
public class CciTemplate implements CciOperations {?
public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... }?
public MappedRecord createMappedRecord(String name) throws DataAccessException { ... }?
}?
21.3.3. DAO支持?
Spring的 CCI 支持為 DAO 提供了一個抽象類,支持 ConnectionFactory 或 CciTemplate 實例的注入。這個類的名字是 CciDaoSupport: 它提供了簡單的 setConnectionFactory 和 setCciTemplate 方法。 在內部,該類將為傳入的 ConnectionFactory 創建一個 CciTemplate 實例, 并把它暴露給子類中具體的數據訪問實現使用。?
public abstract class CciDaoSupport {?
public void setConnectionFactory(ConnectionFactory connectionFactory) { ... }?
public ConnectionFactory getConnectionFactory() { ... }?
public void setCciTemplate(CciTemplate cciTemplate) { ... }?
public CciTemplate getCciTemplate() { ... }?
}?
21.3.4. 自動輸出記錄生成?
如果所用的連接器只支持以輸入輸出記錄作為參數的 Interaction.execute(..) 方法 (就是說,它要求傳入期望的輸出記錄而不是返回適當的輸出記錄), 你可以設定 CciTemplate 類的 outputRecordCreator 屬性來自動生成一個輸出記錄, 當接收到響應時JCA連接器(JCA connector)將填充該記錄并返回給模板的調用者。?
因為這個目的,這個屬性只持有 RecordCreator 接口的一個實現。 RecordCreator 接口已經在 Section 21.3.1, “記錄轉換” 進行了討論。 outputRecordCreator 屬性必須直接在 CciTemplate 中指定,可以在應用代碼中做到這一點。?
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>?
Note?
因為 CciTemplate 類是線程安全的,所以它通常被配置為一個共享實例。?
21.3.5. 總結?
下表總結了 CciTemplate 類和在 CCI Interaction 接口上調用相應方法的機制:?
Table 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)?
21.3.6. 直接使用一個CCI Connection接口和Interaction接口?
類似于 JdbcTemplate 類和 JmsTemplate 類的操作方式, CciTemplate 類同樣提供直接操作CCI 連接和交互的可能性。 比如說如果你想對一個CCI連接執行多種操作,這就會很有用。?
ConnectionCallback 接口提供以CCI Connection 作為參數, 為了在它上面執行自定義動作,添加了創建 Connection 的CCI ConnectionFactory。 后者在獲取相關 RecordFactory 實例和創建indexed/mapped records時很有用。例如:?
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;?
}?
Note?
InteractionSpec 對象還可以在多個template調用之間被共享或者在每個回調方法內重新創建, 這完全取決于 DAO 的實現。?
21.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;?
}?
}?
正如之前討論的那樣,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;?
}?
}?
Note?
當getCciTemplate().execute參數是 ConnectionCallback 時, 所用的 Connection 將被 CciTemplate 管理和關閉, 但是任何在連接上建立的交互都必須被callback實現類所管理。?
對于一個更特殊的callback,你可以實現一個 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;?
}?
}?
在上面的例子中,非托管模式(non-managed)下對應的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環境)下,配置可能如下所示:?
<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>?
21.4. 建模CCI訪問為操作對象?
org.springframework.jca.cci.object 包中包含的支持類允許你以另一種風格訪問EIS: 通過可重用的操作對象,類似于Spring的JDBC操作對象(參見JDBC一章)。 它通常都封裝了 CCI 的API:將應用級的輸入對象傳入到操作對象, 從而它能創建輸入record然后轉換接收到的record數據到一個應用級輸出對象并返回它。?
注意: 這種方法內在地基于 CciTemplate 類和 RecordCreator / RecordExtractor 接口,重用了Spring核心CCI支持的機制。?
21.4.1. MappingRecordOperation?
MappingRecordOperation 本質上與 CciTemplate 做的事情是一樣的, 但是它表達了一個明確的、預配置(pre-configured)的操作作為對象。它提供了兩個模板方法來指明如何將一個輸入對象轉換為輸入記錄, 以及如何將一個輸出記錄轉換為輸出對象(記錄映射):?
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方法,傳遞一個應用級(application-level) 輸入對象,并接收一個應用級輸出對象作為結果:?
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);?
...?
21.4.2. MappingCommAreaOperation?
一些連接器使用了基于COMMAREA的記錄,該記錄包含了發送給EIS的參數和返回數據的字節數組。 Spring提供了一個專門的操作類用于直接操作COMMAREA而不是操作記錄。 MappingCommAreaOperation 類擴展了 MappingRecordOperation 類以提供這種專門的COMMAREA支持。 它隱含地使用了 CommAreaRecord類作為輸入和輸出record類型, 并提供了兩個新的方法來轉換輸入對象到輸入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;?
...?
}?
21.4.3. 自動生成輸出記錄?
由于每個 MappingRecordOperation 子類的內部都是基于 CciTemplate 的,所以 用 CciTemplate 以相同的方式自動生成輸出record都是有效的。 每個操作對象提供一個相應的 setOutputRecordCreator(..) 方法。 更多的信息,請參見前面的Section 21.3.4, “自動輸出記錄生成”一節。?
21.4.4. 總結?
操作對象方法使用了跟 CciTemplate 相同的方式來使用記錄。?
Table 21.2. Usage of Interaction execute methods?
MappingRecordOperation method signature MappingRecordOperationoutputRecordCreator property execute method called on the CCI Interaction?
Object execute(Object) not set Record execute(InteractionSpec, Record)?
Object execute(Object) set boolean execute(InteractionSpec, Record, Record)?
21.4.5. MappingRecordOperation 使用示例?
在本節中,將通過展示使用 Blackbox CCI 連接器訪問一個數據庫來說明 MappingRecordOperation 的用法。?
Note?
該連接器的最初版本是由SUN提供的J2EE SDK(1.3版本)。?
首先,必須在 CCI InteractionSpec 中進行一些初始化動作來指定執行哪些SQL請求。 在這個例子中,我們直接定義了將請求參數轉換為CCI record以及將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;?
}?
}?
然后應用程序會以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 beans的配置看起來類似于下面非托管模式(non-managed mode)的配置:?
<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>?
在托管模式(managed mode)(也就是說,在一個J2EE環境中)),配置可能看起來像這樣:?
<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>?
21.4.6. MappingCommAreaOperation 使用示例?
在本節中,將展示 MappingCommAreaOperation類的用法:通過IBM 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();?
? }?
}?
}?
The abstract EciMappingOperation class can then be subclassed to specify mappings between custom objects and Records.?
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 beans的配置看起來類似于下面非托管模式(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="MyDaoImpl">?
<property name="connectionFactory" ref="connectionFactory"/>?
</bean>?
在托管模式(managed mode)(也就是說,在一個J2EE環境中),配置可能看起來像這樣:?
<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>?
21.5. 事務?
JCA為資源適配器(resource adapters)指定了幾個級別的事務支持。 你可以在 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 為后端(委托給后面的J2EE分布式事務協調程序)。?
對于單獨CCI ConnectionFactory 上的本地事務, Spring為CCI提供了一個專門的事務管理策略, 類似于JDBC中的 DataSourceTransactionManager, CCI API定義了一個本地事務對象和相應的本地事務劃分方法。 Spring的 CciLocalTransactionManager 執行這樣的本地CCI事務, 完全依照Spring中常見的 PlatformTransactionManager 抽象。?
<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>?
聲明式或編程式的事務策略都能被用于任意的Spring事務劃分功能。 這是Spring通用的 PlatformTransactionManager 抽象的結果,它解耦了實際運行策略中的事務劃分。 你可以保持現在的事務劃分,只需要在 JtaTransactionManager 和 CciLocalTransactionManager 之間轉換即可。
轉載于:https://www.cnblogs.com/davidwang456/p/4482922.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的Spring 中JCA CCI分析--转载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Getting started with
- 下一篇: 分布式计算的模式语言读后感--基线架构