JAX-RPC Evolves into Simpler, More Powerful JAX-WS 2.0

s of version 2.0, JAX-RPC has been renamed JAX-WS. But the change is not in name alone. JAX-WS offers simplified development, better platform and language independence, and an end to the chaotic array of earlier Java Web services frameworks. This article explores the high-level architecture of JAX-WS, along with its low-level inner workings. It then walks you step by step through creating your first JAX-WS Web service.

What You Need
The latest version of Java 5
Tomcat (5.5 or later)
Ant (1.6 or later)
JAX-WS

The Architecture of JAX-WS 2.0

Click to enlarge
Figure 1. JAX-WS High-Level Architecture

What is the JAX-WS? Essentially, it consists of the following four things:

  1. An API for developing Web services using Java and XML
  2. A standard implementation (SI, as in JAXWS-SI.jar) of the Web services servlet
  3. Annotations, such as @WebService, that are processed by apt (annotation processing tool) to generate components for the service and client (A list of all JAX-WS annotations can be found here.)
  4. A set of tools (primarily wsimport) for generating the “portable artifacts” (beans, stubs, and XML) for the client code. (wsimport stands for Web service import, which reads in the descriptors of the published Web service and generates the client artifacts.)

Clearly, JAX-WS is more than just an API for building Web services. Figure 1 shows its high-level architecture.

JAX-WS Under the Hood

How does a JAX-WS application work? The developer need be exposed only to the client and service endpoint. The rest is generated and run automatically (see Figure 2).

Click to enlarge
Figure 2. JAX-WS: How It Works

On the client side, the only Java file the developer supplies is the client class itself. The interface and JavaBeans are generated automatically by wsimport. On the server side, the only Java file the developer supplies is the service implementation. The JavaBeans are generated by apt, and the servlet is part of the JAX-WS library.

The generated JavaBeans (also known as a type of portable artifact) are responsible for marshaling/unmarshaling method invocations and responses, as well as service-specific exceptions. Marshaling and unmarshaling are the transformation from XML to Java objects and back using JAXB. Two JavaBeans are generated for each method in the Web service. One bean is for invoking the method and the other for handling the response. An additional JavaBean is generated for each service-specific exception. (JAX-WS 2.0 Beta User’s Guide 3.1.1.1 Generate Portable Artifacts)

Running the Examples

In the following examples, the Web service method uses a custom exception, which must also be supplied to apt by the developer and which has a JavaBean generated for it (but is not shown in Figure 2). Once the Web service has been published and the client artifacts have been generated, the client class can call the Web service method via the Service Endpoint Interface (SEI). The service bean then translates the method call into XML using JAXB and transmits it to the Web service servlet using HTTP/SOAP. The process is then reversed so that the Service Endpoint Implementation (also called SEI) can process the request and return the response. The handling of SOAP and HTTP on the service side is seamlessly provided by the Web service servlet. The handling of SOAP and HTTP on the client side is taken care of behind the scenes by the javax.xml.ws package.

To complete the examples, begin by downloading and unzipping the latest version of Java 5, Tomcat (5.5 or later), Ant (1.6 or later), JAX-WS, and the example code for this article. If you use Java 6, be sure to use a compatible version of Tomcat, Ant, and JAX-WS. These examples will not work using Java 6, Tomcat 5, and JAX-WS RC3 because of library incompatibilities.

Open the build.xml file in the examples directory and set the values of the properties jaxws.home, java.home, and tomcat.home to the root directories of those downloads. Now, open a command prompt and run the following ant targets:

  1. Run $ANT_HOME/bin/ant -buildfile $EXAMPLE_HOME/build.xml install, which copies the *.jar files from jaxws.home/jaxws-ri/lib/ into tomcat.home/commons/lib.
  2. Run $ANT_HOME/bin/ant -buildfile $EXAMPLE_HOME/build.xml server, which generates the Web service files for the example Java code, packages it in a WAR, and deploys it to Tomcat’s /webapps. [NOTE: some warnings and errors may occur when using apt in early versions of JAX-WS. They do not effect the functionality of the examples.]
  3. Start Tomcat, which will automatically deploy the WAR file.
  4. Test that the service is running by opening a browser to the following pages:
  5. Run $ANT_HOME/bin/ant -buildfile $EXAMPLE_HOME/build.xml client, which generates the client artifacts from the deployed WSDL and XSD.
  6. Run $ANT_HOME/bin/ant -buildfile $EXAMPLE_HOME/build.xml run, which executes the client and outputs the result to the command window.

The Development Process

To JAX-WS, the development process is a somewhat simplified version of WS development using RPC. Unlike with the JAX-RPC of old, you can use JAX-WS to transform almost any existing Java class into a Web service. The class doesn’t need to implement an interface and its methods do not need to declare RMI exceptions. The method, however, does require JAXB 2.0-compatible parameters and return values. Simply add the @WebService annotation to the .java file, add some cookie cutter configuration files, and run an Ant script. Figure 3 diagrams the basic process for the Web service.

Click to enlarge
Figure 3. The Development Process for the Web Service

