[jpos-users] JPOS based application design/architecture doubts

classic Classic list List threaded Threaded
5 messages Options
Nik
Reply | Threaded
Open this post in threaded view
|

[jpos-users] JPOS based application design/architecture doubts

Nik
Hi All,

I have been reading a lot about JPOS and thanks to some wonderful posts on this group and the programmer's guide, I have been able to understand the bits and pieces of JPOS. 

However, I still have some confusion related to transaction management in a production system. 

For the sake of simplicity, I will be asking questions with reference to the following system:

1) A JPOS Server running on port 9999.

2) A dumb ISO request listener which does nothing but the following:

                       
 ISOMsg respMsg = (ISOMsg) isoMsg.clone();
 respMsg
.setDirection(ISOMsg.OUTGOING);
 respMsg
.setResponseMTI();
 context
.put(Constants.REQUEST, isoMsg);
 context
.put(Constants.RESPONSE, respMsg);
 context
.put(Constants.SOURCE, isoSource);
 space
.out(queue, context, timeout);


Here, setConfiguration sets up the required timeout, space, queue, etc. 

3) A TransactionManager with a Selector which routes the incoming requests to appropriate Participants based on MTI:

selector = configuration.get(reqIsoMsg.getMTI());

4) Different Participants having PREPARE, COMMIT and ABORT methods to handle Transaction requests, Network requests, etc.

Use case: Client concurrently sends several Transaction ISOMsgs with AccountNumber and DebitAmount. A new database connection should be opened for each incoming request. The mentioned AccountNumber in the request should be debited by the DebitAmount and the transaction should be committed. Appropriate OK ISOMsg should be returned back. In case of insufficient fund, an error ISOMsg should be returned back.

With above usecase in mind, what will be the design of the application. 

In my mind, an application has incoming request flow as View -> Controller -> Service -> Dao -> Database and vice versa for the response back. 

Questions:

1) As per my understanding, TransactionManager creates new Participant instances for each incoming requests which run in their own threads with their own context. Is that true ?

2) Is this a good design ? ---> Factories invoked inside Participant's PREPARE which returns appropriate Service and DAO objects based on MTI. Once Service and DAO objects are at hand, call the appropriate methods inside them handing over information from incoming ISOMsg. Here I am assuming that since there will a new Participant for each incoming requests and since the Factory methods are invoked inside PREPARE of Participant, I will have independent Service, DAO Objects and Database Connections for each incoming request. Is this assumption correct ?

3) Which is a better design ?  :  (Opening, Executing, Committing, Rollingback Database transaction in DAO layer) vs. (Opening a DB Connection in PREPARE, calling each Service and DAO method with this Connection as a parameter, Committing the connection in COMMIT and RollingBack the connection in ABORT in case of any error).

In the first design, everything will happen inside PREPARE method itself. The PREPARE will return PREPARED which means the account will have been successfully debited or will return ABORT in case of any issue with DAO Transaction. I am unsure if this is the right way.

4) Any suggestion from experts on things I may have overlooked will be greatly appreciated. 

Thanks,
Nik

This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.

--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage. Please support jPOS, contact: [hidden email]
---
You received this message because you are subscribed to the Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/00b9e37d-2c2e-4d11-a587-6fb9c51313cb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: [jpos-users] JPOS based application design/architecture doubts

Alejandro Revilla
Please see my comments inline:

2) A dumb ISO request listener which does nothing but the following:

                       
 ISOMsg respMsg = (ISOMsg) isoMsg.clone();
 respMsg
.setDirection(ISOMsg.OUTGOING);
 respMsg
.setResponseMTI();
 context
.put(Constants.REQUEST, isoMsg);
 context
.put(Constants.RESPONSE, respMsg);
 context
.put(Constants.SOURCE, isoSource);
 space
.out(queue, context, timeout);



​There's a new IncomingListener participant that does basically that, feel free to use it (org.jpos.iso.IncomingListener).

You may want to take a look at http://jpos.org/tutorials for a use case example.

Here, setConfiguration sets up the required timeout, space, queue, etc. 

3) A TransactionManager with a Selector which routes the incoming requests to appropriate Participants based on MTI:

selector = configuration.get(reqIsoMsg.getMTI());
 
4) Different Participants having PREPARE, COMMIT and ABORT methods to handle Transaction requests, Network requests, etc.

Use case: Client concurrently sends several Transaction ISOMsgs with AccountNumber and DebitAmount. A new database connection should be opened for each incoming request. The mentioned AccountNumber in the request should be debited by the DebitAmount and the transaction should be committed. Appropriate OK ISOMsg should be returned back. In case of insufficient fund, an error ISOMsg should be returned back.

