9 Replies Latest reply on Apr 18, 2012 7:44 AM by spyhunter99

    How to set new SoapHandler for each invocation?

    meselfe

      From the JBossWS FAQ it appears that the Service object is thread safe:

       

      JAX-WS (JBossWS-Native)

      javax.xml.ws.Service - Thread safe

      The port proxy returned by getPort(..) methods of Service is not thread safe instead.

       

      But I need to set a new SoapHandler for each invocation because it is used to set security stuff that unique to each and every invocation:

       

      Service service = Service.create(someWsdlUrl, someQName);

      MyHandlerResolver resolver = new MyHandlerResolver();

      resolver.addHandler(new MySoapHandler(usercredentials));

      service.setHandlerResolver(resolver);

       

      Since the SoapHandler is set on the Service object it seems Im therefore forced to create a new instance of Service for each invocation? I assume theres a performance penalty associated with creating the Service object. Is there some other way I can set credentials uniquely to the invocation without creating a new Service instance every time?

       

      I should mention that the SoapHandler that deals with security supports many security protocols including one thats home grown.

       

      Using JBoss 5.1.0GA.

       

       


        • 1. Re: How to set new SoapHandler for each invocation?
          spyhunter99

          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

            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

              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

                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

                  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

                    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

                      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

                        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

                          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.