4

I'm trying to access the SOAP request and response via client side so that I can calculate the execution time for each call. I've implemented a SOAPHandler to achieve this but the handleMessage method is not being invoked (breakpoint doesn't get hit or no log gets logged). I am using wsimport to create the client side classes/stubs and also passing a binding file in as a parameter to wsimport command.

This is what I have done so far:

My binding file - handler-chain.xml

<jaxws:bindings
    xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    xmlns:jxb="http://java.sun.com/xml/ns/jaxb">
    <handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
        <handler-chain>
            <handler>
                <handler-name>LoggingSOAPHandler</handler-name>
                <handler-class>com.handler.LoggingSOAPHandler</handler-class>
            </handler>
        </handler-chain>
    </handler-chains>    
</jaxws:bindings>

wsimport command:

  <property name="package"       value="com.ws"/>
  <property name="src"           value="docroot/WEB-INF/src"/>
  <property name="classes"       value="docroot/WEB-INF/classes"/>
  <property name="bindingfile"   value="docroot/WEB-INF/src/com/handler/handler-chain.xml"/>
    <target name="wsimport">
        <exec executable="${jdk.home}/bin/wsimport">
          <arg line="-keep -s ${src} -p ${package} -d ${classes} -b ${bindingfile} ${wsdl}"/>
        </exec>
      </target>

When I run above wsimport command, all the stubs are created and the @HandlerChain annotation gets added to the stub service class as noted below:

@WebServiceClient(name = "TestService", targetNamespace = "http://webservice.com/", wsdlLocation = "http://test:8290/TEST/services/test?wsdl")
@HandlerChain(file = "TestService_Service_handler.xml")
public class TestService_Service
    extends Service
{
    ...
}

Here is the generated TestService_Service_handler.xml:

<?xml version="1.0" encoding="UTF-8"?><handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
  <handler-chain>
    <handler>
      <handler-name>LoggingSOAPHandler</handler-name>
      <handler-class>com.handler.LoggingSOAPHandler</handler-class>
    </handler>
  </handler-chain>
</handler-chains>

Here is my SOAPHandler:

public class LoggingSOAPHandler implements SOAPHandler<SOAPMessageContext> {

    private static Logger _logger = LoggerFactory.getLogger(LoggingSOAPHandler.class);

    @Override
    public boolean handleMessage(SOAPMessageContext messageContext) {

        Boolean outboundProperty = (Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

        if (outboundProperty.booleanValue()) {
            _logger.info("\nOutbound message:");
        } else {
            _logger.info("\nInbound message:");
        }
        return true;
    }

    @Override
    public boolean handleFault(SOAPMessageContext context) {
        _logger.info("Client : handleFault()......");
        return false;
    }

    @Override
    public void close(MessageContext context) {
        _logger.info("Client : close()......");

    }

    @Override
    public Set<QName> getHeaders() {
        _logger.info("Client : getHeaders()......");
        return null;
    }
}

When the webservice is called, handleMessage method doesn't get invoked at all. Any idea?
I'm using JAX-WS RI 2.2.4-b01 to generate the stubs.

Aaron McIver
  • 24,527
  • 5
  • 59
  • 88
shirook
  • 41
  • 1
  • 2

1 Answers1

2

A solution was found for this question but to answer the question, I have to provide more context about this project.

This project uses Spring MVC with JaxWsPortProxyFactoryBean to implement the JAX WS service interface.

Since the goal is to have all SOAP calls use the 'LoggingSOAPHandler' then 'LoggingSOAPHandler' has to be injected into JaxWsPortProxyFactoryBean via a HandlerResolver. I created a HandlerResolver implementation....

CustomHandlerResolver:

public class CustomHandlerResolver implements HandlerResolver {


    /**
     * Overrode in order to load custom handlers.
     * @see javax.xml.ws.handler.HandlerResolver#getHandlerChain(javax.xml.ws.handler.PortInfo)
     */
    public List<Handler> getHandlerChain(PortInfo portInfo) {
        List<Handler> handlerChain = new ArrayList<Handler>();
        LoggingSOAPHandler hh = new LoggingSOAPHandler();
        handlerChain.add(hh);
        return handlerChain;
    }
}

I added the hanlderResolver bean and injection into the service xml configuration file:

        <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:context="http://www.springframework.org/schema/context"
               xmlns:mvc="http://www.springframework.org/schema/mvc"
               xmlns:aop="http://www.springframework.org/schema/aop"       
               xmlns:tx="http://www.springframework.org/schema/tx" 
               xmlns:util="http://www.springframework.org/schema/util"   
               xsi:schemaLocation="http://www.springframework.org/schema/beans
               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
               http://www.springframework.org/schema/context
               http://www.springframework.org/schema/context/spring-context-3.0.xsd
               http://www.springframework.org/schema/mvc
               http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
               http://www.springframework.org/schema/aop
               http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
               http://www.springframework.org/schema/tx
               http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
               http://www.springframework.org/schema/util 
               http://www.springframework.org/schema/util/spring-util-3.0.xsd">

              <!-- Use custom HandlerResolver that loads a list of custom SOAP handlers --> 
              <bean id="CustomHandlerResolver" class="com.ws.handler.CustomHandlerResolver"/>   

              <bean id="registrationService" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
                 <property name="lookupServiceOnStartup" value="false" />  
                 <property name="serviceName"            value="TestService" />
                 <property name="serviceInterface"       value="com.ws.registration.TestService" />
                 <property name="wsdlDocumentUrl"        value="${registration.service}?wsdl" />
                 <property name="namespaceUri"           value="${registration.namespace}" />
                 <property name="endpointAddress"        value="${registration.service}" />
                 <property name="username"               value="${registration.username}"/>
                 <property name="password"               value="${registration.password}"/>
                 <property name="customProperties"       ref="jaxwsCustomProperties" />
                 <property name="handlerResolver"        ref="CustomHandlerResolver"/>
              </bean>

      .......    
    </beans>

So because the handler resolver is injected into the JaxWsPortProxyFactoryBean the handlers specified in the CustomHandlerResolver class are injected at run time.

Ernesto Rendon
  • 312
  • 2
  • 11
  • Could you please guide here: https://stackoverflow.com/questions/60260277/could-not-handle-mustunderstand-headers-http-docs-oasis-open-org-wss-2004-01 ? – PAA Feb 19 '20 at 11:33