With above usecase in mind, what will be the design of the application. 

In my mind, an application has incoming request flow as View -> Controller -> Service -> Dao -> Database and vice versa for the response back. 

Questions:

1) As per my understanding, TransactionManager creates new Participant instances for each incoming requests which run in their own threads with their own context. Is that true ?

​That's not correct. The TM instantiate a single instance for each participant. It uses the flyweight pattern.​ You can't use member variables in your participant implementation, that's the reason the prepare/commit/abort methods accept a Context, that's where you place your per-transaction variables.
 
2) Is this a good design ? ---> Factories invoked inside Participant's PREPARE which returns appropriate Service and DAO objects based on MTI. Once Service and DAO objects are at hand, call the appropriate methods inside them handing over information from incoming ISOMsg. Here I am assuming that since there will a new Participant for each incoming requests and since the Factory methods are invoked inside PREPARE of Participant, I will have independent Service, DAO Objects and Database Connections for each incoming request. Is this assumption correct ?


​No, you need to store your DAO objects and JDBC session pointers in the Context.

 
3) Which is a better design ?  :  (Opening, Executing, Committing, Rollingback Database transaction in DAO layer) vs. (Opening a DB Connection in PREPARE, calling each Service and DAO method with this Connection as a parameter, Committing the connection in COMMIT and RollingBack the connection in ABORT in case of any error).

If your participants need to call external systems that may be slow, then you need to avoid having an open JDBC session, if, on the other hand, everything is processed locally, then you can keep the sessions open and share it among participants.


--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage. Please support jPOS, contact: [hidden email]
---
You received this message because you are subscribed to the Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/CAAgSK%3Dknswst_ecTte1iotGXUMiv5r418jaLp3bhYui1mfuwQA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
Nik
Reply | Threaded
Open this post in threaded view
|

Re: [jpos-users] JPOS based application design/architecture doubts

Nik
Hi Alejandro,

Thanks for the quick response. 

I have updated my comments inline below in orange.

On Tuesday, May 23, 2017 at 9:59:29 AM UTC+8, Alejandro Revilla wrote:
Please see my comments inline:

2) A dumb ISO request listener which does nothing but the following:

                       
 ISOMsg respMsg = (ISOMsg) isoMsg.clone();
 respMsg
.setDirection(ISOMsg.OUTGOING);
 respMsg
.setResponseMTI();
 context
.put(Constants.REQUEST, isoMsg);
 context
.put(Constants.RESPONSE, respMsg);
 context
.put(Constants.SOURCE, isoSource);
 space
.out(queue, context, timeout);



​There's a new IncomingListener participant that does basically that, feel free to use it (org.jpos.iso.IncomingListener).

You may want to take a look at <a href="http://jpos.org/tutorials" target="_blank" rel="nofollow" onmousedown="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjpos.org%2Ftutorials\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEMHACR_0btu5rbLnUG5Gp2NNFdEw&#39;;return true;" onclick="this.href=&#39;http://www.google.com/url?q\x3dhttp%3A%2F%2Fjpos.org%2Ftutorials\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNEMHACR_0btu5rbLnUG5Gp2NNFdEw&#39;;return true;">http://jpos.org/tutorials for a use case example.

Thanks. Will look into IncomingListener.  

Here, setConfiguration sets up the required timeout, space, queue, etc. 

3) A TransactionManager with a Selector which routes the incoming requests to appropriate Participants based on MTI:

selector = configuration.get(reqIsoMsg.getMTI());
 
4) Different Participants having PREPARE, COMMIT and ABORT methods to handle Transaction requests, Network requests, etc.

Use case: Client concurrently sends several Transaction ISOMsgs with AccountNumber and DebitAmount. A new database connection should be opened for each incoming request. The mentioned AccountNumber in the request should be debited by the DebitAmount and the transaction should be committed. Appropriate OK ISOMsg should be returned back. In case of insufficient fund, an error ISOMsg should be returned back.

With above usecase in mind, what will be the design of the application. 

In my mind, an application has incoming request flow as View -> Controller -> Service -> Dao -> Database and vice versa for the response back. 

Questions:

1) As per my understanding, TransactionManager creates new Participant instances for each incoming requests which run in their own threads with their own context. Is that true ?

​That's not correct. The TM instantiate a single instance for each participant. It uses the flyweight pattern.​ You can't use member variables in your participant implementation, that's the reason the prepare/commit/abort methods accept a Context, that's where you place your per-transaction variables.

