Spring프레임워크는 J2EE Connector Architecture (JCA)를 통해 1.2.1버전이후 CICS와 같은 시스템을 위한 지원을 제공하고 있다. Spring프레임워크는 CCI(Common Client Interface) API를 사용하여 CICS에서 사용되는 connectors 를 위한 가볍고 혁신적인 지원을 제공한다.

J2EE Connector Architecture#

JCA는 자바를 사용하는 EIS (enterprise information system)에 접근하는 방법을 명시한다. 이 명시엔 두가지 버전이 있다.
  • 버전 1.0: EIS에 outbound 메시지만을 할당한다. 이것은 클라이언트와 connector사이의 상호작용을 표준화한다. 그리고 connector와 provider사이를 연결하고 풀링과 트랜잭션 그리고 보안 서비스를 제공한다.(이 문서는 1.0버전을 기준으로 서술된다)
  • 버전 1.5: 이전 버전에 기초를 두고, EIS에 대한 inbound메시지를 소개해서 시스템은 connector을 콜백할수 있다.

JCA 1.0은 다음과 같은 두개의 주요 부분으로 나뉜다.

  • 클라이언트와 connector의 상호작용 : connector구현물은 사용할 클라이언트 API를 선택한다. 이것은 JCA스펙에서 언급되는 전용의 것이나 CCI API가 될수 있다. 예를 들면 JDBC DataSource 또는 Hibernate SessionFactory가 JCA connector으로 드러날수 있다.
  • connector와 서비스 제공자의 상호작용 : IBM CICS connectors는 클라이언트처럼 CCI API를 사용한다. 이것의 factory추상화는 JDBC를 위한 DataSource추상화와 유사한 ConnectionFactory인터페이스이다. 이것은 클라이언트 애플리케이션이 EIS와의 연결을 생성하도록 한다.

당신은 두가지 방법중에 하나를 선택할수 있다.

  • connector가 배치된 애플리케이션 서버의 JNDI로 부터. 이 경우 connector는 이것의 서비스(풀링, 트랜잭션, 그리고 보안)를 사용할수 있고 관리모드에서 사용된다.
  • connector의 ManagedConnectionFactory인터페이스 구현물의 설정된 인스턴스로 부터 직접적으로. 이 경우 createConnectionFactory()메소드를 가진 ConnectionFactory를 생성할때 ConnectionManager구현물이 명시되지 않는다면 connector는 비-관리모드에서 사용된다.

다음은 CCI API를 사용하는 요청의 일반적인 수행을 보여주고 있다.

