예제

본 장에서는 JEUS 6와 WebLogic에서 WebTJCA를 사용하는 방법에 대해 설명한다.

1. JEUS 6에서 WebTJCA 사용

1.1. 리소스 어댑터 구성

JCA를 이용하기 위해서 사용자는 우선 리소스 어댑터를 구성해야 한다. 리소스 어댑터에는 웹 애플리케이션 서버 제공 업체의 고유의 설정과 JCA에서 정의한 설정을 정의해야 한다. 리소스 어댑터는 Java Archive(JAR) 형식으로 RAR로 패키징되어야 한다.

JCA에서 정의한 리소스 어댑터에 포함할 목록은 다음과 같다.

Contents of RAR file Requirements Relative location within RAR file

Deployment Descriptor

Required

META-INF/ra.xml

howto.html, image files, etc.

Optional

Arbitary (that is, could be at root level or sub-level)

JAR files

Optional

Arbitary

Platform-specific native libraries

Optional

Arbitary

개발자는 ra.xml과 jeus-connector-dd.xml을 기술한다.

ra.xml, jeus-connector-dd.xml 설정과 디플로이 방법에 관한 자세한 내용은 JEUS 안내서 중 "JEUS JCA 안내서"를 참고한다.

ra.xml 설정

Inflow와 Outbound를 함께 설정한다. 다음은 ra.xml을 설정하는 예제이다.

<?xml version="1.0" encoding="UTF-8"?>
<connector id="Connector_ID" version="1.5" xmlns="http://java.sun.com/xml/ns/j2ee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
  http://java.sun.com/xml/ns/j2ee/connector_1_5.xsd">
  <description>Tmax Sample Resource Adapter</description>
  <display-name>TmaxRA</display-name>
  <vendor-name>TmaxSoft</vendor-name>
  <eis-type>TP Monitor</eis-type>
  <resourceadapter-version>1.0.0.0</resourceadapter-version>
  <resourceadapter>
    <resourceadapter-class>com.tmax.connector.spi.TmaxResourceAdapterImpl</resourceadapter-class>
    <config-property>
        <config-property-name>port</config-property-name>
        <config-property-type>java.lang.Integer </config-property-type>
        <config-property-value>6556</config-property-value>
    </config-property>
    <config-property>
        <config-property-name>fdlfile</config-property-name>
        <config-property-type>java.lang.String</config-property-type>
        <config-property-value>C:\TmaxSoft\JEUS6.0\lib\application\tmax.fdl</config-property-value>
    </config-property>
    <outbound-resourceadapter>
      <connection-definition>
        <managedconnectionfactory-class>com.tmax.connector.spi.TmaxManagedConnectionFactoryImpl
        </managedconnectionfactory-class>
        <config-property>
            <config-property-name>host</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>192.168.1.43</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>host_port</config-property-name>
            <config-property-type>java.lang.Integer</config-property-type>
            <config-property-value>11120</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>backup</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>192.168.1.43</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>backup_port</config-property-name>
            <config-property-type>java.lang.Integer</config-property-type>
            <config-property-value>15300</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>support_xa</config-property-name>
            <config-property-type>java.lang.Boolean</config-property-type>
            <config-property-value>true</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>headerType</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>extendedV4</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>connectTimeout</config-property-name>
            <config-property-type>java.lang.Integer</config-property-type>
            <config-property-value>15000</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>fdlFile</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>C:\TmaxSoft\JEUS6.0\lib\application\tmax.fdl</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>xidMapperPath</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>C:\TmaxSoft\JEUS6.0\lib\application\</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>xidMapperFile</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>webtxidmapper</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>logLevel</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>DEBUG</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>logDir</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>d:\\</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>logFile</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>webt.log</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>logValidDays</config-property-name>
            <config-property-type>java.lang.Integer</config-property-type>
            <config-property-value>1</config-property-value>
        </config-property>
        <config-property>
            <config-property-name>connectionName</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>tmax1</config-property-value>
        </config-property>
        <connectionfactory-interface>javax.resource.cci.ConnectionFactory</connectionfactory-interface>
        <connectionfactory-impl-class>com.tmax.connector.cci.TmaxConnectionFactoryImpl</connectionfactory-impl-class>
        <connection-interface>javax.resource.cci.Connection</connection-interface>
        <connection-impl-class>com.tmax.connector.cci.TmaxConnectionImpl</connection-impl-class>
      </connection-definition>

      <transaction-support>XATransaction</transaction-support>
      <reauthentication-support>false</reauthentication-support>
    </outbound-resourceadapter>
    <inbound-resourceadapter>
        <messageadapter>
            <messagelistener>
                <messagelistener-type>javax.resource.cci.MessageListener</messagelistener-type>
                <activationspec>
                    <activationspec-class>com.tmax.connector.spi.TmaxActivationSpec</activationspec-class>
                    <required-config-property>
                        <config-property-name>serviceName</config-property-name>
                    </required-config-property>
                </activationspec>
            </messagelistener>
        </messageadapter>
    </inbound-resourceadapter>
  </resourceadapter>
