J2EE는 EIS(JCA(자바 연결자 아키텍쳐-Java Connector Architecture)) 에 대한 표준적인 접근을 위한 스펙을 제공한다. 이 스펙은 여러개의 다른 파트로 나뉜다.
SPI (서비스 제공자 인터페이스-Service provider interfaces) 는 연결자 제공자를 구현해야만 한다. 이러한 인터페이스는 J2EE애플리케이션 서버에 배치될수 있는 자원 어댑터를 구성한다. 이러한 상황에서, 서버는 connection pooling, 트랜잭션 과 보안(관리모드)을 다룬다. 애플리케이션 서버는 클라이언트 애플리케이션 외부에 유지되는 설정을 관리하는 책임을 진다. 연결자는 애플리케이션 서버가 없이도 잘 사용될수 있다. 이러한 경우, 애플리케이션은 직접(비-관리모드) 이것을 설정해야만 한다.
CCI (공통 클라이언트 인터페이스-Common Client Interface) 는 애플리케이션이 연결자와 상호작동하고 EIS와 통신하기 위해 사용할수 있다. local트랜잭션구분을 위한 API도 마찬가지로 제공된다.
Spring CCI 지원의 목적은 전형적인 Spring스타일로 Spring의 일반적인 자원과 트랜잭션 관리 기능에 영향력이 미치는 CCI연결자에 접근하는 클래스를 제공하는 것이다.
연결자의 클라이언트측은 언제나 CCI를 사용하는것은 아니다. 몇몇 연결자는 그들 자신만의 API를 가지고, J2EE컨테이너의 시스템 계약(connection pooling, 전역 트랜잭션및 보안)을 사용하기 위한 JCA자원 어댑터만을 제공한다. Spring은 이러한 연결자에 종속적인 API를 위한 특별한 지원은 하지 않는다.
JCA CCI를 사용하기 위한 기본 자원은 ConnectionFactory 인터페이스이다. 사용되는 연결자는 이 인터페이스의 구현물을 제공해야만 한다.
당신의 연결자를 사용하기 위해, 당신은 애플리케이션 서버로 이것을 배치하고 서버의 JNDI환경(관리모드)으로부터 ConnectionFactory를 가져올수 있다. 연결자는 RAR파일(자원 어댑터 압축파일)처럼 패키징되어야만 하고 배치속성을 언급하기 위한 ra.xml 파일을 포함해야만 한다. 자원의 실질적인 이름은 당신이 배치할때 명시된다. Spring에서 이것에 접근하기 위해서, JNDI명으로 factory를 가져오기 위한 Spring의 JndiObjectFactoryBean를 간단히 사용하라.
연결자를 사용하기 위한 다른 방법은 이것을 배치하고 설정하기 위한 애플리케이션 서버를 사용하지 않고 당신의 애플리케이션에 이것을 내장하는 것이다(비-관리모드). Spring은 제공되는 FactoryBean (LocalConnectionFactoryBean)을 통해 bean처럼 연결자를 설정하는 것이 가능하다. 이 방법으로, 당신은 classpath내 연결자 라이브러리를 둘 필요가 있다(RAR파일과 ra.xml 설명자를 둘 필요가 없다). 필요하다면 라이브러리는 연결자의 RAR파일로부터 추출해야만 한다.
ConnectionFactory 인스턴스로 접근했다면, 당신은 이것을 컴포넌트로 삽입할수 있다. 이러한 컴포넌트는 명백한 CCI API에 대해 코딩되거나 CCI접근을 위한 Spring지원 클래스(이를테면, CciTemplate)에 영향을 끼칠수 있다.
비-관리 모드에서 연결자를 사용할때, 당신은 전역 트랜잭션을 사용할수 없다. 자원이 현재 쓰레드의 현재 전역 트랜잭션에 결코 리스트화되거나 리스트에사 빠지지 않을것이다. 자원은 단순히 수행중인 전역 J2EE트랜잭션을 인지하지 않는다.
EIS를 위한 connection을 만들기 위해, 먄약 당신이 관리모드에 있다면 당신은 애플리케이션 서버로부터 ConnectionFactory를 얻거나 비-관리모드에 있다면 Spring으로부터 직접 ConnectionFactory를 얻을 필요가 있다.
관리 모드에서, 당신은 JNDI로부터 ConnectionFactory에 접근한다. 이것의 프라퍼티는 애플리케이션 서버에 설정될것이다.
<bean id="eciConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean"> <property name="jndiName" value="eis/cicseci"/> </bean>
비-관리모드에서, 당신은 Spring설정내에서 사용하길 원하는 ConnectionFactory를 JavaBean처럼 설정해야만 한다. 당신 연결자의 ManagedConnectionFactory구현물로 전달하는 이러한 셋업 스타일을 제공하는 LocalConnectionFactoryBean 클래스는 애플리케이션-레벨의 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스펙의 일부이다. |
JCA CCI는 개발자엑 연결자의 ConnectionSpec 구현물을 사용하여 EIS에 대한 연결을 설정하도록 해준다. 이것의 프라퍼티를 설정하기 위해, 당신은 전용 어댑터를 가진 목표 connection factory인 ConnectionSpecConnectionFactoryAdapter를 포장할 필요가 있다. 그래서 전용 ConnectionSpec은 connectionSpec 프라퍼티로 설정(내부 bean처럼)될수 있다.
이 프라퍼티는 CCI ConnectionFactory인터페이스가 CCI connection을 얻기 위한 서로 다른 두개의 메소드를 정의하기 때문에 필수가 아니다. 몇몇 ConnectionSpec 프라퍼티는 애플리케이션 서버나 관련된 local ManagedConnectionFactory구현물에서 설정될수 있다.
public interface ConnectionFactory implements Serializable, Referenceable { ... Connection getConnection() throws ResourceException; Connection getConnection(ConnectionSpec connectionSpec) throws ResourceException; ... }
Spring은 주어진 factory에서 모든 작업을 위해 사용하는 ConnectionSpec 인스턴스를 명시하는 ConnectionSpecConnectionFactoryAdapter를 제공한다. 어댑터의 connectionSpec프라퍼티가 명시된다면, 어댑터는 인자가 없거나 ConnectionSpec인자를 가지는 getConnection 의 다른 형태를 사용한다.
<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>
하나의 CCI connection을 사용하길 원하다면, Spring은 이것을 관리하기 위한 더 나은 ConnectionFactory 어댑터를 제공한다. SingleConnectionFactory 어댑터는 하나의 connection을 늦게(lazy) 열고 이 bean이 애플리케이션 종료시점에 사라질때 닫힌다. 이 클래스는 기본적인 같은 물리적 connection을 공유하는 특별한 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로 직접 설정될수 없다. SingleConnectionFactory가 당신이 하나의 connection을 요구하는지를 알리는 중계수단의 ConnectionSpecConnectionFactoryAdapter를 사용하라. |
JCA CCI지원의 목적중 하나는 CCI레코드를 변경하기 위한 편리한 기능을 제공하는 것이다. 개발자는 Spring의 CciTemplate을 사용하기 위해 레코드를 생성하고 레코드로부터 데이터를 추출하기 위한 전략을 명시할수 있다. 다음의 인터페이스는 당신이 애플리케이션에 직접 레코드를 가지고 작업하길 원하지 않는다면 입력및 출력 레코드를 사용하기 위한 전략을 설정할것이다.
입력 Record를 생성하기 위해, 개발자는 RecordCreator인터페이스의 전용 구현물을 사용할수 있다.
public interface RecordCreator { Record createRecord(RecordFactory recordFactory) throws ResourceException, DataAccessException; }
당신이 볼수 있는것처럼, createRecord 메소드는 사용되는 ConnectionFactory의 RecordFactory에 관련되는 파라미터로 RecordFactory인스턴스를 가진다. 이 참조는 IndexedRecord 인스턴스나 MappedRecord인스턴스를 생성하기 위해 사용될수 있다. 다음의 샘플은 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인터페이스의 특정 구현물은 출력 Record로부터 데이터를 추출하기 위한 Spring의 CciTemplate로 전달될수 있다.
public interface RecordExtractor { Object extractData(Record record) throws ResourceException, SQLException, DataAccessException; }
다음의 샘플은 RecordExtractor를 사용하는 방법을 보여준다.
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); } }
CciTemplate은 핵심 CCI지원 패키지(org.springframework.jca.cci.core)의 중심 클래스이다. 이것은 자원의 생성과 반환을 다루기 때문에 CCI의 사용을 단순화한다. 이것은 connection을 닫는것을 잊었을때와 같이 공통적인 에러를 피하도록 도와준다. connection의 생명주기와 객체간의 상호작동을 다루고 애플리케이션 데이터로부터 입력 레코드를 생성하고 출력 레코드로부터 애플리케이션 데이터를 추출하는 것에 집중하는 애플리케이션 코드를 둔다.
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은 상호작동에서 호출하기 위한 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 프라퍼티가 템플릿에 셋팅되지 않는다면, 모든 메소드는 두개의 파라미터(InteractionSpec 과 입력 Record)를 가지고 CCI Interaction의 반환값으로 출력 Record를 가지는 execute 메소드를 호출할것이다.
CciTemplate 은 createIndexRecord 와 createMappedRecord메소드를 통해 RecordCreator 구현물 외부에서 IndexRecord 와 MappedRecord을 생성하는 메소드를 제공한다. 이것은 적절한 CciTemplate.execute 메소드에 전달하기 위한 Record인스턴스를 생성하는 DAO구현물내에서 사용될수 있다.
public class CciTemplate implements CciOperations { ... public IndexedRecord createIndexedRecord(String name) throws DataAccessException { ... } public MappedRecord createMappedRecord(String name) throws DataAccessException { ... } ... }
Spring이 CCI지원은 ConnectionFactory 인스턴스나 CciTemplate인스턴스의 삽입을 지원하는 DAO를 위한 추상 클래스를 제공한다. 클래스명은 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() { ... } ... }
사용되는 연결자는 단지 파라미터로 입력및 출력 레코드를 가지는 Interaction.execute 메소드만을 지원한다(이것은 적절한 출력 레코드를 반환하는 대신에 전달되도록 기대하는 출력 레코드를 요구한다.). 당신은 응답을 가져왔을때 JCA연결자에 의해 채워지는 출력 레코드를 자동으로 생성하는 CciTemplate의 outputRecordCreator 프라퍼티를 볼수 있다. 이 레코드는 템플릿의 호출자로 반환될것이다.
이 프라퍼티는 RecordCreator의 구현물을 가진다. RecordCreator인터페이스는 이미 이전 부분에서 언급되었다. outputRecordCreator프라퍼티는 CciTemplate에서 직접 명시되어야만 한다. 이것은 애플리케이션 코드에서 수행될수 있다.
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>
![]() | Note |
---|---|
CciTemplate 클래스가 쓰레드에 안전한것처럼, 이것은 공유 인스턴스처럼 설정될것이다. |
다음의 테이블은 CciTemplate와 CCI Interaction 인터페이스에서 호출되는 대응 메소드의 기법을 개략적으로 설명한다.
Table 21.1. Interaction execute 메소드의 사용법
CciTemplate 메소드 시그너처 | CciTemplate outputRecordCreator 프라퍼티 | CCI Interaction에서 호출되는 execute메소드 |
---|---|---|
Record execute(InteractionSpec, Record) | 셋팅안됨 | Record execute(InteractionSpec, Record) |
Record execute(InteractionSpec, Record) | 셋팅됨 | boolean execute(InteractionSpec, Record, Record) |
void execute(InteractionSpec, Record, Record) | 셋팅안됨 | void execute(InteractionSpec, Record, Record) |
void execute(InteractionSpec, Record, Record) | 셋팅됨 | void execute(InteractionSpec, Record, Record) |
Record execute(InteractionSpec, RecordCreator) | 셋팅안됨 | Record execute(InteractionSpec, Record) |
Record execute(InteractionSpec, RecordCreator) | 셋팅됨 | void execute(InteractionSpec, Record, Record) |
Record execute(InteractionSpec, Record, RecordExtractor) | 셋팅안됨 | Record execute(InteractionSpec, Record) |
Record execute(InteractionSpec, Record, RecordExtractor) | 셋팅됨 | void execute(InteractionSpec, Record, Record) |
Record execute(InteractionSpec, RecordCreator, RecordExtractor) | 셋팅안됨 | Record execute(InteractionSpec, Record) |
Record execute(InteractionSpec, RecordCreator, RecordExtractor) | 셋팅됨 | void execute(InteractionSpec, Record, Record) |
CciTemplate 은 JdbcTemplate 과 JmsTemplate처럼 같은 방법으로 CCI connections 과 interactions을 가지고 직접 작동하는것이 가능하다. 예를 들어, 이것은 당신이 CCI connection 이나 interaction에서 다중 작업을 수행하길 원할때 유용하다.
인터페이스 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; }
![]() | Note |
---|---|
InteractionSpec 객체는 다중 템플릿 호출을 통해 공유될수 있고 모든 콜백 메소드내부에서 새롭게 생성될수 있다. 이것은 DAO구현을 완벽하게 한다. |
이 부분에서, 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 connections 이나 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 { ... } }); } return output; } }
![]() | Note |
---|---|
사용되는 ConnectionCallback을 가지고, Connection은 CciTemplate에 의해 관리되고 닫힐것이다. 하지만 connection에서 생성된 interaction은 콜백 구현물에 의해 관리되어야만 한다. |
특정 콜백에 대한 좀더 많은 정보를 위해, 당신은 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>
관리모드(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>
org.springframework.jca.cci.object 패키지는 Spring의 JDBC작업 객체와 비슷한 재사용가능한 작업객체를 통해 다른 스타일로 EIS에 접근하도록 허용하는 지원 클래스를 포함한다. 이것은 언제나 CCI API를 캡슐화할것이다. 애플리케이션 레벨의 입력 객체는 작업객체로 전달될것이다. 그래서 이것은 입력 레코드를 생성하고 가져온 레코드 데이터를 애플리케이션 레벨 출력 객체로 변환하고 이것을 반환한다.
![]() | Note |
---|---|
이 접근법은 내부적으로 CciTemplate클래스와 RecordCreator / RecordExtractor 인터페이스에 기초한다. Spring의 핵심 CCI지원의 장치를 재사용한다. |
MappingRecordOperation는 기본적으로 CciTemplate과 같은 작업을 수행하지만, 객체로 특별하고 미리 설정된 작업을 표시한다. 이것은 입력 객체를 입력 레코드를 변환하는 방법과 출력 레코드를 출력 객체로 변환하는 방법(레코드 맵핑)을 명시하는 두개의 템플릿 메소드를 제공한다.
입력 객체를 입력 Record로 변환하는 방법을 명시하는 createInputRecord
출력 Record로 부터 출력 객체를 추출하는 방법을 명시하는 extractOutputData
이것은 이러한 메소드의 시그너처이다.
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); ...
몇몇 연결자는 EIS에 보내는 파라미터와 이것에 의해 반환되는 데이터를 포함하는 바이트의 배열을 표시하는 COMMAREA에 기초한 레코드를 사용한다. Spring은 레코드보다 COMMAREA에 직접 작동하기 위한 특별한 작업 클래스를 제공한다. MappingCommAreaOperation클래스는 특별한 COMMAREA지원을 제공하기 위한 MappingRecordOperation을 확장한다. 이것은 입력및 출력 레코드 타입으로 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; ... }
모든 MappingRecordOperation 하위클래스가 내부적으로 CciTemplate에 기초하는것처럼, CciTemplate에서처럼 자동으로 출력 레코드를 생성하기 위한 같은 방법은 사용가능하다. 모든 작업 객체는 대응하는 setOutputRecordCreator메소드를 제공한다. 좀더 많은 정보를 위해, 이전의 "자동 출력 레코드 생성" 부분을 보라.
작업 객체 접근법은 CciTemplate클래스처럼 같은 방법으로 레코드를 사용한다.
이 부분에서, MappingRecordOperation의 사용이 블랙박스 CCI연결자를 가지고 데이터베이스에 접근하는 것을 보여줄것이다.
![]() | Note |
---|---|
이 연결자의 원래의 버전은 Sun에서 사용가능한 J2EE 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; } }
그리고 나서 애플리케이션은 인자로 person id를 가지는 작업객체를 수행할수 있다. 작업객체는 공유 인스턴스이고 쓰레드에 안전한것처럼 셋업될수 있다.
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>
관리 모드(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>
이 부분에서, IBM CICS ECI연결자로 ECI모드에서 CICS접근하는 MappingCommAreaOperation의 사용을 보여줄것이다.
첫번째, 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>
관리모드(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>
JCA는 자원 어댑터를 위한 다양한 레벨의 트랜잭션 지원을 명시한다. 당신의 자원 어댑터가 지원하는 종류의 트랜잭션은 ra.xml파일에 명시된다. 여기엔 3개의 선택사항이 있다. none (CICS EPI 연결자의 예제를 위해), local 트랜잭션 (CICS ECI 연결자의 예제를 위해), global 트랜잭션 (IMS 연결자의 예제를 위해).
<connector> ... <resourceadapter> ... <!-- transaction-support>NoTransaction</transaction-support --> <!-- transaction-support>LocalTransaction</transaction-support --> <transaction-support>XATransaction</transaction-support> ... <resourceadapter> ... <connector>
global트랜잭션을 위해, 당신은 JtaTransactionManager로 트랜잭션을 구분하는 Spring의 일반적인 트랜잭션 구조를 사용할수 있다(J2EE서버의 분산 트랜잭션 조정자에 위임한다.).
하나의 CCI ConnectionFactory에서 local트랜잭션을 위해, Spring은 JDBC를 위한 DataSourceTransactionManager와 유사한 CCI를 위한 특정 트랜잭션 관리 전략을 제공한다. CCI API는 local트랜잭션 객체와 대응되는 local트랜잭션 구분 메소드를 정의한다. Spring의 CciLocalTransactionManager는 Spring의 일반적인 PlatformTransactionManager추상화와 완벽하게 호환되는 local CCI트랜잭션을 수행한다.
<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를 간단히 교체하라.
Spring의 트랜잭션 기능에 대한 좀더 많은 정보를 위해서, 트랜잭션 관리를 보라.