Handler example using JAXWS 2.0

This techtip will focus on how to use JAX-WS 2.0 LogicalMessage Handlers and SOAP Handlers to read a message sent from a client to a webservice endpoint and back again. The example code below was developed and tested using a GlassFish implementation.

To understand the configuration and use of handlers in JAX-WS 2.0 you will need to be familiar with the following specifications


JSR 224: JavaTM API for XML-Based Web Services (JAX-WS) 2.0 specification
JSR 109: Implementing Enterprise Web Services

This handler example will demonstrate how to configure 3 kinds of handlers (Service based, Port based, and Protocol based) for both the client and server. These handlers when run, will simply determine which direction the message is traveling and will display the name of the handler that's doing the processing and the contents of the message. This example makes use of customization files to configure the server side handlers and programatic handlers to configure the client side handlers. Although this is a very simplistic example it does show a way of using handlers to intercept a Logical/SOAP message. Certainly the user could expand and enhance this example to do far greater things.

Developing the WebService Server Side Endpoint

Step 1

Create your wsdl description for your webservices endpoint which will send and receive messages.

a) HandlerTestService.wsdl

The following wsdl was used to develop this example. Notice that there is one operation doHandlerTest and one port HandlerPort that have been specified. During the running of this example, there will be one test that will run using the HandlerPort and doHandlerTest operation.


<?xml version="1.0" encoding="UTF-8"?>
<!--
  Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->

<definitions 
    name="HandlerTestService"
    targetNamespace="http://HandlerTestService.org/wsdl"
    xmlns:types="http://HandlerTestService.org/types"
    xmlns="http://schemas.xmlsoap.org/wsdl/"
    xmlns:tns="http://HandlerTestService.org/wsdl"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">

  <types>
     <schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://HandlerTestService.org/types" targetNamespace="http://HandlerTestService.org/types">
       <complexType name="MyActionType">
            <sequence>
                <element name="inputString" type="xsd:string"/>
            </sequence>
       </complexType>
       <complexType name="MyResultType">
            <sequence>
                <element name="outputString" type="xsd:string"/>
            </sequence>
       </complexType>
    </schema>
  </types>

  <message name="Hello" >
    <part name="action" type="types:MyActionType" />
  </message>
  <message name="HelloResponse">
    <part name="result" type="types:MyResultType" />
  </message>


  <portType name="HandlerPortType">
    <operation name="doHandlerTest">
      <input message="tns:Hello" />
      <output message="tns:HelloResponse" />
    </operation>
  </portType>

  <binding name="HandlerBinding" type="tns:HandlerPortType">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="rpc" />
    <operation name="doHandlerTest">
      <soap:operation soapAction="" />
      <input>
        <soap:body use="literal" namespace="http://HandlerTestService.org/wsdl"/>
      </input>
      <output>
        <soap:body use="literal" namespace="http://HandlerTestService.org/wsdl"/>
      </output>
    </operation>
  </binding>

  <service name="HandlerTestService">
    <port name="HandlerPort" binding="tns:HandlerBinding">
      <soap:address location="http://localhost:8001/HandlerTestService/jaxws/HandlerTest"/>
    </port>
  </service>
</definitions>

Step 2

First, create a customization file for the server side generation.

a) customfile-server.xml


<!--
  Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
--> 

<jaxws:bindings wsdlLocation="wsdl/HandlerTestService.wsdl"  version="2.0" 
    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">    

    <jaxws:bindings node="wsdl:definitions">
        <jaxws:package name="handlertest.server"/> 
    </jaxws:bindings>
    
    <jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='http://HandlerTestService.org/types']" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        <jxb:schemaBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb">
            <jxb:package name="handlertest.server"/> 
        </jxb:schemaBindings>
    </jaxws:bindings>

    <jaxws:bindings>
        <handler-chains xmlns="http://java.sun.com/xml/ns/javaee">
           <!-- ====================== -->
           <!-- service based handlers -->
           <!-- ====================== -->
           <handler-chain>
              <handler>
                  <handler-name>ServerLogicalHandler1</handler-name>
                  <handler-class>handlertest.server.ServerLogicalHandler1</handler-class>
              </handler>
              <handler>
                  <handler-name>ServerSOAPHandler1</handler-name>
                  <handler-class>handlertest.server.ServerSOAPHandler1</handler-class>
              </handler>
           </handler-chain>
           <!-- ====================== -->
           <!-- port based handlers    -->
           <!-- ====================== -->
           <handler-chain>
              <port-name-pattern xmlns:ns1="http://HandlerTestService.org/wsdl">ns1:HandlerPort</port-name-pattern>
              <handler>
                  <handler-name>ServerLogicalHandler2</handler-name>
                  <handler-class>handlertest.server.ServerLogicalHandler2</handler-class>
              </handler>
              <handler>
                  <handler-name>ServerSOAPHandler2</handler-name>
                  <handler-class>handlertest.server.ServerSOAPHandler2</handler-class>
              </handler>
           </handler-chain>
           <!-- ====================== -->
           <!-- protocol based handlers    -->
           <!-- ====================== -->
           <handler-chain>
              <protocol-bindings>##SOAP11_HTTP</protocol-bindings>
              <handler>
                  <handler-name>ServerLogicalHandler3</handler-name>
                  <handler-class>handlertest.server.ServerLogicalHandler3</handler-class>
              </handler>
              <handler>
                  <handler-name>ServerSOAPHandler3</handler-name>
                  <handler-class>handlertest.server.ServerSOAPHandler3</handler-class>
              </handler>
           </handler-chain>
        </handler-chains>
    </jaxws:bindings>
