javaee / metro-jax-ws

https://javaee.github.io/metro-jax-ws/
Other
132 stars 68 forks source link

Asynchrony Support #787

Open glassfishrobot opened 15 years ago

glassfishrobot commented 15 years ago

JAX-WS programming model doesn't support server side asynchrony. Some services could run much longer to produce responses. Keeping http connections open for that long periods is not a scalable solution. So, we require the request message to have an non-anonymous ReplyTo. But that's not enough. A service could require human intervention and that could take a while. This means that the host processing the request would need to keep the jvm/machine up the entire time - which could be days. And, of course, the same is true for the client waiting for the response. It seems that jaxws really should have some mechanism by which it can (sort of) suspend processing so that it can continue later once the response message is ready - then the jaxws runtime can continue from where it left off.

This kind of synchronous method cannot be used for server side asynchrony as there will be a thread to handle the response(java callstack). If the service processing takes a lot of time, keeping threads around is not a scalable solution.

Provider is a low-level API targeted towards document-centric processing. So, there needs to be an asynchronous solution for SEI services. The client side programming model does support it using callback, and polling. See sections 2.3.4 in JAX-WS spec. Typical signatures for polling, and callback are something as follows:

Response getPriceAsync(String ticker) Future<?> getPriceAsync(String ticker, AsyncHandler)

This allows client-side threads to do some other processing until a response is received. The same thing(or similar approach) can be used on the server side. Fox example: JAX-WS runtime: Calls getPriceAsync with its own impl of AsyncHandler Application: Releases JAX-WS runtime thread. Starts Processing in its own JAX-WS runtime: JAX-WS runtime reuses the original thread Application: Calls AsyncHandler#handleResponse when it has response JAX-WS runtime: Gets the response from Response, and starts the response processing

glassfishrobot commented 15 years ago

Reported by jitu@java.net

glassfishrobot commented 15 years ago

gilbertpilz@java.net said: A scenario that illustrates a use case for this issue can be found here: http://www.wstf.org/docs/scenarios/sc009/sc009.xml.

glassfishrobot commented 15 years ago

dugibm@java.net said: This is becoming a very important issue for us. Not having support in jax-ws for long running async operations will limit jax-ws's adoption in enterprise applications.

glassfishrobot commented 14 years ago

m_potociar@java.net said: This is mainly a JAX-WS RI related comment, but it might be relevant:

When designing the solution it would be good to keep in mind that there are (addressable or WS-MakeConnection enabled) endpoint scenarios in which a server-side tube wants to autonomously generate and send a "response" protocol message (without receiving a prior request message).

glassfishrobot commented 14 years ago

jitu@java.net said: Created an attachment (id=266) Proposal and Issues

glassfishrobot commented 14 years ago

m_potociar@java.net said: Hi Jitu, In your proposal, the ResponseDispatch interface defines send() and sendFault() methods. Looking at the existing JAX-WS API, There are 2 similar classes:

1. AsyncHandler - which defines handleResponse() method 2. Dispatch - which defines a set of invoke...() methods

I wonder if it would be possible to reuse one of these two method name patterns rather than defining a new one. My preferred choice for the ResponseDispatch interface would be:

public interface ResponseDispatch

{ void invoke(T response); void invoke(Throwable exception); }

I am not sure about the purpose of the proposed getContext() method. It seems to me as it should belong to a different interface. At first sight it doesn't seem to be related to the main function of the proposed ResponseDispatch interface.

Another thing is the name of @AsyncFault annotation. I wonder if it could be renamed just to @Fault or @ApplicationFault ? That would decouple the annotation name from the async MEP so potentially we could reuse the annotation also for other MEPs in the future if needed.

The last two things: 1. I don't like the coupling between the JAX-WS interface and the underlying transport (HTTP) in your proposal. A true SOAP stack should be transport independent. 2. If WS-MakeConnection is used, it should be possible to invoke the asynchronous endpoint even from a non-addressable client (a client that sends messages containing WS-MC anonymous address in the wsa:ReplyTo header).

glassfishrobot commented 14 years ago

jitu@java.net said:

AsyncHandler - which defines handleResponse() method

Why AsyncHandler is not reused is explained in the proposal. If has considered server-side asynchrony in the first version, it would have been possible.

2. Dispatch - which defines a set of invoke...() methods

That has two much client side baggage like Dispatch extending BindingProvider. Otherwise, it would have been good choice.