Notice in Figure 3 that SimpleMethod.java and SimpleMethodResopnse.java are the JavaBeans responsible for marshaling/unmarshaling the invocation and response. Notice also that the developer inputs only three files; the remaining components are generated by apt and the servlet container. The servlet container generates the WSDL and schema at the time of deployment, which is a change from JAX-RPC. These files are therefore not bundled in the WAR.

SimpleJAXWS.java (see Listing 1) is the same as a non-Web service class definition except for the @WebService annotation:

@WebServicepublic class SimpleJAXWS { public int simpleMethod(int number1, int number2) throws SimpleException { if ( number2 == 0 ) {throw new SimpleException("Cannot divide by zero!","Numbers: " + number1 + ", " + number2); }return number1 / number2; }}

The sun-jaxws.xml file (see Listing 2) designates the URL for the service endpoint implementation:

The web.xml (see Listing 3) file assigns the WSServlet to the Web service’s URL:

simpleexamplecom.sun.xml.ws.transport.http.servlet.WSServletsimpleexample/simplemethod

The URL http://localhost:8080/jaxws-simpleexample/simplemethod?wsdl shows the definition for the simpleMethod message:

 

The URL http://localhost:8080/jaxws-simpleexample/simplemethod?xsd=1 shows the simple method and it’s parameters:

  

Figure 4 diagrams the basic development process on the client side.

Click to enlarge
Figure 4. The Development Process for the Client

Notice in Figure 4 that the developer inputs only three files; the remaining components are generated by wsimport. The other files required by wsimport are the WSDL and schema generated by the servlet container at time of deployment. This is why it’s important to wait for Tomcat to completely deploy the Web service before building the client.

The wsimport-generated files can be found in the build/classes/simpleexample/client directory of the example’s home. SimpleMethod.java and SimpleMethodResopnse.java are the JavaBeans that marshal/unmarshal the invocation and response. Because package-level annotations are declared in their own .java file, @XMLSchema is found in package-info.java. The annotation maps the client package name to an XML namespace. ObjectFactory.java uses the class-level annotation @XMLRegistry to indicate it will be an XML registry with the factory methods for the client’s JavaBeans and their XML equivalents. Other JavaBeans not shown in Figure 4 are generated for handling the exception used by the service.

SimpleMethodClient.java (Listing 4) has a main method that instantiates the SimpleJAXWS Web service object and calls its method. The SimpleJAXWS object is treated the same as a non-webservice object once it has been instantiated:

SimpleJAXWS port = new SimpleJAXWSService().getSimpleJAXWSPort(); double result = port.simpleMethod ( 20, 10 );

The build.properties file (Listing 5) designates the SEI and client class, the client’s bindings for its WSDL and schema:

# service endpoint implementation classsei=simpleexample.server.SimpleMethod # customization filesclient.binding=custom-client.xml, custom-schema.xmlserver.binding=client.wsdl=http://localhost:8080/jaxws-simpleexample/simplemethod?wsdl client=simpleexample.client.SimpleMethodClient

The custom-client.xml file (Listing 6) binds the package to the WSDL:

 

The custom-schema.xml file (Listing 7) binds the package to the schema:

     node="/xsd:schema"> 

Of course, much of this code can be generated by a development tool very simply. As the next section demonstrates, coding all these cookie cutter files by hand can be tedious. As with most JSRs, JAX-WS was designed by Java tool vendors for Java tool vendors. What JAX-WS really does is provide the framework by which the developer’s tool of choice can provide one-click generation of a Web service and client skeleton.

Transform Existing Java Classes into a Web Service/Client

A good demonstration of the development process is to customize the example from the previous section using your own Java class file. Add the “@WebService” annotation to the line after the imports and make the following changes to the additional files in order:

  1. Copy the JAXWS_EXAMPLE directory and change the two directories named “simpleExample” in “simpleExample/src/simpleExample” to your project name.
  2. Replace SimpleJAXWS.java and SimpleException.java with your new @WebService java file and any accompanying exceptions.
  3. Rename SimpleMethodClient.java to your class name.
  4. Open all the .java, .properties, and .xml files (including build.xml) in an editor, and use batch search/replace to make the following changes (be sure the replacements are case sensitive):
    • Replace all “simpleexample” references with your project name.
    • Replace all “simpleMethod” references with your method name.
    • Replace all “SimpleJAXWS” references with your class name.
    • Replace all “simplemethod” references with your URL pattern.
    • Replace all “SimpleException” references with your exception class name.
    • Replace all remaining “SimpleMethod” references with your method name (these occur in pointers to the derivative classes).
  5. Now you must edit the client class in accordance with the parameters and return the type of the Web service.
  6. Lastly, run the ant targets server and client, and run the same as above.

By following these steps you have transformed your own Java class into a Web service, enabling it to communicate over a network in a distributed computing environment.

Raw SOAP for Web Services Is Now Obsolete

With the advent of JAX-WS, the use of raw SOAP for Web services has become deprecated. This means that popular projects such as Apache Axis (Apache’s implementation of SOAP) are no longer necessary for Web service developers. By abstracting the protocol binding, JAX-WS can provide simultaneous support for SOAP 1.1 and 1.2. By utilizing annotations, simplified build tools, and JAXB, JAX-WS removes many of the unnecessary complications of JAX-RPC.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

Recent Articles: