JAX-WS: How to input and output XML AnyType

JAX-WS works in a very simple and effective way if you have defined all objects in a XML Schema definition. But sometimes you can’t define a schema for an operation because e.g. it is a generic operation and accepts or returns dynamic XML.

Nevertheless we would like to use for this operation the same tool chain with JAX-WS which is working perfectly for other operations.

In the first step we define the interface of the operation testXMLCall in the WSDL (better the XSD referenced by the WSDL).

1 <xsd:element name='testXMLCall'> 2 <xsd:complexType> 3 <xsd:sequence> 4 <xsd:element minOccurs='1' maxOccurs='1' name='name' type='xsd:string'/> 5 <xsd:element minOccurs='1' maxOccurs='1' name='requestXMLData' type='xsd:anyType'/> 6 </xsd:sequence> 7 </xsd:complexType> 8 </xsd:element> 9 <xsd:element name='testXMLCallResponse'> 10 <xsd:complexType> 11 <xsd:sequence> 12 <xsd:element minOccurs='1' maxOccurs='1' name='responseXMLData' type='xsd:anyType'/> 13 </xsd:sequence> 14 </xsd:complexType> 15 </xsd:element>

From this WSDL we generate the interface PortType of the webservice. The implementation of the interface needs an operation of this definition:

1 @WebMethod(action = "http://localhost/testXMLCall") 2 @WebResult(name = "responseXMLData", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1") 3 @RequestWrapper(localName = "testXMLCall", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1", className = "com.oc.soa.sample.ws.v1.messages.TestXMLCall") 4 @ResponseWrapper(localName = "testXMLCallResponse", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1", className = "com.oc.soa.sample.ws.v1.messages.TestXMLCallResponse") 5 public Object testXMLCall( 6 @WebParam(name = "name", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1") 7 String name, 8 @WebParam(name = "requestXMLData", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1") 9 Object requestXMLData);

We make an implementation:

1 @WebMethod(action = "http://localhost/testXMLCall") 2 @WebResult(name = "responseXMLData", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1") 3 @RequestWrapper(localName = "testXMLCall", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1", className = "com.oc.soa.sample.ws.v1.messages.TestXMLCall") 4 @ResponseWrapper(localName = "testXMLCallResponse", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1", className = "com.oc.soa.sample.ws.v1.messages.TestXMLCallResponse") 5 public Object testXMLCall( 6 @WebParam(name = "name", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1") 7 String name, 8 @WebParam(name = "requestXMLData", targetNamespace = "http://opitz-consulting.com/interfaces/TestMessages/V1") 9 Object requestXMLData) { 10 TestXMLCallResponse result = new TestXMLCallResponse(); 11 if (requestXMLData instanceof Element) { 12 Element requestXMLDataElement = ((Element) requestXMLData); 13 LOG.info("XML in: n" + getPrintString(requestXMLDataElement)); 14 XmlObject xmlResult; 15 try { 16 xmlResult = doSomething(requestXMLDataElement); 17 } catch (RuntimeException e) { 18 LOG.error("Error while doSomething with XML: n" + getPrintString(requestXMLDataElement), e); 19 throw e; 20 } 21 LOG.info("XML out: n" + getPrintString(xmlResult.getDomNode())); 22 result.setResponseXMLData(xmlResult.getDomNode().getFirstChild()); 23 } else if (requestXMLData == null) { 24 LOG.error("Data is null." ); 25 } else { 26 LOG.error("Unknown data of type '"+ requestXMLData.getClass() + "'." ); 27 } 28 return result; 29 }

We make an implementation of the method getPrintString for a readable output of the XML.

1 public static String getPrintString(Node node) { 2 try { 3 DOMSource domSource = new DOMSource(node); 4 StringWriter writer = new StringWriter(); 5 StreamResult result = new StreamResult(writer); 6 TransformerFactory tf = TransformerFactory.newInstance(); 7 Transformer transformer = tf.newTransformer(); 8 transformer.transform(domSource, result); 9 writer.flush(); 10 return writer.toString(); 11 } catch (TransformerException e) { 12 LOG.warn("Unable to convert XML-Node '" + node.toString() + "' of class '" + node.getClass() + "' to string representation.", e); 13 return "[non printable xml]"; 14 } 15 }

And finally the method doSomething processing the xml element and returning an XmlObject needs to be implemented.

Bernhard Mähr @ OPITZ-CONSULTING published at http://thecattlecrew.wordpress.com/

Leave a Reply