You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Jesse Pangburn <Je...@infor.com> on 2013/11/20 19:34:49 UTC

long running asynchronous service provider

Hi,
I use the jax-ws Provider mechanism to implement a service provider:
@WebServiceProvider
@ServiceMode(value = Service.Mode.MESSAGE)
public class SOAPProvider implements Provider<StreamSource>

If WS-Addressing is enabled and I receive a message with a ReplyTo address, then the server will automatically send back an immediate HTTP 202 to the request.  When I finish computing a reply message and return it in a StreamSource (in this case), then CXF automatically makes a new HTTP request to the ReplyTo address and sends the reply there.  This is the normal (and expected) asynchronous processing flow.

It works, but it's not practical for a service that needs to reliably send reply messages to requests that it received.  Suppose the service even processed the request for a minute- it's quite likely that a service will be interrupted by a server restart or something.  The caller will never get their callback.  Worse, what if the transactions run for days?  And there are lots of them?  This mechanism works for testing but is not production quality for anything that needs reliable responses.

Is there a mechanism I'm missing for storing these transactions to a database or something, and putting the response processing in a separate thread as well?  Some way to make asynchronous transactions reliable?

Thanks,
Jesse

Re: long running asynchronous service provider

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
Hi Jesse,

I think the biggest con for WS-RM is that it adds overhead to the 
message processing, including additional message exchanges by the WS-RM 
protocol itself. If you're doing very high-volume transactions it might 
not be a good choice for that reason. Likewise if you're exchanging very 
large messages, since WS-RM has to keep a serialized copy of every 
message until it's been acknowledged.

The advantage of WS-RM over JMS is mostly just that WS-RM is 
standardized across web services stacks, while JMS is Java-specific. CXF 
3.0 includes WS-RM fixes that make it much more interoperable with other 
stacks. There are still problems with interoperability when WS-Security 
is also used, but I'm working to get those fixed now.

Dan's other suggestion, of just polling for responses, is also a good 
alternative for many types of applications. But it does mean that you're 
effectively implementing a simplified form of WS-RM in your application 
code, and need to add logic to your application to handle retrys and 
recovery.

TANSTAAFL, and YMMV. :-)

   - Dennis

On 11/21/2013 11:12 AM, Jesse Pangburn wrote:
> Hi Dan,
> Good advice, thanks!  I was really only looking at this from the server perspective as that's where the question arose, but you make the point about the client having the exact same issue.
>
> I solved the immediate problem using a method similar to your #2 suggestion ("a couple of one-ways") and storing a non WS-A message id to handle the linking, but as this problem has come up more than once recently I figured I'd better ask you guys.  I didn't use JMS, but the benefits are clear.
>
> I like Dennis's WS-RM suggestion.  I'm aware of it, and have tried sending WS-RM messages using CXF, but am definitely not well-versed enough in its usage to understand all the pros and cons.
>
> Thanks,
> Jesse
>
> -----Original Message-----
> From: Daniel Kulp [mailto:dkulp@apache.org]
> Sent: Wednesday, November 20, 2013 1:51 PM
> To: users@cxf.apache.org; Jesse Pangburn
> Subject: Re: long running asynchronous service provider
>
>
> In general, once the message patterns become longer than about 30 seconds, I would recommend completely rethinking the problem.  It's no longer really a request/reply style invocation and likely shouldn't be modeled as one.   At that point, I'd recommend one of a couple solutions:
>
> 1) Return an "id" from the initial post, then poll.  Basically, the client posts the request, the service does a quick validation of the request to make sure it's valid and replies immediately with some sort of unique ID.  The client can then poll for the result, save the ID locally and continue polling if the client has to shutdown/restart, etc...   The client would have to be careful not to poll too often to not flood the server, but it shouldn't require much computing power no the server side to see if the response is ready or not.
>
> 2) Async based, but using something like JMS with a persistent store for the transport.   I'd likely even not use WS-Addressing for this to make the client restart case much easier to implement.  One of the actual parameters to the service is the URL/JMS information to send the response to.   When the client starts up, it can connect to it's queue.  If the queue is persistent, if the server had sent a response already, it would be there.  Fairly simple.   Everything is more or less modeled as a couple of one-ways for simplicity.   The JMS broker just makes sure the delivery is OK.
>
> That said, WS-RM is there for this particular use case.   I just haven't used it much.  I'd definitely defer to Dennis' and Aki's judgement and expertise for information about that.
>
>
> Dan
>
>
> On Nov 20, 2013, at 1:34 PM, Jesse Pangburn <Je...@infor.com> wrote:
>
>> Hi,
>> I use the jax-ws Provider mechanism to implement a service provider:
>> @WebServiceProvider
>> @ServiceMode(value = Service.Mode.MESSAGE) public class SOAPProvider
>> implements Provider<StreamSource>
>>
>> If WS-Addressing is enabled and I receive a message with a ReplyTo address, then the server will automatically send back an immediate HTTP 202 to the request.  When I finish computing a reply message and return it in a StreamSource (in this case), then CXF automatically makes a new HTTP request to the ReplyTo address and sends the reply there.  This is the normal (and expected) asynchronous processing flow.
>>
>> It works, but it's not practical for a service that needs to reliably send reply messages to requests that it received.  Suppose the service even processed the request for a minute- it's quite likely that a service will be interrupted by a server restart or something.  The caller will never get their callback.  Worse, what if the transactions run for days?  And there are lots of them?  This mechanism works for testing but is not production quality for anything that needs reliable responses.
>>
>> Is there a mechanism I'm missing for storing these transactions to a database or something, and putting the response processing in a separate thread as well?  Some way to make asynchronous transactions reliable?
>>
>> Thanks,
>> Jesse
> --
> Daniel Kulp
> dkulp@apache.org - http://dankulp.com/blog Talend Community Coder - http://coders.talend.com
>
>