So, each participants are singletons but they work on and process data inside Context object passed to them by TransactionManager. As each request has its own Context object, the calls to PREPARE (and COMMIT/ABORT for that matter) for concurrent requests stay independent of each other. Right?
 
 
2) Is this a good design ? ---> Factories invoked inside Participant's PREPARE which returns appropriate Service and DAO objects based on MTI. Once Service and DAO objects are at hand, call the appropriate methods inside them handing over information from incoming ISOMsg. Here I am assuming that since there will a new Participant for each incoming requests and since the Factory methods are invoked inside PREPARE of Participant, I will have independent Service, DAO Objects and Database Connections for each incoming request. Is this assumption correct ?


​No, you need to store your DAO objects and JDBC session pointers in the Context.

With my understanding from (1) above and assuming that everything is processed locally (from (3) below), does the following sound right ?

In PREPARE

java.sql.Connection tranConnection = MyService.getConnection();  // this returns a new database connection object for this individual request
tranConnection
.setAutoCommit(false);
tranRolledBack
= false;
ctx
.put("DBConnection",tranConnection);

boolean allOK = MyService.doMyBusiness(ctx); // all the business logic goes here

if(allOK)
 
return PREPARED;

return ABORT;


In COMMIT

java.sql.Connection tranConnection = (Connection)ctx.get("DBConnection");
tranConnection
.commit();
tranConnection
.close();

In ABORT

java.sql.Connection tranConnection = (Connection)ctx.get("DBConnection");
tranConnection
.rollback();
tranConnection
.close();

So my PREPARE method will return ABORT in case of any business logic error, in which case ABORT method will be called by TransactionManager and any updates/modifications to database will be rolled back for that individual request. 
In a happy flow, PREPARE will return PREPARED, in which case COMMIT method will be called by TransactionManager and any updates/modifications to database will be committed for that individual request. 

All concurrent requests will be similarly processed with their own Context Object and their own DB Connection therein.

Right ?
 

 
3) Which is a better design ?  :  (Opening, Executing, Committing, Rollingback Database transaction in DAO layer) vs. (Opening a DB Connection in PREPARE, calling each Service and DAO method with this Connection as a parameter, Committing the connection in COMMIT and RollingBack the connection in ABORT in case of any error).

If your participants need to call external systems that may be slow, then you need to avoid having an open JDBC session, if, on the other hand, everything is processed locally, then you can keep the sessions open and share it among participants.



This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.

--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage. Please support jPOS, contact: [hidden email]
---
You received this message because you are subscribed to the Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/f403d066-3807-41f4-a70a-9c76e6296e98%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply | Threaded
Open this post in threaded view
|

Re: [jpos-users] JPOS based application design/architecture doubts

Alejandro Revilla


So, each participants are singletons but they work on and process data inside Context object passed to them by TransactionManager. As each request has its own Context object, the calls to PREPARE (and COMMIT/ABORT for that matter) for concurrent requests stay independent of each other. Right?

​Correct. If you are not using PAUSE, you could also use ThreadLocals to pass data between your participants, but it's easier to use the Context.
 
 
2) Is this a good design ? ---> Factories invoked inside Participant's PREPARE which returns appropriate Service and DAO objects based on MTI. Once Service and DAO objects are at hand, call the appropriate methods inside them handing over information from incoming ISOMsg. Here I am assuming that since there will a new Participant for each incoming requests and since the Factory methods are invoked inside PREPARE of Participant, I will have independent Service, DAO Objects and Database Connections for each incoming request. Is this assumption correct ?


​No, you need to store your DAO objects and JDBC session pointers in the Context.

With my understanding from (1) above and assuming that everything is processed locally (from (3) below), does the following sound right ?

In PREPARE

java.sql.Connection tranConnection = MyService.getConnection();  // this returns a new database connection object for this individual request
tranConnection
.setAutoCommit(false);
tranRolledBack
= false;
ctx
.put("DBConnection",tranConnection);

boolean allOK = MyService.doMyBusiness(ctx); // all the business logic goes here

if(allOK)
 
return PREPARED;

return ABORT;


In COMMIT

java.sql.Connection tranConnection = (Connection)ctx.get("DBConnection");
tranConnection
.commit();
tranConnection
.close();

In ABORT

java.sql.Connection tranConnection = (Connection)ctx.get("DBConnection");
tranConnection
.rollback();
tranConnection
.close();

So my PREPARE method will return ABORT in case of any business logic error, in which case ABORT method will be called by TransactionManager and any updates/modifications to database will be rolled back for that individual request. 
In a happy flow, PREPARE will return PREPARED, in which case COMMIT method will be called by TransactionManager and any updates/modifications to database will be committed for that individual request. 


