An Echo Web Service

The impatient can very quickly create and call a generic Web Service by creating a .jws file. A .jws file is a file that represents a Web Service but that is compiled and deployed automatically. A sample .jws file is Listing 10.15.

Listing 10.15
start example
 public class EchoService {  public String doEcho( String input) {  return "Hello world " + input;  } } 
end example

Listing 10.15 looks just like a Java class file, and indeed it is. The extension .jws is used to define a compilable file, which is a Java class file. You can reconfigure the extension using the Web application configuration file web.xml .

The Web Service is called using a client application like Listing 10.16.

Listing 10.16
start example
 public class Client { static String _endPointJWS = "http://localhost:8080/axis/EchoService.jws"; public void doEchoServiceJWS() throws Exception{ Service service = new Service(); Call call = (Call)service.createCall(); call.setTargetEndpointAddress( new URL( Client._endPointJWS)); call.setOperationName( new QName( "urn:echoservice.localhost", "doEcho")); call.addParameter( "input", XMLType.XSD_STRING,  ParameterMode.IN); call.setReturnType( XMLType.XSD_STRING); String sendText = "hello world"; System.out.println((String)call.invoke( new Object[] { sendText })); } public static void main(String[] args) { try { Client client = new Client(); client.doEchoServiceJWS(); } catch( Exception ex) { System.out.println( "oops error " + ex.toString()); } } } 
end example

Listing 10.16 is a sample of a manual Web Service request. The code is manual because the Web Service client request is created manually using the appropriate object and method call. When you use the code generation tools, all of the manual steps in Listing 10.16 are encapsulated in generated easy-to-use classes.

To call a Web Service, you need to instantiate the class Service . This class provides the base infrastructure for all client requests . To create a Web Service and call a Call class instance, use the method createCall . Once the Call class instance has been created, you can specify various parameters that make up the Web Service request.

The method setTargetEndpointAddress specifies the URL where the Web Service is located. Because the server Web Service is a .jws file, a direct reference to the .jws is defined. The method setOperationName accepts a QName class instance as a single parameter. A QName is a legitimate XML term signifying an XML element and its associated namespace. Remember when we talked about the SOAP specification that namespaces have to be used. Therefore, to be able to specify an XML element and its associated namespace, the class QName is used. The only issue is that in Listing 10.16 the namespace is not relevant because a .jws file is called.

Looking back at Listing 10.15, the method doEcho has one parameter and a return value. Therefore, in Listing 10.16 the client has to allocate space for both a parameter and return value. The method addParameter has three parameters: "input" , XMLType. XSD_STRING , and ParameterMode.In . The first parameter, "input" , specifies the name of the parameter and must match the name of the parameter in Listing 10.15. The second parameter, XMLType.XSD_String , specifies the parameter type, which in Listing 10.15 is a string data type. It is important to match the parameter types because the marshalling code, which converts Java types to XML and vice versa, on the client and server side uses the specified parameter data types to format the data correctly. The third and last parameter, ParameterMode.In , specifies the direction of the parameter. The direction of the parameter is used to optimize network traffic. In the case of Listings 10.15 and 10.16, the parameter input is sent from the sender to the receiver only. If the parameter were ParameterMode.INOUT , then the data would travel from the sender to the receiver and back to the sender. If the parameter were ParameterMode.OUT , then the data would travel from the receiver to the sender. To specify a return value, you use the method setReturnType . The method setReturnType has only one parameter, which specifies the return value data type.

Once the method call has been set up, the call to the Web Service can be made using the method call invoke . The method call invoke accepts as a parameter an array of objects that represent the individual parameters defined earlier in the program. When the invoke method completes, an object representing the returned message and associated data is automatically generated and returned to the caller of the method.

Watching the Data

