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.
精彩评论