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
Step 2
Create a service endpoint interface
- 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
- 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
- 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
- <?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
- 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
- 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