The simple Web Service will do what is required of it. The simple Web Service demo is about as exciting as watching paint dry because most of the action about the Web Service is happening at a lower level. To be able to watch this lower level, you need to start a SOAP protocol spy. Within the Axis toolkit is an application called TcpMon. The application TcpMon is a port sniffer that captures requests and then delegates the requests to a destination port. TcpMon could be considered a sort of proxy, except it does nothing that useful other than sniff SOAP requests. The details of running TcpMon are outlined in Chapter 11. Listing 10.17 is the request for the simple Web Service, and Listing 10.18 is the response from the Web Service.

Listing 10.17
start example
 POST /axis/EchoService.jws HTTP/1.0 Content-Type: text/xml; charset=utf-8 Accept: application/soap+xml, application/dime, multipart/related, text/* User-Agent: Axis/1.1RC2 Host: Cache-Control: no-cache Pragma: no-cache SOAPAction: "" Content-Length: 478 <?xml version="1.0" encoding="UTF-8"?>  <soapenv:Envelope  xmlns:soapenv=""  xmlns:xsd=""  xmlns:xsi=""> <soapenv:Body>  <ns1:doEcho  soapenv:encodingStyle=""  xmlns:ns1="urn:echoservice.localhost "> <input xsi:type="xsd:string">hello world</input>  </ns1:doEcho> </soapenv:Body>  </soapenv:Envelope> 
end example
Listing 10.18
start example
 HTTP/1.1 200 OK Set-Cookie: JSESSIONID=F042CD79C0C7E00ABDA5D2CF07D028CD; Path=/axis Content-Type: text/xml; charset=utf-8 Date: Fri, 13 Jun 2003 13:25:04 GMT Server: Apache Coyote/1.0 Connection: close <?xml version="1.0" encoding="UTF-8"?>  <soapenv:Envelope  xmlns:soapenv=""  xmlns:xsd=""  xmlns:xsi=""> <soapenv:Body>  <ns1:doEchoResponse soapenv:encodingStyle="" xmlns:ns1="urn:echoservice.localhost "> <doEchoReturn xsi:type="xsd:string">Hello world hello world</doEchoReturn>  </ns1:doEchoResponse> </soapenv:Body>  </soapenv:Envelope> 
end example

In Listings 10.17 and 10.18, we kept the HTTP headers so that we could illustrate the information that is sent between the server and client. Notice how, in both listings, the SOAP message is wrapped in namespaces and Schema information. The soapenv namespace identifier is used to identify the SOAP message specification type, which is not SOAP 1.2, but SOAP 1.1. Also notice that the attribute soapenv:encodingStyle is used to indicate a SOAP-encoded format for the parameters. We implicitly chose this format because the Web Service is an RPC-style Web Service. The HTTP header Content-Type refers to a content payload of text/xml , which is the correct Multipurpose Internet Mail Extensions (MIME) encoding. The HTTP header Accept refers to various formats that can be generated by a Web Service. Specifically, the MIME encoding application/dime is a format of SOAP that supports attachments. One of the last items to notice is how the content data that is encapsulated by the XML tag soapenv:Body has its own custom namespace that references a namespace identifier. The namespace identifier is identical to the QName defined in Listing 10.16.

Auto-Generating the Client Stub

When you're writing professional Web Service applications, the client application in Listing 10.16 involves too much coding. Within the Axis toolkit is a tool to generate WSDL from a Web Service, and a tool to generate client or server stubs from a WSDL. For example, on the client side, the stubs contain the manual steps defined in Listing 10.16. Since the Web Service is already deployed and working, the objective would be to use a WSDL file to generate a client implementation. To generate a WSDL file, you can use the built-in WSDL generator. To generate a WSDL file, use the Web Service URL endpoint and add the text ?wsdl . For example, in Listing 10.16 the endpoint URL was http://localhost:8080/ xis/EchoService.jws; therefore, the WSDL URL would be http://localhost:8080/axis/EchoService.jws?wsdl . The generated WSDL will be returned as an XML response, which could be saved. Typically, the end user would use a browser when generating the WSDL and then save the content, which is shown in Listing 10.19 (the details to notice are in bold).

Listing 10.19
start example
 <wsdl:definitions targetNamespace="http://localhost:8080/axis/EchoService.jws" xmlns="" xmlns:apachesoap="" xmlns:impl="http://localhost:8080/axis/EchoService.jws" xmlns:intf="http://localhost:8080/axis/EchoService.jws" xmlns:soapenc="" xmlns:wsdl="" xmlns:wsdlsoap="" xmlns:xsd=""> <wsdl:message name="doEchoResponse"> <  wsdl:part name="doEchoReturn" type="xsd:string"/  > </wsdl:message> <wsdl:message name="doEchoRequest"> <  wsdl:part name="input" type="xsd:string"/  > </wsdl:message> <wsdl:portType name="EchoService"> <  wsdl:operation name="doEcho" parameterOrder="input"  > <  wsdl:input message="impl:doEchoRequest" name="doEchoRequest"/  > <  wsdl:output message="impl:doEchoResponse" name="doEchoResponse"/  > <  /wsdl:operation  > </wsdl:portType> <wsdl:binding name="EchoServiceSoapBinding" type="impl:EchoService"> <  wsdlsoap:binding style="rpc" transport=""/  > <wsdl:operation name="doEcho"> <  wsdlsoap:operation soapAction=""/  > <wsdl:input name="doEchoRequest"> <  wsdlsoap:body   encodingStyle=""   namespace="http://localhost:8080/axis/EchoService.jws" use="encoded"/  > </wsdl:input> <wsdl:output name="doEchoResponse"> <wsdlsoap:body encodingStyle="" namespace="http://localhost:8080/axis/EchoService.jws" use="encoded"/> </wsdl:output> </wsdl:operation> </wsdl:binding> <wsdl:service name="EchoServiceService"> <wsdl:port binding="impl:EchoServiceSoapBinding" name="EchoService"> <  wsdlsoap:address location="http://localhost:8080/axis/EchoService.jws"/  > </wsdl:port> </wsdl:service> </wsdl:definitions> 
end example

In the WSDL file defined by Listing 10.19, there is no WSDL types section. This is done on purpose because the types are so simple that there does not need to be a WSDL types section. The WSDL tag wsdl:message defines two SOAP messages. The identifiers are generated using the name of the Web Service method appended with the direction of the SOAP message, which is either response or request. The Web Service method is called doEcho , and hence the names of WSDL messages are doEchoRequest and doEchoResponse . The do-EchoResponse message corresponds to the return value of the initial EchoService.jws file defined in Listing 10.15.

Java does not label its return parameters, so the return value is generated using a combination of the method name and the text "Return." The doEchoRequest message labels its parameter according to the identifier of the parameter in the EchoService.jws file defined in Listing 10.15. In each of these messages, the parameter is a string, which corresponds to the XML Schema data type xsd:string .

For the WSDL operation, the messages are combined into a request response message conversation. What is special is the attribute parameterOrder . This attribute is optional and specifies the order of the parameters in the SOAP method calls.

The WSDL tag wsdlsoap:binding tag specifies that the SOAP conversation is an RPC type using the transport specified by the HTTP binding. The more dangerous tags in the sense of configuration issues are the tags wsdlsoap:body and wsdlsoap:address . These tags are problematic for configuration because they reference absolute addresses where the Web Service exists. The URL references the localhost address. For testing purposes, this is fine, but for Internet or Intranet access, this is a problem. The client-generated code will attempt to make a request on the localhost Web server, which most likely will not work. Therefore, before deploying the WSDL file, you need to update these settings. This means for development purposes that it is fine to dynamically generate a WSDL file. In production, though, all WSDL files should be made available statically.

Once the WSDL file has been generated, you can use the Axis tool that converts the WSDL to a number of Java files. The generated Java files perform the exact same operations as the manual client did. The difference is that the code is generated and presents an easy-to-use interface, as shown in Listing 10.20.

Listing 10.20
start example
 EchoServiceServiceLocator locator = new EchoServiceServiceLocator(); EchoService service = locator.getEchoService( new URL( Client._endPointJWS)); System.out.println( service.doEcho( "hello world")); 
end example

The code in Listing 10.20 has been shrunk down to three lines of Java source code. All of the classes used in Listing 10.20 are generated classes. The classes do follow a naming convention in that the name of the Web Service is combined with the generated class name. The class EchoServiceServiceLocator is used to locate the Web Service. To retrieve an actual instance of the Web Service, the method getEchoService is used. This method has one parameter. The single parameter represents the URL of the endpoint of the Web Service. The single parameter is optional and, if it's not specified, the WSDL-defined URL is used. The method getEchoService returns an interface instance that is identical in method signature to the Web Service implementation defined in Listing 10.15.

The Axis Web Service implements the Commons Bridge best practice when generating the Web Service implementations . This is good because it means that a factory can decide on the fly to return an actual implementation of the Web Service or a proxy, which delegates the call to the network.

Formal Deployment of the Web Service

For simple Web Services, the .jws extension technique we've just shown is very effective. However, it assumes that the Web Service is RPC based and has standard parameters. For anything more complex or special, it is not possible to use that type of technique. In those other situations, the Web Service has to be formally deployed. The Web Service that will be deployed is based on Listing 10.15 and is shown in Listing 10.21.

Listing 10.21
start example
 public class Echo {  public String doEcho( String input) {  return "Your Message: (" + input + ")";  } } 
end example

To formally deploy a Web Service, you need to create a .wsdd file. In the SOAP and WSDL specification, there is a hole: the definition of the implementation details. For example, the WSDL file specifies the parameters, messages, and URL of the Web Service. However, it doesn't specify how to cross-reference the Web Service WSDL file with the Java class files. When the .jws file was deployed and copied to the server, the cross-reference between the WSDL file and the implementation happened automatically. Listing 10.22 is a sample deploy.wsdd file.

Listing 10.22
start example
 <deployment name="Echo" xmlns="" xmlns:java="" xmlns:xsi="">  <service name="Echo" provider="java:RPC">  <parameter name="className" value=""/>  <parameter name="allowedMethods" value="doEcho"/>  </service> </deployment> 
end example

In Listing 10.22, the deployment file is defined using the XML tag deployment Within the XML tag deployment can be one or multiple XML service tags. Each XML tag service represents an individual Web Service that is to be deployed. A basic Web Service is defined using the attributes name and provider The attribute name defines the basic identifier for the Web Service catalog on the Servlet container. The attribute provider defines the type of Web Service, which can either be java:RPC or java:MSG . Since the Web Service being deployed is RPC based, the java:RPC identifier would be appropriate.

Within the XML tag service can be multiple parameter XML tags. Each parameter XML tag has a name and value attribute. The name attribute references an identifier parameter. In Listing 10.22, two parameter identifiers are used. The parameter identifier className defines the class that is loaded and represents an XML RPC Web Service. The parameter identifier allowedMethods defines a list of comma-separated methods that accept Web Service requests.

To remove a deployed Web Service, you need to create an undeployment file like the one shown in Listing 10.23.

Listing 10.23
start example
 <undeployment name="Echo" xmlns=""> <service name="Echo"/> </undeployment> 
end example

In Listing 10.23, the XML tag undeployment is used to undeploy a file. Within the XML tags can be multiple service XML tags. Each service XML tag represents a service that is to be undeployed. The deployment and undeployment files are manipulated using a program called the AdminClient , which is a Java class file. It is invoked using a command line similar to Listing 10.24.

Listing 10.24
start example
 java org.apache.axis.client.AdminClient [deployment file or undeployment file] 
end example

Progress messages are output, and a successful deployment or undeployment will result in a final success message.

Applied Software Engineering Using Apache Jakarta Commons
Applied Software Engineering Using Apache Jakarta Commons (Charles River Media Computer Engineering)
ISBN: 1584502460
EAN: 2147483647
Year: 2002
Pages: 109 © 2008-2017.
If you may any questions please contact us: