JAX-WS SOAP handler Service side

For basic understanding of SOAP handlers please go through SOAP handler overview article.

Now we know that handlers can be used to intercept the incoming or outgoing SOAP messages.

In this article, we will learn about defining the SOAP handler at the server side.

Requirement


Create a web service and attach a handler to it.

This handler’s responsibility is to validate the incoming SOAP message to check the Client MAC address is within our trusted MAC address list or not.

If Client MAC address is within the trusted list then only allow client to access the published service.

If Client MAC address is not within the trusted list then throw SOAPFaultException to the client.

Let’s implement the Requirement step by step


Step 1

Create a new Java maven project in eclipse

soap_handler_server_proj_structure

Step 2

Create a service endpoint interface

1
2
3
4
5
6
7
8
9
10
11
12
package com.kb.ws;
 
import javax.jws.WebMethod;
import javax.jws.WebService;
 
@WebService
public interface HelloWorldService {
    
    @WebMethod
    public String sayHelloWorld();
 
}
package com.kb.ws;

import javax.jws.WebMethod;
import javax.jws.WebService;

@WebService
public interface HelloWorldService {
	
	@WebMethod
	public String sayHelloWorld();

}


We have created an interface and added one method sayHelloWorld() to expose as a service

Step 3

Create a service endpoint implementation

1
2
3
4
5
6
7
8
9
10
11
package com.kb.ws;
 
import javax.jws.WebService;
 
@WebService(endpointInterface="com.kb.ws.HelloWorldService")
public class HelloWorldServiceImpl implements HelloWorldService {
 
    public String sayHelloWorld() {
        return "Hello World";
    }
}
package com.kb.ws;

import javax.jws.WebService;

@WebService(endpointInterface="com.kb.ws.HelloWorldService")
public class HelloWorldServiceImpl implements HelloWorldService {

	public String sayHelloWorld() {
		return "Hello World";
	}
}


We have developed a web service implementation class by defining sayHelloWorld() method to return Hello World message.
We have also provided the end point interface to point to the interface defined in Step 2

Step 4

Create a SOAP handler class

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package com.kb.handler;
 
import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
 
import javax.xml.namespace.QName;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;
 
public class MACAddressValidationHandler implements SOAPHandler<SOAPMessageContext>{
        //Defined an array of trusted MAC address,If client passes any MAC address other than this,
        //Throw SOAPFaultException
    String arr[] = {"E0-DB-55-A4-10-Z4","E0-DB-55-A4-10-Z5","E0-DB-55-A4-10-Z6",
                                                                   "E0-DB-55-A4-10-Z7"};
    List<String> validMacAddresses = Arrays.asList(arr);
    
    public boolean handleMessage(SOAPMessageContext context) {
        System.out.println("Server : handleMessage() Begin");
        Boolean outBoundProperty  = (Boolean)    
                                           context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
        //If its an incoming message from client, then outBoundProperty will be false
        if(!outBoundProperty){
            try{
                SOAPMessage soapMsg = context.getMessage();
                SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
                    SOAPHeader soapHeader = soapEnv.getHeader();
 
                    //if no header, throw SOAPFaultException
                if (soapHeader == null){
                        generateErrorMessageAndThrowException(soapMsg, 
                                                                         "Missing SOAP header.");
                 }
                     
                 Iterator itr = 
                           soapHeader.extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT);
 
             //if no header block for next actor found,then throw SOAPFaultException
                 if (itr == null || !itr.hasNext()){
                     generateErrorMessageAndThrowException(soapMsg, 
                                                         "Missing header block for next actor.");
                     }
 
            //if no MAC address found then throw SOAPFaultException
                 Node macNode = (Node) itr.next();
                 String macValue = (macNode == null) ? null : macNode.getValue();
 
                  if (macValue == null){
                      generateErrorMessageAndThrowException(soapMsg, 
                                                        "Missing mac address in header block.");
                  }
 
               //if MAC address is not within the trusted MAC list, then throw SOAPFaultException
                   if(!validMacAddresses.contains(macValue)){
                       generateErrorMessageAndThrowException(soapMsg, 
                                                       "Invalid mac address, Access is denied.");
                   }
 
                   //Output the message to console
                   soapMsg.writeTo(System.out);
 
                }catch(SOAPException e){
                    System.err.println(e);
                }catch(IOException e){
                    System.err.println(e);
                }
 
                }
 
