Sunday, January 26, 2014

J2EE SOAP Interceptor example

  In this post I will give an example about How to use SOAP Handlers In J2EE application. Suppose that you have developed a web service, and you want to intercept the incoming or the inbound message before it is hit the web service.

  For Instance, if you want to check the incoming credentials if it is correct or not, if yes, let the user complete his/her request and forward the request to the web services, else, through an Exception that stating that the incoming credentials are not valid.

1.     SOAP Header Interceptor Class
The following class must implements SOAPHandler class to be an interceptor for the inbound message.

import java.util.Iterator;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPFault;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPHeaderElement;
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 SOAPHeaderInterceptor implements SOAPHandler<SOAPMessageContext> {
      
       public boolean handleMessage(SOAPMessageContext messageContext) {

              try {        
                /** Read SOAP message */
                SOAPMessage soapMsg = messageContext.getMessage();
                Boolean outboundProperty =
(Boolean) messageContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

           /** Read SOAP requests only */
           if ( ! outboundProperty ) {
              SOAPHeader soapHeader = messageContext.getMessage().getSOAPHeader();
              SOAPBody soapBody = messageContext.getMessage().getSOAPBody();
                          
              if (soapHeader != null ) {
                 // Extract all Soap Headers
                 Iterator iterator = soapHeader.extractAllHeaderElements();
                                 
                 if (iterator.hasNext()) {
                     SOAPHeaderElement he = (SOAPHeaderElement)            iterator.next();
                     NodeList list = he.getChildNodes();

                    /** Extract Child Nodes username and password elements */
                    for (int i = 0; i < list.getLength(); i++) {

                       /** Read element userName from the SOAP message
                          and check its value, if it's wrong raise an error */
                        if (list.item(i).getLocalName() != null) {
                           if (list.item(i).getLocalName().equals("userName")) {
                              if (!list.item(i).getTextContent().equals("test")) {
                                  attacheErrorMessage( soapMsg );
                                                              }
                                                             
        /** Read element password from the SOAP message
                         and check its value, if it's wrong raise an error  */
                        } else if( list.item(i).getLocalName().equals("password") ) {
                          if (!list.item(i).getTextContent().equals("test")) {
                                  attacheErrorMessage(soapMsg );
                          }
                        }
                      }
                    }
                  }
                }
              }

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

              return true;
       } //handleMessage

      
       /** Method to inject any information about a given
        * error into the soap message request
        * @param errorMessage
        * @param cause
        */
       private void attacheErrorMessage( SOAPMessage errorMessage ) {
           try {
              SOAPBody soapBody = errorMessage.getSOAPPart().getEnvelope().getBody();
              SOAPFault soapFault = soapBody.addFault();
              soapFault.setFaultString( "Wrong credentials" );
                    
              throw new SOAPFaultException(soapFault);

              } catch (SOAPException e) {

              }

       } //attacheErrorMessage

       public boolean handleFault(SOAPMessageContext messageContext) {
              return true;
       } //handleFault

       public void close(MessageContext context) {
       } //close

       @Override
       public Set<QName> getHeaders() {
              // TODO Auto-generated method stub
              return null;
       }
}//SOAPHeaderInterceptor Class - END

2.     Add annotation to the Web Service.

To use your SOAP Handler class, you need to use @javax.jws.HandlerChain annotation. Locate the SOAPHandler class in the file property of this annotation.

@ HandlerChain( file = "ws_handler.xml" )
@ WebService
public class InterceptAnyRequestBeforeReachingMeService {
                        ……..
                        ……..
                        ……..
}

3.     Create Configuration file

Create the handler configuration file named ws_handler.xml, the one you specified in the HandlerChain annotation. You create this file to associate a handler chain with your web service.

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