2 Replies Latest reply on Aug 8, 2011 10:48 AM by Ulrich K

    Websphere and Webservice: No Seam context, SOAPHandler not called

    Ulrich K Newbie

      I am trying to port our application to Websphere 7. This application (also) uses Webservices. Right now I am trying to get a simple example working: I have extended the jee5/booking example in Seam 2.2.2 with a simple TestService class.


      Everything seems to be working except that SOAP requests sent to this Webservice are not handled by the Seam SOAPRequestHandler.


      I always get an IllegalStateException: No active session context when calling any Seam method (like Identity.instance()). Also injection does not work; for example @Logger is null.


      --


      Details:


      The test Webservice is configured and running in Websphere:




      • It can be accessed with ?wsdl and the wsdl specification is shown

      • Methods can be called as long as they do not contain Seam specific operations

      • There are not Exceptions on startup in the server log





      This is what the Webservice class looks like (excerpt):


      @Stateless
      @Name("testService")
      @WebService
      public class TestService implements TestServiceRemote {
              @Logger private Log log;
              
              @WebMethod
              public String reverse(String sArg) {            
                      Identity idc = (Identity)Component.getInstance(Identity.class, true);
      
                      StringBuffer sb = new StringBuffer();
                      for (int i=sArg.length()-1; i>=0; --i)
                              sb.append(sArg.charAt(i));
      
                      return sb.toString();                   
              }
      }



      The file standard-jaxws-endpoint-config.xml is present as specified in the documentation.



      What I also tried:


      I have tried to specify an additional handler at many different locations. Ie as an addition to the webservices.xml (which I must provide for Websphere) or with the help of the @HandlerChain annotation.
      All show the same behavior: org.jboss.seam.webservice.SOAPRequestHandler does not seem to be used.
      This is also the result of debugging the call and examining the call trace.



      Anyone got any idea?

        • 1. Re: Websphere and Webservice: No Seam context, SOAPHandler not called
          Ulrich K Newbie

          Got it working for my simple example.


          It looks like Websphere (v7) requires handlers to be implementing the old (Java 1.4?) interface: javax.xml.rpc.handler.Handler.
          Seam uses the newer javax.xml.ws.handler.Handler for SOAPRequestHandler. They are unfortunately not compatible.


          So basically I have rewritten the SOAPRequestHandler for Websphere and the older handler interface.


          Also I only found one location where Websphere accepted my handler definition: That is in the webservices.xml inside the port-component.
          It looks like this:


          <handler>
                <handler-name>Websphere Seam Bridge Handler</handler-name>
                <handler-class>de.some.path.WebsphereSeamSoapHandler</handler-class>
          </handler>



          My handler class looks like this:



          package de.some.path.;
          
          import java.util.HashSet;
          import java.util.Iterator;
          import java.util.Set;
          
          import javax.servlet.http.HttpServletRequest;
          import javax.xml.namespace.QName;
          import javax.xml.rpc.handler.HandlerInfo;
          import javax.xml.soap.SOAPElement;
          import javax.xml.soap.SOAPEnvelope;
          import javax.xml.soap.SOAPException;
          import javax.xml.soap.SOAPHeader;
          
          import org.jboss.seam.contexts.Lifecycle;
          import org.jboss.seam.contexts.ServletLifecycle;
          import org.jboss.seam.core.ConversationPropagation;
          import org.jboss.seam.core.Manager;
          import org.jboss.seam.log.LogProvider;
          import org.jboss.seam.log.Logging;
          import org.jboss.seam.servlet.ServletRequestSessionMap;
          import org.jboss.seam.web.ServletContexts;
          
          // javax.xml.rpc.handler.Handler is taken from j2ee.jar from Websphere
          
          public class WebsphereSeamSoapHandler implements javax.xml.rpc.handler.Handler {
          
               public static final QName CIDQN = new QName("http://www.jboss.org/seam/webservice", "conversationId", "seam");
               private static final LogProvider log = Logging.getLogProvider(WebsphereSeamSoapHandler.class);   
               private Set<QName> headers = new HashSet<QName>();
               private String handlerName;
          
          
               @Override
               public boolean handleRequest(javax.xml.rpc.handler.MessageContext rpcContext) {
                    // It is a javax.xml.rpc.handler.soap.SOAPMessageContext
          
                    try
                    {          
                         HttpServletRequest request = 
                              (HttpServletRequest)rpcContext.getProperty("transport.http.servletRequest");
          
                         // Only for newer version of Seam?
                         //ServletLifecycle.beginRequest(request, ServletLifecycle.getServletContext());
                         
                         ServletLifecycle.beginRequest(request);
          
                         ServletContexts.instance().setRequest(request);
          
                         String conversationId = extractConversationId(rpcContext);
                         ConversationPropagation.instance().setConversationId( conversationId );
                         Manager.instance().restoreConversation();
          
                         ServletLifecycle.resumeConversation(request);             
          
                         return true;
                    }
                    catch (SOAPException ex)
                    {
                         log.error("Error handling inbound SOAP request", ex);
                         return false;
                    }
               }
          
               @Override
               public boolean handleResponse(javax.xml.rpc.handler.MessageContext rpcContext) {
                    try
                    {                
                         HttpServletRequest request = 
                              (HttpServletRequest)rpcContext.getProperty("transport.http.servletRequest");
          
                         String conversationId = Manager.instance().getCurrentConversationId();
                         if (conversationId != null)
                         {
                              javax.xml.rpc.handler.soap.SOAPMessageContext smc = 
                                   (javax.xml.rpc.handler.soap.SOAPMessageContext)rpcContext;
          
                              SOAPHeader header = smc.getMessage().getSOAPHeader();
                              if (header != null)
                              {
                                   SOAPElement element = header.addChildElement(CIDQN);
                                   element.addTextNode(conversationId);
                                   smc.getMessage().saveChanges();               
                              }            
                              else
                              {
                                   SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
                                   header =  envelope.addHeader();
                                   SOAPElement element = header.addChildElement(CIDQN);
                                   element.addTextNode(conversationId);
                                   smc.getMessage().saveChanges();
                              }
                         }
          
                         Manager.instance().endRequest(new ServletRequestSessionMap(request));
          
                         return true;
                    }
                    catch (SOAPException ex)
                    {
                         log.error("Exception processing outbound message", ex);
                         return false;
                    }
               }
          
               @Override
               public boolean handleFault(javax.xml.rpc.handler.MessageContext rpcContext) {
                    return true;
               }
          
               @Override
               public void init(HandlerInfo arg0) {
          
               }
          
               @Override
               public void destroy() {
                    Lifecycle.endRequest();
               }
          
               @Override
               public QName[] getHeaders() {
                    QName[] aHeaders = new QName[headers.size()];
                    headers.toArray(aHeaders);
                    return aHeaders;
               }
          
          
               public void setHeaders(Set<QName> headers) {
                    this.headers = headers;
               }   
          
               public String getHandlerName() {
                    return handlerName;
               }
          
               public void setHandlerName(String handlerName) {
                    this.handlerName = handlerName;
               }
          
          
               @Override
               public String toString() {
                    return (handlerName != null ? handlerName : super.toString());
               } 
          
               private String extractConversationId(
                         javax.xml.rpc.handler.MessageContext messageContext)
               throws SOAPException {
          
                    javax.xml.rpc.handler.soap.SOAPMessageContext smc 
                    = (javax.xml.rpc.handler.soap.SOAPMessageContext) messageContext;
          
                    SOAPHeader header = smc.getMessage().getSOAPHeader();
          
                    if (header != null) {
                         Iterator iter = header.getChildElements(CIDQN);
                         if (iter.hasNext()) {
                              SOAPElement element = (SOAPElement) iter.next();
                              return element.getFirstChild().getNodeValue();
                         }
                    }
          
                    return null;
               }
                  
          }
          
          



          This is the log file entry that finally gave me some hint about what to do. It does not appear very often:


          WSDDJAXRPCHan E com.ibm.ws.webservices.engine.deployment.wsdd.WSDDJAXRPCHandlerInfo getJavaClass WSWS3123E: Fehler: Die Java-Klasse de.some.path.DebugHandler, die für Handler null angegeben ist, muss javax.xml.rpc.handler.Handler oder com.ibm.wsspi.webservices.rpc.handler.HandlerClassFactory implementieren. Der Handler wird übersprungen.


          After that I did find a respective documentation entry for Websphere 7...

          • 2. Re: Websphere and Webservice: No Seam context, SOAPHandler not called
            Ulrich K Newbie

            On a side note: the whole business was finally solved/implemented with using JAXWS for Websphere (and the command endptEnabler).