              //Returning true makes other handler chain to continue the execution
              return true;
    }
 
    public boolean handleFault(SOAPMessageContext context) {
        System.out.println("Server : handleFault() Begin");
        return true;
    }
 
    public void close(MessageContext context) {
        System.out.println("Server : close() Begin");
        
    }
 
    public Set<QName> getHeaders() {
        System.out.println("Server : getHeaders() Begin");
        return null;
    }
    
    private void generateErrorMessageAndThrowException(SOAPMessage msg, String reason) {
           try {
              SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
              SOAPFault soapFault = soapBody.addFault();
              soapFault.setFaultString(reason);
              throw new SOAPFaultException(soapFault);
           }
           catch(SOAPException e) {
               System.err.println(e);
           }
        }
}
package com.kb.handler;

import java.io.IOException;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.Node;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPConstants;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;
import javax.xml.ws.soap.SOAPFaultException;

public class MACAddressValidationHandler implements SOAPHandler<SOAPMessageContext>{
        //Defined an array of trusted MAC address,If client passes any MAC address other than this,
        //Throw SOAPFaultException
	String arr[] = {"E0-DB-55-A4-10-Z4","E0-DB-55-A4-10-Z5","E0-DB-55-A4-10-Z6",
                                                                   "E0-DB-55-A4-10-Z7"};
	List<String> validMacAddresses = Arrays.asList(arr);
	
	public boolean handleMessage(SOAPMessageContext context) {
		System.out.println("Server : handleMessage() Begin");
		Boolean outBoundProperty  = (Boolean)    
                                           context.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
		//If its an incoming message from client, then outBoundProperty will be false
		if(!outBoundProperty){
			try{
			    SOAPMessage soapMsg = context.getMessage();
			    SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
		            SOAPHeader soapHeader = soapEnv.getHeader();

		            //if no header, throw SOAPFaultException
			    if (soapHeader == null){
			            generateErrorMessageAndThrowException(soapMsg, 
                                                                         "Missing SOAP header.");
			     }
		             
			     Iterator itr = 
                           soapHeader.extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT);

	         //if no header block for next actor found,then throw SOAPFaultException
			     if (itr == null || !itr.hasNext()){
			    	 generateErrorMessageAndThrowException(soapMsg, 
                                                         "Missing header block for next actor.");
		             }

	        //if no MAC address found then throw SOAPFaultException
			     Node macNode = (Node) itr.next();
			     String macValue = (macNode == null) ? null : macNode.getValue();

			      if (macValue == null){
			    	  generateErrorMessageAndThrowException(soapMsg, 
                                                        "Missing mac address in header block.");
			      }

               //if MAC address is not within the trusted MAC list, then throw SOAPFaultException
			       if(!validMacAddresses.contains(macValue)){
			    	   generateErrorMessageAndThrowException(soapMsg, 
                                                       "Invalid mac address, Access is denied.");
			       }

			       //Output the message to console
			       soapMsg.writeTo(System.out);

				}catch(SOAPException e){
					System.err.println(e);
				}catch(IOException e){
					System.err.println(e);
				}

			    }

			  //Returning true makes other handler chain to continue the execution
			  return true;
	}

	public boolean handleFault(SOAPMessageContext context) {
		System.out.println("Server : handleFault() Begin");
		return true;
	}

	public void close(MessageContext context) {
		System.out.println("Server : close() Begin");
		
	}

	public Set<QName> getHeaders() {
		System.out.println("Server : getHeaders() Begin");
		return null;
	}
	
	private void generateErrorMessageAndThrowException(SOAPMessage msg, String reason) {
	       try {
	          SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
	          SOAPFault soapFault = soapBody.addFault();
	          soapFault.setFaultString(reason);
	          throw new SOAPFaultException(soapFault);
	       }
	       catch(SOAPException e) {
	    	   System.err.println(e);
	       }
	    }
}