</connector>
jeus-connector-dd.xml 설정

다음은 jeus-connector-dd.xml을 설정하는 예제이다. 해당 예제에서 export-name은 Outbound Connection을 참고할 수 있는 JNDI 이름이다.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jeus-connector-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
    <module-name>TmaxRA</module-name>
    <use-workmanager>true</use-workmanager>
    <connection-pool>
        <export-name>TmaxConnector</export-name>
        <transaction-support>XATransactionOnly</transaction-support>
        <pool-management>
            <min>5</min>
            <max>20</max>
        </pool-management>
    </connection-pool>
</jeus-connector-dd>
디플로이

다음의 과정으로 디플로이한다.

  1. 디플로이 할 폴더를 구성한다.

    webt5.9.7.0.jar
    META-INF/ra.xml
    META-INF/jeus-connector-dd.xml
  2. jar로 TmaxRA.rar 파일을 생성한다.

  3. JCA로 JEUS에 디플로이한다. JEUS WebAdmin의 [애플리케이션 모듈 디플로이] 메뉴를 사용해서 디플로이한다.

1.2. Outbound 예제

다음은 Tmax의 TOUPPER 서비스를 호출하는 jsp 예제이다.

<%@ page language="java" contentType="text/html; charset=EUC-KR"
    pageEncoding="EUC-KR"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<%@page import="javax.resource.cci.Connection"%>
<%@page import="javax.naming.InitialContext"%>
<%@page import="javax.resource.cci.ConnectionFactory"%>
<%@page import="javax.resource.cci.RecordFactory"%>
<%@page import="javax.resource.cci.MappedRecord"%>
<%@page import="javax.resource.cci.Interaction"%>
<%@page import="javax.resource.cci.InteractionSpec"%>
<%@page import="com.tmax.connector.cci.TmaxInteractionSpecImpl"%>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=EUC-KR">
    <title>Insert title here</title>
</head>
<body>
<%
 InitialContext ctx = new InitialContext();
 ConnectionFactory connFactory = (ConnectionFactory)ctx.lookup("TmaxConnector");
 Connection conn = connFactory.getConnection();

 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");
 }
 conn.close();
 System.out.println("end lookup");
%>
</body>
</html>

1.3. Inflow 예제

JCA의 Inflow는 JCA에서 Tmax로부터 서비스 요청이 있을 경우 등록된 Message Driven Bean으로 호출하는 구조이다. 사용자는 Message Driven Bean을 구현하여 디플로이해서 사용해야 한다.

TmaxListenerBean.java

다음은 WebTJCA에서 서비스 요청을 수신하여 Message Driven Bean의 OnMessage를 호출하여 서비스 명에 따라서 다른 EJB를 호출하는 구조의 예제이다.

package com.tmax.sample.echoMBean;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.MessageDrivenBean;
import javax.ejb.MessageDrivenContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.resource.ResourceException;
import javax.resource.cci.MappedRecord;
import javax.resource.cci.MessageListener;
import javax.resource.cci.Record;
import javax.rmi.PortableRemoteObject;
import com.tmax.sample.TmaxBLSample;
import com.tmax.sample.TmaxBLSampleHome;

public class TmaxListenerBean implements MessageListener, MessageDrivenBean {
 /**
  *
  */
 private static final long serialVersionUID = 7971664840039920708L;
 public TmaxListenerBean() {
 }

 public void ejbCreate() throws EJBException {
 }

 public void ejbRemove() throws EJBException {
  // TODO Auto-generated method stub
 }

 public void setMessageDrivenContext(MessageDrivenContext ctx)
      throws EJBException {
  }

 public Record onMessage(Record in) throws ResourceException {
  System.out.println(in);
  String svcName = (String)((MappedRecord)in).get("$ServiceName");

  if( svcName.equalsIgnoreCase("echostring") )
  {
     return in;
  }
  else if( svcName.equalsIgnoreCase("create_account_b"))
  {
      System.out.println(((MappedRecord)in).get("$Message"));
      Context initial;
      try {
            System.setProperty("java.naming.factory.initial",
                       "jeus.jndi.JNSContextFactory");
            System.setProperty("java.naming.factory.url.pkgs", "jeus.jndi.jns.url");
            System.setProperty("java.naming.provider.url", "192.168.11.253");

            initial = new InitialContext();

             Object object = initial.lookup("TmaxBLSample");    // return EJB Home
             if( object == null )
             {
                return createFailRecord(in, -6);
             }

             TmaxBLSampleHome home = (TmaxBLSampleHome)
             PortableRemoteObject.narrow(object, TmaxBLSampleHome.class);
             TmaxBLSample sample =  home.create();
             if( sample.createAccount(in) )
             {
                MappedRecord out = (MappedRecord) in.clone();
                out.put("$ReturnCode", new Integer(0));
                out.put("RESULT", "OK");
                return out;
             }
             else
             {
                return createFailRecord(in, -1);
             }
      } catch (NamingException e) {
           e.printStackTrace();
           return createFailRecord(in, -2);
      } catch (RemoteException e) {
           e.printStackTrace();
           return createFailRecord(in, -3);
      } catch (CreateException e) {
           e.printStackTrace();
           return createFailRecord(in, -4);
      } catch (CloneNotSupportedException e) {
           e.printStackTrace();
           return createFailRecord(in, -5);
      }
  }
  else if( svcName.equalsIgnoreCase("transfer_money_b"))
  {
      System.out.println(((MappedRecord)in).get("$Message"));

      Context initial;
      try {
            System.setProperty("java.naming.factory.initial",
                       "jeus.jndi.JNSContextFactory");
            System.setProperty("java.naming.factory.url.pkgs", "jeus.jndi.jns.url");
            System.setProperty("java.naming.provider.url", "192.168.11.253");

            initial = new InitialContext();

             Object object = initial.lookup("TmaxBLSample");    // return EJB Home
             if( object == null )
             {
                 return createFailRecord(in, -6);
             }

             TmaxBLSampleHome home = (TmaxBLSampleHome)
             PortableRemoteObject.narrow(object, TmaxBLSampleHome.class);
             TmaxBLSample sample =  home.create();
             if( sample.transferMoney(in) )
             {
                 MappedRecord out = (MappedRecord) in.clone();
                 out.put("$ReturnCode", new Integer(0));
                 out.put("RESULT", "OK");
                 return out;
             }
             else
             {
                return createFailRecord(in, -1);
             }
      } catch (NamingException e) {
          e.printStackTrace();
          return createFailRecord(in, -2);
      } catch (RemoteException e) {
          e.printStackTrace();
          return createFailRecord(in, -3);
      } catch (CreateException e) {
          e.printStackTrace();
          return createFailRecord(in, -4);
      } catch (CloneNotSupportedException e) {
          e.printStackTrace();
          return createFailRecord(in, -5);
      }
  }
  return in;
 }

 public Record createFailRecord(Record src, int usrcode)
 {
     MappedRecord out = null;
     try {
           out = (MappedRecord) src.clone();
       }
       catch (CloneNotSupportedException e) {
           e.printStackTrace();
           return null;
        }
     out.put("$ReturnCode", new Integer(-1));
     out.put("$UserCode", new Integer(usrcode));
     out.put("RESULT", "FAIL");
     return out;
 }
}
ejb-jar.xml

EJB 2.0 파일을 위한 배치 지시자로서 다음과 같은 옵션 정보를 포함하고 있다.

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar id="ejb-jar_ID" version="2.1" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
 <display-name>TmaxListenerBean</display-name>
 <enterprise-beans>
  <message-driven>
   <display-name>TmaxListenerBean</display-name>
   <ejb-name>TmaxListenerBean</ejb-name>
   <ejb-class>com.tmax.sample.echoMBean.TmaxListenerBean</ejb-class>
   <transaction-type>Container</transaction-type>
   <message-destination-link>TmaxRA</message-destination-link>
   <activation-config>
    <activation-config-property>
     <activation-config-property-name>serviceName</activation-config-property-name>
     <activation-config-property-value>
     ECHOSTRING,CREATE_ACCOUNT_B,TRANSFER_MONEY_B
     </activation-config-property-value>
    </activation-config-property>
   </activation-config>
  </message-driven>
 </enterprise-beans>
</ejb-jar>
jeus-ejb-dd.xml

JEUS의 EJB 2.0 파일을 위한 배치 지시자이다.

<?xml version="1.0"?>
<jeus-ejb-dd xmlns="http://www.tmaxsoft.com/xml/ns/jeus">
 <beanlist>
  <jeus-bean>
   <ejb-name>TmaxListenerBean</ejb-name>
   <mdb-resource-adapter-name>TmaxRA</mdb-resource-adapter-name>
  </jeus-bean>
 </beanlist>
</jeus-ejb-dd>

jeus-ejb-dd.xml에 대한 자세한 내용은 JEUS 안내서 중 "JEUS EJB 안내서"의 "5.3.1.4. jeus-ejb-dd.xml 디플로이 디스크립터 작성"을 참고한다.

2. WebLogic에서 WebTJCA 사용

WebLogic에서 WebTJCA를 사용하는 방법에 대해 설명한다.

2.1. 리소스 어댑터 구성

JCA를 이용하기 위해서는 사용자는 우선 리소스 어댑터를 구성해야 한다. 리소스 어댑터에는 웹 애플리케이션 서버 제공의 고유 설정과 JCA에서 정의한 설정을 정의해야 한다. 리소스 어댑터는 Java Archive(JAR) 형식으로 RAR로 패키징되어야 한다.

JCA에서 정의한 리소스 어댑터에 포함할 목록은 다음과 같다.

Contents of RAR file Requirements Relative location within RAR file

Deployment Descriptor

Required

META-INF/ra.xml

howto.html, image files, etc.

Optional

Arbitary (that is, could be at root level or sub-level)

JAR files

Optional

Arbitary

Platform-specific native libraries

Optional

Arbitary

개발자는 다음과 같이 ra.xml과 weblogic-ra.xml을 기술한다.

ra.xml 설정

Inflow와 Outbound를 함께 설정한다. ra.xml 설정에 대한 자세한 내용은 WebTJCA ra.xml 설정을 참고하고 설정하는 방법은 리소스 어댑터 구성의 "ra.xml 설정" 예제를 참고한다.

weblogic-ra.xml 설정

다음은 weblogic-ra.xml 설정 예제이다. 해당 예제에서 jndi-name은 Outbound Connection을 참고할 수 있는 JNDI 이름이다.

<?xml version="1.0" ?>
<weblogic-connector xmlns="http://www.bea.com/ns/weblogic/90">
 <jndi-name>TmaxRA</jndi-name>
    <enable-access-outside-app>true</enable-access-outside-app>
    <outbound-resource-adapter>
     <connection-definition-group>
      <connection-factory-interface>javax.resource.cci.ConnectionFactory
      </connection-factory-interface>
   <connection-instance>
    <jndi-name>TmaxConnector</jndi-name>
    <connection-properties>
     <pool-params>
      <initial-capacity>2</initial-capacity>
      <max-capacity>10</max-capacity>
      <capacity-increment>1</capacity-increment>
      <shrinking-enabled>true</shrinking-enabled>
      <shrink-frequency-seconds>60</shrink-frequency-seconds>
     </pool-params>
    </connection-properties>
   </connection-instance>
     </connection-definition-group>
    </outbound-resource-adapter>
</weblogic-connector>
디플로이

다음의 과정으로 디플로이한다.

  1. 디플로이할 폴더를 구성한다.

    webt5.9.7.0.jar
    META-INF/ra.xml
    META-INF/weblogic-ra.xml
  2. jar로 TmaxRA.rar 파일을 생성한다.

  3. JCA로 WebLogic에 디플로이한다. WebLogic 관리자에서 [애플리케이션 디플로이]를 사용해서 디플로이한다.

