HomeDigital EditionSys-Con RadioSearch Web Services Cd
B2B Beginning WS Business Process Management Case Studies Content Management Distributing Computing e-Business Electronic Data Interchange Enterprise Industry Insight Integration Interviews Java & Web Services .NET Portal Product Reviews Scalability & Performance Security SOAP Source Code UDDI Wireless WS Standards WS Tips & Techniques WSDL WS Editorials XML

Apply a Little SOAP to Your Java, by J. Jeffrey Hanson
WSJ Vol 02 Issue 04 - pg.18

	

Listing 1 <SOAP-ENV:Envelope xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsd=http://www.w3.org/1999/XMLSchema xmlns:soap=http://schemas.xmlsoap.org/wsdl/soap/ xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/ SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <myns:getTime xmlns:myns="http://www.myserver.com/webservices"> <city xsi:type="xsd:string">Buffalo</city> <state xsi:type="xsd:string">New York</state> </myns:getTime> </SOAP-ENV:Body> </SOAP-ENV:Envelope> Listing 2 <SOAP-ENV:Envelope xmlns:SOAP-ENV=http://schemas.xmlsoap.org/soap/envelope/ xmlns:xsd=http://www.w3.org/1999/XMLSchema xmlns:soap=http://schemas.xmlsoap.org/wsdl/soap/ xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/ SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> <SOAP-ENV:Body> <SOAP-ENV:Fault> <faultcode>SOAP-ENV:Client</faultcode> <faultstring>Time retrieval failed: missing city name.</faultstring> </SOAP-ENV:Fault> </SOAP-ENV:Envelope> Listing 3 <Bowlers xmlns:bowl=http://www.myserver.com/schema/bowlers xmlns:lane=http://www.myserver.com/schema/lanes> <bowl:BowlerInformation> <bowl:BowlerName>Big Daddy Jones</bowl:BowlerName > < lane:LaneInformation> < lane:Name>Rock Roll</lane:Lane> < lane:Street>123 Anywhere St.</lane:Street> < lane:City>Mytown</lane:City> < lane:State>MN</lane:State> < lane:Zip>54321</lane:Zip> </lane:LaneInformation> </bowl:BowlerInformation > </Bowlers > Listing 4 <BowlerInformation xmlns:bowl=http://www.myserver.com/schema/bowlers xmlns=http://www.myserver.com/xmlns/teams> <BowlerData> <bowl:Name>Big Daddy Jones</bowl:Name> <bowl:Handicap>195</bowl:Handicap> <Teams> <Team> <Name>Hurricanes</Name> <Score>210</Score> </Team> <Team> <Name>Gutter Rats</Name> <Score>180</Score> </Team> </Teams> </BowlerData > </BowlerInformation > Listing 5 package com.mycompany.services.web; public class SOAPServlet extends javax.servlet.http.HttpServlet { public static final String VERSION_MISMATCH_FAULT = "100"; public static final String MUST_UNDERSTAND_FAULT = "200"; public static final String INVALID_REQUEST_FAULT = "300"; public static final String APPLICATION_DEFINED_FAULT = "400"; public void doPost(javax.servlet.http.HttpServletRequest servletReq, javax.servlet.http.HttpServletResponse servletRes) throws java.io.IOException, javax.servlet.ServletException { SOAPRequest soapRequest = null; try { // Get Method Name String methodName = servletReq.getHeader("SOAPMethodName"); if (methodName == null) throw new javax.servlet.ServletException ("Fault: " + INVALID_REQUEST_FAULT + " [Missing SOAP Method Name]"); javax.servlet.ServletInputStream servletInStream = servletReq.getInputStream(); // extract SOAP document from stream and validate content MySOAPParser mySOAPParser = new MySOAPParser(servletInStream); soapRequest = new SOAPRequest(mySOAPParser, servletReq, servletRes); SOAPResponse soapResponse = soapRequest.handleRequest(methodName); if (soapResponse != null) { servletRes.setContentType("text/xml"); javax.servlet.ServletOutputStream servletOutStream = servletRes.getOutputStream(); // create a serializer for the response // serializer appends headers retrieved from response // serializer appends body retrieved from response MySerializer serializer = MySerializer.create(soapResponse); serializer.write(servletOutStream); servletOutStream.close(); } } catch (Exception exception) { servletRes.setContentType("text/xml"); javax.servlet.ServletOutputStream servletOutStream = servletRes.getOutputStream(); // create fault object // use a serializer to write to ouputstream MyFaultSerializer myFaultSerializer = new MyFaultSerializer(exception); myFaultSerializer.write(servletOutStream); servletOutStream.close(); } } } /** This class parses an InputStream and extracts parameters, type info., etc. */ class MySOAPParser extends org.apache.xerces.parsers.SAXParser { public MySOAPParser(javax.servlet.ServletInputStream inStream) { } public void parse() { // Depending upon which version of SAX you are using, you will use // one of the following pairs of callbacks in your parser: // 1) startNamespaceDeclScope(String s, String s1) // and public void endNamespaceDeclScope(String s) // 2) public void startPrefixMapping(String prefix, String uri) // and public void endPrefixMapping(String prefix) // You will extract namespace references from either of these methods // and save in a list or map } } class SOAPRequest { MySOAPParser parser; public SOAPRequest(MySOAPParser parser, javax.servlet.http.HttpServletRequest servletReq, javax.servlet.http.HttpServletResponse servletRes) { this.parser = parser; } public SOAPResponse handleRequest(String methodName) { parser.parse(); // if (EJB) { // Properties p = new Properties(); // p.put("java.naming.factory.initial", "factory name"); // p.put("java.naming.provider.url", "Host URL"); // InitialContext context = new InitialContext(p); // Object obj = context.lookup("Home Name"); // ObjectHome objectHome = // (ObjectHome)PortableRemoteObject.narrow(obj, // sourceClass.getClass()); // Object object = objectHome.create(); // } // else { object = sourceClass.newInstance(); } // class-specific code here return null; // return a valid response from request } } class SOAPResponse { public SOAPResponse() { } } class MySerializer { public static MySerializer create(SOAPResponse soapResponse) { return null; } public MySerializer() { } public void write(java.io.OutputStream servletOutStream) { } } class MyFaultSerializer extends MySerializer { private Exception exception; public MyFaultSerializer() { super(); } public MyFaultSerializer(Exception e) { exception = e; } public void write(java.io.OutputStream servletOutStream) { // write specific contents for this fault here } } Listing 6 package com.mycompany.services.web; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; public class SOAPReflector { static final String[] SERVLET_CONTENTS = { "public class SOAPServlet extends javax.servlet.http.HttpServlet\n", "{\n", " public static final String VERSION_MISMATCH_FAULT = \"100\";\n", " public static final String MUST_UNDERSTAND_FAULT = \"200\";\n", " public static final String INVALID_REQUEST_FAULT = \"300\";\n", " public static final String APPLICATION_DEFINED_FAULT = \"400\";\n", "\n", " public void doPost(javax.servlet.http.HttpServletRequest servletReq,\n", " javax.servlet.http.HttpServletResponse servletRes)\n", " throws java.io.IOException, javax.servlet.ServletException\n", " {\n", " SOAPRequest soapRequest = null;\n", " try\n", " {\n", " // Get Method Name\n", " String methodName = servletReq.getHeader(\"SOAPMethodName\");\n", " if (methodName == null)\n", " throw new javax.servlet.ServletException(\"Fault: \" + INVALID_REQUEST_FAULT\n", " + \" [Missing SOAP Method Name]\");\n", "\n", " javax.servlet.ServletInputStream servletInStream =\n", " servletReq.getInputStream();\n", " // extract SOAP document from stream and validate content\n", " MySOAPParser mySOAPParser = new MySOAPParser(servletInStream);\n", "\n", " soapRequest = new SOAPRequest(mySOAPParser, servletReq, servletRes);\n", " SOAPResponse soapResponse = soapRequest.handleRequest(methodName);\n", "\n", " if (soapResponse != null)\n", " {\n", " servletRes.setContentType(\"text/xml\");\n", " javax.servlet.ServletOutputStream servletOutStream =\n", " servletRes.getOutputStream();\n", " // create a serializer for the response\n", " // serializer appends headers retrieved from response\n", " // serializer appends body retrieved from response\n", " MySerializer serializer = MySerializer.create(soapResponse);\n", " serializer.write(servletOutStream);\n", " servletOutStream.close();\n", " }\n", " }\n", " catch (Exception exception)\n", " {\n", " servletRes.setContentType(\"text/xml\");\n", " javax.servlet.ServletOutputStream servletOutStream =\n", " servletRes.getOutputStream();\n", " // create fault object\n", " // use a serializer to write to ouputstream\n", " MyFaultSerializer myFaultSerializer =\n", " new MyFaultSerializer(exception);\n", " myFaultSerializer.write(servletOutStream);\n", " servletOutStream.close();\n", " }\n", " }\n", "}\n" }; static final String[] PARSER_CONTENTS = { "/** This class parses an InputStream and extracts parameters, type info., etc. */\n", "class MySOAPParser extends org.apache.xerces.parsers.SAXParser\n", "{\n", " public MySOAPParser(javax.servlet.ServletInputStream inStream)\n", " {\n", " }\n", "\n", " public void parse()\n", " {\n", " // Depending upon which version of SAX you are using, you will use\n", " // one of the following pairs of callbacks in your parser:\n", " // 1) startNamespaceDeclScope(String s, String s1)\n", " // and public void endNamespaceDeclScope(String s)\n", " // 2) public void startPrefixMapping(String prefix, String uri)\n", " // and public void endPrefixMapping(String prefix)\n", " // You will extract namespace references from either of these methods\n", " // and save in a list or map\n", " }\n", "}\n" }; static final String[] REQUEST_HEAD = { "class SOAPRequest\n", "{\n", " MySOAPParser parser;\n", "\n", " public SOAPRequest(MySOAPParser parser,\n", " javax.servlet.http.HttpServletRequest servletReq,\n", " javax.servlet.http.HttpServletResponse servletRes)\n", " {\n", " this.parser = parser;\n", " }\n", "\n", " public SOAPResponse handleRequest(String methodName)\n", " {\n", " parser.parse();\n", " // get parameters, type info., etc. from parser\n", " // then match the method name and\n", " // make one of the following requests\n" }; static final String[] REQUEST_TAIL = { " return null; // return a valid response from request\n", " }\n", "}\n" }; static final String[] RESPONSE_CONTENTS = { "class SOAPResponse\n", "{\n", " public SOAPResponse()\n", " {\n", " }\n", "}\n" }; static final String[] SERIALIZER_CONTENTS = { "class MySerializer\n", "{\n", " public static MySerializer create(SOAPResponse soapResponse)\n", " {\n", " return null;\n", " }\n", "\n", " public MySerializer()\n", " {\n", " }\n", "\n", " public void write(java.io.OutputStream servletOutStream)\n", " {\n", " }\n", "}\n" }; static final String[] MYFAULTSERIALIZER_CONTENTS = { "class MyFaultSerializer extends MySerializer\n", "{\n", " private Exception exception;\n", "\n", " public MyFaultSerializer()\n", " {\n", " super();\n", " }\n", "\n", " public MyFaultSerializer(Exception e)\n", " {\n", " exception = e;\n", " }\n", "\n", " public void write(java.io.OutputStream servletOutStream)\n", " {\n", " // write specific contents for this fault here\n", " }\n", "}\n" }; Class sourceClass = null; public SOAPReflector(String className) throws ClassNotFoundException { sourceClass = Class.forName(className); } public void reflect() { for (int i = 0; i < SERVLET_CONTENTS.length; i++) { System.out.print(SERVLET_CONTENTS[i]); } for (int i = 0; i < PARSER_CONTENTS.length; i++) { System.out.print(PARSER_CONTENTS[i]); } for (int i = 0; i < REQUEST_HEAD.length; i++) { System.out.print(REQUEST_HEAD[i]); } String[] methods = getMethods(); if (methods != null) { System.out.println("// if (EJB) {"); System.out.println("// Properties p = new Properties();"); System.out.println("// p.put(\"java.naming.factory.initial\", \"factory name\");"); System.out.println("// p.put(\"java.naming.provider.url\", \"Host URL\");"); System.out.println("// InitialContext context = new InitialContext(p);"); System.out.println("// Object obj = context.lookup(\"Home Name\");"); System.out.println("// ObjectHome objectHome = "); System.out.println("// (ObjectHome)PortableRemoteObject.narrow(obj, sourceClass.getClass());"); System.out.println("// Object object = objectHome.create();"); System.out.println("// }"); System.out.println("// else { object = sourceClass.newInstance(); }"); for (int i = 0; i < methods.length; i++) { System.out.println("// if (methodName == " + methods[i] + ") { // make call }"); System.out.println("// " + methods[i]); } } for (int i = 0; i < REQUEST_TAIL.length; i++) { System.out.print(REQUEST_TAIL[i]); } for (int i = 0; i < RESPONSE_CONTENTS.length; i++) { System.out.print(RESPONSE_CONTENTS[i]); } for (int i = 0; i < SERIALIZER_CONTENTS.length; i++) { System.out.print(SERIALIZER_CONTENTS[i]); } for (int i = 0; i < MYFAULTSERIALIZER_CONTENTS.length; i++) { System.out.print(MYFAULTSERIALIZER_CONTENTS[i]); } } public String[] getMethods() { Method[] methods = sourceClass.getMethods(); java.util.Vector methodList = new java.util.Vector(); if (methods != null) { for (int i = 0; i < methods.length; i++) { String sourceCode = ""; String returnType = methods[i].getReturnType().getName(); sourceCode += returnType +" "; String methodName = methods[i].getName(); sourceCode += methodName +"("; Class[] parameters = methods[i].getParameterTypes(); if (parameters != null) { for (int j = 0; j < parameters.length; j++) { if (j > 0) { sourceCode += ", "; } sourceCode += parameters[j].getName() +" p" +j; } } sourceCode += ")"; Class[] exceptions = methods[i].getExceptionTypes(); if ((exceptions != null) && (exceptions.length > 0)) { sourceCode += " throws "; for (int j = 0; j < exceptions.length; j++) { if (j > 0) { sourceCode += ", "; } sourceCode += exceptions[j].getName(); } } methodList.addElement(sourceCode); } } String[] strArray = new String[methodList.size()]; methodList.copyInto(strArray); return strArray; } } Listing 7 <?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions targetNamespace="http://webservices.mycompany.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:intf="http://webservices.mycompany.com/intf" xmlns:impl="http://webservices.mycompany.com/impl" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns="http://schemas.xmlsoap.org/wsdl/"> <types> <schema targetNamespace="http:// webservices.mycompany.com" xmlns="http://www.w3.org/1999/XMLSchema"> <element name="GetEndorsingBoarder"> <complexType> <sequence> <element name="manufacturer" type="string"/> <element name="model" type="string"/> </sequence> </complexType> </element> <element name="getMessageOneResponse"> <complexType> <all> <element name="MessageOneResponse" type="string"/> </all> </complexType> </element> <element name=" getMessageOneResponseFault"> <complexType> <all> <element name="errorCode" type="string"/> </all> </complexType> </element> </schema> </types> <wsdl:message name="getMessageOneRequest"> </wsdl:message> <wsdl:message name="getMessageOneResponse"> <wsdl:part name="getMessageOneResult" type="xsd:string"/> </wsdl:message> <wsdl:message name="setMessageTwoRequest"> <wsdl:part name="arg0" type="xsd:string"/> </wsdl:message> <wsdl:message name="setMessageTwoResponse"> <wsdl:part/> </wsdl:message> <wsdl:portType name="TestServicePortType"> <wsdl:operation name="getMessageOne"> <wsdl:input message="intf:getMessageOneRequest"/> <wsdl:output message="intf:getMessageOneResponse"/> </wsdl:operation> <wsdl:operation name="setMessageTwo"> <wsdl:input message="intf:setMessageTwoRequest"/> <wsdl:output message="intf:setMessageTwoResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="TestServiceSoapBinding" type="intf:TestServicePortType"> <soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="getMessageOne"> <soap:operation soapAction="" style="rpc"/> <wsdl:input> <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://webservices.mycompany.com"/> </wsdl:input> <wsdl:output> <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://webservices.mycompany.com"/> </wsdl:output> </wsdl:operation> <wsdl:operation name="setMessageTwo"> <soap:operation soapAction="" style="rpc"/> <wsdl:input> <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://webservices.mycompany.com"/> </wsdl:input> <wsdl:output> <soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://webservices.mycompany.com"/> </wsdl:output> </wsdl:operation> <wsdl:service name="TestService"> <wsdl:port name="TestServicePort" binding="intf:TestServiceSoapBinding"> <soap:address/> </wsdl:port> </wsdl:service> </wsdl:definitions>