Java Web services: Introducing Metro

Learn about a Web services framework based on the JAXB and JAX-WS reference implementations

The Metro Web service stack provides a comprehensive solution for accessing and implementing Web services. It's based on the reference implementations of the JAXB 2.x and JAX-WS 2.x Java™ standards, with added components to support WS-* SOAP extension technologies and actual Web service deployment. This article continues Dennis Sosnoski's Java Web services column series with a look at the basic principles of Metro client and server development.

Dennis Sosnoski, Architecture Consultant and Trainer, Sosnoski Software Solutions, Inc.

Author photoDennis Sosnoski is a consultant and trainer specializing in Java-based XML and Web services. His professional software development experience spans more than 30 years, with the last 10 focused on server-side XML and Java technologies. Dennis is the lead developer of the open source JiBX XML Data Binding framework and the associated JiBX/WS Web services framework, as well as a committer on the Apache Axis2 Web services framework. He was also one of the Expert Group members for the JAX-WS 2.0 and JAXB 2.0 specifications. The material for the Java Web Services series is based on Dennis' training classes.



03 November 2009

Also available in Chinese Japanese Portuguese

The Metro Web services stack is an open source tool developed by Sun Microsystems. It incorporates the reference implementations of the JAXB 2.x data-binding and JAX-WS 2.x Web services standards, along with other XML-related Java standards. Metro also includes added nonstandard components to support both basic JAX-WS service definition and usage and a variety of WS-* extensions to SOAP message exchange.

About this series

Web services are a crucial part of Java technology's role in enterprise computing. In this series of articles, XML and Web services consultant Dennis Sosnoski covers the major frameworks and technologies that are important to Java developers using Web services. Follow the series to stay informed of the latest developments in the field and aware of how you can use them to aid your programming projects.

Metro can be used either as a stand-alone Web services stack or as an integrated component within the open source Glassfish application server. Web service configuration is somewhat easier when you use Glassfish, especially if you're developing on the open source NetBeans IDE, which includes GUI tools for configuring both basic Web services and WS-* extensions. In keeping with the focus on Web services, this series looks only at the stand-alone use of Metro in an IDE-independent manner, just as earlier articles discussed stand-alone use of Apache Axis2 rather than application servers incorporating Axis2 and supporting GUI tools.

Metro basics vs. Axis2

Prior articles in this series have covered Axis2 in depth, so a discussion of the similarities and differences between Metro and Axis2 is a good starting point. The similarities are limited and mostly revolve around the common requirements of developing code using Web services. Both frameworks allow you either to start from existing Java code and build a Web service (though in the case of Axis2 the support for this approach is limited unless you use a separate tool such as Jibx2Wsdl) or to start from a WSDL Web service description and generate Java code to use or implement the service. Both frameworks model service operations as method calls, and service port-types as interfaces.

The differences between Metro and Axis2 are much more striking than the similarities. On a fundamental level, Metro is designed around JAXB 2.x and JAX-WS 2.x, with no interest in supporting any alternatives to these technologies (except for legacy JAX-RPC usage). Axis2 is designed to support an open-ended range of technologies, especially in the XML data-binding area; although it includes support for JAXB 2.x and JAX-WS 2.x, it doesn't give them any special status. (If anything, JAX-WS is somewhat of a second-class alternative in Axis2 because — as discussed in "JAXB and JAX-WS in Axis2" — you can't configure WS-Security or other features for a JAX-WS service.)

Structurally, both stacks use handlers as part of the request and response processing. Axis2 builds on this handler approach to implement modules : pluggable extensions to the basic SOAP message exchange that are used to implement WS-* technologies in a highly configurable manner. Metro supports a wide range of WS-* technologies with handlers, but these technologies are integrated into the Metro engine, rather than separable components. The integration approach Metro uses is not as flexible as Axis2 modules, but it does provide some advantages when it comes to configuring and using WS-* extensions.

The two stacks also differ in terms of how the client code uses WSDL service definitions. Axis2 primarily uses WSDL service definitions for client-side code generation, extracting the service configuration information from the WSDL and generating code to construct a matching Axis2 client configuration at run time (though you can also parse a WSDL service definition at run time). JAX-WS 2.x, and hence Metro, requires a WSDL service definition at run time in order to build the service configuration. This run-time WSDL usage adds some startup overhead — though only for the first service invocation — without any obvious benefits.