</jaxws:bindings>

b) Run wsimport to generate the server side artifacts using the above customization file.


Execute the command: ant import-wsdl-server

The output follows:

Buildfile: build.xml

import-wsdl-server:

do-wsdl2java:
     [echo] Invoking WsImport task (WSDL-to-Java mapping)
 [wsimport] command line: wsimport /files/jdk/jdk1.5.0_06/jre/bin/java -classpath /files/sun/appserver9.0.pe.promoted/lib/javaee.jar:/files/sun/appserver9.0.pe.promoted/lib/appserv-ws.jar:/home/user/blog/handlertest/classes com.sun.tools.ws.WsImport -d /home/user/blog/handlertest/classes -keep -s /home/user/blog/handlertest/generated -verbose wsdl/HandlerTestService.wsdl -wsdllocation WEB-INF/wsdl/HandlerTestService.wsdl -b /home/user/blog/handlertest/src/handlertest/customfile-server.xml
 [wsimport] handlertest/server/HandlerPortType.java
 [wsimport] handlertest/server/HandlerTestService.java
 [wsimport] handlertest/server/MyActionType.java
 [wsimport] handlertest/server/MyResultType.java
 [wsimport] handlertest/server/ObjectFactory.java
 [wsimport] handlertest/server/package-info.java
 [wsimport] handlertest/server/HandlerPortType.java
 [wsimport] handlertest/server/HandlerTestService.java
 [wsimport] handlertest/server/MyActionType.java
 [wsimport] handlertest/server/MyResultType.java
 [wsimport] handlertest/server/ObjectFactory.java
 [wsimport] handlertest/server/package-info.java

Step 3

Create and implement the code for the webservices server side endpoint along with the various server side handlers.

a) HandlerTestImpl.java


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.server;

import javax.jws.WebService;

@WebService(
    portName="HandlerPort",
    targetNamespace="http://HandlerTestService.org/wsdl",
    serviceName="HandlerTestService",
    wsdlLocation="WEB-INF/wsdl/HandlerTestService.wsdl",
    endpointInterface="handlertest.server.HandlerPortType")

public class HandlerTestImpl implements HandlerPortType {
    public MyResultType doHandlerTest(MyActionType action){
        System.out.println("in endpoint");
        System.out.println("MSG="+action.getInputString());
        MyResultType mrt = new MyResultType();
        mrt.setOutputString("endpoint");
        return mrt;
    }
}

b) ServerLogicalHandlerBase.java

The following base class implements all the necessary functionality of a Logical Handler. The actual server side Logical Handlers will extend this class.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.server;

import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.LogicalMessage;

import javax.xml.transform.OutputKeys;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;

import javax.annotation.PreDestroy;
import javax.annotation.PostConstruct;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

public class ServerLogicalHandlerBase implements LogicalHandler
{

    private String handlerName=null;
   
    public void setHandlerName(String h) {
        handlerName=h;
    }
    public String getHandlerName() {
        return handlerName;
    }

    @PostConstruct
    public void myInit() {
        System.out.println("in "+handlerName+":myInit");
        System.out.println("exiting "+handlerName+":myInit");
    }

    @PreDestroy
    public void myDestroy() {
        System.out.println("in "+handlerName+":myDestroy");
        System.out.println("exiting "+handlerName+":myDestroy");
    }

    public boolean handleMessage(LogicalMessageContext context)
    {
        System.out.println("in "+handlerName+":handleMessage");

        boolean direction= ((Boolean)context.get(LogicalMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();
        if (direction) {
            System.out.println("direction = outbound");
        } else {
            System.out.println("direction = inbound");
        }

        dumpMsg(context);

        System.out.println("exiting "+handlerName+":handleMessage");
        return true;
    }

    public void close(MessageContext context)
    {
        System.out.println("in "+handlerName+":close");
        System.out.println("exiting "+handlerName+":close");
    }

    public boolean handleFault(LogicalMessageContext context)
    {
        System.out.println("in "+handlerName+":handleFault");
        System.out.println("exiting "+handlerName+":handleFault");
        return true;
    }

    public void dumpMsg(MessageContext context) {
        System.out.println("in "+handlerName+":dumpMsg");

        try {
            LogicalMessage lm = ((LogicalMessageContext)context).getMessage();
            if (lm != null) {
                Source source = lm.getPayload();
                if (source != null) {
                    System.out.println("MSG="+getSourceAsString(source));
                } else {
                    System.out.println("No message payload was present");
                }
            } else {
               System.out.println("No message was present");
            }
        } catch (Exception e) {
              e.printStackTrace();
        }

        System.out.println("exiting "+handlerName+":dumpMsg");


       return;
    }

    public String getSourceAsString(Source s) throws Exception {
        System.out.println("in "+handlerName+":getSourceAsString");

        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        OutputStream out = new ByteArrayOutputStream();
        StreamResult streamResult = new StreamResult();
        streamResult.setOutputStream(out);
        transformer.transform(s, streamResult);

        System.out.println("exiting "+handlerName+":getSourceAsString");
        return streamResult.getOutputStream().toString();
    }
}

c) ServerSOAPHandlerBase.java

The following base class implements all the necessary functionality of a SOAP Handler. The actual server side SOAP Handlers will extend this class.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.server;

import javax.xml.transform.Source;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.PreDestroy;
import javax.annotation.PostConstruct;

import javax.xml.namespace.QName;

import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPMessage;

import java.io.ByteArrayOutputStream;

public class ServerSOAPHandlerBase implements SOAPHandler
{
    private String handlerName=null;

