WebTJCA API

본 절에서는 Outbound 통신을 개발하기 위해서 CCI를 구현한 WebTJCA API를 설명한다.

1. CCI

CCI는 리소스 어댑터를 사용하기 위한 표준 클라이언트 API를 정의한 스펙이다. 사용자는 CCI를 이용하여 다양한 리소스 어댑터에 대해서도 동일한 애플리케이션 코드를 생성할 수 있다.

JCA 스펙에서 CCI는 필수 구현 조건은 아니다. 사용자는 CCI를 이용해서 서비스를 호출해도 무방하지만 업체마다 고유의 스펙으로 애플리케이션을 작성해도 된다.

스펙에서 구현해야 할 인터페이스는 다음과 같다. WebTJCA에서는 다음의 CCI를 이용해서 애플리케이션을 구현할 수 있다.

  • 애플리케이션에서 생성할 Connection 관련 인터페이스

    • javax.resource.cci.connectionFactory

    • javax.resource.cci.Connection

    • javax.resource.cci.ConnectionSpec

    • javax.resource.cci.LocalTransaction

  • EIS와 상호 동작을 위한 인터페이스

    • javax.resource.cci.Interaction

    • javax.resource.cci.InteractionSpec

  • Inflow 구조에서 Message Driven Bean에서 구현할 메시지 리스너(Message listener) 인터페이스

    • javax.resource.cci.MessageListener

  • EIS와 주고받는 데이터를 표현하기 위한 인터페이스

    • javax.resource.cci.Record

    • javax.resource.cci.MappedRecord

    • javax.resource.cci.IndexedRecord

    • javax.resource.cci.RecordFactory

    • javax.resource.cci.Streamable

    • javax.resource.cci.ResultSet

    • java.sql.ResultSetMetaData

  • 리소스 어댑터 구현과 EIS Connection에 관한 기본 정보를 제공하는 메타데이터 관련 인터페이스

    • javax.resource.cci.ConnectionMetaData

    • javax.resource.cci.ResourceAdapterMetaData

    • javax.resource.cci.ResultSetInfo

  • 추가 인터페이스

    • javax.resource.ResourceException

    • javax.resource.cci.ResourceWarning

인터페이스의 메소드는 JDK JavaDoc을 참고한다.

1.1. Connection 관련 API

리소스 어댑터를 디플로이한 이후에는 사용자는 JNDI를 이용하여 ConnectionFactory를 참고할 수 있으며 ConnectionFactory를 이용하여 Connection을 생성할 수 있다. getConnection()을 호출할 때 새로운 Connection을 생성하거나 이미 생성한 Connection을 반환한다.

다음은 WebTJCA의 Connection 사용 예제이다.

ConnectionFactory connFactory = (ConnectionFactory)ctx.lookup("TmaxConnector");
Connection conn = connFactory.getConnection();

1.2. 서비스 요청을 위한 API

서비스 요청을 하기 위한 Interaction 인터페이스는 Connection 인터페이스에서 생성한다. 어떤 서비스를 호출할 지는 InteractionSpec을 구현한 클래스를 이용한다. InteractionSpec을 생성하는 인터페이스는 스펙에 없기 때문에 WebTJCA에서는 TmaxInteractionSpecImpl을 이용하여 생성한다. WebTJCA는 동기 호출(tpcall)만 제공한다.

다음은 서비스 요청에 관한 예제이다.

Interaction action = conn.createInteraction();
TmaxInteractionSpecImpl aspec = new TmaxInteractionSpecImpl();
aspec.setSvcName("TOUPPER");
aspec.setAction(InteractionSpec.SYNC_SEND_RECEIVE);

RecordFactory recordFactory = connFactory.getRecordFactory();
MappedRecord sndBuf = recordFactory.createMappedRecord(null);
sndBuf.put("$String","abc");
MappedRecord rcvBuf = recordFactory.createMappedRecord(null);

if( action.execute(aspec, sndBuf, rcvBuf) )
{
    String result = (String)rcvBuf.get("$String");
    System.out.println(result);
}

1.3. 데이터 표현 API

WebTJCA는 Tmax에서 제공하는 데이터 중 String, CArray, FDL 타입의 데이터를 제공한다.

ConnectionFactory로부터 getRecordFactory() 메소드를 이용하여 RecodFactory를 얻어와서 createMappedRecord()로 데이터 객체를 생성하여 사용하는 데이터를 입력한다.

다음은 RecordFactory 생성 예제이다.

RecordFactory recordFactory = connFactory.getRecordFactory();
MappedRecord sndBuf = recordFactory.createMappedRecord(null);

다음은 각 타입별로 메소드를 사용하는 방법에 대한 설명이다.

  • String 사용

    MappedRecord의 put 메소드를 이용하여 설정한다. put의 키에 "$String"을 입력할 경우 value는 String으로 인식하여 Tmax에 String형의 메시지를 전달한다. get 함수를 이용할 경우에도 키에 "$String"을 입력하면 저장된 String 객체를 반환한다. 다음은 String을 사용해서 데이터를 표현하는 예제이다.

    MappedRecord sndBuf = recordFactory.createMappedRecord(null);
    sndBuf.put("$String","abc");
  • CArray 사용

    MappedRecord의 put 메소드를 이용하여 설정한다. put의 키에 "$CArray"를 입력할 경우 value는 byte[ ]로 인식하여 Tmax에 CArray형의 메시지를 전달한다. get 함수를 이용할 경우에도 키에 "$String"을 입력하면 저장된 byte[ ]를 반환한다. 다음은 CArray을 사용해서 데이터를 표현하는 예제이다.

    MappedRecord sndBuf = recordFactory.createMappedRecord(null);
    sndBuf.put("$CArray",new byte[]{0,1,2});
  • FDL 사용

    MappedRecord의 put 메소드를 이용하여 설정한다. put의 키에 FDL에서 설정한 키를 입력할 경우 value는 해당하는 필드 타입으로 인식하여 Tmax에 FDL 타입의 메시지를 전달한다. put 메소드를 이용하여 필드키와 데이터를 쌍으로 저장한다. 다음은 FDL을 사용해서 데이터를 표현하는 예제이다.

    MappedRecord sndBuf = recordFactory.createMappedRecord(null);
    sndBuf.put("ID","tmax001");
    sndBuf.put("PASS","abcd");
    sndBuf.put("AGE",16);

    put 메소드로 저장한 데이터를 참고하기 위해서는 get 메소드를 이용한다. get 메소드의 반환 객체는 해당 필드의 값을 저장하고 있는 IndexedRecord를 구현한 com.tmax.connector.cci.TmaxFdlRecord를 반환한다. 사용자는 IndexedRecord의 get(int index) 메소드를 이용하여 저장한 필드값을 참고한다.

    IndexedRecord field = sndBuf.get("ID");
    String id = field.get(0);

2. 트랜잭션

2.1. XA 트랜잭션

WebTJCA는 XA 트랜잭션을 지원한다. 사용자는 ra.xml에서 <support-xa> 항목을 true로 설정해야 하며 <transaction-support> 항목도 XA 트랜잭션으로 설정해야 한다.

XA 트랜잭션은 설정만 하면 getConnection을 실행할 때에 자동으로 트랜잭션에 참여하며 애플리케이션에서 Commit이나 Rollback을 하는 경우 2PC 작업으로 Tmax에 Prepare, Commit 요청을 한다.

복구 처리를 위해서는 반드시 <outbound-resourceadapter><connection-definition>에 xid 매핑 파일 관련 정보를 입력해야 한다. 만약 이 파일이 존재하지 않는다면 웹 애플리케이션 서버가 재기동할 때는 xid 매핑 정보가 존재하지 않아 복구 작업을 수행 할 수 없다.

XA 트랜잭션 작업을 위해서는 Tmax의 jeusgw를 설정하여 해당 포트에 접속해야 한다.

2.2. 로컬 트랜잭션

로컬 트랜잭션 처리를 위해서 사용자는 Connection에서 getLocalTransaction 메소드를 이용해야 한다. 설정에 따라서 자동으로 웹 애플리케이션 서버에서 처리해 준다.

다음은 로컬 트랜잭션 사용 예제이다.

ConnectionFactory connFactory = (ConnectionFactory)ctx.lookup("TmaxConnector");
Connection conn = connFactory.getConnection();
conn.getLocalTransaction().begin();
...

conn.getLocalTransaction().commit();

로컬 트랜잭션을 위해서는 Tmax의 기본 포트에 접속해야 한다. JAVAGW에 접속해서 로컬 트랜잭션으로 처리할 수 없다.

3. Logging

리소스 어댑터를 사용하면서 발생하는 로그는 ra.xml을 사용할 때 설정한 로그 파일과 로그 레벨의 적용을 받아서 생성한다. <outbound-resourceadapter><connection-definition>에 로그 관련 설정에 Connection을 사용하는 로그를 출력한다. 자세한 사항은 리소스 어댑터 구성의 "ra.xml 설정"을 참고한다.

4. 비동기 요청/대화형 통신 지원

현재 정의한 CCI 스펙만으로는 Tmax에서 지원하는 비동기 요청과 대화형 통신을 지원할 수 없기 때문에 다음과 같이 기존 WebT API를 이용하여 구현해야 한다.

Connection으로부터 WebtConnection을 참고하여 WebtRemoteService()WebtDialogueService()를 이용하여 비동기, 대화형 통신을 할 수 있다.

다음은 비동기 요청의 예제이다.

ConnectionFactory connFactory = (ConnectionFactory)ctx.lookup("TmaxConnector");
Connection conn = connFactory.getConnection();
WebtConnection webtConn = ((TmaxConnectionImpl)conn).getInConnection();
WebtRemoteService svc = new WebtRemoteService("TOUPPER", webtConn);
int cd = svc.tpacall(sendBuf);
rcvBuf = svc.tpgetrply(cd);
conn.close();

다음은 대화형 통신의 예제이다.

ConnectionFactory connFactory = (ConnectionFactory)ctx.lookup("TmaxConnector");
Connection conn = connFactory.getConnection();
WebtConnection webtConn = ((TmaxConnectionImpl)conn).getInConnection();
WebtDialogueService svc = new WebtDialogueService("TOUPPER_CONV", webtConn);
svc.tpconnect(sndbuf..
...
conn.close();