views:

631

answers:

3

Hi,

I am calling a Web Service and i want it to respond within 5 seconds. If it can't process it in 5 secs (ignoring network latency) i want it rollback the transaction and send me a Timeout exception.

I can see timeouts being set only on the Calling Client's code. I want this to be enforced by the Web Service Implementer (Server side). I can't seem to find any way to do this.

If i timeout by specifying the timeout in the client side, the server would likely go ahead and complete the transaction. I would not even know whether the original request was successful or if it encountered any errors as it timed out before the server finished processing of the request.

I am using Java client talking to a WS implemented by a EJB. Appreciate any inputs.

Thanks, Manglu

A: 

If I get you right, the EJB implements the service and it shall respond within 5 secs or rollback the transaction and send a timeout response. Looks like you need stateful bean anyway, because you want to track the time for each service call individually.

I would start a 'kill' thread from the EJB for each service call. The thread will wait 5 secs and notify the EJB after that period, that it has to rollback and responds with an error message. The EJB can terminate the kill thread for the (usual) case, that it can respond within the expected timeframe.

Andreas_D
Yes your understanding is correct. The EJB implementation is exposed a web serviceI thought along these lines but spawning a thread and killing threads wouldn't that be bad for EJBs as the EJB Container would not be able to control them.Thanks,Manglu
Manglu
A: 

I think most J2EE app servers let you set a max transaction time and will rollback once that time is exceeded. Because you want to respond in a nice way to your caller, you might consider putting the "meat" of your transaction in Bean A and the SOAP handling stuff in Bean B. So, in Bean B, you catch RollbackException (I think there's a subclass for timeouts?) and respond to your caller in the nice way.

If you are using JBoss (and perhaps other app servers?), you can apparently use BMT and set transaction time-outs dynamically. http://www.jboss.org/community/wiki/TransactionTimeout

ShabbyDoo
Hi,You are correct in stating the transation timeouts.But rememmber, if i have two web services ,one which needs a time out of 5 seconds and the other with say 10 seconds would naturally not work by utilizing the J2EE Trnasaction timeouts.Thanks,Manglu
Manglu
You can't set the timeouts on a per-session bean basis (presuming one session bean per web service)? I recall that Weblogic allowed this in more recent versions. What container(s) are you targeting?
ShabbyDoo
Hi,Mine is a WebSphere based application.Manglu
Manglu
A: 

I'll suggest a pattern that might work. But first ... I'd like to suggest that perhaps the requirement may be benefit from a little interpretation. What's actually going on that needs a 5 second timeout, and needs to be very sure (abort transaction sure) that that work didn't happen if the timeout is reached? And in which case how upset would the user be if his browser crashed or a network glitch happened before they saw the result - because in that case we can't know from the client end what happened, and the client is under the conditions of the questions (and almost inevitably) not participating in the transaction.

So a different model of interaction might be simpler to implement and give quite good reliability. I'll describe that model and then explain how you can refine it to give the 5 second timeout too if you do need it.

My suggested model of interaction is the "place-order, check-for-fills-later" model. This is what is ofetn used for an online trading system. The client sends a request, the system stashes the request away safely somewhere and immediately responds to the client. No timeout needed the stashing away is very quick. Then in an a worker thread (use an MDB in JEE land, or WebSphere's asynch beans) the real work can be done.

The client later can ask "that order number 73, how's it going?" or "please cancel order 73". Using Ajax or callback techniques we can give a very nice UI over that model.

Note that the implementation of client saying "cancel" and the system going "finished that one" needs to be mediated by suitable locking, usually by some database.

Using optimistic locking, a SQL statment meaning something like

Update order 73 to cancelled WHERE its state is working
if the number of rows updated == 0 then "TOO LATE we already filled it"

Hence the filler can, in its primary transaction, attend to update to "FILLED" and abort the transaction if the record has been cancelled.

We have meadiated between two asychronous "threads".

For many system this is enough.

Bear in mind:

  • if your worker is taking a long time, it may be very bad for overall throuput to cancel it at the end of the work, will the user jusy submit the request again.
  • While the work is down in the depths of JDBC you probably cannot interrupt it, so "runaway" queries will not be stopped by anything we've discussed here.

If you do need the 5 second timeout, all you do is exactly the above except the the service is coded to do the cancel check after sleeping, rather than immediately returning to the client and doing the check in a later, separate request. So the client code lookes like:

Begin tran
     stash request
Commit

// now the worker may get round to starting the work sometime

Sleep 5 seconds

Begin Tran
     attempt to cancel!
     // that will fail if the work is completed
     // the WHERE will not find the record in the right state
if update worked COMMIT
     // now worker cannot complete
else ABORT

// by here the work is either complete or cancelled
// even if worker is still running it cannot complete

return state of record
djna