    public void setHandlerName(String h) {
        handlerName=h;
    }
    public String getHandlerName() {
        return handlerName;
    }

    @PostConstruct
    public void myInit() {
        System.out.println("in "+handlerName+":myInit");
        System.out.println("exiting "+handlerName+":myInit");
    }

    @PreDestroy
    public void myDestroy() {
        System.out.println("in "+handlerName+":myDestroy");
        System.out.println("exiting "+handlerName+":myDestroy");
    }

    public Set getHeaders() {
        return new TreeSet();
    }

    public boolean handleMessage(SOAPMessageContext context)
    {
        System.out.println("in "+handlerName+":handleMessage");

        boolean direction= ((Boolean)context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();
        if (direction) {
            System.out.println("direction = outbound");
        } else {
            System.out.println("direction = inbound");
        } 

        dumpMsg(context);
        
        System.out.println("exiting "+handlerName+":handleMessage");
        return true;
    }

    public void close(MessageContext context)
    {
        System.out.println("in "+handlerName+":close");
        System.out.println("exiting "+handlerName+":close");
    }

    public boolean handleFault(SOAPMessageContext context)
    {
        System.out.println("in "+handlerName+":handleFault");
        System.out.println("exiting "+handlerName+":handleFault");
        return true;
    }


    public void dumpMsg(MessageContext context) {
       System.out.println("in "+handlerName+":dumpMsg");
       try {
          System.out.println("in "+handlerName+":dumpMsg");
          SOAPMessage soapmsg = ((SOAPMessageContext)context).getMessage();
          System.out.println("MSG="+getMsgAsString(soapmsg));

       } catch (Exception e) {
           e.printStackTrace();
       }
       System.out.println("exiting "+handlerName+":dumpMsg");
       return;
    }


    public String getMsgAsString(SOAPMessage message) {
        System.out.println("in "+handlerName+":getMsgAsString");
        String msg  = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            message.writeTo(baos);
            msg = baos.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("exiting "+handlerName+":getMsgAsString");
        return msg;
    }
}

d) ServerLogicalHandler1.java

The following handler extends the Logical Handler base class. The remaining Logical Handlers are identical to this hander except for the name. For brevity, I won't list the code here but you will be able to download the entire example at the end of this blog.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.server;

public class ServerLogicalHandler1 extends ServerLogicalHandlerBase
{
    private final String HANDLERNAME="ServerLogicalHandler1";

    public ServerLogicalHandler1(){
       super();
       super.setHandlerName(HANDLERNAME);
    }
}
e) ServerSOAPHandler1.java

The following handler extends the Logical Handler base class. The remaining Logical Handlers are identical to this hander except for the name. For brevity, I won't list the code here but you will be able to download the entire example at the end of this blog.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.server;

public class ServerSOAPHandler1 extends ServerSOAPHandlerBase
{
    private final String HANDLERNAME="ServerSOAPHandler1";

    public ServerSOAPHandler1(){
       super();
       super.setHandlerName(HANDLERNAME);
    }
}
Step 4

Build and compile the webservices server side endpoint code and package it in a war file.


Execute the command:ant compile-server create-war

The output follows:

compile-server:
     [echo] compile-server
    [javac] Compiling 9 source files to /home/user/blog/handlertest/classes

compile-server-w2j:
     [echo] compile-server-w2j

create-war:
     [echo] create-war
     [echo] Creating war file /home/user/blog/handlertest/dist/handlertest/HandlerTestService.war
      [war] Building war: /home/user/blog/handlertest/dist/handlertest/HandlerTestService.war
     [echo] Created war file /home/user/blog/handlertest/dist/handlertest/HandlerTestService.war

build-server-w2j:

build-server:
Step 5

Deploy the webservices endpoint packaged in the war to a GlassFish appserver environment.


Execute the command:ant deploy

The output follows:

Buildfile: build.xml

checkPlatform:

configUnix:

configWindows:

filter.password.file:
     [copy] Copying 1 file to /home/user/blog/handlertest/build

configPlatform:

deploy:
     [echo] deploy
     [echo] Deploying /home/user/blog/handlertest/dist/handlertest/HandlerTestService.war.
     [echo] asadmin deploy --user admin --passwordfile /home/user/blog/handlertest/build/password.txt --host localhost --port 4848 --contextroot HandlerTestService --target server --updload=true
     [exec] Command deploy executed successfully.