01     ConnectionFactory connectionFactory = getConnectionFactory();
02     Connection connection = null;
03     Interaction interaction = null;
04     try {
05       connection = connectionFactory.getConnection();
06       interaction = connection.createInteraction();
07       InteractionSpec iSpec = createInteractionSpec();
08       Record inputRecord = createRecord();
09       populateInputRecord(inputRecord);
10       Record outputRecord = createRecord();
11       interaction.execute(iSpec, inputRecord, outputRecord);
12     catch (ResourceException ex) {
13       // Manage the exceptions
14     finally {
15       closeInteraction(interaction);
16       closeConnection(connection);
17     }

라인 1에서, ConnectionFactory인터페이스의 인스턴스를 선택된 전략에 의존해서 가져온다.
라인 5에서, EIS와의 연결이 생성되고 작업을 수행하기 위해 상호작동한다.
라인 7에서, InteractionSpec의 인스턴스는 작업을 파라미터화하기 위해 생성된다.
라인 8와 9에서, 입력, 출력 레코드가 EIS로부터 데이터를 보내고 받기위해 생성된다.
라인 11에서, 요청은 실질적으로 수행되고 출력 레코드는 EIS로부터 받은 데이터로 활성화된다.
라인 15와 16에서, 애플리케이션은 예외발생 유무에 상관없이 모든 생성된 자원을 반환해야만 한다.

이 시점에서 Spring의 JCA지원은 JCA의 클라이언트 부분에만 할당되고 당신에게 CCI API를 사용하도록 돕는다. LocalConnectionFactoryBean클래스는 비-관리모드내 connector를 설정하기 위해 제공된다. 그럼에도 불구하고 지원은 LocalConnectionFactoryBean클래스내 ConnectionManager인터페이스의 구현물을 삽입하여 J2EE애플리케이션 서버밖에서 관리모드내 connector를 설정하기 위해 사용될수 있다.

JCA지원은 Spring의 JDBC프레임워크와 유사하다. 첫번째 목적은 사용되는 factory의 설정을 추상화하고 작업하는 개발자로 하여금 사용가능하도록 허용하기 위해 CCI API의 사용을 단순화한다.

다음 그림은 JCA를 사용하는 애플리케이션의 다른 컴포넌트와 관리모드및 비-관리모드내 상호작용을 보여준다. JCA-호환 connector의 자원 어댑터, 애플리케이션 서버의 서비스, 사용되는 connector의 클라이언트 API, 그리고 Spring의 JCA지원

1.gif

Spring의 JCA지원은 두가지 기능을 가진다. 첫번째는 connector의 설정을 할당한다. 관리모드에서 개발자는 ConnectionFactory를 표현하는 JNDI이름을 가리킬수만 있고 connector는 다음의 목록2처럼 Spring의 JndiObjectFactoryBean으로 애플리케이션 서버내 설정된다.

<bean id="connectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
   <property name="jndiName"><value>eis/cicseci</value></property>
</bean>

만약 당신이 비-관리모드내 connector을 사용하도록 선택한다면, 당신은 목록 3처럼 ManagedConnectionFactory인터페이스의 connector구현물로 Spring내 connector을 완전하게 설정해야만 한다.

<bean id="managedConnectionFactory" class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
       ...
</bean>

<bean id="connectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
  <property name="managedConnectionFactory">
            <ref local="managedConnectionFactory" />
      </property>
</bean>

Spring의 JCA지원의 두번째 기능은 애플리케이션 특성의 작업에 집중할수 있는 개발자로부터 반복적이거나 에러를 발생시키는 경향이 있는 코드를 숨기는 CCI API의 사용을 할당한다.

  • InteractionSpec인터페이스의 connector구현물로 EIS요청을 설정하기
  • 하나 또는 그 이상의 파라미터로부터 입력 레코드를 생성하는 방법을 결정하기
  • 출력 레코드로부터 데이터를 추출하거나 반환된 객체를 활성화시키는 방법을 결정하기

Spring은 당신이 필요하다면 명시적으로 CCI레코드를 사용하여 작업하도록 한다.

위 작업을 완성하기 위해 Spring의 JCA지원은 두가지 접근법을 제공한다.

  • 템플릿 기반의 접근법 : 애플리케이션은 EIS의 요청을 수행하기 위해 CciTemplate클래스를 사용해야만 하고 생성자(creator)와 콜백 인터페이스로 각각의 호출을 설정할수 있다.
  • 객체 기반의 접근법 : 애플리케이션은 MappingRecordOperation추상 클래스를 상속하여 객체로 작동을 생성해야만 한다. Spring의 JCS지원은 CICS처럼 commarea에 기반한 작동을 위해 MappingCommAreaOperation하위클래스를 제공한다.

목록 4는 템플릿 기반의 접근법을 사용하는 목록 1로부터 같은 코드를 보인다.

01     ECIInteractionSpec interactionSpec = new ECIInteractionSpec();
02     interactionSpec.setFunctionName("LOGIPROG");
03     interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
04 
05     getCciTemplate().execute(interactionSpec, new RecordCreator() {
06       public Record createRecord(RecordFactory recordFactorythrows ResourceException, DataAccessException {
07         // Create the record with the parameters
08       }
09     }new RecordExtractor() {
10       public Object extractData(Record recordthrows ResourceException, SQLException, DataAccessException {
11         // Extract the data from the record
12       }
13     });

목록 5는 객체기반의 접근법을 보여준다.

01 public abstract class ECIMappingOperation extends MappingRecordOperation {
02   public ECIMappingQuery(ConnectionFactory connectionFactory, String programName) {
03     setConnectionFactory(connectionFactory);
04     ECIInteractionSpec interactionSpec = new ECIInteractionSpec();
05     // Initialize the interaction spec
06     setInteractionSpec(interactionSpec);
07     setOutputRecordCreator(new ECIOutputRecordCreator());
08   }
09 
10   private class ECIOutputRecordCreator implements RecordCreator {
11     public Record createRecord(RecordFactory recordFactorythrows ResourceException, DataAccessException {
12       // Returns a Record that will be used for output
13     }
14   }
15 }

목록 6은 목록 5내에서 생성된 작동 객체의 사용을 보여준다.

01 ECIMappingOperation query=new ECIMappingQuery(getConnectionFactory(),"LOGIPROG") {
02      protected Record createInputRecord(RecordFactory recordFactory,
03                Object inputObjectthrows ResourceException, DataAccessException {
04         // Create the record with the parameters
05      }
06 
07      protected Object extractOutputData(Record outputRecord)
08                       throws ResourceException, SQLException, DataAccessException {
09         // Extract the data from the record
10     }
11 });
12 return query.execute(input);

나는 지금 CICS connector를 사용하여 Spring의 JCA지원을 사용하는 방법의 견고한 예제를 언급한다.

CICS에 접근하기 위한 구조와 요구되는 애플리케이션은 그림 2에서 보여진다.

2.gif

그림 2는 CICS가 다른 자원에 접근하는것을 허용하는것을 보여준다.

  • 트랜잭션 : 3270개의 스크린(또는 터미널)을 표현하고 그러한 스크린간의 상호작용을 하는 방법을 하는 프리젠테이션 프로그램에 기반한다. 이러한 종류의 프로그램은 데이터를 표시하기 위한 몇몇 비지니스 로직 프로그램을 호출할수 있다. CICS를 사용하여 트랜잭션에 접근하기 위한 인터페이스는 EPI(외부적 프리젠테이션 인터페이스)이다.
  • 프로그램 : 처리를 수행한다. 프로그램이 구현하는 트랜잭션은 직접적으로 호출될수 없다는 것에 주의하라. 오직 commarea기반 프로그램만이 할수 있다. CICS를 사용하여 트랜잭션에 접근하기 위한 인터페이스는 ECI(외부적 호출 인터페이스)이다.

그림 2는 TCP62 정취자(listener)가 이 프로토콜을 사용하여 통신하기 위한 원격 클라이언트를 허용하도록 CICS가 설정되어야만 한다는것을 강조한다. 추가적으로, IBM CICS connector가 CICS클라이언트처럼 게이트웨이모드나 직접적으로 사용될수 있는 CICS Transaction Gateway에 기반을 둔다. 이러한 connector는 ECI와 EPI호출을 모두 지원하는 CTG API를 포장한다. CTG는 J2EE애플리케이션과 CICS사이의 우회(indirection)의 레벨을 제공한다. 사실, 이것은 실제 CICS이름 대신에 클라이언트에 의해 사용되는 모든 CICS를 위한 로직적인 이름을 정의한다. 마지막으로, 그림 2에서, 우리는 IBM CICS connector의 클라이언트 부분이 CCI기반인것을 볼수 있다. 게다가 Spring의 JCS지원은 이러한 종류의 connector를 위해 사용될수 있다.

CICS프로그램과 교환되는 메시지가 commarea에 기반하는것처럼(바이트배열은 프로그램에 보내는 요청 데이터와 이것으로부터 받는 응답 데이터 모두를 표현한다.), JCA레코드는 이 commarea를 표현하는 바이트배열에 기초를 두어야만 한다. Spring의 JCA지원은 전용 레코드 구현물(CommAreaRecord클래스)을 제공한다.

다음 부분에서, 나는 connector의 설정과 Spring의 JCA로 CICS프로그램을 호출하는 방법을 보여준다.

시작하기 위해 애플리케이션 서버나 Spring내에서 선택한 모드에 의존하여 IBM CICS ECI connector를 설정하자. XA트랜잭션의 사용은 비-관리모드에서는 허용되지 않는다. 하지만 우리의 경우 connector가 로컬 트랜잭션만을 지원하도록 사용하기 때문에 문제가 되지 않는다.

이 글에서, 우리는 비-관리모드에서 설정한다.

이전에 언급된것처럼, 설정은 connector는 ManagedConnectionFactory인터페이스 구현물을 사용하여 완성된다. IBM CICS ECI connector을 위한 파라미터는 아래와 같다.

파라미터 이름 파라미터 설명
serverName CICS의 이름, 이 이름은 ctg.ini설정파일내 CICS를 위한 논리적인 이름을 참조한다.
connectionURL CTG에 접근하기 위한 connection URL. 만약 애플리케이션이 게이트웨이 모드에서 사용되지 않는다면 이 값은 local:, 이나 tcp://<host>:<port>가 되어야만 한다.
userName 인증을 위한 사용자명
password 사용자의 비밀번호
Spring내에서 connector의 설정은 목록 7에서 보여진다.

<bean id="eciManagedConnectionFactory"        class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
     <property name="serverName">
          <value>TXSERIES</value>
 </property>
   <property name="connectionURL">
               <value>local:</value>
   </property>
   <property name="userName">
            <value>CICSUSER</value>
 </property>
   <property name="password">
            <value>CICS</value>
     </property>
</bean>

<bean id="eciConnectionFactory" class="org.springframework.jca.support.LocalConnectionFactoryBean">
 <property name="managedConnectionFactory">
            <ref local="eciManagedConnectionFactory" />
   </property>
</bean>

CICS프로그램에 접근하기 위한 컴포넌트를 개발하기 위해, 우리는 객체-기반 접근법을 사용한다. 게다가, 우리는 수행하기 위한 요청의 설정을 숨기기 위한 추상 클래스를 생성할 필요가 있다. 사용자는 호출하기 위한 프로그램의 이름만을 줄것이다.

MappingCommAreaOperation는 목록 8에서 보여지는 것처럼 레코드로부터 commarea를 표현하는 바이트배열로 추출하기 위해 사용된다. 게다가 애플리케이션은 바이트 배열로/부터 객체의 변환을 직접적으로 할당할수 있다. 레코드는 CommAreaRecord클래스에 의해 구현된다.

01 public abstract class ECIMappingOperation extends MappingCommAreaOperation {
02 
03   public ECIMappingOperation(ConnectionFactory connectionFactory, String programName, int responseLength) {
04     setConnectionFactory(connectionFactory);
05     ECIInteractionSpec interactionSpec = new ECIInteractionSpec();
06     interactionSpec.setFunctionName(programName);
07     interactionSpec.setCommareaLength(responseLength);
08     doSetInteractionVerb(interactionSpec);
09     setInteractionSpec(interactionSpec);
10     setOutputRecordCreator(new ECIOutputRecordCreator());
11   }
12 
13   private void doSetInteractionVerb(ECIInteractionSpec interactionSpec) {
14     try {
15       interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
16     catch (ResourceException ex) {
17       ex.printStackTrace();
18     }
19   }
20 
21   private class ECIOutputRecordCreator implements RecordCreator {
22     public Record createRecord(RecordFactory recordFactorythrows ResourceException, DataAccessException {
23       return new CommAreaRecord();
24     }
25   }
26 }

클래스 생성자에서, 우리는 첫번째 사용할 connection factory를 셋팅하고(라인 5) connector의 InteractionSpec를 설정한다(라인 6에서 10까지). 다음으로 IBM CICS ECI connector는 출력 레코드를 인스턴스화하기 위해 사용하기 때문에, 우리는 출력 레코드를 자동적으로 생성하기 위해 사용될 outputRecordCreator프라퍼티를 셋팅해야만 한다(라인 11). 그 다음, 우리는 Spring기능이 삽입되어야만 하는 ConnectionFactory가 설정된 컴포넌트내 프로그램을 호출하는 목록 9에서 보여지는 클래스를 사용한다.

01 public class CustomersCciEciDaoImpl extends CciDaoSupport implements CustomersCciEciDao {
02   public Customer getCustomer(final int customerId) {
03     ECIMappingOperation operation = new ECIMappingOperation(getConnectionFactory()"LOGIPROG"55) {
04       protected byte[] objectToBytes(Object inObjectthrows IOException, DataRetrievalFailureException {
05         return (String.valueOf((IntegercustomerId)).getBytes();
06       }
07 
08       protected Object bytesToObject(byte[] bytesthrows IOException, DataRetrievalFailureException {
09         String chaine = new String(bytes);
10         int customerId = Integer.parseInt(chaine.substring(05));
11         String customerLastName = chaine.substring(530);
12         String customerFirstName = chaine.substring(3055);
13         Customer customer = new Customer(customerId, customerLastName, customerFirstName);
14         return customer;
15       }
16     };
17     return (Customeroperation.execute(new Integer(customerId));
18   }
19 }

라인 6의 메소드 objectToBytes()는 입력 객체로부터 바이트배열의 생성을 허용한다. 배열은 commarea기반 레코드내에서 캡슐화될것이다. 반면에 메소드 bytesToObject()는 바이트배열로 부터 데이터의 추출을 허용하고 출력 객체를 활성화한다. 라인 22에서 작동을 수행한다.

목록 10은 관련된 컴포넌트 설정을 보여준다.

<bean id="eciDao" class="javaworld.jca.CustomersCciEciDao">
   <property name="connectionFactory">
      <ref local="eciConnectionFactory"/>
   </property>
</bean>

끝내기 위해, Spring의 JCA지원은 CciLocalTransactionManager클래스로 CCI기반의 로컬 트랜잭션을 관리하기 위한 Spring의 PlatformTransactionManager인터페이스의 전용 구현물을 제공한다. Spring의 트랜잭션관리가 통합된것처럼 당신은 다른 기술들처럼 트랜잭션을 사용할수 있다. 당신은 오직 트랜잭션 관리자를 삽입할 필요가 있다.

Add new attachment

Only authorized users are allowed to upload new attachments.

List of attachments

Kind Attachment Name Size Version Date Modified Author Change note
gif
1.gif 18.4 kB 1 04-Feb-2006 17:11 이동국
gif
2.gif 18.1 kB 1 04-Feb-2006 17:11 이동국
« This page (revision-6) was last changed on 06-Apr-2006 09:45 by 이동국