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

Source Code for this article

It's beginning to look like you can't talk about Web development, enterprise application integration, XML, professional football, or cat juggling without someone mentioning Web services. If Web services have accomplished anything, succeeded in cornering the hype market.

In reality, they are starting to show up and they're proving they can actually get some work done. Perhaps not anything too exciting yet, but the possibilities they present, to imaginative propeller-heads, are downright exhilarating.

With enough creativity and the right Web services, I'll be able to craft a framework of software goodies to allow me to aggregate my financial portfolio, my fantasy football scores, the weather in Cameroon, the quote-of-the-day, and the time in Guam into a single, composite document I can bend, fold, and mutilate to display on my magic Orphan Annie decoder ring. If this doesn't prove useful, I don't know what will.

Web services, by themselves, are presently just globs of XML data floating around in HTTP ether waiting for someone or something to take them out for a good time. Since Java is being used for everything from ASP to ZSP, let's find out how we can turn some of it into something I like to call "Web services."

Dirty Deeds Done With SOAP
Web services want to be, need to be, just have to be, associated with the terms "pervasive" and "ubiquitous." This means they must share their information and behavior using something everybody uses ­ XML.

XML is the foundation a Web service builds its house on. Everybody likes XML. XML does this and XML does that and XML...well, you know the rest. XML has infiltrated our systems and processes to make itself the number one choice for data transfer and integration for 9 out of 10 people who think they matter. Since XML is used primarily for data transfer, how will we represent behavior for a Web service? We simply apply a little SOAP.

The Simple Object Access Protocol (SOAP) has found its way to the forefront of the Web services scene and stepped forward to handle the task of representing data and behavior simultaneously on different platforms. SOAP is an XML-based protocol used to describe Web service messages and user-defined datatypes, along with remote procedure calls (RPC) and responses.

SOAP does three things for us:

  1. It defines a Web service as a message and defines the intended recipient of the message.
  2. It presents a way to define and serialize arbitrary datatypes.
  3. It defines operations a Web service can perform as remote procedure calls and the responses returned by these calls.
The Envelope, Please
A SOAP message is encapsulated in an element called a "SOAP envelope." The envelope consists of an optional header element and a mandatory body element. The optional header can be used to represent SOAP extensions for things such as transaction management and authentication. The body element is used to contain the name and data for each operation of a message and one optional element known as a "SOAP Fault," which contains error or status information.

Listing 1 shows a SOAP envelope containing a body used to call the getTime method; Listing 2 shows a SOAP envelope containing a body used to return an error from the getTime method.

Namespaces
A namespace is an arbitrary domain that provides a means for identically named elements to coexist. A file system provides a good example of a name space. In a Unix-like file system, I can have two files named mycon tacts.txt residing on my hard drive. One file resides in the directory, /home/my name/ contacts, and an identically named file is in the directory, /home/myname/my docs. Since the fully qualified name for each file is different, there are no name collisions. In other words, to reference one file, I might enter/home/ myname/contacts/mycon tacts.txt and to reference the other file, I would enter /home/myname/mydocs/my contacts.txt. As you can see, when applying the full paths to the files, we end up with names that are unique.

XML also uses namespaces to avoid name collisions. A namespace in XML is identified by a Uniform Resource Identifier (URI). URIs are strings that typically identify resources on the Web such as documents, images, services, e-mailboxes, and other resources. An XML URI points to a file or Web address that defines the namespace. An XML document can assign a namespace a variable name in order to designate which namespace subsequent elements belong to. Listing 3 demonstrates the definition of multiple namespaces in an XML document.

The example refers to a bowlers namespace and assigns it a variable name, bowl. Also, shown is a second namespace, lanes, which is assigned to the variable, lane. The variable names are usually referred to as prefixes, since they're used as prefixes for element names.

Default namespaces can also be declared and used. Any element or attribute that isn't prefixed/qualified, belongs to the default namespace (see Listing 4).

In the example, the <Name> element has been used more than once. Since the teams namespace was declared as the default, the teams elements don't require a prefix.

When different document type definitions (DTDs) are included in the same XML document, name collisions can occur. XML namespaces solve the name-collision problem between elements that have the same name in these different documents. Namespaces can be shared by multiple documents, and businesses will typically use namespaces to identify elements specific to their documents.

A namespace attribute defines a shorthand prefix for a namespace that's used throughout a document. For example, xml ns:xsd defines xsd as a shorthand prefix for the namespace http://www.w3.org/2001/XMLSchema. With this shorthand prefix defined, we can qualify a reference to a datatype later in the document by using just the prefix, as in xsd:int. Table 1 shows some common prefixes and corresponding namespaces. The targetNamespace attribute defines the namespace to which all names declared in a given element belong.

Table 1

SOAP and HTTP
Since HTTP is ubiquitous throughout the Web infrastructure, it's being presented as the protocol of choice for transporting SOAP request and response data. A typical SOAP request over HTTP proceeds as shown in Figure 1.

Figure 1