Step 6 Verify web service application is deployed:

In your browser go to URL location of the published WSDL for this server:


o http://host:port/HandlerTestService/jaxws/HandlerTest?WSDL

where host and port are the settings of your configured GlassFish web server host and port settings, HandlerTestService is the context root of your web service application, /jaxws/HandlerTest is the URL alias specified in the web.xml deployment descriptor for deployed endpoint and ?WSDL is how the published WSDL is accessed.

A WSDL should be displayed if the service is up and running.

Developing WebServices Client Side code

Step 1

Run wsimport to generate the client side artifacts to communicate with the webservices endpoint developed in previous section pointing to the wsdl of the deployed endpoint on a GlassFish appserver environment.

a) First create the customization file for the client side generation.

customfile-client.xml


<!--
  Copyright 2006 Sun Microsystems, Inc. All rights reserved.
  SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
-->

<jaxws:bindings wsdlLocation="wsdl/HandlerTestService.wsdl"  version="2.0" 
    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">    
   
    <jaxws:bindings node="wsdl:definitions">
        <jaxws:package name="handlertest.client"/>
    </jaxws:bindings>
 
    <jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='http://HandlerTestService.org/types']" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        <jxb:schemaBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb">
            <jxb:package name="handlertest.client"/> 
        </jxb:schemaBindings>
    </jaxws:bindings>
</jaxws:bindings>

b) Run wsimport to generate the client side artifacts to communicate with the endpoint developed in the previous section pointing to the wsdl of the deployed endpoint on a GlassFish appserver environment using the above customization file.


Execute the command:ant import-wsdl-client

The output follows:

Buildfile: build.xml

import-wsdl-client:

do-wsdl2java:
     [echo] Invoking WsImport task (WSDL-to-Java mapping)
 [wsimport] command line: wsimport /files/jdk/jdk1.5.0_06/jre/bin/java -classpath /files/sun/appserver9.0.pe.promoted/lib/javaee.jar:/files/sun/appserver9.0.pe.promoted/lib/appserv-ws.jar:/home/user/blog/handlertest/classes com.sun.tools.ws.WsImport -d /home/user/blog/handlertest/classes -keep -s /home/user/blog/handlertest/generated -verbose wsdl/HandlerTestService.wsdl -wsdllocation http://localhost:8001/HandlerTestService/jaxws/HandlerTest?WSDL -b /home/user/blog/handlertest/src/handlertest/customfile-client.xml
 [wsimport] handlertest/client/HandlerPortType.java
 [wsimport] handlertest/client/HandlerTestService.java
 [wsimport] handlertest/client/MyActionType.java
 [wsimport] handlertest/client/MyResultType.java
 [wsimport] handlertest/client/ObjectFactory.java
 [wsimport] handlertest/client/package-info.java
 [wsimport] handlertest/client/HandlerPortType.java
 [wsimport] handlertest/client/HandlerTestService.java
 [wsimport] handlertest/client/MyActionType.java
 [wsimport] handlertest/client/MyResultType.java
 [wsimport] handlertest/client/ObjectFactory.java
 [wsimport] handlertest/client/package-info.java
Step 3

Create the client code to communicate with the deployed endpoint and the various client side handlers.

a) Client.java


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.client;

import java.io.\*;
import java.net.\*;
import java.util.\*;
import javax.xml.soap.\*;

import javax.xml.ws.handler.HandlerResolver;
import javax.xml.ws.handler.PortInfo;
import javax.xml.ws.handler.Handler;
import javax.xml.ws.WebServiceRef;

import javax.xml.namespace.QName;


public class Client {
    private static HandlerPortType port = null;

    @WebServiceRef
    private static HandlerTestService service = null;

    public static void main(String[] args ) {
	Client client = new Client();

	System.out.println("------------------------------------------");
	System.out.println("Executing Tests");
	System.out.println("------------------------------------------");
	client.doHandlersTest();
    }