​Yes, that's more or less what our standard Open and Close participants do, look at them here:


All concurrent requests will be similarly processed with their own Context Object and their own DB Connection therein.


​Sure. That's how it works.

--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage. Please support jPOS, contact: [hidden email]
---
You received this message because you are subscribed to the Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/CAAgSK%3DkZgZhD_MVDmMV0wZC1f%2BHgojtmXhmDosvBqLgfZXLB2Q%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.
Nik
Reply | Threaded
Open this post in threaded view
|

Re: [jpos-users] JPOS based application design/architecture doubts

Nik
Thanks Alejandro!! :)

On Wednesday, May 24, 2017 at 7:33:27 AM UTC+8, Alejandro Revilla wrote:


So, each participants are singletons but they work on and process data inside Context object passed to them by TransactionManager. As each request has its own Context object, the calls to PREPARE (and COMMIT/ABORT for that matter) for concurrent requests stay independent of each other. Right?

​Correct. If you are not using PAUSE, you could also use ThreadLocals to pass data between your participants, but it's easier to use the Context.
 
 
2) Is this a good design ? ---> Factories invoked inside Participant's PREPARE which returns appropriate Service and DAO objects based on MTI. Once Service and DAO objects are at hand, call the appropriate methods inside them handing over information from incoming ISOMsg. Here I am assuming that since there will a new Participant for each incoming requests and since the Factory methods are invoked inside PREPARE of Participant, I will have independent Service, DAO Objects and Database Connections for each incoming request. Is this assumption correct ?


​No, you need to store your DAO objects and JDBC session pointers in the Context.

With my understanding from (1) above and assuming that everything is processed locally (from (3) below), does the following sound right ?

In PREPARE

java.sql.Connection tranConnection = MyService.getConnection();  // this returns a new database connection object for this individual request
tranConnection
.setAutoCommit(false);
tranRolledBack
= false;
ctx
.put("DBConnection",tranConnection);

boolean allOK = MyService.doMyBusiness(ctx); // all the business logic goes here

if(allOK)
 
return PREPARED;

return ABORT;


In COMMIT

java.sql.Connection tranConnection = (Connection)ctx.get("DBConnection");
tranConnection
.commit();
tranConnection
.close();

In ABORT

java.sql.Connection tranConnection = (Connection)ctx.get("DBConnection");
tranConnection
.rollback();
tranConnection
.close();

So my PREPARE method will return ABORT in case of any business logic error, in which case ABORT method will be called by TransactionManager and any updates/modifications to database will be rolled back for that individual request. 
In a happy flow, PREPARE will return PREPARED, in which case COMMIT method will be called by TransactionManager and any updates/modifications to database will be committed for that individual request. 


​Yes, that's more or less what our standard Open and Close participants do, look at them here:

   <a href="https://github.com/jpos/jPOS-EE/tree/master/modules/txn/src/main/java/org/jpos/transaction" target="_blank" rel="nofollow" onmousedown="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fjpos%2FjPOS-EE%2Ftree%2Fmaster%2Fmodules%2Ftxn%2Fsrc%2Fmain%2Fjava%2Forg%2Fjpos%2Ftransaction\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGNDlPCbDm8afCyz8AJ4z-axr2ITA&#39;;return true;" onclick="this.href=&#39;https://www.google.com/url?q\x3dhttps%3A%2F%2Fgithub.com%2Fjpos%2FjPOS-EE%2Ftree%2Fmaster%2Fmodules%2Ftxn%2Fsrc%2Fmain%2Fjava%2Forg%2Fjpos%2Ftransaction\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNGNDlPCbDm8afCyz8AJ4z-axr2ITA&#39;;return true;">https://github.com/jpos/jPOS-EE/tree/master/modules/txn/src/main/java/org/jpos/transaction

All concurrent requests will be similarly processed with their own Context Object and their own DB Connection therein.


​Sure. That's how it works.


This email and any files transmitted with it are confidential and intended solely for the use of the individual or entity to whom they are addressed. If you have received this email in error please notify the system manager. This message contains confidential information and is intended only for the individual named. If you are not the named addressee you should not disseminate, distribute or copy this e-mail. Please notify the sender immediately by e-mail if you have received this e-mail by mistake and delete this e-mail from your system. If you are not the intended recipient you are notified that disclosing, copying, distributing or taking any action in reliance on the contents of this information is strictly prohibited.

--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage. Please support jPOS, contact: [hidden email]
---
You received this message because you are subscribed to the Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To post to this group, send email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/28280952-5f34-43e6-b84c-72df56d031ca%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.