RE: long running asynchronous service provider

Posted by Jesse Pangburn <Je...@infor.com>.
Hi Dan,
Good advice, thanks!  I was really only looking at this from the server perspective as that's where the question arose, but you make the point about the client having the exact same issue.

I solved the immediate problem using a method similar to your #2 suggestion ("a couple of one-ways") and storing a non WS-A message id to handle the linking, but as this problem has come up more than once recently I figured I'd better ask you guys.  I didn't use JMS, but the benefits are clear.

I like Dennis's WS-RM suggestion.  I'm aware of it, and have tried sending WS-RM messages using CXF, but am definitely not well-versed enough in its usage to understand all the pros and cons.

Thanks,
Jesse

-----Original Message-----
From: Daniel Kulp [mailto:dkulp@apache.org] 
Sent: Wednesday, November 20, 2013 1:51 PM
To: users@cxf.apache.org; Jesse Pangburn
Subject: Re: long running asynchronous service provider


In general, once the message patterns become longer than about 30 seconds, I would recommend completely rethinking the problem.  It's no longer really a request/reply style invocation and likely shouldn't be modeled as one.   At that point, I'd recommend one of a couple solutions:

1) Return an "id" from the initial post, then poll.  Basically, the client posts the request, the service does a quick validation of the request to make sure it's valid and replies immediately with some sort of unique ID.  The client can then poll for the result, save the ID locally and continue polling if the client has to shutdown/restart, etc...   The client would have to be careful not to poll too often to not flood the server, but it shouldn't require much computing power no the server side to see if the response is ready or not.

2) Async based, but using something like JMS with a persistent store for the transport.   I'd likely even not use WS-Addressing for this to make the client restart case much easier to implement.  One of the actual parameters to the service is the URL/JMS information to send the response to.   When the client starts up, it can connect to it's queue.  If the queue is persistent, if the server had sent a response already, it would be there.  Fairly simple.   Everything is more or less modeled as a couple of one-ways for simplicity.   The JMS broker just makes sure the delivery is OK.

That said, WS-RM is there for this particular use case.   I just haven't used it much.  I'd definitely defer to Dennis' and Aki's judgement and expertise for information about that.


Dan