    public void doHandlersTest() {
	 System.out.println("doHandlersTest");
	 boolean pass = true;

      final String THEBINDINGPROTOCOL = javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING;
      final String NAMESPACEURI = "http://HandlerTestService.org/wsdl";
      final String PORT_NAME    = "HandlerPort";
      final QName PORT_QNAME = new QName(NAMESPACEURI, PORT_NAME);


	 System.out.println("Configuring client side handlers");
      service.setHandlerResolver(new HandlerResolver() {
        public List<Handler> getHandlerChain(PortInfo info) {
           List<Handler> handlerList = new ArrayList<Handler>();
           System.out.println("--------------------------------------------------");
           System.out.println("Registering the following service based handlers:"); 
           System.out.println("ClientSOAPHandler1, ClientLogicalHandler1");
           System.out.println("--------------------------------------------------");
           System.out.println("Construct HandleInfo for ClientSOAPHandler1 and add to HandlerChain");
           Handler handler = new handlertest.client.ClientSOAPHandler1();
           handlerList.add(handler);
           System.out.println("Construct HandleInfo for ClientLogicalHandler1 and add to HandlerChain");
           handler = new handlertest.client.ClientLogicalHandler1();
           handlerList.add(handler);
           if (info.getBindingID().equals(THEBINDINGPROTOCOL)) {
               System.out.println("--------------------------------------------------");
               System.out.println("Registering the following protocol based handlers:"); 
               System.out.println("ClientSOAPHandler2, ClientLogicalHandler2");
               System.out.println("--------------------------------------------------");
               System.out.println("Construct HandleInfo for ClientSOAPHandler2 and add to HandlerChain");
               handler = new handlertest.client.ClientSOAPHandler2();
               handlerList.add(handler);
               System.out.println("Construct HandleInfo for ClientLogicalHandler2 and add to HandlerChain");
               handler = new handlertest.client.ClientLogicalHandler2();
               handlerList.add(handler);
           }
           if (info.getPortName().equals(PORT_QNAME)) {
               System.out.println("--------------------------------------------------");
               System.out.println("Registering the following port based handler:"); 
               System.out.println("ClientSOAPHandler3");
               System.out.println("--------------------------------------------------");
               System.out.println("Construct HandleInfo for ClientSOAPHandler3 and add to HandlerChain");
               handler = new handlertest.client.ClientSOAPHandler3();
               handlerList.add(handler);
           }
           System.out.println("HandlerChainList="+handlerList);
           System.out.println("HandlerChain size = " + handlerList.size());
           return handlerList;
        }
 
     });
	
     port = service.getHandlerPort();
	System.out.println("port="+port);

     String expected="endpoint";

	try {
         MyActionType request = new MyActionType();
         request.setInputString("client");
	    MyResultType response = port.doHandlerTest(request);
         String actual = response.getOutputString();
         System.out.println("result="+actual);
         if (!actual.equals(expected)){
	       pass = false;
         }
	} catch(Exception e) {
	    System.err.println("Caught exception: " + e.getMessage());
            e.printStackTrace(System.err);
	    pass = false;
 	}
	if (pass)
	    System.out.println("doHandlersTest PASSED");
	else
	    System.err.println("doHandlersTest FAILED");
    }
}

b) ClientLogicalHandlerBase.java

The following base class implements all the necessary functionality of a Logical Handler. The actual client side Logical Handlers will extend this class.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.client;

import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.LogicalHandler;
import javax.xml.ws.handler.LogicalMessageContext;
import javax.xml.ws.LogicalMessage;

import javax.xml.transform.OutputKeys;

import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamResult;

import javax.annotation.PreDestroy;
import javax.annotation.PostConstruct;

import java.io.ByteArrayOutputStream;
import java.io.OutputStream;

public class ClientLogicalHandlerBase implements LogicalHandler<LogicalMessageContext>
{

    private String handlerName=null;
   
    public void setHandlerName(String h) {
        this.handlerName=h;
    }
    public String getHandlerName() {
        return this.handlerName;
    }

    @PostConstruct
    public void myInit() {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":myInit");
        System.out.println("exiting "+handlerName+":myInit");
        System.out.println("------------------------------------");
    }

    @PreDestroy
    public void myDestroy() {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":myDestroy");
        System.out.println("exiting "+handlerName+":myDestroy");
        System.out.println("------------------------------------");
    }

    public boolean handleMessage(LogicalMessageContext context) {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":handleMessage");

        boolean direction= ((Boolean)context.get(LogicalMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();
        if (direction) {
            System.out.println("direction = outbound");
        } else {
            System.out.println("direction = inbound");
        }

        dumpMsg(context);

        System.out.println("exiting "+handlerName+":handleMessage");
        System.out.println("------------------------------------");
        return true;
    }

    public void close(MessageContext context) {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":close");
        System.out.println("exiting "+handlerName+":close");
        System.out.println("------------------------------------");
    }

    public boolean handleFault(LogicalMessageContext context) {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":handleFault");
        System.out.println("exiting "+handlerName+":handleFault");
        System.out.println("------------------------------------");
        return true;
    }

    public void dumpMsg(MessageContext context) {
        try {
            LogicalMessage lm = ((LogicalMessageContext)context).getMessage();
            if (lm != null) {
                Source source = lm.getPayload();
                if (source != null) {
                    System.out.println("MSG="+getSourceAsString(source));
                } else {
                    System.out.println("No message payload was present");
                }
            } else {
               System.out.println("No message was present");
            }
        } catch (Exception e) {
              e.printStackTrace();
        }
        return;
    }

    public String getSourceAsString(Source s) throws Exception {
        Transformer transformer = TransformerFactory.newInstance().newTransformer();
        transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
        transformer.setOutputProperty(OutputKeys.METHOD, "xml");
        OutputStream out = new ByteArrayOutputStream();
        StreamResult streamResult = new StreamResult();
        streamResult.setOutputStream(out);
        transformer.transform(s, streamResult);

        return streamResult.getOutputStream().toString();
    }
}

c) ClientSOAPHandlerBase.java

The following base class implements all the necessary functionality of a SOAP Handler. The actual client side SOAP Handlers will extend this class.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.client;

import javax.xml.transform.Source;
import java.util.Set;
import java.util.TreeSet;
import javax.annotation.PreDestroy;
import javax.annotation.PostConstruct;

