Today i want to share about Implementation JPos Transaction Manager. In this post, i will implement the integration with ISORequestListener, Transaction Manager Group Selector, Transaction Participant, and Abort Participant.
From JPos Programmer guide book, the explanation of TransactionManager is:
The TransactionManager implementation takes care of ‘driving’ the transaction by calling all of the participants’ prepare methods. If all of them return ‘PREPARED’, then the transaction moves to the committing phase, at which point the TransactionManager will call all of the participants’ commit methods.
If one of the participants’ prepare methods were to return ABORTED, then the transaction would move into an aborting phase, and all the participants’ abort methods would get called.
In this post, we will implement GroupSelector interface for choose the transaction group. GroupSelector is used to simplify the TransactionManager.
A participant implementing the GroupSelector interface can modify the flow of this transaction by returning a space-separated list of group names (or can specify ‘null’ to signify no action).
you can read the JPos Programmer Guide for more explanation about TransactionManager. You can purchase here.
As always, we have to create some xml file on deploy folder.
- 00_logger.xml
- 10_server.xml
- 20_transaction_manager.xml
- 30_clientsimulator_channel.xml
- 40_clientsimulator_mux.xml
- 50_jposclient_channel_manager.xml
- 99_sysmon.xml
There are channel, mux, and channel manager in this tutorial, because we will get some data from another server. The Flow service is shown on picture below:
In this post, we will implement the Front End Server
First of all, we have to create 10_server.xml file.
[xml]
[/xml]
This server will listen on port 12260, using NACChannel with CustomPackager, and the request will be listened on JPosServerListener class.
Then, the JPosServerListener is look like:
[java]
public class JPosServerListener implements ISORequestListener, Configurable {
private String queueName;
private Space
private Long timeout;
public JPosServerListener() {
super();
}
public static void main(String[] args) {
Q2 q2 = new Q2();
q2.start();
}
@Override
public boolean process(ISOSource isoSrc, ISOMsg isoMsg) {
Context ctx = new Context();
ctx.put(Constant.REQUEST, isoMsg);
ctx.put(Constant.ISOSOURCE, isoSrc);
sp.out(queueName, ctx, timeout);
return true;
}
@SuppressWarnings(“unchecked”)
@Override
public void setConfiguration(Configuration cfg)
throws ConfigurationException {
queueName = cfg.get(“queue”);
timeout = cfg.getLong(“timeout”);
sp = SpaceFactory.getSpace(cfg.get(“space”));
}
}
[/java]
In process method, we will create new context then put the request message, and requester (IsoSource) to the context, then put the context to the space, so TransactionManager will process the request.
Then, after creating the server, we have to configure the TransactionManager. The 20_transaction_manager.xml look like:
[xml]
[/xml]
By using GroupSelector, we have to class that implement GroupSelector interface. In this tutorial, i create Switch class and will override the select class of GroupSelector interface.
[java]
/**
* GroupSelector implementation class
* @author Didik Hari
* @since 02-Feb-2015
*/
public class Switch implements GroupSelector, Configurable {
private Configuration cfg;
@Override
public void abort(long id, Serializable context) { }
@Override
public void commit(long id, Serializable context) { }
@Override
public int prepare(long id, Serializable context) {
return PREPARED | READONLY | NO_JOIN;
}
@Override
public String select(long id, Serializable context) {
try {
ISOMsg reqMsg = (ISOMsg) ((Context)context).get(Constant.REQUEST);
return cfg.get(reqMsg.getMTI(), null);
} catch (Exception e) {
return null;
}
}
@Override
public void setConfiguration(Configuration cfg)
throws ConfigurationException {
this.cfg = cfg;
}
}
[/java]
if the select method return 0800, JPos will invoke NetworkManagement group, and if return 0200 FinancialTransaction group will be invoked.
And finally we have to implement the transactionParticipant for the implementation of group participant.
The first participant we create is message validator class. This class will overade method prepare and abort. the abort method will send response to the requester (isoSource) with response code ’01’ or general error. And the prepare methods will validate the bit124, if bit 124 not valid, transactionManager will abort the transaction, and send response to the client using abort method.
[java]
/**
* Validate the request message
* if bit 124 is null or filled with space or empty string, then abort the transaction
* abort method will send response with response code ’01’ (General Error)
*
* @author Didik Hari
*
*/
public class FinancialTransactionValidateMessage implements TransactionParticipant {
@Override
public void abort(long id, Serializable context) {
try {
ISOSource requester = (ISOSource) ((Context)context).get(Constant.ISOSOURCE);
ISOMsg reqMsg = (ISOMsg) ((Context) context).get(Constant.REQUEST);
ISOMsg respMsg = (ISOMsg) reqMsg.clone();
respMsg.setResponseMTI();
respMsg.set(39, “01”);
requester.send(respMsg);
} catch (ISOException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void commit(long id, Serializable context) { }
@Override
public int prepare(long id, Serializable context) {
try {
ISOMsg reqMsg = (ISOMsg) ((Context) context).get(Constant.REQUEST);
String bit124 = reqMsg.getString(124);
String custId = bit124.substring(0, 5).trim();
if (custId != null && custId.length() > 0) {
return PREPARED;
}
} catch (Exception e) {
return ABORTED;
}
return ABORTED;
}
}
[/java]
Second transaction participant is for query to the back-end server. using channel, mux, and channel manager we create before. the implementation of channel manager is already described here
[java]
/**
* This class is responsible for fetch data from backend system
* @author Didik Hari
*
*/
public class FinancialTransactionQueryRemoteHost implements AbortParticipant {
private ChannelManager channelManager;
@Override
public void abort(long id, Serializable context) { }
@Override
public void commit(long id, Serializable context) { }
@Override
public int prepare(long id, Serializable context) {
try {
channelManager = ((ChannelManager) NameRegistrar.get(“channel-manager”));
ISOMsg reqMsg = (ISOMsg) ((Context)context).get(Constant.REQUEST);
ISOMsg respMsg = channelManager.sendMsg(reqMsg);
((Context)context).put(Constant.RESPONSE, respMsg);
return PREPARED;
} catch (NameRegistrar.NotFoundException e) {
e.printStackTrace();
return ABORTED;
} catch (Throwable t) {
t.printStackTrace();
return ABORTED;
}
}
@Override
public int prepareForAbort(long id, Serializable context) {
return ABORTED;
}
}
[/java]
And the last participant is for response to the client or channel. We already put response message on query remote host participant, so in this class all we have to do is just get the response message, and send the message to the requester back.
[java]
/**
* This class is for sending response to channel
* @author Didik Hari
*
*/
public class FinancialTransactionResponse implements AbortParticipant {
@Override
public void abort(long id, Serializable context) { }
@Override
public void commit(long id, Serializable context) { }
@Override
public int prepare(long id, Serializable context) {
try {
ISOMsg respMsg = (ISOMsg) ((Context) context).get(Constant.RESPONSE);
ISOSource requester = (ISOSource) ((Context) context).get(Constant.ISOSOURCE);
requester.send(respMsg);
return PREPARED;
} catch (Exception e) {
e.printStackTrace();
return ABORTED;
}
}
@Override
public int prepareForAbort(long id, Serializable context) {
return ABORTED;
}
}
[/java]
in network management group, we just set response MTI and response code to ’00’.
hope this post about Implementation JPos Transaction Manager can help you, and please write some comment below.
Thanks for visiting my blog.
Leave a Reply