On Nov 20, 2013, at 1:34 PM, Jesse Pangburn <Je...@infor.com> wrote:

> Hi,
> I use the jax-ws Provider mechanism to implement a service provider:
> @WebServiceProvider
> @ServiceMode(value = Service.Mode.MESSAGE) public class SOAPProvider 
> implements Provider<StreamSource>
> 
> If WS-Addressing is enabled and I receive a message with a ReplyTo address, then the server will automatically send back an immediate HTTP 202 to the request.  When I finish computing a reply message and return it in a StreamSource (in this case), then CXF automatically makes a new HTTP request to the ReplyTo address and sends the reply there.  This is the normal (and expected) asynchronous processing flow.
> 
> It works, but it's not practical for a service that needs to reliably send reply messages to requests that it received.  Suppose the service even processed the request for a minute- it's quite likely that a service will be interrupted by a server restart or something.  The caller will never get their callback.  Worse, what if the transactions run for days?  And there are lots of them?  This mechanism works for testing but is not production quality for anything that needs reliable responses.
> 
> Is there a mechanism I'm missing for storing these transactions to a database or something, and putting the response processing in a separate thread as well?  Some way to make asynchronous transactions reliable?
> 
> Thanks,
> Jesse

--
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog Talend Community Coder - http://coders.talend.com


Re: long running asynchronous service provider

Posted by Daniel Kulp <dk...@apache.org>.
In general, once the message patterns become longer than about 30 seconds, I would recommend completely rethinking the problem.  It’s no longer really a request/reply style invocation and likely shouldn’t be modeled as one.   At that point, I’d recommend one of a couple solutions:

1) Return an “id” from the initial post, then poll.  Basically, the client posts the request, the service does a quick validation of the request to make sure it’s valid and replies immediately with some sort of unique ID.  The client can then poll for the result, save the ID locally and continue polling if the client has to shutdown/restart, etc…   The client would have to be careful not to poll too often to not flood the server, but it shouldn’t require much computing power no the server side to see if the response is ready or not.

2) Async based, but using something like JMS with a persistent store for the transport.   I’d likely even not use WS-Addressing for this to make the client restart case much easier to implement.  One of the actual parameters to the service is the URL/JMS information to send the response to.   When the client starts up, it can connect to it’s queue.  If the queue is persistent, if the server had sent a response already, it would be there.  Fairly simple.   Everything is more or less modeled as a couple of one-ways for simplicity.   The JMS broker just makes sure the delivery is OK.

That said, WS-RM is there for this particular use case.   I just haven’t used it much.  I’d definitely defer to Dennis’ and Aki’s judgement and expertise for information about that.


Dan


On Nov 20, 2013, at 1:34 PM, Jesse Pangburn <Je...@infor.com> wrote:

> Hi,
> I use the jax-ws Provider mechanism to implement a service provider:
> @WebServiceProvider
> @ServiceMode(value = Service.Mode.MESSAGE)
> public class SOAPProvider implements Provider<StreamSource>
> 
> If WS-Addressing is enabled and I receive a message with a ReplyTo address, then the server will automatically send back an immediate HTTP 202 to the request.  When I finish computing a reply message and return it in a StreamSource (in this case), then CXF automatically makes a new HTTP request to the ReplyTo address and sends the reply there.  This is the normal (and expected) asynchronous processing flow.
> 
> It works, but it's not practical for a service that needs to reliably send reply messages to requests that it received.  Suppose the service even processed the request for a minute- it's quite likely that a service will be interrupted by a server restart or something.  The caller will never get their callback.  Worse, what if the transactions run for days?  And there are lots of them?  This mechanism works for testing but is not production quality for anything that needs reliable responses.
> 
> Is there a mechanism I'm missing for storing these transactions to a database or something, and putting the response processing in a separate thread as well?  Some way to make asynchronous transactions reliable?
> 
> Thanks,
> Jesse

-- 
Daniel Kulp
dkulp@apache.org - http://dankulp.com/blog
Talend Community Coder - http://coders.talend.com


RE: long running asynchronous service provider