import javax.xml.namespace.QName;

import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.soap.SOAPMessage;

import java.io.ByteArrayOutputStream;

public class ClientSOAPHandlerBase implements SOAPHandler<SOAPMessageContext>
{

    private String handlerName=null;

    public void setHandlerName(String h) {
        this.handlerName=h;
    }
    public String getHandlerName() {
        return this.handlerName;
    }

    @PostConstruct
    public void myInit() {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":myInit");
        System.out.println("exiting "+handlerName+":myInit");
        System.out.println("------------------------------------");
    }

    @PreDestroy
    public void myDestroy() {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":myDestroy");
        System.out.println("exiting "+handlerName+":myDestroy");
        System.out.println("------------------------------------");
    }

    public Set<QName> getHeaders() {
        return new TreeSet<QName>();
    }

    public boolean handleMessage(SOAPMessageContext context) {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":handleMessage");

        boolean direction= ((Boolean)context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY)).booleanValue();
        if (direction) {
            System.out.println("direction = outbound");
        } else {
            System.out.println("direction = inbound");
        } 

        dumpMsg(context);
        
        System.out.println("exiting "+handlerName+":handleMessage");
        System.out.println("------------------------------------");
        return true;
    }

    public void close(MessageContext context) {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":close");
        System.out.println("exiting "+handlerName+":close");
        System.out.println("------------------------------------");
    }

    public boolean handleFault(SOAPMessageContext context) {
        System.out.println("------------------------------------");
        System.out.println("in "+handlerName+":handleFault");
        System.out.println("exiting "+handlerName+":handleFault");
        System.out.println("------------------------------------");
        return true;
    }


    public void dumpMsg(MessageContext context) {
       try {
          SOAPMessage soapmsg = ((SOAPMessageContext)context).getMessage();
          System.out.println("MSG="+getMsgAsString(soapmsg));

       } catch (Exception e) {
           e.printStackTrace();
       }
       return;
    }


    public String getMsgAsString(SOAPMessage message) {
        String msg  = null;
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            message.writeTo(baos);
            msg = baos.toString();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return msg;
    }
}

d) ClientLogicalHandler1.java

The following handler extends the Logical Handler base class. The remaining Logical Handlers are identical to this hander except for the name. For brevity, I won't list the code here but you will be able to download the entire example at the end of this blog.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.client;

public class ClientLogicalHandler1 extends ClientLogicalHandlerBase
{
    private final String HANDLERNAME="ClientLogicalHandler1";

    public ClientLogicalHandler1(){
       super();
       super.setHandlerName(HANDLERNAME);
    }
}

e) ClientSOAPHandler1.java

The following handler extends the SOAP Handler base class. The remaining Logical Handlers are identical to this hander except for the name. For brevity, I won't list the code here but you will be able to download the entire example at the end of this blog.


/\*
 \* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
 \* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 \*/

package handlertest.client;

public class ClientSOAPHandler1 extends ClientSOAPHandlerBase
{
    private final String HANDLERNAME="ClientSOAPHandler1";

    public ClientSOAPHandler1(){
       super();
       super.setHandlerName(HANDLERNAME);
    }
}
Step 3

Build and compile the client code.


Execute the command:ant compile-client

The output follows:

Buildfile: build.xml

compile-client:
     [echo] compile-client
    [javac] Compiling 9 source files to /home/user/blog/handlertest/classes
Step 4

Run the client code which will communicate with the deployed webservices endpoint


Execute the command:ant runclient

The output follows:

Buildfile: build.xml

checkPlatform:

configUnix:

configWindows:

filter.password.file:
     [copy] Copying 1 file to /home/user/blog/handlertest/build

configPlatform:

