|
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>
|