-
1. Re: How to set new SoapHandler for each invocation?
spyhunter99 Apr 17, 2012 9:29 AM (in response to meselfe)I've written soap handlers for virtually every framework that exists. I can't recall a single one that is stateful. They are all stateless. Instances of the service scale up and down with load and are controlled in the application container.
On the client side, they will persist as long as the client proxy object exists. One thing you can do is remove the handler from the collection, then readd it. Again, handlers are stateless. Having static variables inside them is unreliable.
Credentials are typically set in jaxws using the request context map object. Perhaps your solution might include clearing out the appropriate settings from there and readding them before invoking.
I'm not really sure what the question or problem is.
-
2. Re: How to set new SoapHandler for each invocation?
meselfe Apr 17, 2012 10:41 AM (in response to spyhunter99)The problem is Im trying to figure out how to build a web service client that will be running in a web application and will be used by hundreds of threads concurrently. It must set various security aspects uniquely on every invocation. The security is more customized than what is usually set through the BindingProvider thus Im using a SoapHandler.
So correct me if Im wrong: what I should do is create one Service instance and set the HandlerResolver only once? Each thread should use the same Service instance to create a Port instance confined to the thread?
The SoapHandler is thus used by all threads concurrently because its bound to the Service instance?
But then what about the SOAPMessageContext passed to the SoapHandler - is that unique to the thread? I would like to do something like this in the SoapHandler:
public boolean handleMessage(SOAPMessageContext msgContext) {
...
msgContext.put(MessageContext.HTTP_REQUEST_HEADERS,Collections.singletonMap(MY_HTTP_HEADER,Collections.singletonList(resolver.getUserCredentials())));
The "resolver" above will get the users credentials from the FacesContext in a way that would unique to the thread. I have this working but is this solution correct - Is the use of the SoapHandler and SOAPMessageContext correct from a thread safety perspective?
BTW where do you find this information about the SoapHandler - Ive been scouring through jsr 181,224,109 and various javadoc but theres hardly any info on the SoapHandler.
-
3. Re: How to set new SoapHandler for each invocation?
meselfe Apr 17, 2012 11:12 AM (in response to meselfe)Aha this one from jsr 224 cleared things up for me:
9.3.3 Handler Implementation Considerations
Handler instances may be pooled by a JAX-WS runtime system. All instances of a specific handler are
considered equivalent by a JAX-WS runtime system and any instance may be chosen to handle a particular
message. Different handler instances may be used to handle each message of an MEP. Different threads
may be used for each handler in a handler chain, for each message in an MEP or any combination of the
two. Handlers should not rely on thread local state to share information. Handlers should instead use the
message context, see section 9.4.
-
4. Re: How to set new SoapHandler for each invocation?
spyhunter99 Apr 17, 2012 12:56 PM (in response to meselfe)Well, it's my job to know, and primarily through experimentation and testing. I've also stumbled upon that jsr too, but only after I had came to the same conclusion.
The only thing that works differently than this is ASP.NET's Soap Extensions which is a totally different animal. If you are creating the client proxy object on demand from a jsp page, then once the page is done loading/executing, that object goes away, along with any handlers tied to it. The SOAP Message context of the client proxy object is unique to the instance of the client proxy object. This object can be used in multiple threads, but in your case (a jsp file) it is not. To the best of my knowledge, it's thread safe for use in a web app/jsp.
FYI, adding http headers to request/response messages via handlers isn't super reliable.
-
5. Re: How to set new SoapHandler for each invocation?
spyhunter99 Apr 17, 2012 1:01 PM (in response to spyhunter99)FYI, I don't use the handler resolver API. I usually type cast the service object to a binding provider, then get the request or response context and add the handlers that way. The good old configuration file is an even more flexible way to do it.
-
6. Re: How to set new SoapHandler for each invocation?
meselfe Apr 18, 2012 5:25 AM (in response to spyhunter99)Found this one http://www.javaworld.com/javaworld/jw-02-2007/jw-02-handler.html?page=3 that also describes what you said - set chainhandler in binding - or i can set my custom security stuff in the requestcontext which will be copied to the messagecontextthats passed to the soahhandler.
-
7. Re: How to set new SoapHandler for each invocation?
meselfe Apr 18, 2012 7:27 AM (in response to spyhunter99)spyhunter99 wrote:
FYI, adding http headers to request/response messages via handlers isn't super reliable.
I have that problem on JBoss too but not on Weblogic. What is the alternative method for setting the http header?
-
8. Re: How to set new SoapHandler for each invocation?
spyhunter99 Apr 18, 2012 7:41 AM (in response to meselfe)soap headers
I think what you're referring to was written to more or less identify what happens at the web service, not the client for the web service. Most frameworks/containers will spawn as many as 10 or more instances of a web service in order to handle concurrent requests, this also implies that any handlers associated with the service will also be created. The jsr statement is saying that it's possible for only one instance of the handler to be created and thus serve all of the inbound service requests etc.
Regardless, of how many copies of the handler that are, each invocation has its own message context which is unique to each client proxy instance. As long as you don't rely on private variables in your handler and store state information in the message context, then you're good to go
-
9. Re: How to set new SoapHandler for each invocation?
spyhunter99 Apr 18, 2012 7:44 AM (in response to spyhunter99)In addition, I just relooked at your code, you're pass the credentials via a constructor to the handler. that's no good. Add the credentials to the message context map in the client code, then pick then up again in the handler process message.