Creating a Simple Service

NOTE

All the examples in the rest of this chapter refer to the J2EE Reference Implementation. However, the information required and the techniques used are common across all implementations of JAX-RPC. Basically, the tools might change but the artifacts and information you have to provide as a developer don't.


The initial service is servlet-based and will just pass strings back and forth to exchange greetings. After you are comfortable with this simple service, we will move on to look at how to provide a Web Service front-end for a session EJB.

Files and Tools

In common with other J2EE components, a J2EE-based Web Service implementation consists of multiple parts:

  • A reference to the implementation of the functionality to be exposed by the Web Service, which can point to simple Java classes bundled with the component or which can refer to one or more EJBs

  • Code that maps between the exposed functionality and the container—for example, skeletons (or ties) and serializers

  • A WSDL definition of the interface implemented by the service

  • Configuration files that tell the J2EE implementation more about how the service should be deployed and the services it requires from its container

A Web Service client has similar code and configuration files but does not carry an interface definition or service implementation information.

All the configuration files are encoded in XML. Some of them are reasonably simple and can easily be created by hand. Other files, such as the WSDL interface definition, are far more complex and will typically be generated by tools. The stubs and skeletons required will also be automatically generated. To generate the stubs, skeletons, and WSDL interface definition, we will use the wscompile tool provided as part of the J2EE Reference Implementation.

Defining the Interface and Implementation

As with RMI, a remote interface definition is central to the use of JAX-RPC. This interface is either written by a developer and then used to generate a WSDL file, or the Java interface is generated from a pre-provided WSDL file. In the examples we look at today, the WSDL file is generated from the Java interface definition. The Java interface definition must extend java.rmi.Remote and all methods must be declared as throwing java.rmi.RemoteException. The simple Web Service is based around a simple Java Remote interface, Greeting, containing a single method called sayHelloTo(). The sayHelloTo() method takes a single String parameter—the name of the person to greet—and returns the resultant greeting. The Greeting interface is shown in Listing 20.1.

Listing 20.1. Interface for the Greeting Service (Greeting.java)
package wsexamples;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Greeting extends Remote
{
    public String sayHelloTo(String name) throws RemoteException;
}

The sayHelloTo() method is the Web Service equivalent of the “Hello World!” program used as a first step in learning programming languages such as C and Java. In Web Service terms, the method is simple because it takes a single parameter and returns a single value. These values are both strings, and strings are easily marshaled between the on-the-wire XML representation used by SOAP and the internal java.lang.String type.

The Greeting interface is implemented by the GreetingImplementation class. The sayHelloTo() method simply appends the name passed in onto a suitable greeting and passes back the resultant string. The GreetingImplementation class is shown in Listing 20.2.

Listing 20.2. Implementation of the Greeting Service (GreetingImplementation.java)
package wsexamples;

public class GreetingImplementation implements Greeting
{
    public String sayHelloTo(String name)
    {
        return "Hi there " + name;
    }
}

As you can see, there is nothing special about the GreetingImplementation class. If you did not know that Greeting was a Remote interface, the rest of the class gives you no indication. As stated earlier, this first example will be a servlet-based Web Service. However, there is no servlet definition in the interface or implementation. As the creation of a servlet to implement a given interface is something of a predictable task, all this can be automated. Think of the implementation class as being like the bean class in an EJB—it will get surrounded by “scaffolding” as it is deployed and configured. This “scaffolding” consists of the fixed infrastructure provided by J2EE, such as the SOAP routing servlet discussed earlier, and some files specifically generated for your service, such as the Web Service stub and skeleton files.

Web Service Compiler Configuration File

When you created EJBs earlier, you had to include various configuration files to tell the container about the EJB and its requirements. The same principle applies for a JAX-RPC Web Service. Somehow, a variety of artifacts must be created that describe the service for potential clients and help to integrate the service with its container. In the J2EE Reference Implementation, the main tool for this is wscompile. The wscompile tool can generate WSDL, server-side scaffolding, and client-side scaffolding. For the time being, you will concentrate on the WSDL and server-side scaffolding.