Posted by Jesse Pangburn <Je...@infor.com>.
Hi Dennis,
Thanks for the suggestion!  I agree WS-ReliableMessaging can be used to solve the problem, but it requires the client to support the WS-RM protocol as well.

I was thinking that with regular asynchronous messaging that once the client got their HTTP 202 ack back, that they could count on getting a callback if the server side had some sort of storage to persist the relationship between message ids and ReplyTo URLs.  You are saying this is not possible (or maybe even desirable) and solving this problem requires using WS-RM?

Thanks,
Jesse

-----Original Message-----
From: Dennis Sosnoski [mailto:dms@sosnoski.com] 
Sent: Wednesday, November 20, 2013 12:06 PM
To: users@cxf.apache.org
Subject: Re: long running asynchronous service provider

You can use WS-ReliableMessaging for this: 
http://cxf.apache.org/docs/ws-reliablemessaging.html

   - Dennis

Dennis M. Sosnoski
Java Web Services Consulting <http://www.sosnoski.com/consult.html>
CXF and Web Services Security Training
<http://www.sosnoski.com/training.html>
Web Services Jump-Start <http://www.sosnoski.com/jumpstart.html>

On 11/21/2013 07:34 AM, Jesse Pangburn wrote:
> Hi,
> I use the jax-ws Provider mechanism to implement a service provider:
> @WebServiceProvider
> @ServiceMode(value = Service.Mode.MESSAGE) public class SOAPProvider 
> implements Provider<StreamSource>
>
> If WS-Addressing is enabled and I receive a message with a ReplyTo address, then the server will automatically send back an immediate HTTP 202 to the request.  When I finish computing a reply message and return it in a StreamSource (in this case), then CXF automatically makes a new HTTP request to the ReplyTo address and sends the reply there.  This is the normal (and expected) asynchronous processing flow.
>
> It works, but it's not practical for a service that needs to reliably send reply messages to requests that it received.  Suppose the service even processed the request for a minute- it's quite likely that a service will be interrupted by a server restart or something.  The caller will never get their callback.  Worse, what if the transactions run for days?  And there are lots of them?  This mechanism works for testing but is not production quality for anything that needs reliable responses.
>
> Is there a mechanism I'm missing for storing these transactions to a database or something, and putting the response processing in a separate thread as well?  Some way to make asynchronous transactions reliable?
>
> Thanks,
> Jesse
>


Re: long running asynchronous service provider

Posted by Dennis Sosnoski <dm...@sosnoski.com>.
You can use WS-ReliableMessaging for this: 
http://cxf.apache.org/docs/ws-reliablemessaging.html

   - Dennis

Dennis M. Sosnoski
Java Web Services Consulting <http://www.sosnoski.com/consult.html>
CXF and Web Services Security Training 
<http://www.sosnoski.com/training.html>
Web Services Jump-Start <http://www.sosnoski.com/jumpstart.html>

On 11/21/2013 07:34 AM, Jesse Pangburn wrote:
> Hi,
> I use the jax-ws Provider mechanism to implement a service provider:
> @WebServiceProvider
> @ServiceMode(value = Service.Mode.MESSAGE)
> public class SOAPProvider implements Provider<StreamSource>
>
> If WS-Addressing is enabled and I receive a message with a ReplyTo address, then the server will automatically send back an immediate HTTP 202 to the request.  When I finish computing a reply message and return it in a StreamSource (in this case), then CXF automatically makes a new HTTP request to the ReplyTo address and sends the reply there.  This is the normal (and expected) asynchronous processing flow.
>
> It works, but it's not practical for a service that needs to reliably send reply messages to requests that it received.  Suppose the service even processed the request for a minute- it's quite likely that a service will be interrupted by a server restart or something.  The caller will never get their callback.  Worse, what if the transactions run for days?  And there are lots of them?  This mechanism works for testing but is not production quality for anything that needs reliable responses.
>
> Is there a mechanism I'm missing for storing these transactions to a database or something, and putting the response processing in a separate thread as well?  Some way to make asynchronous transactions reliable?
>
> Thanks,
> Jesse
>