Use the soap handler to intercept the request/response
here is the source code, it intercept the fault response message by adding the type for some tags:
1. add annotation @HandlerChain (file = "soaphandlerchain.xml") to the class which has @WebService annotation
2. put the soaphandlerchain.xml as the same package as the web service impl class.
3. implement the handler descripted in the soaphandlerchain.xml
Hello.java
package helloservice.endpoint;import javax.ejb.Stateless;import javax.jws.HandlerChain;import javax.jws.WebMethod;import javax.jws.WebParam;import javax.jws.WebResult;import javax.jws.WebService;@WebService (serviceName = "services", portName = "hello", targetNamespace = "http://mytest.com")@Stateless (mappedName = "HelloEjb")@HandlerChain (file = "soaphandlerchain.xml")public class Hello{private String message = new String ("Hello, ");public void Hello (){}@WebMethodpublic String sayHello (String name) throws MyException{if (name == null || name.isEmpty ()){final String msg = "The name cannot be null.";MyExceptionBean faultBean = new MyExceptionBean ();faultBean.setErrorCode ("E60001");throw new MyException (msg, faultBean);}return message + name;}}
now it is the xml file soaphandlerchain.xml, this file must be at the same package as the Hello.java
<?xml version="1.0" encoding="UTF-8"?><jws:handler-chains xmlns:jws="http://java.sun.com/xml/ns/javaee"><jws:handler-chain><jws:handler><jws:handler-name>HelloSoapHandler</jws:handler-name><jws:handler-class>helloservice.endpoint.HelloSoapHandler</jws:handler-class></jws:handler></jws:handler-chain></jws:handler-chains>
now it is the SOAP Handler class (changed based on http://blog.jdevelop.eu/2008/03/08/how-to-modify-jax-ws-soap-messages/)
package helloservice.endpoint;import java.io.ByteArrayOutputStream;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import java.util.Set;import javax.annotation.PostConstruct;import javax.annotation.PreDestroy;import javax.xml.namespace.QName;import javax.xml.soap.SOAPBody;import javax.xml.soap.SOAPBodyElement;import javax.xml.soap.SOAPElement;import javax.xml.soap.SOAPEnvelope;import javax.xml.soap.SOAPException;import javax.xml.soap.SOAPMessage;import javax.xml.soap.SOAPPart;import javax.xml.ws.handler.MessageContext;import javax.xml.ws.handler.soap.SOAPHandler;import javax.xml.ws.handler.soap.SOAPMessageContext;/**
* This class handles the SOAP-Requests before they reach the* Web Service Operation. It is possible to read and manipulate* the SOAP-Message.**/public class HelloSoapHandler implements SOAPHandler<SOAPMessageContext>{/**
* Is called after constructing the handler and before executing any othe method.*/@PostConstructpublic void init (){}/**
* Returns the <code>Set</code> of supported SOAP headers*/public Set<QName> getHeaders (){return null;}/**
* Returns the message encoding (e.g. utf-8)** @param msg* @return* @throws javax.xml.soap.SOAPException*/private String getMessageEncoding (SOAPMessage msg) throws SOAPException{String encoding = "utf-8";if (msg.getProperty (SOAPMessage.CHARACTER_SET_ENCODING) != null){encoding = msg.getProperty (SOAPMessage.CHARACTER_SET_ENCODING).toString ();}return encoding;}/**
* Dump SOAP Message to console** @param msg*/private void dumpSOAPMessage (SOAPMessage msg){if (msg == null){System.out.println ("SOAP Message is null");return;}System.out.println ("");System.out.println ("--------------------");System.out.println ("DUMP OF SOAP MESSAGE");System.out.println ("--------------------");try{ByteArrayOutputStream baos = new ByteArrayOutputStream ();msg.writeTo (baos);System.out.println (baos.toString (getMessageEncoding (msg)));// show included valuesString values = msg.getSOAPBody ().getTextContent ();System.out.println ("Included values:" + values);}catch (Exception e){e.printStackTrace ();}}/**
* This method handles the incoming and outgoing SOAP-Message.* It's an excellent point to manipulate the SOAP.** @param SOAPMessageContext* @return boolean*/public boolean handleMessage (SOAPMessageContext context){//Inquire incoming or outgoing message.boolean outbound = (Boolean) context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);try{if (outbound){// OUTBOUNDSystem.out.println ("Direction=outbound (handleMessage)");SOAPMessage msg = ((SOAPMessageContext) context).getMessage ();// get SOAP-PartSOAPPart sp = msg.getSOAPPart ();//edit EnvelopeSOAPEnvelope env = sp.getEnvelope ();// add namespacesenv.addNamespaceDeclaration ("xsd", "http://www.w3.org/2001/XMLSchema");env.addNamespaceDeclaration ("xsi","http://www.w3.org/2001/XMLSchema-instance");env.addNamespaceDeclaration ("soap","http://schemas.xmlsoap.org/soap/envelope");// get the SOAP-BodySOAPBody body = env.getBody ();// add an additional Element to the SOAP-BodySOAPBodyElement bodyElement = body.addBodyElement (new QName ("http://http://www.comverse.com/msg", "testMessage"));bodyElement.addTextNode ("test message");// print SOAP-MessagedumpSOAPMessage (msg);}else{// INBOUNDSystem.out.println ("Direction=inbound (handleMessage)");SOAPMessage msg = ((SOAPMessageContext) context).getMessage ();dumpSOAPMessage (msg);}}catch (Exception e){//All other unhandled problems.e.printStackTrace ();}return true;}/**
* Handles SOAP-Errors.** @param context* @return*/public boolean handleFault (SOAPMessageContext context){System.out.println ("ServerSOAPHandler.handleFault");boolean outbound = (Boolean) context.get (MessageContext.MESSAGE_OUTBOUND_PROPERTY);if (outbound){System.out.println ("Direction=outbound (handleFault)");SOAPMessage msg = ((SOAPMessageContext) context).getMessage ();// get SOAP-PartSOAPPart sp = msg.getSOAPPart ();//edit EnvelopeSOAPEnvelope env;try{env = sp.getEnvelope ();// add namespacesenv.addNamespaceDeclaration ("xsd", "http://www.w3.org/2001/XMLSchema");env.addNamespaceDeclaration ("xsi","http://www.w3.org/2001/XMLSchema-instance");env.addNamespaceDeclaration ("soap","http://schemas.xmlsoap.org/soap/envelope");// get the SOAP-BodySOAPBody body = env.getBody ();Iterator iter1 = body.getChildElements ();while (iter1.hasNext ()){SOAPBodyElement bodyElement = (SOAPBodyElement) iter1.next ();Iterator iter2 = bodyElement.getChildElements ();while (iter2.hasNext ()){Object node = iter2.next ();correctElement (node);}}}catch (SOAPException e){// TODO Auto-generated catch blocke.printStackTrace ();}// print SOAP-MessagedumpSOAPMessage (msg);}else{System.out.println ("Direction=inbound (handleFault)");}SOAPMessage msg = ((SOAPMessageContext) context).getMessage ();dumpSOAPMessage (msg);if (!outbound){try{if (context.getMessage ().getSOAPBody ().getFault () != null){String detailName = null;try{detailName = context.getMessage ().getSOAPBody ().getFault ().getDetail ().getFirstChild ().getLocalName ();System.out.println ("detailName=" + detailName);}catch (Exception e){}}}catch (SOAPException e){e.printStackTrace ();}}return true;}static Map<String, String> tagMap;{tagMap = new HashMap ();tagMap.put ("errorCode", "xsd:string");tagMap.put ("faultstring", "xsd:string");tagMap.put ("ns4:fault", "ns4:MyException");}private void correctElement (Object node){System.out.println ("Node: " + node);SOAPElement child;try{child = (SOAPElement) node;}catch (Exception e){return;}String tagName = child.getTagName ();if (tagMap.containsKey (tagName)){try{child.addAttribute (new QName ("http://www.w3.org/2001/XMLSchema-instance", "type", "xsi"),tagMap.get (tagName));}catch (SOAPException e){// TODO Auto-generated catch blocke.printStackTrace ();}}Iterator iter = child.getChildElements ();while (iter.hasNext ()){node = iter.next ();correctElement (node);}}public void close (MessageContext messageContext){}/**
* Is executed before this handler is being destroyed -* means after close() has been executed.*/@PreDestroypublic void destroy (){}}
the exception class: MyException.java (ref: http://io.typepad.com/eben_hewitt_on_java/2009/07/using-soap-faults-and-exceptions-in-java-jaxws-web-services.html)
package helloservice.endpoint;import java.io.Serializable;import javax.xml.ws.WebFault;@WebFault (name = "fault", targetNamespace = "http://myexceptions.test.com")public class MyException extends Exception implements Serializable{private static final long serialVersionUID = -4552704108896976212L;/**
* Java type that goes as soapenv:Fault detail element.*/private MyExceptionBean faultInfo;public MyException (String message, MyExceptionBean faultInfo){super (message);this.faultInfo = faultInfo;}public MyException (String message, MyExceptionBean faultInfo, Throwable cause){super (message, cause);this.faultInfo = faultInfo;}public MyExceptionBean getFaultInfo (){return faultInfo;}}
and the bean class: MyExceptionBean.java:
package helloservice.endpoint;import javax.xml.bind.annotation.XmlAccessType;import javax.xml.bind.annotation.XmlAccessorType;import javax.xml.bind.annotation.XmlElement;import javax.xml.bind.annotation.XmlType;@XmlAccessorType (XmlAccessType.FIELD)@XmlType (name = "MyException", propOrder ={ "errorCode" })public class MyExceptionBean{private String errorCode = "654321";public String getErrorCode (){return errorCode;}public void setErrorCode (String errorCode){this.errorCode = errorCode;}}
here is the pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"><modelVersion>4.0.0</modelVersion><groupId>TestWS</groupId><artifactId>testws</artifactId><version>0.0.1-SNAPSHOT</version><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>2.0.2</version><configuration><source>1.5</source><target>1.5</target></configuration></plugin><plugin><groupId>org.codehaus.mojo</groupId><artifactId>jaxws-maven-plugin</artifactId><version>1.10</version><executions><execution><goals><goal>wsgen</goal></goals><configuration><sei>helloservice.endpoint.Hello</sei><!--for demo purpose only, the webapp does not--><!--need the generated wsdl files--><genWsdl>true</genWsdl><keep>true</keep></configuration></execution></executions></plugin></plugins></build><pluginRepositories><pluginRepository><id>maven2-repository.dev.java.net</id><url>http://download.java.net/maven/2/</url></pluginRepository></pluginRepositories><dependencies><dependency><groupId>javax</groupId><artifactId>javaee-api</artifactId><version>6.0</version></dependency><dependency><groupId>xalan</groupId><artifactId>xalan</artifactId><version>2.7.0</version></dependency></dependencies></project>
1 Comments:
Thanks.. it is really helpful for me. I was trying to log inbound and outbound messages using interceptors. But I was failed to log the outbound messages. This really works.
Post a Comment
<< Home