A Technology Blog About Code Development, Architecture, Operating System, Hardware, Tips and Tutorials for Developers.

Tuesday, December 4, 2012

JAX-WS Web Service Handler (Server)

5:56:00 PM Posted by Satish , , , , , , , No comments
SOAP handler is a SOAP message interceptor, which is able to intercept incoming or outgoing SOAP message and manipulate its values. For example, attach a SOAP handler in client side, which will inject authentication credential into the SOAP header block for every outgoing SOAP message that is send by the client. In server side, attach another SOAP handler, to retrieve back the authentication credential in SOAP header block from every incoming SOAP message. In this way we can validate the incoming requests and secure our system.

For this tutorial I will be using the following tools.
  • JDK 7
  • Eclipse Juno
  • Maven2
  • GlassFish Metro
  • Tomcat 7
In this article, I show you how to create a SOAP handler and attach it to web service, to retrieve the credential in SOAP header block from every incoming SOAP message. And do validation to allow only username as “foo” and password as “bar” to access this published service. If a request comes with an invalid credential, return a response with fault description and fault code. We are going to do the following thing here.
  • Create Web Service
  • Create SOAP Handler
  • Handler Configuration
  • Hander Mapping
Create Web Service:

As I have already wrote an article to demonstrate how to  create web service, I will not be explaining it again . Please refer JAX-WS Web Integration (Glassfish Metro) to create and deploy a web service in tomcat.

Create Soap Handler:

In order to create a SOAP handler, we have to implement javax.xml.ws.handler.soap.SOAPHandler. We have to give a logical implementation in handleMessage(). This method returns a true in case success and false in case of failure. Be very careful to return false in case of failure or else it will bypass the security and hit to the endpoint. So eventually in all cases web service will be get accessed.

  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
113
114
115
116
117
118
119
120
121
package com.techiekernel.ws.jaxws.handler;

import java.io.IOException;
import java.util.Iterator;
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 AuthenticationHandler implements SOAPHandler<SOAPMessageContext> {

         public boolean handleMessage(SOAPMessageContext context) {

                 System.out.println("handleMessage() called.");

                 Boolean isRequest = (Boolean) context
                                   .get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);

                 // for request message only, true for outbound messages, false for
                 // inbound
                 if (!isRequest) {

                          try {
                                   SOAPMessage soapMsg = context.getMessage();
                                   SOAPEnvelope soapEnv = soapMsg.getSOAPPart().getEnvelope();
                                   SOAPHeader soapHeader = soapEnv.getHeader();

                                   // if no header, add one
                                   if (soapHeader == null) {
                                            soapHeader = soapEnv.addHeader();
                                            // No header found, throw exception
                                            embedSOAPException(soapMsg, "Missing Header", "ERR:001");
                                   }

                                   // Get user Id and password from SOAP header
                                   Iterator<Node> it = soapHeader
                                                     .extractHeaderElements(SOAPConstants.URI_SOAP_ACTOR_NEXT);

                                   // if no header block for next actor found? throw exception
                                   if (it == null || !it.hasNext()) {
                                            embedSOAPException(soapMsg, "No Header Data", "ERR:002");
                                   }

                                   String userName = null;
                                   String password = null;

                                   while (it.hasNext()) {
                                            Node node = it.next();
                                            if (node != null && node.getNodeName().equals("userName"))
                                                    userName = node.getValue();
                                            if (node != null && node.getNodeName().equals("password"))
                                                    password = node.getValue();
                                   }

                                   if (userName == null || password == null) {
                                            embedSOAPException(soapMsg, "No userName or password.",
                                                             "ERR:003");
                                   }

                                   // the auth code
                                   if (!userName.equals("foo") || !password.equals("bar")) {
                                            embedSOAPException(soapMsg, "Authentication Failed",
                                                             "ERR:004");
                                   }

                                   // tracking
                                   soapMsg.writeTo(System.out);

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

                 }

                 // continue other handler chain
                 return true;
         }

         public boolean handleFault(SOAPMessageContext context) {

                 System.out.println("handleFault() called.");

                 return true;
         }

         public void close(MessageContext context) {
                 System.out.println("close() called");
         }

         public Set<QName> getHeaders() {
                 System.out.println("getHeaders() called");
                 return null;
         }

         private void embedSOAPException(SOAPMessage msg, String reason,
                          String faultCode) throws SOAPException, IOException {
                 SOAPBody soapBody = msg.getSOAPPart().getEnvelope().getBody();
                 SOAPFault soapFault = soapBody.getFault();
                 if (soapFault == null)
                          soapFault = soapBody.addFault();
                 soapFault.setFaultString(reason);
                 soapFault.setFaultCode(faultCode);
                 msg.writeTo(System.out);
         }

}

Handler Configuration:

Let’s create define the handler in a handler mapping file and name it as handler.xml.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
<?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.techiekernel.ws.jaxws.handler.AuthenticationHandler

                          </javaee:handler-class>

                 </javaee:handler>

         </javaee:handler-chain>

</javaee:handler-chains>

Handler Mapping:

To attach above SOAP handler to web service FooBarImpl.java, just annotate with @HandlerChain and specify the SOAP handler file name inside. We have to keep the hander configuration file i.e. handler.xml in the class path.

 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
package com.techiekernel.ws.jaxws.document;



import javax.jws.WebMethod;

import javax.jws.WebService;

import javax.jws.HandlerChain;



@WebService
@HandlerChain(file="handler.xml")
public class FooBarImpl{



         public String callFooBar(String name) {

                 // TODO Auto-generated method stub

                 return "FooBar called by " + name;

         }



         public Server getServerDetail(String client) {

                 // TODO Auto-generated method stub

                 Server server = new Server();

                 server.setName("Techie Kernel");

                 server.setIp("192.168.1.0");

                 server.setMac("12-75-61-09-12-22");

                 server.setOs("Ubuntu");

                 return server;

         }

}

Now We are ready to deploy the application to the tomcat container.

Source Code:

You can pull the complete code from GitHub. The shared code contains handler code along with the web services.

0 comments:

Post a Comment