Reputation: 1596
I want to update a file using RMI .How i can ensure status of operations.
Client connected to server and call a method. Just after, connection between client and server broken and client get a RemoteException
, but called method continue to work and change a file then return and get exception (Assuming it will realize connection lost when writing response to socket).
Upvotes: 4
Views: 277
Reputation: 66662
This is quite complex to do in practice. You would need to implement a two phase commit protocol, where the client can get an indicator that the server can guarantee a commit, then order the commit.
There is an off-the-shelf protocol called XA for managing this process, and this is supported by the Java Transaction API. Essentially you could build an XA compatible resource manager for your file.
This is not a trivial undertaking but is not outside the bounds of possibility if you don't mind including an application server or transaction manager in your infrastructure. The advantage of this approach is that you could hook into a mature, debugged transaction management infrastructure.
A couple of alternatives would be to:
Implement your own two-phase commit protocol, or
Structure the file updating code that it is idempotent (multiple calls to make the same update just make that update). In this case you can re-try the update until your client gets an indicator of success from the server.
Note that you will also have to come up with a protocol for locking and/or managing conflicting updates on the same record unless you can guarantee sequential writes from the client. Depending on your application this could possibly be an optimistic concurrency protocol but you would still have to lock the range you're working on while operating on it to make the writes atomic.
Upvotes: 5
Reputation: 17864
If you choose to roll your own pseudo-transaction system, here's the basic:
On the server side:
On the client:
Upvotes: 0
Reputation: 53694
You can pass a sequential counter argument from the client to server with each operation. Depending on what your usage scenario is, your server will need to remember one or more of the most recent counters sent. if a value is seen which has already happened, you can return success (or whatever). If the values need to be unique across multiple clients, you could use something like a UUID (mentioned by another answer). A lot of this depends on what the return values are and what the call sequence looks like.
as an example, i implemented this idea in the rmiio project to deal with this very problem. in the rmiio library, you only have to deal with the possibility of the "current" operation being repeated, so you only need to track the last counter value.
Upvotes: 0
Reputation: 137717
You're dealing with distributed processing. This means that you cannot guarantee that a particular message (method call, etc.) will arrive at the other end; the connection can always be dropped arbitrarily. Because of this, you need a mitigation strategy that doesn't rely on any particular message arriving.
One such strategy is to use a reliable messaging system, which essentially puts databases to hold queues of messages that are then delivered reliably in order (by sending the message — tagged with a sequence identifier — repeatedly until an acknowledgement is received) but this is a lot of overhead, and should probably be saved for critical things (e.g., financial transactions).
Another strategy is to use a distributed transaction manager, but those have fairly large problems (unless you implement a distributed consensus system, and that's complex and still has potential failure modes).
I think the simplest way is to reorganize what is considered definitive. Have the client communicate with the server to assemble a transient description of the operation to be committed on the server (including a unique id, e.g. UUID), then the client can send a short message that starts the commit; at that point the server needs to log that it's started work on processing that UUID. If the response can't be sent, that's still after the commit. If any message gets lost, it's no big deal: either it's before the commit starts (in which case it didn't happen and can be retried) or after in which case there will be a permanent record that it's been attempted and so easy to report what happened (“I'm still working on it”, “I've succeeded”, “I've failed”). The only state that the client needs to remember is the UUID, and that can be allocated outside a transaction (a wonderful property of UUIDs that is admittedly only probabilistically true, but the odds of a problem are truly negligible).
Upvotes: 0