Examples
This chapter describes examples of WebTAsync inbound/outbound.
1. Inbound Example
1.1. Configuration
The environment must be configured for Tmax and JTmaxNServer to use the Inbound service.
Tmax 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 the IP address and the port number to connect to JTmaxNServer.
When Tmax starts, it establishes as many connections as specified by the number of JTmaxNServer and the product of the maxchl * cpc settings.
JTmaxNServer 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.
-
Configuring TmaxInboundEApplication.ear in /META-INF/weblogic-application.xml
To start JTmaxNServer in the WebLogic server, configure the weblogic-application.xml file under the "/META-INF" directory as follows.
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>
-
Configuring webt.properties
When using the WebT API with JTmaxNServer, configure the webt.properties file as follows to enable logging or use FDL. To run WebLogic Server, set the system property -Dwebt.properties to the absolute path of the file.
log.level=debug log.dir=D:\\tmax log.file=tmax_webt.log fdl.file=D:\\tmax\\tmax.fdl
-
Configuring com.tmax.inbound.properties
This file contains basic properties to run JTmaxNServer and EJB settings required for handling messages.
The following configuration defines a service named ECHOSTRING, which, when invoked, executes the echoString method of the echo EJB. This example is a sample configuration file that you can modify as needed.
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
1.2. Starting a Server
Use JTmaxNServerImpl to create a JTmaxNServer instance that handles service requests from Tmax.
When creating a JTmaxNServer, specify a JTmaxNJGMessageHandler—a callback interface for handling services—as an argument. The server opens a socket on the specified listening port and creates an acceptor thread to wait for incoming requests.
JTmaxNServer server = new JTmaxNServerImpl(“JTmaxNServer1”, 8881,100, 50, new WebLogicJTmaxNJGMessageHandler()); server.startServer();
The following shows the constructor for JTmaxNServerImpl.
JTmaxServerImpl(String serverName, int port, int connection, int thread, JTmaxNJGMessageHandler handler)
Item | Description |
---|---|
serverName |
Name of the JTmaxNServer instance. |
port |
Listening port number. |
connection |
Number of allowable connections. |
thread |
Number of user threads used for callbacks when receiving messages. |
handler |
Message handler. |
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 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(); } }
For more information about the APIs, refer to WebtAsync 2.0.0.0 API. |
2. Outbound Example
2.1. Configuration
The environment must be configured for Tmax to use the Outbound service.
Tmax 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 the port number for receiving connection requests from a WebTAsync application.
2.2. Client Program
Example of tpcall
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(); } }
Example of tpacall
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.
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(); } }
Example of Xatpacall
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.
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
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
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.3. Configuring Key Features
Timeout
The timeout period for waiting for a response to a sent message or for attempting to connect to Tmax is set using the setTimeout(long connectTimeout, long readTimeout) method of WebtEndpoint. The timeout values are specified in milliseconds.
The setTimeout method applies globally. To set timeouts for individual messages, use the following method of WebtNService.
tpacall(WebtBuffer sndBuffer, String serviceName, WebtAttribute attribute, long readtimeout, WebtEventHandler handler)
When a timeout occurs, the user handler’s handleError is called. For more information, refer to Example of tpcall.
Failover
The WebtAsync library attempts to reconnect during tpacall if no active connection exists. If the connection to the main server defined by setMainServerInfo of WebtEndPoint fails, it retries the connection to the backup server configured with setFailoverServerInfo. For more information, refer to Example of tpcall.
Failback
The WebtEndPoint class supports the startCheckFailBack method, which helps restore the connection to the main server when it returns to a normal state. While a backup server is in use, this method periodically checks whether the main server has recovered and notifies the user of its current status. The user implements FailBackMonitor and passes it as an argument. When availableMainServer is called, message processing is suspended. After all pending messages are received, the connection to the backup server is closed, and subsequent messages are sent to the main server. To perform the check, create a thread. For more information, refer to Example of tpcall.
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; } }
Logging features
Depending on the option configured for the selector thread, the entire contents of a request message (excluding the Tmax header) are logged in hexadecimal format up to the specified length, regardless of the log level.
webtasync.appmsg.isdump=<true | false> webtasync.appmsg.dump.length=<Length>
-
webtasync.appmsg.isdump=<true | false>
Enables the feature.
-
webtasync.appmsg.dump.length=<Length>
Configures the length of the data to print from the request content.
For a user application that implements the recoverRecieved method of WebtNRecoverHandler, 'decision' must be defined. For more information, refer to Example of Xatpacall. |
3. Other Features
3.1. Event handler for establishing/closing connections
The com.tmax.nio.common.ConnectionMessageHandler interface exchanges the IP addresses and port numbers between the connected parties when a connection is established or closed. The openSession event is triggered when a connection is established with the counterpart, and the closeSession event is triggered when the connection is closed.
public interface ConnectionMessageHandler { void openSession(int sessionID, String sourceAddress, int sourcePort, String destinationAddress, int destinationPort); void closeSession(int sessionID, String sourceAddress, int sourcePort, String destinationAddress, int destinationPort); }
Item | Description |
---|---|
sessionID |
Session ID of the connection with the counterpart. |
sourceAddress |
Local IP address. |
sourcePort |
Local port number. |
destinationAddress |
Counterpart (remote) IP address. |
destinationPort |
Counterpart (remote) port number. |