We have created a SOAP Handler which will retrieve the MAC address from the SOAP Header for each incoming SOAP message

Handler will be executed before the actual web service implementation is executed.
So handler will decide whether call has to be continued to web service or not.

In our case, handler will throw SOAPFaultException if client’s MAC address is different from the trusted list otherwise it will take a call to the actual web service implementation.

Step 5

Create a SOAP handler XML file
handler-chain.xml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
    xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <javaee:handler-chain>
        <javaee:handler>
            <javaee:handler-class>com.kb.handler.MACAddressValidationHandler</javaee:handler-class>
        </javaee:handler>
    </javaee:handler-chain>
</javaee:handler-chains>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<javaee:handler-chains xmlns:javaee="http://java.sun.com/xml/ns/javaee"
	xmlns:xsd="http://www.w3.org/2001/XMLSchema">
	<javaee:handler-chain>
		<javaee:handler>
			<javaee:handler-class>com.kb.handler.MACAddressValidationHandler</javaee:handler-class>
		</javaee:handler>
	</javaee:handler-chain>
</javaee:handler-chains>


We have created the handler-chain.xml file to add our SOAP handler MACAddressValidationHandler in the handler list.

Step 6

Attach SOAP handler to Web service using @HandlerChain

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.kb.ws;
 
import javax.jws.HandlerChain;
import javax.jws.WebService;
 
@WebService(endpointInterface="com.kb.ws.HelloWorldService")
@HandlerChain(file="../handler/handler-chain.xml")
public class HelloWorldServiceImpl implements HelloWorldService {
 
    public String sayHelloWorld() {
        return "Hello World";
    }
}
package com.kb.ws;

import javax.jws.HandlerChain;
import javax.jws.WebService;

@WebService(endpointInterface="com.kb.ws.HelloWorldService")
@HandlerChain(file="../handler/handler-chain.xml")
public class HelloWorldServiceImpl implements HelloWorldService {

	public String sayHelloWorld() {
		return "Hello World";
	}
}


This file is already developed in Step 3,now we are giving information about the handlers to this web service implementation using @HandlerChain annotation.
In this annotation,we have specified the handler-chain.xml file name developed in previous step

Step 7

Create a web service publisher

1
2
3
4
5
6
7
8
9
10
11
12
13
package com.kb.endpoint;
 
import javax.xml.ws.Endpoint;
 
import com.kb.ws.HelloWorldServiceImpl;
 
public class HelloWorldPublisher {
 
    public static void main(String[] args) {
        Endpoint endpoint = Endpoint.create(new HelloWorldServiceImpl());
        endpoint.publish("http://localhost:8888/ws/soapHandler");
    }
}
package com.kb.endpoint;

import javax.xml.ws.Endpoint;

import com.kb.ws.HelloWorldServiceImpl;

public class HelloWorldPublisher {

	public static void main(String[] args) {
		Endpoint endpoint = Endpoint.create(new HelloWorldServiceImpl());
		endpoint.publish("http://localhost:8888/ws/soapHandler");
	}
}


We have created a web service end point publisher class which can publish our web service.

Step 8

Run the publisher class to publish the web service

Step 9

Verify the published service is running by accessing the WSDL using below url

http://localhost:8888/ws/soapHandler?wsdl

Download this project SOAPHandlerServer.zip

About the Author

Karibasappa G C (KB)
Founder of javainsimpleway.com
I love Java and open source technologies and very much passionate about software development.
I like to share my knowledge with others especially on technology 🙂
I have given all the examples as simple as possible to understand for the beginners.
All the code posted on my blog is developed,compiled and tested in my development environment.
If you find any mistakes or bugs, Please drop an email to kb.knowledge.sharing@gmail.com

Connect with me on Facebook for more updates

Share this article on