A SOAP method can be thought of simply as a SOAP-encoded HTTP POST request. SOAP requests should use the text/xml content-type. A SOAP request over HTTP should indicate the SOAP method to be called using the SOAPAction HTTP header. The SOAPAction header contains an application-specific method name.

A SOAP request is an XML document containing the in and out parameters of the SOAP method. These values are child elements within the SOAP body and share the same namespace as the SOAP method name.

A SOAP response is similar to a SOAP request, in that the content for the response must be contained within the SOAP body and typically uses the same datatypes as the request.

Handling SOAP Messages
Since HTTP is the primary protocol used to transmit SOAP messages, we want to find a mechanism in Java that will handle HTTP for us. The component we build needs to do three things:

  1. Parse the SOAP message from XML and convert it into a Java method call.
  2. Invoke the object responsible for handling the message.
  3. Serialize a response or error (if either is needed) back into XML and deliver it to the submitter of the request.
Java HTTP servlets are designed to handle the HTTP protocol, so that's what we'll use.

Servlets to the Rescue
A servlet is a Java object designed to handle a request/response-based protocol. Servlets that extend javax.servlet.http.Http Servlet are used to respond to HTTP requests. We'll exploit the HttpServlet to implement a SOAP-over-HTTP handler that will field HTTP requests and respond with appropriate responses or errors. We'll use the SAX parser APIs provided by the Apache/Axis project to handle any XML parsing tasks. The code in Listing 5 will be the servlet implementation we'll dynamically produce.

Some SOAP with Your Java?
Java is being used in a vast number of enterprise/Web application architectures. In fact, some would argue (at the risk of starting a holy war) that Java is the language of choice for enterprise/Web application development. We'll avoid military action here and just assume that Java is worthy of our attention and deserves an attempt at Web services integration.

Java is a very descriptive language. At runtime, Java presents all kinds of information about its environment and the objects running in it. We can exploit this information to dynamically generate data and objects that are needed to create and publish a Web service.

Reflections
Java provides a powerful API for obtaining information about classes and objects at runtime. This API, contained in the java. lang.reflect package, will be used to dynamically create the servlet code for our Web service. Listing 6 provides our reflection class.

As the code demonstrates, we handle EJBs and regular Java classes quite similarly. The main difference is the lookup and creation of an EJB, as opposed to a standard object instantiation for a regular Java class.

Datatypes and Encodings
The latest XML Schema at http://www.w3.org/TR/2001/PR-xmlschema-2-20010330 defines a set of built-in datatypes for the namespace, http://www.w3.org/2000/10/XMLSchema. Along with these built-in datatypes, user-defined datatypes can be specified. Table 2 shows a list of some built-in XML datatypes and the built-in Java datatypes we can use to represent them.

Table 2

XML Schemas can be used to specify user-defined datatypes. These datatypes can be represented in XML as part of a SOAP envelope. This gives us the ability to encode any datatype in a SOAP message that can be described in an XML schema.

Publish That Thing
Once we have our Web service implementation complete, we must provide a way for clients/consumers to discover our Web service. The current trend for solving this problem is to publish a Web service in a globally accessible registry. The Universal Description, Discovery and Integration (UDDI) specifications define one such registry.

UDDI
UDDI uses XML to define a distributed registry of businesses and their Web service descriptions. UDDI defines a meta-data construct, known as a tModel, to identify technical specifications for Web services. Of interest to us is the overviewURL child element of the overviewDoc element within a tModel construct. The overviewURL element is used to store a URL that points to a specification document describing our Web service. This specification document is called a Web Services Description Lan-guage (WSDL) document.

WSDL
A WSDL document is used to describe a Web service's operations and data types in XML. A WSDL document specifies a namespace to which the Web service and its datatypes belong. If our Web service defines elements or documents that don't need to be considered globally unique, we can use the URI, http://tempuri.org/, as the base for a namespace within our WSDL document. This "temporary" URI is useful when testing a version of our Web service that isn't ready for production. It's also useful for versioning an entity without having to come up with new, unique URIs for each version

A summary of the WSDL file, known as an implementation file, is what's actually used to publish a Web service to a UDDI registry. Listing 7 is an example of a WSDL file. In this example, you'll notice that a WSDL file is comprised of elements with names such as Message, PortType, Binding, and Service. The main thing to remember is that a WSDL file defines an abstract definition of our Web service and details about the concrete implementation of our service. We won't delve into the details of each element in this article, instead, we'll point out that the Apache/Axis project defines a valuable tool called Java2WSDL, which will dynamically generate a WSDL file for an existing Java class.

Summary
SOAP, WSDL, UDDI, and XML form a robust and comprehensive framework for delivering Web services. Java provides an extensive API set for dynamic discovery of object and class information at runtime. Using these technologies with a toolkit such as the Apache/Axis project, gives us the power to produce Web services dynamically with little or no interaction with the original developer of a Java class or EJB.

Author Bio
Jeff Hanson has more than 17 years of experience in the industry, including working as senior engineer for the Windows OpenDoc port and lead architect for the Route 66 framework at Novell. He is currently chief architect for Zareus, Inc. info@sys-con.com

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>

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.

  E-mail: info@sys-con.com

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.