Background
I have Spring Client application that provisions a service to two servers using RMI. In the the client I save an entity to the database (easy) and make rmi calls to two servers with details of the entity. I am using Spring 3.0.2 on the servers and the client is a simple Spring-mvc site.
Requirements
My requirement is that if any of the rmi calls fail to the servers that the whole transaction rolls back, that is the entity is not saved on the client and if either rmi call was successful that this too rolls back.
I am relatively new to Distributed transactions, but I guess I want a XA like transaction using RMI calls.
I did find a nice link on the subject here but it does not mention the pattern for when calling two remote method calls to different servers. I would love to hear more about the subject in terms of recommended reading and also any pointers on how to achieve this using spring. Is using a transaction manager for this possible?
Thank you.
Here is how this situation could be theoretically handled. First you need to have several JTA distributed transaction manager on each nodes. One acts as the master, the other as the slaves. The master coordinate the commit/rollback of the distributed transaction to the slaves. Stand alone JTA implementations exist, e.g. JOTM.
Vanilla RMI does not support propagating context information such as the transaction ID of the operation. But I think RMI has hooks so that it can be extended to support that. You can have a look at Carol.
You will need to use XAResource to wrap the participants in the transaction so that they can be enlisted in the distributed transaction. The master will need to send commit/rollback messages to the slaves, which will need to use XATerminator to act accordingly.
The JTA spec is only a distributed transaction manager, logging of the operations in a transaction log needs to be done by the servers. Library exists for transaction log management, e.g. HOWL.
I don't think Spring can be used -- even with a distributed transaction manager -- to do that easily. I tried once to use RMI with distributed transaction controlled from a stand alone client and several slaves. Here is a blog post about it. It was rather complicated.
You can get all that for free if you use a Java EE application server, with IIOP. IIOP support distributed transaction propagation. The client can be an application client container, and you can control the transactions with UserTransaction. That's actually one of the rare case, where I think using an application server is really justified.
But that said, distributed transaction are complicated things, which can lead to heuristic failures, timeout if one node dies, and complicated recovery procedures.
My last advice would then be: try to find a design which does not involve distributed transaction if possible. That will make your like a lot easier.
You can maybe draw inspiration at BPEL compensation mechanism. There are maybe other design approaches for error handling and robustness which can avoid the usage distributed transactions.
As far as I know, Spring per se doesn't manage distributed transactions. It may use JtaTransactionManager which in its turn delegates to a Java EE server's transaction coordinator. So as far as I understand this kind of transactions available only across datasources registered in application container.
You may try to write your own XAResource implementation (not sure if it's the best way, but still) and register it in application container, but Spring won't help you much with that.
Related
The current situation
Got a project using: spring-boot, spring-cloud, postgresql, as a microservice system.
There are 2 services, say SA and SB, they operate on 2 RDBMS databases respectively, say DA and DB.
Now, there is an operation contains 2 sub steps:
Http client would make a request to service SA, to save a record RA, into DA.
Then, SA send a request to service SB, to save a record RB, into DB.
As a whole, the 2 sub steps should either both commit, or both rollback.
Analysis
If move both operations into a single service, then could use Spring's distributed transaction to sovled it with JTA (based on 2PC protocol).
But here, the 2 operations are in 2 services, and they communicated via http REST protocol. Maybe could use mq + compensation to solve this, but I am not sure is there a better approach.
The questions are
In this case, does JTA (based on 2PC protocol) still work?
If not, what is the preferred solution?
Possible solutions I can guess:
Refactor code to move the 2 operations into a single service.
Implementat the mq + compensation architecture to support this.
Maybe this project is helpful for you https://github.com/apache/servicecomb-pack
Apache ServiceComb Pack is an eventually data consistency solution for micro-service applications. ServiceComb Pack currently provides TCC and Saga distributed transaction co-ordination solutions by using Alpha as a transaction coordinator and Omega as an transaction agent
I read that SOAP web service when compared to REST supports ACID property.Could anyone explain this for me with an example?
Web Services Atomic Transaction (WS-AtomicTransaction) Version 1.2
Web Services Coordination (WS-Coordination) Version 1.2
https://docs.oracle.com/cd/E21764_01/web.1111/e13734/transaction.htm#WSADV382
"This specification defines three specific agreement coordination protocols for the Atomic Transaction coordination type: completion, volatile two-phase commit, and durable two-phase commit. Developers can use any or all of these protocols when building applications that require consistent agreement on the outcome of short-lived distributed activities that have the all-or-nothing property."
http://docs.oasis-open.org/ws-tx/wstx-wsat-1.2-spec-cs-01/wstx-wsat-1.2-spec-cs-01.html
"The framework enables existing transaction processing, workflow, and other systems for coordination to hide their proprietary protocols and to operate in a heterogeneous environment."
http://docs.oasis-open.org/ws-tx/wstx-wscoor-1.2-spec-cs-01/wstx-wscoor-1.2-spec-cs-01.html
"Web services provide an automatic transaction mechanism. Any web method can automatically run within the scope of a transaction. All you need to do to take advantage of this capability is add a property to the WebMethod attribute—there's no extra code required. If an exception is thrown from within the web method and not caught, the transaction will be aborted automatically; if no exceptions are thrown, the transaction is committed. You can catch exceptions within the web method, but then you have to throw an exception—after you've performed any steps that you need to perform—in order to abort the transaction. This article shows you how to use automatic web service transactions effectively."
http://www.informit.com/articles/article.aspx?p=30231&seqNum=2
I was asked the following question in an interview and couldn't answer that.
How do you include a jdbc operation,a web service call and a JMS operation into one single transaction. That means if one of them fails all has to be roll backed.
I have heard about two-phase commit protocol and oracl XA in case of database transactions involving multiple databases. But not sure whether the same can be used here.
The critical factor is that the web services you connect to have been built using a web services framework that supports transactions. JBoss Narayana is one such web services framework. Once the web services endpoint you are connecting to is on such a framework, it's just a matter of configuring spring to use the appropriate client.
In the case of Narayana, the spring config (from http://bgshinhung.blogspot.ca/2012/10/integrating-spring-framework-jetty-and.html) for transactions with web services:
You are never going to be able to do this in a completely bomb-proof way as the systems are separate. A failure in one stage of the system (for example between the SQL commit and the JMS commit the power on your server gets turned off) will leave the SQL commit in place.
The only way to resolve that would be to keep some record of partial commits somewhere and scan that on startup to fix any resulting problems but now what happens if you have a failure processing or keeping that list.
Essentially the solution is to do your own implementation of the multiple-stage-commit and rollback process wrapping the three operations you need to make. If any of the operations fails then you need to reverse (preferably using an internal transaction mechanism, if not then by issuing reversing commands) any that have been done so far.
There are a lot of corner cases and potential ways for a system like this to fail though, so really the first approach should be to consider whether you can redesign the system so you don't need to do this at all!
It may be trick question and the right answer is "it can not be done".
But I would try to pseodo-code something like this:
try{
jdbc.startTransaction();
Savepoint saveJdbc = jdbc.setSavepoint();
JMS.startTransaction();
Savepoint saveJMS = JMS.setSavepoint();
jdbs.doSomeStuff();
JMS.doSomeStuff();
jdbc.commit();
JMS.commit();
if(webServise.doSomeStuff() == fail){throw new Exception();}
}
catch(Eception e){
jdbc.rollback(saveJdbc);
JMS.rollback(saveJMS);
}
You prepare one servise that has roll back. You prepare second servise that has roll back. You will try web servise and if web servise fail you will roll back those two which have rollback.
May be it is a way to implement rollback to your web servise.
We had same situation like web service will push the data, we have to read the xml stream and persist to db(oracle). implementation we followed is.
Web service send soap message and that will contain xml stream data.
all request soap messages pushed to jms.
respective listner will read the stream and persist the data into 'Temporary tables'.
if request processed successfully then move data from temp table to actual table.
if any error roll back.
hope above points may help.
To my mind, it looks like interviewer liked to understand your ability to think in terms of enterprise wide distribution. Few points:
JDBC is used for Database connectivity
WebService is probably a mechanism to send control command to a
server from any client.
JMS is mainly used for alerts of what is being happened in the
system.
My guess is your interviewer might be having a typical scenario with him that they wish to suffice the following situation:
Data is on one tier ( cluster, or machine )
Clients may be any kind, mobile, app, ios, objective c, browser pay, etc.
JMS is configured to listen to topics. Or is that he wishes he could do that.
Now probably the best approach is to write a JMS Subscriber which decides what to do in the onMessage() method. As an example, suppose a web service is initiated a payment request from client. This will initiate a JMS publisher to tell a DAO do the necessary internal connection to database and when transaction is in middle and when it finishes, one message will be published to subscriber. You will have full grain control of every step as that would be configured to be published through JMS. Though this is difficult to achieve, this could be your interviewer's expected approach from you. (This is Only my guess, and please note.)
Is there a possibility having transactions across multiple systems?
For exeample:
layer 1 - exposes web services (Deployed to weblogic)
layer 2 - .NET front end (Deployed to IIS)
Can we have transaction commit or rollback for multiple web service calls initiated from .NET?
If so, can someone point me any resource or document? And is there any special requirement for each of the layer comply to participate in transactions?
Yes, it is possible. WCF allows for the consumption of web services that utilize the WS-Atomic Transaction standard, assuming you have System.Transactions.TransactionScope available in your .NET client (Silverlight, for example, does not have this).
There is an excellent example on CodeProject that shows both how to produce and consume transaction web services in .NET using TransactionScope.
casperOne's mention of TransactionScope is an excellent solution if it is available in your scenario. I have fallen in love with the simplicity and power it brings to the table.
However, I note that you have a Java tag and mention Weblogic as the web service tier, so the TransactionScopeRequired property would have to be implemented via WS-AT (Web Services Atomic Transaction) or a similar transcriptional protocol.
See here: http://publib.boulder.ibm.com/infocenter/wsdoc400/v6r0/index.jsp?topic=/com.ibm.websphere.iseries.doc/info/ae/ae/cjta_wstran.html
Its definitely possible, but could prove to be harrier than you'd think. You need control to modify the execution environment of those web services to augment them such that they can consume the WS-AT headers. In addition as with any distributed transaction environment you probably will incur a performance increase because of the substantial administrative overhead.
SOA-WORLD had some great articles that explain Web Service transactions and all the related OASIS standards. Here is the one on WS-Coordination if I can find the rest I'll add them.
I have a web-based application which makes use of remote EJBs for its business logic. Some of these EJBs are also exposed as Web Services. I need to keep a small state for some of these calls in order to allow subsequent calls to function correctly. Which of the following would you recommend?
Stateful EJBs (will this work with Web Services?)
Return the state to the client (what if I want to prevent the client from altering the state?)
Reload the state from the DB on each method (should I worry about the overhead?)
All three proposed solutions can be made to work, but the best solution will depend on the details of your application.
I don't use Stateful Session Beans (SFSBs) at all. SFSBs are designed to keep session state, but using them via a Web Service raises questions about what exactly is a session? If you have a complicated deployment environment or users use multiple instances of the application then this could be a fragile solution.
Returning state - as the question indicates, there could be security issues unless you are certain that the server can trust its clients. You could use encryption techniques to verify that the state object had not been modified, but it is much safer not to give sensitive data to a potentially hostile client. Another situation where this might be useful is if the client is permitted to alter the state, or if no harm can be done if the client does so. If client access to the system is always through a web-tier, this is a good place to store session state. The web-tier and application-tier can safely exchange state objects.
Reloading the state from the database is probably the most generally applicable approach. If you use an entity bean or an Object Relational Mapping library then the server should be able to reduce the number of database queries.
The only option you have is to store appropriate information associated with a certain UserId in the DB.
You can't expose Statefull bean as Webservice.
In case of exposing your Beans as Webservices you could try to send additional information back and forth by putting in the SOAP header to prevent modifications in the body. But in this case clients will be able to alter it.