There are also differences on the server side. For the common case of HTTP transport, Axis2 is normally set up as a distinct Web application (a WAR file), with any number of individual services deployed to that Axis2 Web application (though it can also be packaged as part of an application WAR). You can deploy services via Web page upload, or by dropping the Axis2 service AAR file directly into the appropriate directory of the expanded Axis2 Web application. The individual service configuration information is normally generated by Axis2 from your WSDL service definition at build time, and then included in the service AAR file. The standard Axis2 Web application also provides a variety of monitoring and control tools via a Web page interface.

Metro, in contrast, requires you to build a separate WAR file for each Web service application, with the Metro library JAR files either included in the WAR or otherwise in the classpath (as part of the HTTP server installation) and a WEB-INF/web.xml file present in the WAR that references both your service and a Metro servlet. When using Metro stand-alone, you also need to create a sun-jaxws.xml configuration file, which provides additional information about the service configuration. The information from these configuration files is combined with the JAX-WS annotations in your actual Web services classes to configure Metro fully for your service. Because it's designed for use in this embedded manner, Metro does not provide any direct monitoring or control tools.

Both Axis2 and Metro also provide integrated HTTP server support. In the Metro case, this comes by way of a JAX-WS feature, the javax.xml.ws.Endpoint class. Both the Axis2 and Metro/JAX-WS integrated HTTP servers are suitable for use in testing or as an asynchronous response port, but for hosting a production Web service, a Java application server supporting the Servlet API is the preferred approach.


Sample application

The code download provides a version of the simple library-management service used in previous articles of this series, this one modified to demonstrate Metro usage. As with the earlier versions, the WSDL service definition defines four operations:

  • getBook to retrieve the details for a particular book identified by International Standard Book Number (ISBN)
  • getBooksByType to retrieve the details for all books of a particular type
  • getTypes to find the types of books available
  • addBook to add a new book to the library

In "JAXB and JAX-WS in Axis2" you saw how this application worked in Axis2, first with normal Axis2 code generation using JAXB 2.x data binding, then with JAX-WS 2.x service configuration. Most of what you saw in that article also applies when using Metro. The WSDL is identical except for the service name and endpoint address, the generated JAXB data model is the same, and even the generated service classes are identical except for the Java package and the service name used in the JAX-WS annotations.

Client-side usage

Client-side code for the sample application on Metro is identical to that for using JAX-WS with Axis2, and even the build steps are the same. See "JAXB and JAX-WS in Axis2" for details of the code and handling.

Server-side usage

The server-side code for the sample application on Metro is also identical to that for using JAX-WS with Axis2, but the build steps are somewhat different. With Axis2, you prepared the service for deployment by creating a JAR file containing the service and data model classes, then deployed the service by dropping that JAR into the WEB-INF/servicejars directory in an Axis2 server installation.