wscompile requires a variety of information about the artifacts you need to create. You define this information in an XML-encoded configuration file. The root element is configuration and its sole attribute indicates that the file conforms to the RI's JAX-RPC schema:

<configuration xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">

Within this root element you will typically define one of two child elements:

  • service— Contains information to help generate a WSDL file based on a Remote interface

  • wsdl— Defines information about a Web Service definition from which a Remote interface is to be generated

The element you require will depend on whether you are starting from a Java interface definition or starting from WSDL. In this case, you will start from the code and generate the WSDL. Although this is convenient as a learning exercise, it is not the best practice to follow when creating industrial-strength Web Services. Some of the reasons for this are discussed in the section “Starting from WSDL” later today.

In this case, because you are generating a WSDL file from a Remote interface, you need a service element within the root. The attributes of this element define the following:

  • The name of the service (name) that is to be defined in the WSDL description.

  • The target namespace (targetNamespace) within which the service's messages and message parts are to be defined.

  • The namespace (typeNamespace) within which the service's data types are to be defined.

  • The package into which generated Java artifacts are to be placed (packageName). Because you are only defining a WSDL document at the moment, this is not used, but it must still be provided; otherwise, wscompile will fail.

The resultant element will look something like this:

<service name="GreetingService"
         targetNamespace="urn:J2EE21Examples"
         typeNamespace="urn:J2EE21ExamplesTypes"
         packageName="wsexamples"
>

Each service element can contain one or more interface elements. The interface element describes a Web Service endpoint that is exposed as part of the service. The name attribute defines the name of the Java interface that implements the methods to be exposed. This should be set to the fully qualified name of the interface you created earlier (you can also specify the name of the implementation, or servant, class using the servantName attribute although this does not affect the generation of the WSDL):

<interface name="wsexamples.Greeting" servantName="wsexamples.GreetingImplementation"/>

Listing 20.3 shows a full wscompile configuration file that will generate the WSDL for the simple Greeting interface shown earlier.

Listing 20.3. wscompile Web Service Configuration File (config-service.xml)
<?xml version="1.0" encoding="UTF-8"?>
<configuration
  xmlns="http://java.sun.com/xml/ns/jax-rpc/ri/config">
  <service
      name="GreetingService"
      targetNamespace="urn:J2EE21Examples"
      typeNamespace="urn:J2EE21ExamplesTypes"
      packageName="wsexamples">
      <interface name="wsexamples.Greeting" servantName="wsexamples.GreetingImplementation"/>
  </service>
</configuration>

You define which artifacts you want wscompile to generate using command-line options. Once you have created the configuration file shown in Listing 20.3, you can use wscompile to generate the WSDL description and mapping file for the Greeting service.

Under Microsoft Windows:

wscompile -define -classpath %CLASSPATH%;classes -nd wsgenerated –mapping wsgenerated
mapping.xml wsconfig-service.xml

Under Unix:

wscompile -define -classpath $CLASSPATH:classes -nd ws/generated –mapping ws/generated
/mapping.xml ws/config-service.xml

The line shown assumes that the compiled classes for Greeting and GreetingImplementation reside in the classes subdirectory and that the configuration file is in the ws subdirectory. The –define flag indicates that you want just the service definition at the moment (no server or client artifacts), the –nd flag indicates that the resultant WSDL file should be placed in the ws/generated subdirectory, and the –mapping flag indicates where the generated mapping file is to be saved.

The code for all of today's examples is on the Web site that accompanies this book. You will find them in the examples directory for Day 20. With the code supplied on the accompanying Web site, you can use the following Ant command to build the supplied Greeting service, which includes the creation of the WSDL and the mapping file:

asant build

The WSDL File

The WSDL file generated by wscompile is shown in Listing 20.4. It is worth taking a few moments to study this information because it provides a good insight into the way that Web Services work.

Listing 20.4. Generated GreetingService WSDL (GreetingService.wsdl)
<?xml version="1.0" encoding="UTF-8"?>