I wonder if it would be possible to reuse one of these two method name patterns

It would be possible. Do you see any advantages or convenience for the developer ?

I am not sure about the purpose of the proposed getContext() method.

It is primarily the WebServiceContext.getMessageContext(). We are are still discussing whether getContext() should give WebServiceContext itself.

Another thing is the name of @AsyncFault annotation. I am hoping that this would go away as the SEI methods can have throws clause with service-specific exceptions. Still in discussion.

1. I don't like the coupling between the JAX-WS interface and the underlying transport (HTTP) in your proposal. A true SOAP stack should be transport independent.

The API and the spec will be transport independent. But, we will define certain binding aspects for SOAP/HTTP.

2. If WS-MakeConnection is used, it should be possible to invoke the asynchronous endpoint even from a non-addressable client (a client that sends messages containing WS-MC anonymous address in the wsa:ReplyTo header).

I think you are saying the same as in Issue9 in the proposal. An endpoint may contain both synchronous and asynchronous operations. I am hoping that all(sync & async) the operations can be invoked without addressing in the picture. But ResponseDispatch serailization will be allowed only with addressing+non- anonymous responses. Still under discussion.

glassfishrobot commented 14 years ago

jitu@java.net said: Adding chen to cc

glassfishrobot commented 14 years ago