With Metro, you instead need to create a WAR file containing the service and data model classes, the Metro library JARs (though you can instead install the Metro JARs directly into your Web server — if you're using Tomcat, the Metro download includes a metro-on-tomcat.xml Ant build file to install the JARs, with instructions in the documentation), and a pair of configuration files. The WEB-INF/web.xml file configures the actual servlet handling. Listing 1 shows the version used for the sample application:

Listing 1. Sample application web.xml
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee">
  <display-name>MetroLibrary</display-name>
  <description>Metro Library Service</description>
  <listener>
    <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener
    </listener-class>
  </listener>
  <servlet>
    <servlet-name>MetroLibraryPort</servlet-name>
    <display-name>MetroLibraryService</display-name>
    <description>Endpoint for Metro Library Service</description>
    <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>MetroLibraryPort</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <session-config>
    <session-timeout>60</session-timeout>
  </session-config>
</web-app>

If you've worked with Java Web applications before, the Listing 1 WEB-INF/web.xml file should look familiar (at least in structure). The particular entries used tell the servlet engine to which the WAR file is deployed to use the com.sun.xml.ws.transport.http.servlet.WSServletContextListener class as a listener for servlet context events and to use the com.sun.xml.ws.transport.http.servlet.WSServlet class as an actual servlet. These classes are specific to Sun's Metro stack, and the references to the classes are required in order to work with Metro. The servlet is configured to receive all requests coming to this Web application (by the <url-pattern>/</url-pattern> entry).

In and of itself, the Listing 1 WEB-INF/web.xml file just configures the servlet engine to use a Metro-provided listener and servlet. A separate file, WEB-INF/sun-jaxws.xml (shown in Listing 2), is used to configure Metro to route requests received by the servlet to the service-implementation code.

Listing 2. Sample application sun-jaxws.xml
<endpoints xmlns="http://java.sun.com/xml/ns/jax-ws/ri/runtime" version="2.0">

    <endpoint name="MetroLibraryPort"
        implementation="com.sosnoski.ws.library.metro.MetroLibraryImpl"
        url-pattern="/"
        wsdl-location="WEB-INF/wsdl/library.wsdl"/>

</endpoints>

The Listing 2 WEB-INF/sun-jaxws.xml file is as about simple as it can get, with a single endpoint definition giving the port name, implementation class, pattern to be matched for requests, and a WSDL document location. The WSDL document location is the only optional part of this endpoint definition. If you don't specify a WSDL document for a service endpoint in the sun-jaxws.xml file, Metro automatically generates one at run time.

The problems of bundling

As of Java SE 6, the JAXB 2.x and JAX-WS 2.x reference implementation runtimes (except for vendor extensions) became part of the standard Java Runtime Environment (JRE) libraries. This was intended to promote the use of these technologies as Java standards, but it has an unfortunate side-effect: you may need to make a change to your JRE installation to use newer versions of these technologies.

The build.xml used in the sample application download copies the Metro JAR files directly into the service WAR file. This worked on the author's system when the application was deployed to an Apache Tomcat 6.0.20 Web server, using both Java SE 5 and Java SE 6 JDK/JRE installations. If classloading conflicts (such as ClassCastExceptions thrown, or com.sun.xml... classes not found) cause problems when you use Java SE 6 or later, here's how to fix them:

  • Make sure you're using the latest version of the JRE available for your system, because the updates may include later versions of JAXB 2.x and JAX-WS 2.x.
  • Use the java.endorsed.dirs system property to specify a directory containing the webservices-api.jar file from the Metro lib directory (only the webservices-api.jar file, because including the other JARs will cause classloading conflicts) as a source of updated libraries. (Tomcat 6.0.x supports this mechanism by looking for a JAVA_ENDORSED_DIRS environment variable and using it as the system property value.)
  • If all else fails, create an endorsed directory within the lib directory of your JRE installation (if not already present), and copy the Metro webservices-api.jar file into this directory.

With either of the last two techniques, you don't need to include the Metro webservices-api.jar in your service WAR file because it'll be directly available in the Web server's classpath.

Building and running the sample code

Before you can try out the sample code, you need to download and install a current version of Metro (the code was tested with the 1.5 release) on your system (see Resources). You also need to edit the build.properties file in the root directory of the unzipped sample code download to change the value of the metro-home property to the path to your Metro installation. If you're going to be testing with a server on a different system or port, you may need to change the host-name and host-port.

To build the sample application using the supplied Ant build.xml, open a console to the root directory of the download code and type ant. This will first invoke the JAX-WS wsimport tool (included in the Metro distribution), then compile the client and server, and finally package the server code as a WAR. You can then deploy the generated metro-library.war file to your test server, and finally type ant run on the console to try running the sample client. The sample client runs through a sequence of several requests to the server, printing brief results for each request.


Next up on Metro

In this article, you've seen the basics of working with the Metro Web services stack. Because Metro uses JAX-WS 2.x annotations for configuration, the same JAX-WS 2.x sample application code used in "JAXB and JAX-WS in Axis2" also works with Metro. The only changes needed concern how the code is packaged and deployed on the server side, and there Metro and Axis2 are significantly different. Metro uses an embedding approach whereby you create a Web application for each service or group of services (and no control or monitoring functions are provided). Axis2 normally uses a single dedicated Web application as the host for any number of individual services (with basic control and monitoring functions provided directly via a Web page interface).

Beyond the basics of Web service message exchange, Metro also supports SOAP extensions such as WS-Security. Just as with the service-packaging issue, Metro and Axis2 take different approaches to very similar requirements in this area. In the next article, you'll see how Metro handles the same WS-Security examples previously used in this series with Axis2.


Download

DescriptionNameSize
Source code for this articlej-jws9.zip13KB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Java technology on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology, SOA and web services, Open source
ArticleID=441962
ArticleTitle=Java Web services: Introducing Metro
publish-date=11032009