<definitions name="GreetingService"
             targetNamespace="urn:J2EE21Examples"
             xmlns:tns="urn:J2EE21Examples"
             xmlns="http://schemas.xmlsoap.org/wsdl/"
             xmlns:xsd="http://www.w3.org/2001/XMLSchema"
             xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <types/>
    <message name="Greeting_sayHelloTo">
        <part name="String_1" type="xsd:string"/>
    </message>
    <message name="Greeting_sayHelloToResponse">
        <part name="result" type="xsd:string"/>
    </message>
    <portType name="Greeting">
        <operation name="sayHelloTo" parameterOrder="String_1">
            <input message="tns:Greeting_sayHelloTo"/>
            <output message="tns:Greeting_sayHelloToResponse"/>
        </operation>
    </portType>
    <binding name="GreetingBinding" type="tns:Greeting">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"style="rpc"/>
        <operation name="sayHelloTo">
            <soap:operation soapAction=""/>
            <input>
                <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                           use="encoded"
                           namespace="urn:J2EE21Examples"/>
            </input>
            <output>
                <soap:body encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
                           use="encoded"
                           namespace="urn:J2EE21Examples"/>
            </output>
        </operation>
    </binding>
    <service name="GreetingService">
        <port name="GreetingPort" binding="tns:GreetingBinding">
            <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
        </port>
    </service>
</definitions>

The document consists of the following sections:

  • The XML prolog (<?xml ...?>) and root element(definitions)— The namespace declarations on the root element show that the operations defined here belong in the namespace urn:J2EE21Examples and that this namespace is also represented by the tns prefix. The default namespace declaration indicates that all unqualified elements and attributes come from the W3C's WSDL definitions. The xsd prefix denotes types from the W3C XML Schema definition, whereas the soap prefix denotes types from the SOAP schema.

  • The types section— There are no complex types in the Greeting interface, so all the type definitions required come from the XML Schema. Hence, the types element is empty.

  • WSDL message definitions— These define two matched messages: a request and a response. The request (Greeting_sayHelloTo) takes a single string parameter, and the response (Greeting_sayHelloToResponse) also returns a single string.

  • WSDL portType definitions— A portType is the equivalent of an interface definition. It contains one or more operation definitions, which in turn are built from the message definitions in the document. In this case, there is a single operation defined in the Greeting called sayHelloTo. This consists of the two messages, Greeting_sayHelloToRequest and Greeting_sayHelloToResponse, seen earlier.

  • The binding element— Called GreetingBinding, it indicates that clients can access the Greeting port type through the SOAP protocol. Now that you have an interface (portType), you can define the protocols over which that interface can be accessed. The WSDL operation is mapped to a SOAP operation with input and output soap:body elements defined to map the request and response.

    Within this WSDL binding, a SOAP binding (soap:binding) is defined— Because SOAP can work with a variety of underlying transports and it can work in an RPC-centric or document-centric way, the attributes on the soap:binding indicate that it is an RPC-style binding that uses HTTP.

  • Finally, an instance of the service is defined in the WSDL service element— A WSDL service contains a list of WSDL port elements. Each port element defines a specific instance of a server that conforms to one of the WSDL binding elements defined earlier.

    Again, in the case of the simple Greeting service, the service element (named GreetingService) contains a single WSDL port called GreetingPort. This specifies that a server conforming to the GreetingBinding can be found at the SOAP address defined by the location attribute.

This is a very simple WSDL document defining a very simple service. WSDL documents are typically far longer and more complex. Because of this, WSDL is largely intended for manipulation by tools and applications.

By examining the WSDL document, you can see how the information defined in the wscompile configuration file forms part of the WSDL. The targetNamespace and tns prefix in the WSDL are associated with the targetNamespace defined in the configuration file. The name of the WSDL service comes from the name attribute of the service element in the configuration file. The WSDL port is formed by appending the string “Port” to the name of the interface defined as a child of the service element in the configuration file.

One thing to note about the generated WSDL is that it is not complete. All the relevant type definitions are there (none in this case, but you will see more later), as are the definitions of the operations and their parameters and the protocol bindings. However, in the SOAP address associated with the port element, there is no endpoint address (the location is set to “REPLACE WITH ACTUAL URL”). This is not surprising because this WSDL has been generated from a class on the disk and wscompile has no way of knowing where this service will be deployed. Part of the deployment process will involve filling out this WSDL endpoint information so that the WSDL can be employed by a Web Service client.