romixlev@java.net said: It is not so obvious from your proposal (https://jax- ws.dev.java.net/nonav/issues/showattachment.cgi/266/ResponseDispatch.html) if it supports usual parameters of user-defined types as it is the case for the usual @WebService services. It is also not quite clear, if this proposed model would support Java->WSDL generation. For example, the special ResponseDispatch parameter is probably not mapped (or reflected in by any other means) to an operation parameter in WSDL in all situations, e.g. when clients are not supposed to be aware of asynchrony on the server-side and should continue using usual synchronous, blocking invocations (on the client-side). But ResponseDispatch's template parameter type should be probably mapped to the WSDL's operation response type.

Also, I have the feeling that ResponseDispatch, while being technically a pretty good proposal, mixes implementation details with the exposure details of web services towards WS clients. For example, if WS-Adressing is not used, then the fact that a given WS uses server-side asynchrony is a pure implementation detail, that should not affect anything else like clients or tooling.

Especially, Java->WSDL mapping may be affected by it, eventually, and become more complex and less straight-forward. Developer who develops a Web Service with server-side asynchrony, needs to use a special new ResponseDispatch parameter in his exposed web method and by doing that changes this method's API at the Java class level. May be using the usual way of describing the web methods (i.e. annotated Java method with a user-defined return value type and parameter types, reflecting only externally visible interfaces used by clients) and special new annotations like @AsyncWebMethod, plus some sort of resource injection for ResponseDispatch or AsyncProvider's Callback and for WebServiceContext, would make server-side asynchronous WS programming model more similar to the usual-one. Also the tooling like wsimport and wsgen, as well as many IDEs supporting Web Services, would need less modifications to supppot the new features, I guess, because they do not need to treat any special ResponseDispatch parameters in a special way.

BTW, one of the main reasons why many developers are leaving JavaEE towards other frameworks is that efficient asynchronous execution of components and explicit control over multi-threading is too limiting in JavaEE for certain kinds of applications. There is a need for very scalable, soft real-time performance in many enterprise and telecommunications systems. Some of such applications need to serve tens or hundreds of thousends of requests per second. I think, there is a lot of movement recently towards scalable non JavaEE soltuions, e.g. Scala with its actors, many of the scripting languages on top of the JVM, frameworks like Kilim and JetLang, etc. Many of them revolve around very light-weight threads, NIO and the like. Most of them do not integrate nicely with JavaEE, mostly due to the reasons mentioned above (no way efficiently to control multi-threading, heavy weight threads used by Java, etc). It is important to keep that in mind, when working on the new JSRs and improving the existing JSRs. It would benefit everyone, if JSRs/specs could be used by all those non JavaEE frameworks. But this requires that specs and RIs are written and implemented with this idea in mind and do not assume that only JavaEE is the target.

Specifically for JAX-WS it may mean that the spec or RI should not assume only the usual threading models (Thread, Executor) and may be take into account that other alternatives may be in place. Having a configurable support for alternative multi-threading mechanisms (e.g. by means of having more abstract interfaces for multi-threading and the like) may allow effective usage of JAX-WS with other non JavaEE frameworks (Scala, Kilim, JetLang, etc).

glassfishrobot commented 14 years ago

scchen@java.net said: This ResponseDispatch proposal is specifically for "long running" async(LRA) operation in which case the request information may need to be stored and retrieved later when the response is ready. The ResponseDispatch is intended to encapsulate the correlation between the request and response.

If the "long running" situation is taken into the consideration, several of romixlev's questions might be answered. Because it is long running, the client app most likely will not want to call it in the synchronous style, and it has to use some protocol support (ex. ws-addressing) in order to be async.

This proposal does not assume how or which thread will execute the ResponseDispatch to send the response or fault. The ResponseDispatch is made serializable so that the application logic can restore the ResponseDispatch instance whenever the response is ready; the API could provide other mechanism to restore the ResponseDispatch instance than serializable.

A LRA operation is allowed to use user-defined value types as long as the value types are supported by JAXB2. The type argument of ResponseDispatch is mapped to the output message of the wsdl operation. LRA operation is for both java2wsdl and wsdl2java. In java2wsdl, in addition to use a parameterized ResponseDispatch as parameter to make a method LRA, we may want to add some new annotations (ex. @AsyncFault). In wsdl2java, a new wsdl2java customization element may be used to generate a LRA style method from a wsdl request-response operation. The details are still under discussion.

If you don't expect your business logic takes a long time to complete, you do not need to use this ResponseDispatch programming model. I believe JAX-WS has (or will have in near future) the annotations to mark an normal method as async so that the container knows to deliver the response in async fashion.

I certainly agreed with romixlev in that we want to improve the JavaEE programming model so that it supports more scalable implementation. It is not so clear to me how the LRA/ResponseDispatch programming model could also accommodate the threading discussion romixlev had. We would like to have more information on this.

glassfishrobot commented 14 years ago

romixlev@java.net said:

This ResponseDispatch proposal is specifically for "long running" async(LRA) operation in which case the request information may need to be stored and retrieved later when the response is ready. The ResponseDispatch is intended to encapsulate the correlation between the request and response.

If the "long running" situation is taken into the consideration, several of romixlev's questions might be answered.

I understand that the main focus of the proposal is more on really "long running" async operations (where long may mean minutes, hours, days).

But on my side, I have more interest in the scalability in terms of number of requests that can be accepted for processing and processed simultaneously. I would like to escape the "one-thread-per-request" model, which limits this kind of scalability. I'd like to be able to accept dozens or even hundreds of thousands of requests. Each of these requests is not very long running, but there is a huge number of such requests. Deploymens on the AS and triggering via HTTP Servlets just does not scale to this extent (mainly due to the one thread per request approach). We started looking into a standalone usage of JAX-WS (may be via Grizzly) to overcome some of these issues.

Applications that I have in mind are sort of workflows (distantly similar to BPEL) exposed via WS. Such workflows receive a huge number of triggering requests (e.g. from different users) and reacts to them by e.g. invoking other external SOAP web services based on dynamic conditions and then returning the results of such invocations back to the caller. Most of the time, these workflows actually wait for the completion of those external WS invocations. Once external WS returns a value, it is propagated to the original caller that triggered the workflow.

As you can imagine, while waiting for results of external WS, the workflow WS just occupies the thread even though it does not consume any CPU time. This may result in the situation, where all available threads just wait and no new request can be processed as all of the threads are occupied. Such outcome is of course very unfortunate. Therefore, the ability to decouple request processing from the receiving thread (so that it can be freed for more meaningful tasks than waiting) and ability to return results later (eventually inside a different thread) is a very nice solution to this problem.

As far as I understand, your proposal would easily cover such a scenario and eventually much more.

BTW, I'm aware that there are some other potential solutions, like JMS, etc. But mentioned workflows should be easy to integrate with e.g. Web 2.0 application. So, use of JMS is not really an option.

Because it is long running, the client app most likely will not want to call it in the synchronous style, and it has to use some protocol support (ex. ws-addressing) in order to be async.

See my above comments. Invocations of workflows are not so long running that clients always need to provide callbacks via WS-Adressing or do polling. More over, many of Web 2.0 clients cannot easily support WS-addressing. And then, such an explicitly asynchronous solution requires that both sides follow this architecture. This is probably fine, if you control (development and execution) both sides. But in my case, many client apps are developed and controlled by 3rd parties. Therefore, I cannot force all of them to follow this way of communication, but still want to support them as good as I can.

A LRA operation is allowed to use user-defined value types as long as the value types are supported by JAXB2. The type argument of ResponseDispatch is mapped to the output message of the wsdl operation. LRA operation is for both java2wsdl and wsdl2java. In java2wsdl, in addition to use a parameterized ResponseDispatch as parameter to make a method LRA, we may want to add some new annotations (ex. @AsyncFault). In wsdl2java, a new wsdl2java customization element may be used to generate a LRA style method from a wsdl request-response operation. The details are still under discussion.

OK. I see how you would do java2wsdl and wsdl2java mappings. But what I meant with my comment is: Yes, this can be done as you describe. But it would require changes in the tooling for doing these mappings. And even more important, it would require that a developer adds a new ResponseDispatch parameter to the signature of the exposed web method, even though this parameter is not a real parameter passed by a web service client. This parameter is actually inserted/injected by the run-time. Why is the return type in the signature of the exposed method void? And why does the type argument of this special parameter ResponseDispatch becomes the output message of the WSDL operation? For usual exposed web methods it would be handled totally differently. Their return type would be mapped to the output message of the WSDL operation, wouldn't it?

So, I'm asking if the proposed method of mapping is the most natural way of doing it? Wouldn't a more transparent approach be easier to use and also require less modifications in the tooling? In the ideal case, it should be actually almost transparent for the developer. It should be as easy as adding an annotation on the web method or having an XML descriptor describing which methods should be handled asynchronously. BTW, if signatures of web methods are not touched by LRA, it can be even possible to add such annotations programatically at run-time (e.g. AOP, etc) to any JAX-WS web service, which potentially opens up some interesting opportunities.

If you don't expect your business logic takes a long time to complete, you do not need to use this ResponseDispatch programming model. I believe JAX-WS has (or will have in near future) the annotations to mark an normal method as async so that the container knows to deliver the response in async fashion.

Could you elaborate a bit more on this? What annotations exactly do you have in mind? Can you provide any concrete references?

I certainly agreed with romixlev in that we want to improve the JavaEE programming model so that it supports more scalable implementation. It is not so clear to me how the LRA/ResponseDispatch programming model could also accommodate the threading discussion romixlev had. We would like to have more information on this.

OK. I just wanted to say, that there are some very popular non JavaEE frameworks and languages (Scala, Clojure, Groovy, J-you-name-it, etc) that still use Java or at least JVM. Those systems could also greatly benefit from using JAX-WS.

Many of these systems do not have some of JavaEE limitations like lack of explicit control over multi-threading, etc. Some of those system are significantly more scalable and even provide alternative multi-threading implementations, e.g. light-weight threads (e.g. Kilim can start 1000000 light- weight threads on a usual JVM). As you can imagine, it may slightly shift the perspective. With that in mind, all parts of the spec that somehow depend on multi-threading or implicitly rely on JavaEE semantics of it may require a review. It may turn out that these parts of the spec just assume too much, e.g. that everyone uses only Executors or that number of threads should be kept small, etc.

In understand, that JSRs are written and agreed in such a way, that it is "doable" to implement them on a typical deployment platform, which is in many cases JavaEE. But I think that in general JSRs(especially those representing major stacks like SOAP, REST and so on) should not ignore or underestimate all those mentioned alternative systems and frameworks running on top of Java or JVM, just because they are not part of JavaEE or the like. Eventually, those systems will become a mainstream. It is better for JSRs and RIs based on it to be a part of this evolving infrastructure. Otherwise, there is a change to become obsolete.

glassfishrobot commented 14 years ago

scchen@java.net said: 1. You can use @Addressing annotation to make a regular non-void webmethod an async one without using the ResponseDispatch which is specifically for long running operation that needs to reconstruct the correlation context later.

@Addressing(responses=

{NON_ANONYMOUS, ANONYMOUS}

) String echo(String str) {...

2. The JAX-WS spec does not dictate "one-thread-per-request" model; I am not sure if the servlet spec requires that threading model either. But I understood that is usually how the server is implemented because it is simple and straightforward. I am not sure if the JSR-109 or JavaEE-WebService dictates the threading model, but the @WebServiceContext injection defined in JSR-109 could imply "one-thread-per-request" model because the WebServiceContext contains the messageContext which is per request.

glassfishrobot commented 14 years ago

File: ResponseDispatch.html Attached By: jitu@java.net

glassfishrobot commented 7 years ago

This issue was imported from java.net JIRA JAX_WS-787