runclient:
     [echo] runclient handlertest.client.Client
     [exec] ------------------------------------------
     [exec] Executing Tests
     [exec] ------------------------------------------
     [exec] doHandlersTest
     [exec] Configuring client side handlers
     [exec] --------------------------------------------------
     [exec] Registering the following service based handlers:
     [exec] ClientSOAPHandler1, ClientLogicalHandler1
     [exec] --------------------------------------------------
     [exec] Construct HandleInfo for ClientSOAPHandler1 and add to HandlerChain
     [exec] Construct HandleInfo for ClientLogicalHandler1 and add to HandlerChain
     [exec] --------------------------------------------------
     [exec] Registering the following protocol based handlers:
     [exec] ClientSOAPHandler2, ClientLogicalHandler2
     [exec] --------------------------------------------------
     [exec] Construct HandleInfo for ClientSOAPHandler2 and add to HandlerChain
     [exec] Construct HandleInfo for ClientLogicalHandler2 and add to HandlerChain
     [exec] --------------------------------------------------
     [exec] Registering the following port based handler:
     [exec] ClientSOAPHandler3
     [exec] --------------------------------------------------
     [exec] Construct HandleInfo for ClientSOAPHandler3 and add to HandlerChain
     [exec] HandlerChainList=[handlertest.client.ClientSOAPHandler1@3fa6cd, handlertest.client.ClientLogicalHandler1@dfe303, handlertest.client.ClientSOAPHandler2@b0ede5, handlertest.client.ClientLogicalHandler2@1d27069, handlertest.client.ClientSOAPHandler3@d22462]
     [exec] HandlerChain size = 5
     [exec] port=com.sun.xml.ws.client.EndpointIFInvocationHandler@17b1d64
     [exec] ------------------------------------
     [exec] in ClientLogicalHandler1:handleMessage
     [exec] direction = outbound
     [exec] MSG=<ans:doHandlerTest xmlns:ans="http://HandlerTestService.org/wsdl"><action><inputString>client</inputString></action></ans:doHandlerTest>
     [exec] exiting ClientLogicalHandler1:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientLogicalHandler2:handleMessage
     [exec] direction = outbound
     [exec] MSG=<ans:doHandlerTest xmlns:ans="http://HandlerTestService.org/wsdl"><action><inputString>client</inputString></action></ans:doHandlerTest>
     [exec] exiting ClientLogicalHandler2:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler1:handleMessage
     [exec] direction = outbound
     [exec] MSG=<?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soapenv:Body><ans:doHandlerTest xmlns:ans="http://HandlerTestService.org/wsdl"><action><inputString>client</inputString></action></ans:doHandlerTest></soapenv:Body></soapenv:Envelope>
     [exec] exiting ClientSOAPHandler1:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler2:handleMessage
     [exec] direction = outbound
     [exec] MSG=<?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soapenv:Body><ans:doHandlerTest xmlns:ans="http://HandlerTestService.org/wsdl"><action><inputString>client</inputString></action></ans:doHandlerTest></soapenv:Body></soapenv:Envelope>
     [exec] exiting ClientSOAPHandler2:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler3:handleMessage
     [exec] direction = outbound
     [exec] MSG=<?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soapenv:Body><ans:doHandlerTest xmlns:ans="http://HandlerTestService.org/wsdl"><action><inputString>client</inputString></action></ans:doHandlerTest></soapenv:Body></soapenv:Envelope>
     [exec] exiting ClientSOAPHandler3:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler3:handleMessage
     [exec] direction = inbound
     [exec] MSG=<?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soapenv:Body><ans:doHandlerTestResponse xmlns:ans="http://HandlerTestService.org/wsdl"><result><outputString>endpoint</outputString></result></ans:doHandlerTestResponse></soapenv:Body></soapenv:Envelope>
     [exec] exiting ClientSOAPHandler3:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler2:handleMessage
     [exec] direction = inbound
     [exec] MSG=<?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soapenv:Body><ans:doHandlerTestResponse xmlns:ans="http://HandlerTestService.org/wsdl"><result><outputString>endpoint</outputString></result></ans:doHandlerTestResponse></soapenv:Body></soapenv:Envelope>
     [exec] exiting ClientSOAPHandler2:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler1:handleMessage
     [exec] direction = inbound
     [exec] MSG=<?xml version="1.0" ?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soapenv:Body><ans:doHandlerTestResponse xmlns:ans="http://HandlerTestService.org/wsdl"><result><outputString>endpoint</outputString></result></ans:doHandlerTestResponse></soapenv:Body></soapenv:Envelope>
     [exec] exiting ClientSOAPHandler1:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientLogicalHandler2:handleMessage
     [exec] direction = inbound
     [exec] MSG=<ans:doHandlerTestResponse xmlns:ans="http://HandlerTestService.org/wsdl"><result><outputString>endpoint</outputString></result></ans:doHandlerTestResponse>
     [exec] exiting ClientLogicalHandler2:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientLogicalHandler1:handleMessage
     [exec] direction = inbound
     [exec] MSG=<ans:doHandlerTestResponse xmlns:ans="http://HandlerTestService.org/wsdl"><result><outputString>endpoint</outputString></result></ans:doHandlerTestResponse>
     [exec] exiting ClientLogicalHandler1:handleMessage
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler3:close
     [exec] exiting ClientSOAPHandler3:close
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler2:close
     [exec] exiting ClientSOAPHandler2:close
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientSOAPHandler1:close
     [exec] exiting ClientSOAPHandler1:close
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientLogicalHandler2:close
     [exec] exiting ClientLogicalHandler2:close
     [exec] ------------------------------------
     [exec] ------------------------------------
     [exec] in ClientLogicalHandler1:close
     [exec] exiting ClientLogicalHandler1:close
     [exec] ------------------------------------
     [exec] result=endpoint
     [exec] doHandlersTest PASSED

Note: If you examine the output of the appservers server.log file, you will see similar output as that displayed by the client

Sample code

A sample package which provides the complete example of the techniques covered by this techtip is downloadable from here

The sample package includes the source code, required descriptor files, and the build scripts inorder to build the example.


Steps to install and run the sample:

Step  1. Download GlassFish from the GlassFish Project page.

Step  2. Set the following environment variables:

          ANT_HOME  - path to location of Ant installation. This example uses Ant 1.6.5.
          JAVA_HOME - path to location of JDK5.0 installation.

         Also, add the Ant location to your PATH environment variable.

Step  3. Download the sample package and extract its contents.

	To get started using this techtip all you have to edit is the
	following file:
	
	o handlertest/build/common.properties
	
	The main properties to set are the ones listed below based on your
	glassfish installation properties. You should check the others to ensure
	they are also correct
	
	
	<!-- Main Properties to Set -->

	<!-- Only these need be set -->
	<property name="jdk.home" value="/files/java/jdk1.5.0"/>
	<property name="appserver.home" value="/sun/appserver9"/>
	<property name="tests.home" value="/home/user/handlertest"/>
	<property name="webserver.host" value="localhost"/>
	<property name="webserver.port" value="8001"/>

Step  4. Start the GlassFish Application Server 

Step  5. cd handlertest/src/handlertest

Step  6. Type the following to build, deploy and run the sample:

         ant
Comments:

thank you for this example.
Please, I want to know How do you to get the wsdl?
Because I generated my own, based on my interface, and he is not a party mime.
Is what I need to change in the interface or modify the wsdl by hand?
Thanks

Posted by Ghita on March 27, 2008 at 05:19 AM EDT #

In section "Developing the WebService Server Side Endpoint" above, step 6 shows you how to access the wsdl from a browser.

Posted by Stephen DiMilla on May 05, 2008 at 04:27 AM EDT #

How to return FileInputStream from JAX-WS @webMethod?
I am using NetBeans 6.0, Apachae Tomcat 6.0 and JAX-WS 2.1.

Posted by Somesh Ghosh on May 20, 2008 at 07:33 PM EDT #

Thanks for the post on doing MTOM. It should be a big help. After I found and edited common.properties, I had no problem building the server & client. But when I run, the client fails on every test. I am using JAX-WS RI 2.1.3.1-hudson-417-SNAPSHOT and I am wondering if you could post the version you used.

Posted by Pam Holzner on May 22, 2008 at 05:59 AM EDT #

Pam
Thanks for the post. I've been on vacation for a week so I'm trying to catchup with emails. Once I'm done, I'll start to look at your issue and get back to you. Thanks again steved

Posted by Stephen DiMilla on May 23, 2008 at 03:51 AM EDT #

Somesh, Thanks for the post. I've been on vacation for a week so I'm trying to catchup with emails. Once I'm done, I'll start to look at your issue and get back to you. Thanks again steved

Posted by Stephen DiMilla on May 23, 2008 at 03:51 AM EDT #

sss

Posted by guest on June 11, 2008 at 07:20 AM EDT #

Please ignore my question about which version of JAX-WS to use. I was able to get your example to work. What IDE do you use? I'm using NetBeans and wondering if there is a better choice.

Posted by Pam Holzner on June 13, 2008 at 09:18 AM EDT #

can anybody please comment.
what would happen if the code implements soaphandler but the request do not contain soap protocol. say may be using xml over http.
will the server side program throw error or does nothing?
the main question is like can I use same design pattern for all types of protocol requests.

Posted by abc on June 15, 2008 at 10:50 PM EDT #

If you take a look at the jaxws 2.0/2.1 spec, you'll see that there are 3 ways to match a handler, by port, protocol, and pattern. If the request doesn't fit into one of those 3 categories, I believe the request will be ignored by the handlers.
steved

Posted by Stephen DiMilla on June 16, 2008 at 01:09 AM EDT #

Pam
I have used netbeans 5.5.1 in the past but for most of my work I still use VI on solaris.

Posted by Stephen DiMilla on June 16, 2008 at 01:16 AM EDT #

Hello Stephen,
I was trying to build and run the sample, got some error. Please help.

-----------------------
BUILD FAILED
C:\\handlertest\\src\\handlertest\\build.xml:11: The following error occurred while
executing this line:
C:\\handlertest\\build\\common.xml:18: taskdef class com.sun.tools.ws.ant.WsImport
cannot be found
-----------------------

Posted by Arvi on July 17, 2008 at 06:39 AM EDT #

The first thing that comes to mind is, did you set the values in the common.properties file. Specifically "<property name="appserver.home" value="C:\\work\\ri\\appserver9.0.pe.promoted"/>"
to the location of the appserver (ie. glassfish location)??

Basically the build infrastructure can't find the wsimport ant task that is included in the appserver.

steved

Posted by Stephen DiMilla on July 17, 2008 at 07:03 AM EDT #

Thanks for your response Stephen. My system path variable was pointing to the ant inside Glassfish v2 (C:\\Program Files\\glassfish-v2ur2\\lib\\ant). Changing this to point standalone ant version fixed the issue.

Thanks Again !

Posted by Arvi on July 17, 2008 at 09:08 AM EDT #

sd

Posted by guest on July 07, 2010 at 04:15 PM EDT #

can i have the example of the build script

Posted by MDCS on September 27, 2010 at 04:26 PM EDT #

This example uses ant to build so I'm not sure what "build script" your asking about.

steved

Posted by Stephen DiMilla on September 28, 2010 at 01:02 AM EDT #

Step 3 of the "Steps to install and run the sample:" instructions allows you to download all the code and build infrastructure. You can obtain it from there.

To save you time the URL is:
http://blogs.sun.com/roller/resources/sdimilla/handlertest.zip

Posted by Stephen DiMilla on September 28, 2010 at 06:45 AM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

sdimilla

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today