The Mapping File

The mapping file—mapping.xml—provides a link between information in the WSDL document and the Java code supplied to support the service defined. There is a 1-1 relationship between mapping files and WSDL documents, and there are other constraints on the WSDL to assist the mapping, such as there being only one service description in a WSDL file. A full list of these restrictions and a detailed description of the mapping file (termed the “JAX-RPC Mapping Deployment Descriptor”) can be found in section 7.3 of the document Web Services for J2EE document that was produced by JSR109.

Thankfully, the mapping file for our simple Greeting service is itself simple. It starts with a standard prolog and the root element java-wsdl-mapping:

<?xml version="1.0" encoding="UTF-8"?>
<java-wsdl-mapping version="1.1"
                   xmlns="http://java.sun.com/xml/ns/j2ee"
                   xmlns: "xsi=http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                      http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd">

Within the root, you define package-mapping elements that map the namespaces using the WSDL to Java packages in which you define your classes. For the simple service, you just need to indicate that the service defined in the WSDL document under the target namespace of urn:J2EE21Examples is associated with the code defined in the Java package wsexamples:

<package-mapping>
    <package-type>wsexamples</package-type>
    <namespaceURI>urn:J2EE21Examples</namespaceURI>
</package-mapping>

The remainder of the mapping file defines how the WSDL service, port and binding relate to the parts of the Java Greeting interface defined earlier. The full mapping file is shown in Listing 20.5.

Listing 20.5. Mapping File for the Simple Greeting Service (mapping.xml)
<java-wsdl-mapping version="1.1"
                   xmlns="http://java.sun.com/xml/ns/j2ee"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
                       http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd">
  <package-mapping>
    <package-type>wsexamples</package-type>
    <namespaceURI>urn:J2EE21ExamplesTypes</namespaceURI>
  </package-mapping>
  <package-mapping>
    <package-type>wsexamples</package-type>
    <namespaceURI>urn:J2EE21Examples</namespaceURI>
  </package-mapping>
  <service-interface-mapping>
    <service-interface>wsexamples.GreetingService</service-interface>
    <wsdl-service-name xmlns:serviceNS="urn:J2EE21Examples">serviceNS:GreetingService<
/wsdl-service-name>
    <port-mapping>
      <port-name>GreetingPort</port-name>
      <java-port-name>GreetingPort</java-port-name>
    </port-mapping>
  </service-interface-mapping>
  <service-endpoint-interface-mapping>
    <service-endpoint-interface>wsexamples.Greeting</service-endpoint-interface>
    <wsdl-port-type xmlns:portTypeNS="urn:J2EE21Examples">portTypeNS:Greeting</wsdl-port-type>
    <wsdl-binding xmlns:bindingNS="urn:J2EE21Examples">bindingNS:GreetingBinding<
/wsdl-binding>
    <service-endpoint-method-mapping>
      <java-method-name>sayHelloTo</java-method-name>
      <wsdl-operation>sayHelloTo</wsdl-operation>
      <method-param-parts-mapping>
        <param-position>0</param-position>
        <param-type>java.lang.String</param-type>
        <wsdl-message-mapping>
          <wsdl-message xmlns:wsdlMsgNS="urn:J2EE21Examples">wsdlMsgNS:Greeting_sayHelloTo<
/wsdl-message>
          <wsdl-message-part-name>String_1</wsdl-message-part-name>
          <parameter-mode>IN</parameter-mode>
        </wsdl-message-mapping>
      </method-param-parts-mapping>
      <wsdl-return-value-mapping>
        <method-return-value>java.lang.String</method-return-value>
        <wsdl-message xmlns:wsdlMsgNS="urn:J2EE21Examples">wsdlMsgNS
:Greeting_sayHelloToResponse</wsdl-message>
        <wsdl-message-part-name>result</wsdl-message-part-name>
      </wsdl-return-value-mapping>
    </service-endpoint-method-mapping>
  </service-endpoint-interface-mapping>
</java-wsdl-mapping>

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.125.51