weblogic-ra.xml 설정에 대한 자세한 내용은 BEA WebLogic Server 안내서 중 "Programming WebLogic Resource Adapters"를 참고한다. 디플로이 방법에 대한 자세한 내용은 BEA WebLogic Server 안내서 중 "Deploying Applications to WebLogic Server"를 참고한다.

2.2. Outbound 예제

Tmax의 TOUPPER 서비스를 호출하는 jsp 예제 파일이다. Outbound 예제는 Outbound 예제를 참고한다.

2.3. Inflow 예제

JCA의 Inflow는 JCA에서 Tmax로부터 서비스 요청이 있을 경우 등록된 Message Driven Bean으로 호출하는 구조이다. 사용자는 Message Driven Bean을 구현하여 디플로이해서 사용해야 한다.

TmaxListenerBean.java

WebTJCA 에서 서비스 요청을 수신하여 Message Driven Bean의 OnMessage를 호출하여 서비스명에 따라서 다른 EJB를 호출하는 구조이다. 해당 예제는 Inflow 예제의 TmaxListenerBean.java의 예제를 참고한다.

ejb-jar.xml

EJB 2.0파일을 위한 배치 지시자로서 다음과 같은 옵션 정보를 포함하고 있다.

모든 EJB의 구조 정보를 담고 있는 <enterprise-beans>, 애플리케이션 배치를 위한 옵션 정보를 담을 <assembly-descriptor>로 구성되며, 해당 beans에 대한 트랜잭션 처리 방법이나 보안 정책 등을 설정한다. 특히 예제의 설정은 MDB로 이루어진 TmaxListenerBean을 배치하기 위한 것이다.

<ejb-jar id="ejb-jar_ID" version="2.1"
 xmlns="http://java.sun.com/xml/ns/j2ee"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
 http://java.sun.com/xml/ns/j2ee/ejb-jar_2_1.xsd">
  <display-name>TmaxListenerBean</display-name>
  <enterprise-beans>
    <message-driven>
      <display-name>TmaxListenerBean</display-name>
      <ejb-name>TmaxListenerBean</ejb-name>
      <ejb-class>com.tmax.sample.echoMBean.TmaxListenerBean</ejb-class>
      <messaging-type>javax.resource.cci.MessageListener</messaging-type>
      <transaction-type>Container</transaction-type>
      <message-destination-link>TmaxRA</message-destination-link>
      <activation-config>
        <activation-config-property>
          <activation-config-property-name>serviceName
          </activation-config-property-name>
          <activation-config-property-value>
             ECHOSTRING,CREATE_ACCOUNT_B,TRANSFER_MONEY_B
          </activation-config-property-value>
        </activation-config-property>
      </activation-config>
    </message-driven>
   </enterprise-beans>
   <assembly-descriptor>
     <message-destination>
       <message-destination-name>TmaxRA</message-destination-name>
     </message-destination>
    </assembly-descriptor>
</ejb-jar>

JEUS와 달리 WebLogic에서는 다음과 같이 설정해야 한다. WebLogic에서는 message link와 assembly descriptor를 설정하면 안 된다.

<!-- message--link>TmaxRA</message-destination-link -->
<!-- assembly-descriptor>
   <message-destination>
      <message-destination-name>TmaxRA</message-destination-name>
   </message-destination>
</assembly-descriptor -->
weblogic-ejb-jar.xml

WebLogic에 의존적인 속성에 관련된 부분을 정의하는 파일로 캐싱, 클러스터링, 최적화와 관련된 내용이 포함된다.

<?xml version="1.0" ?>
<weblogic-connector xmlns="http://www.bea.com/ns/weblogic/90">
  <jndi-name>TmaxRA</jndi-name>
<?xml version="1.0" encoding="UTF-8"?>
<weblogic-ejb-jar
 xmlns="http://www.bea.com/ns/weblogic/90"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://www.bea.com/ns/weblogic/90
 http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd">
  <weblogic-enterprise-bean>
    <ejb-name>TmaxListenerBean</ejb-name>
    <message-driven-descriptor>
     <resource-adapter-jndi-name>TmaxRA</resource-adapter-jndi-name>
    </message-driven-descriptor>
  </weblogic-enterprise-bean>
</weblogic-ejb-jar>