Chapter 2. Examples

Table of Contents

2.1. Inbound Example
2.1.1. Environment Configuration
2.1.2. Starting a Server
2.1.3. Requesting a Service
2.2. Outbound Example
2.2.1. Environment Configuration
2.2.2. Client Program
2.2.3. Major Functions

This chapter describes examples of WebTAsync inbound/outbound.

2.1. Inbound Example

2.1.1. Environment Configuration

The environment must be configured for Tmax and JTmaxNServer to use the Inbound service.

Tmax Environment Configuration

In the GATEWAY section of the Tmax configuration file, set GWTYPE to "JEUS_ASYNC". Other configurations are the same as Java gateway settings.

*SERVICE
ECHO_STRING SVRNAME=javagwa

*GATEWAY
javagwa GWTYPE=JEUS_ASYNC,
        NODENAME=tmax,
        PORTNO=8550,
        RGWADDR="192.168.11.240",
        RGWPORTNO=8282,
        CLOPT="-r"

For Inbound, set GWTYPE=JEUS_ASYNC, RGWADDR="192.168.11.240", and RGWPORTNO=8282. Set RGWADDR and RGWPORTNO to an IP address and a port number respectively to connect to JTmaxNServer.

When Tmax starts, 'JTmaxNServer and maxchl * cpc' number of connections are established.

JTmaxNServer Environment Configuration

To describe the JTmaxNServer environment configuration, it is assumed that JTmaxNServer starts in the WebLogic server. To start a sample JTmaxNServer, deploy a JTmaxNServer application in a WebLogic server as an .ear file.

TmaxInboundEApplication.ear, the sample application, implements the start and end of JTmaxServer and JTmaxNJGMessageHandler for handling messages.

  • TmaxInboundEApplication.ear /META-INF/weblogic-application.xml configuration

    When WebLogic server starts, start JTmaxNServer and configure the following in weblogic-application.xml under "/META-INF."

    Implement the TmaxServerLifeCycle class by inheriting ApplicationLifecycleListener, which is provided by WebLogic.

    <?xml version="1.0" encoding="UTF-8"?>
    <weblogic-application xmlns="http://www.bea.com/ns/weblogic/90">
    <listener>
            <listener-class>com.tmax.inbound.TmaxServerLifeCycle
            </listener-class>
            <listener-uri>TmaxInboundEApplicationEJB.jar</listener-uri>
    </listener>
    </weblogic-application>
  • webt.properties configuration

    When a WebT API is used in JTmaxNServer, configure the following in webt.properties to record logs or to use FDL. When the WebLogic server starts, set "-Dwebt.properties= absolute path."

    log.level=debug
    log.dir=D:\\tmax
    log.file=tmax_webt.log
    fdl.file=D:\\tmax\\tmax.fdl
  • com.tmax.inbound.properties configuration

    com.tmax.inbound.properties configures basic settings to start JTmaxNServer and EJB settings to handle messages.

    The following configuration calls the echoString method of echo EJB when the ECHOSTRING service is called. com.tmax.inbound.properties sets the sample JTmaxNServer as an option. The configuration can be set with other methods.

    ejb.names=ejb1
    ejb1.exportname=Echo
    ejb1.methodname=echoString
    ejb1.tmax.servicename=ECHO_STRING
    tmax.inbound.servers=jtmax1
    jtmax1.listen.port=8282
    jtmax1.worker.thread.max = 20
    jtmax1.worker.connection.max = 50 

2.1.2. Starting a Server

Use JTmaxNServerImpl to create JTmaxNServer to handle service requests from Tmax.

When creating JTmaxNServer, use JTmaxNJGMessageHandler, which is a callback interface for handling a service, as an argument. A socket opens with a listening port to wait for a request, and an acceptor thread is created.

JTmaxNServer server = new JTmaxNServerImpl(“JTmaxNServer1”, 8881,100, 50, 
                      new WebLogicJTmaxNJGMessageHandler());
server.startServer(); 

The following describes JTmaxNServerImpl, a creator API.

JTmaxServerImpl(String serverName, int port, int connection, int thread,
                JTmaxNJGMessageHandler handler)
ItemDescription
serverNameJTmaxNServer name.
portListening port number.
connectionNumber of allowable connections.
threadNumber of user threads for calling callback when receiving a message.
handlerMessage handler.

2.1.3. Requesting a Service

Tmax Client Service Request

The Tmax client requests a service as if it were a service Tmax. If serviceHandler.serviceFinished() is called after handling service logic, a result is sent to the Tmax server.

...
if ((sndbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) {
        printf("sndbuf alloc failed !\n");
        tpend();
        exit(1);
}
cd = tpacall("ECHO_STRING", sndbuf, 0, 0);
...

Service Request to JTmaxNServer

The Tmax service receives a request from a client through the Async Java gateway and sends the request to JTmaxNServer. When JTmaxNServer receives the request, JTmaxNJGMessageHandler serviceExecute is called. A developer must implement service handling logic corresponding to serviceName in the serviceExecute method.

...
public void serviceExecute(int sessionId, Xid xid, String serviceName, 
                        WebtBuffer receiveBuffer, JTmaxNServiceHandler
                        serviceHandler) {
        // service handling logic part
        EchoHome home = (EchoHome) PortableRemoteObject.narrow(objref,
                                                          EchoHome.class);
        Echo echo = home.create();
        String value = echo.echoString(receiveBuffer.getString());
        WebtBuffer sendBuffer = new WebtStringBuffer();
        sendBuffer.setString(value);
        if (serviceHandler != null) {
                serviceHandler.serviceFinished
                (JTmaxNServiceHandler.TPSUCCESS,EJB_SVC_SUCCESS, sendBuffer);
        }
}
...

EJBCallWorker, XACommitWorker, XAPrepareWorker, and XARollbackWorker are user thread classes for handling services.

public class WebLogicJTmaxNJGMessageHandler implements
        JTmaxNJGMessageHandler {
             public WebLogicJTmaxNJGMessageHandler () {
        }
        private XAResource getXAResource() {
             return TxHelper.getServerInterposedTransactionManager().getXAResource();
        }
        public void bulkRecover(Xid[] xids) throws NotSupportedException {
             if (xids == null) {
             return;
             }
             TmaxXid tmaxXid = null;
             for (int i = 0; i < xids.length; i++) {
                     tmaxXid = (TmaxXid) xids[i];
                     int decision = tmaxXid.getDecision();
                     switch (decision) {
                     case tmax.webt.io.Webt.TM_XA_COMMIT:
                     case tmax.webt.io.Webt.TM_XA_COMMIT2:
                             xaCommit(-1, xids[i], false, null);
                             break;
                     case tmax.webt.io.Webt.TM_XA_RBACK:
                     case tmax.webt.io.Webt.TM_XA_RBACK2:
                             xaRollback(-1, xids[i], null);
                             break;
                     default:
                     break;
                     }
             }
        }
        public void closeSession(int sessionId) {
             System.out.println("closed sessionId = " + sessionId);
        }
        public void closeTrunk(TmaxAliveInfo info) {
             for (int i = 0; i < info.getTrunkSize(); i++) {
                Hashtable<Integer, String> table = info.getTrunk(i);
                Iterator<Integer> it = table.keySet().iterator();
                while (it.hasNext()) {
                    Integer key = (Integer) (it.next());
                    String ip = (String) (table.get(key));
                    System.out.println("client index = " + key +", ip = " + ip);
                }
             }
        }
        public Xid[] recover() {
             Xid[] xids = null;
             try {
                     xids = getXAResource().recover(XAResource.TMSTARTRSCAN);
             } catch (XAException e) {
                     e.printStackTrace();
                     return null;
             }
              return xids;
        }
        public void serviceExecute(int sessionId, String serviceName, 
        WebtBuffer receiveBuffer) {
                        new Thread(new EjbCallWorker(sessionId, serviceName,
                                   receiveBuffer)).start();
        }
        public void serviceExecute(int sessionId, Xid xid, String serviceName,
                                   WebtBuffer receiveBuffer, JTmaxNServiceHandler
        serviceHandler) {
                new Thread(new EjbCallWorker(sessionId, xid, serviceName,
                           receiveBuffer, serviceHandler)).start();
        }
        public void xaCommit(int sessionId, Xid xid, boolean onePhrase,
                             JTmaxNServiceHandler serviceHandler) {
                new Thread(new XACommitWorker(sessionId, xid, onePhrase, 
                           serviceHandler)).start();
        }
        public void xaPrepare(int sessionId, Xid xid, 
                              JTmaxNServiceHandler serviceHandler) {
                new Thread(new XAPrepareWorker(sessionId, xid, 
                           serviceHandler)).start();
        }
        public void xaRollback(int sessionId, Xid xid, 
                               JTmaxNServiceHandler serviceHandler) {
                new Thread(new XARollbackWorker(sessionId, xid, 
                           serviceHandler)).start();
        }
}

Note

For more information about related APIs, refer to WebTAsync 2.0.0.0 API.

2.2. Outbound Example

2.2.1. Environment Configuration

The environment must be configured for Tmax to use the Outbound service.

Tmax Environment Configuration

In the GATEWAY section of the Tmax configuration file, set GWTYPE to "JEUS_ASYNC". Other configurations are the same as Java gateway settings.

*SERVICE
TOUPPER SVRNAME=svr2a

*GATEWAY
javagwa GWTYPE=JEUS_ASYNC,
NODENAME=tmax,
PORTNO=8550,
RGWADDR="192.168.11.240",
RGWPORTNO=8282,
CLOPT="-r"

For Outbound, set GWTYPE=JEUS_ASYNC, PORTNO=8550. Set PORTNO to a port number for receiving a connection request from a WebTAsync application.

2.2.2. Client Program

tpcall Example

Create a WebtEndpoint object to connect to the Tmax Async Java gateway and configure the connection and other information. The number of connections that access the Async Java gateway through WebtEndpoint can be set in MAXINRGW of the GATEWAY section. When the default value of MAXINRGW (32) is used, the maximum number of connections is 62 (32 + 30).

public class TpcallSample {
        public final String TMAX_HOST_ADDR = "192.168.1.48";
        public final int TMAX_JGW_PORT = 8881;
        public final String BACKUP_HOST_ADDR = "192.168.1.44";public final 
        int BACKUP_JGW_PORT = 8881;
        public final int MAX_THREAD = 20;
        public final int MAX_CONNECTION = 100;
        public String serviceName = "TOUPPER";
        public TpcallSample() {
        }
        public void excute() {
            WebtEndpoint webtEndpoint = new WebtEndpointImpl();
            webtEndpoint.setMainServerInfo(TMAX_HOST_ADDR, TMAX_HOST_PORT);
            webtEndpoint.setFailoverServerInfo(BACKUP_HOST_ADDR, BACKUP_HOST_PORT);
            webtEndpoint.setTimeout(3 * 1000, 4 * 1000);
            try {
                 webtEndpoint.startClientManager("WebT-001", MAX_THREAD, 
                                                 MAX_CONNECTION);
            } 
            catch (IOException e) {
                 e.printStackTrace();
            }
            webtEndpoint.startCheckFailBack(new
            SampleFailBackMonitor(webtEndpoint),5 * 1000, 1 * 1000);
            WebtNService service = new WebtNServiceImpl(webtEndpoint);
            WebtBuffer sndBuffer = new WebtStringBuffer();
            WebtBuffer receiveBuffer = null;
            try {
                 sndBuffer.setString("abc/ABC");
                 receiveBuffer = service.tpcall(sndBuffer, serviceName, 
                                                new WebtAttribute());
                 System.out.println("receive data = " 
                                     + receiveBuffer.getString());
            } 
            catch (WebtException e) {
                   e.printStackTrace();
            } 
            catch (ConnectorException e) {
                   e.printStackTrace();
            } 
            finally {
                 webtEndpoint.stopClientManager();
            }
        }
        public static void main(String[] args) {
                new TpcallSample().excute();
        }
}

tpacall Example

To receive a response for a service request, a callback interface that implements WebtEventHandler must be set when calling tpacall. When a normal response is received from Tmax, the WebtEventHandler handleEvent method is called. When an error occurs, the handleError method is called. For more information about WebtEventHandler, refer to SampleWebtEventHandler Example.

public class TpacallSample {
        public final String TMAX_HOST_ADDR = "192.168.1.48";
        public final int TMAX_JGW_PORT = 8881;
        public final int MAX_THREAD = 20;
        public final int MAX_CONNECTION = 100;
        public final int BLOCK_TIME = 60;
        public String serviceName = "TOUPPER";
        public TpacallSample() {
        }
        public void excute() {
        WebtEndpoint webtEndpoint = new WebtEndpointImpl();
        webtEndpoint.setMainServerInfo(TMAX_HOST_ADDR,TMAX_HOST_PORT);
        webtEndpoint.setUseOnlyTpacall(true);
        try {
            webtEndpoint.startClientManager("WebT-001", MAX_THREAD, 
                                             MAX_CONNECTION);
        } 
        catch (IOException e) {
           e.printStackTrace();
        }
        WebtNService service = new WebtNServiceImpl(webtEndpoint);
        SampleWebtEventHandler handler = new SampleWebtEventHandler();
        WebtBuffer sndBuffer = new WebtStringBuffer();
        WebtBuffer receiveBuffer = null;
        try {
             sndBuffer.setString("abc/ABC");
             service.tpacall(sndBuffer, serviceName, new WebtAttribute(), handler);
        } 
        catch (WebtException e) {
             e.printStackTrace();
        } 
        catch (ConnectorException e) {
             e.printStackTrace();
        }
        int checker = 0;
        while (true) {
           if (handler.isSuccess()) {
               receiveBuffer = handler.getReceiveBuffer();
               break;
           } 
           else {
              if (handler.isFail()) {
              break;
           } 
           else {
              System.out.println("Data don't receivedyet " + (checker++));
              try {
                   Thread.sleep(1000);
              } 
              catch (InterruptedException e) {
                     e.printStackTrace();
              }
              if (checker >= BLOCK_TIME) {
                  System.out.println("Block Time over("+BLOCK_TIME+")");
                  break;
               }
             }
          }
        }
        webtEndpoint.stopClientManager();
        if (receiveBuffer != null) {
             System.out.println("receive data = " +
             receiveBuffer.getString());
        }
        }
        public static void main(String[] args) {
                new TpacallSample().excute();
        }
}

Xatpacall Example

Since WebTAsync supports only XA transactions, a user must convert a transaction into an XA transaction using an XA resource related API from the WebTAsync library.

Perform end, prepare, and commit with XA resources in use using the service.getUsingXAResource() method after requesting a service with tpacall and receiving a message response from handleEvent. For more information about XASampleWebtEventHandler, refer to XASampleWebtEventHandler Example.

public class XaTpacallSample {
        public final String TMAX_HOST_ADDR = "192.168.1.48";
        public final int TMAX_JGW_PORT = 8350;
        public final int MAX_THREAD = 20;
        public final int MAX_CONNECTION = 100;
        public final int BLOCK_TIME = 60;
        public String serviceName = "FDLINS";
        public XaTpacall() {
        }
        public void excute() {
                WebtEndpoint webtEndpoint = new WebtEndpointImpl();
                webtEndpoint.setMainServerInfo(TMAX_HOST_ADDR,TMAX_JGW_PORT);
                webtEndpoint.setRecoverHandler(new RecoverWebtHandler());
                try {
                        webtEndpoint.startClientManager("WebT-001",
                        MAX_THREAD, MAX_CONNECTION);
                } 
                catch (IOException e) {
                        e.printStackTrace();
                }
                WebtNService service = new
                WebtNServiceImpl(webtEndpoint);
                XAResource resource = service.getXAResource();
                XASampleWebtEventHandler handler = new 
                XASampleWebtEventHandler(service);
                Xid xid = getUniqueXid();
                try {
                        resource.start(xid, XAResource.TMNOFLAGS);
                } 
                catch (XAException e) {
                        e.printStackTrace();
                }
                WebtBuffer sndBuffer = getEmployeeFieldBuffer(1111);
                WebtBuffer receiveBuffer = null;
                try {
                        service.tpacall(sndBuffer, serviceName, new
                        WebtAttribute(), handler);
                } 
                catch (WebtException e) {
                        e.printStackTrace();
                } 
                catch (ConnectorException e) {
                        e.printStackTrace();
                }
                int checker = 0;
                while (true) {
                        if (handler.isSuccess()) {
                                receiveBuffer = handler.getReceiveBuffer();
                                break;
                        } 
                        else {
                               if (handler.isFail()) {
                                    break;
                                } 
                                else {
                                    System.out.println("Data don'treceived yet " + 
                                    (checker++));
                                    try {
                                        Thread.sleep(1000);
                                    } 
                                    catch (InterruptedException e) {
                                        e.printStackTrace();
                                    }
                                    if (checker >= BLOCK_TIME) {
                                       System.out.println("Block Timeover 
                                                    (" + BLOCK_TIME+ ")");
                                       break;
                                    }
                                }
                        }
                }
                webtEndpoint.stopClientManager();
                if (receiveBuffer != null) {
                        System.out.println("receive buffer = " +receiveBuffer);
                }
        }
        private int getRandomIndex() {
                return new Random().nextInt(10);
        }
        private Xid getUniqueXid() {
                byte[] formatId = new byte[4];
                formatId[0] = (byte) getRandomIndex();
                formatId[1] = (byte) getRandomIndex();
                formatId[2] = (byte) getRandomIndex();
                formatId[3] = (byte) getRandomIndex();
                int globalId = getRandomIndex() * 100;
                int branchId = getRandomIndex() * 100;
                return new TmaxXid(formatId, globalId, branchId);
        }
        private WebtBuffer getEmployeeFieldBuffer(int empNo) {
                WebtBuffer sendBuffer = new WebtFieldBuffer();
                sendBuffer.createField("EMPNO").add(empNo);
                sendBuffer.createField("ENAME").add("tmax001");
                sendBuffer.createField("JOB").add("qa");
                sendBuffer.createField("MGR").add(7839);
                sendBuffer.createField("SAL").add(1000);
                sendBuffer.createField("COMM").add(100);
                sendBuffer.createField("DEPTNO").add(20);
                return sendBuffer;
        }
        public static void main(String[] args) {
                new XaTpacallSample().excute();
        }
}

WebtEndpoint can be accessed through Tmax, CLH, and the Async Java gateway. To request an XA service, an Async Java gateway port must be used.

The following must be set when requesting a non-XA service after connecting to WebtEndpoint through CLH.

webtEndpoint.setUseOnlyTpacall(true);

SampleWebtEventHandler Example

If a response for a service request is successfully received using a class that implements the WebtEventHandler interface, handleEvent is called. If it fails, handleError is called.

public class SampleWebtEventHandler implements WebtEventHandler {
        private WebtBuffer receiveBuffer;
        private boolean success;
        private boolean fail;
        public SampleWebtEventHandler() {
        }
        public void handleError(WebtException we) {
                fail = true;
                System.out.println("handleError = " + we.toString());
        }
        public void handleEvent(int type, WebtBuffer buffer, int len,int flags) {
                receiveBuffer = buffer;
                success = true;
                System.out.println("handleEvent");
        }
        public WebtBuffer getReceiveBuffer() {
                return receiveBuffer;
        }
        public boolean isSuccess() {
                return success;
        }
        public boolean isFail() {
                return fail;
        }
}

XASampleWebtEventHandler Example

If a response for a service request is successfully received using a class that implements the WebtEventHandler interface to handle an XA service, handleEvent is called. If it fails, handleError is called.

public class XASampleWebtEventHandler implements WebtEventHandler {
        private WebtNService service;
        private boolean fail;
        private boolean success;
        private WebtBuffer receiveBuffer;
        public XASampleWebtEventHandler(WebtNService service) {
                this.service = service;
        }
        public void handleError(WebtException we) {
                try {
                        IWebtNXAResource resource 
                         = service.getWebtNUsingXAResource();
                        resource.end(service.getXid(), XAResource.TMFAIL);
                } catch (XAException e) {
                        e.printStackTrace();
                }
                fail = true;
                System.out.println("handleError = " + we.toString());
        }
        public void handleEvent(int type, WebtBuffer buffer, int len,int flags) {
                try {
                        IWebtNXAResource resource 
                        = service.getWebtNUsingXAResource();
                        Xid xid = service.getXid();
                        resource.end(xid, XAResource.TMSUCCESS);
                        resource.prepare(xid);
                        resource.commit(xid, true);
                } catch (XAException e) {
                        e.printStackTrace();
                }
                receiveBuffer = buffer;
                success = true;
                System.out.println("handleEvent");
        }
        public WebtBuffer getReceiveBuffer() {
                return receiveBuffer;
        }
        public boolean isFail() {
                return fail;
        }
        public boolean isSuccess() {
                return success;
        }
}

2.2.3. Major Functions

Configuring Timeout

WebtEndpoint setTimeout (long connectTimeout, long readTimeout) sets the maximum time allowed to wait for a response and to access Tmax. The unit is millisecond.

The setTimeout method is globally set using the following method of WebtNService whenever a message is transferred.

tpacall(WebtBuffer sndBuffer, String serviceName, WebtAttribute attribute, 
        long readtimeout, WebtEventHandler handler)

If timeout occurs, handleError of a user handler is called. For more information, refer to tpcall Example.

Failover

The WebTAsync library attempts to establish a connection again if there is no connection when calling tpacall. If a main server set in setMainServerInfo of WebtEndpoint cannot be accessed, a connection to a backup server set in setFailoverServerInfo is attempted. For more information, refer to tpcall Example.

Failback

WebtEndpoint supports startCheckFailBack so a connection to the main server can be made if the main server becomes alive while a backup server is used. This method checks whether the main server is alive and notifies the user of the main server status. The user must implement FailBackMonitor to suspend a message when availableMainServer is called. After all messages are received and the existing connection is terminated, the following messages are sent to the main server. To check whether a main server becomes alive, create a thread. For more information, refer to tpcall Example.

public class SampleFailBackMonitor implements FailBackMonitor {
        private WebtEndpoint webtEndpoint;
        public SampleFailBackMonitor(WebtEndpoint webtEndpoint) {
                this.webtEndpoint = webtEndpoint;
        }
        public void availableMainServer() {
                webtEndpoint.disconAllConnections();
                System.out.println("Disconnected all connection!!");
        }
}

Transaction Recovery

If a transaction goes into a pending state in Tmax due to a system failure, the WebTAsync library gets a pending transaction xid list from Tmax and calls a user application to check the decision on how to handle the transaction when a connection is reestablished.

public class RecoverSampleWebtHandler implements WebtNRecoverHandler {
        public RecoverSampleWebtHandler() {
        }
        public Xid[] recoverRecieved(Xid[] xids) {
             TmaxXid xid = null;
             for (int i = 0; i < xids.length; i++) {
                xid = (TmaxXid) xids[i];
                xid.setDecision(Webt.TM_XA_COMMIT);
                // xid.setDecision(Webt.TM_XA_RBACK);
              }
              return xids;
        }
}

Log-related Function

A requested message (except for Tmax header) is recorded as a log for the specified length in hexadecimal numbers according to an option in selector-thread.

webtasync.appmsg.isdump=<true | false>
webtasync.appmsg.dump.length=<Length>
  • webtasync.appmsg.isdump=<true | false>

    Enables or disables the function.

  • webtasync.appmsg.dump.length=<Length>

    Sets the length of data to be displayed from an entire requested message.

Note

When implementing the recoverReceived method of WebtNRecoverHandler, a user application must define the decision. For more information, refer to Xatpacall Example.