In November of 2001, IBM and Microsoft jointly published a draft of the Web Services Inspection Language (see Resources). Billed as "an XML format for assisting in the inspection of a site for available [Web] services," the fundamental intent of the specification was to provide a simple means of discovering when new services had been made available at a particular endpoint location. Unfortunately, while a few implementations of the specification did emerge in a few products, use of WS-Inspection never really took off. The specification has remained untouched and essentially forgotten since its publication.
Since that time, however, the need for a simple means of discovering when new web services are available has not diminished, and work has continued in other areas. The W3C Web Services Addressing Working Group, for example, has been working to develop the means of addressing and referencing web services endpoints. Unfortunately, neither the WS-Addressing specifications nor the related WS-* specifications being developed under the auspices of the W3C and OASIS organizations address the fundamental problem of providing a simple means of notifying clients when new web services have become available.
Enter Atom 1.0. Over the course of the past year, the IETF Atom Publishing Format and Protocol Working Group has been working to define a standard XML format designed, in part, to allow clients to receive notification of when Web-based resources have been created or modified. Originally targeted at the syndication of Weblog and news content, the Atom Syndication Format is capable of serving as a means for distributing any arbitrary data format.
In the discussion that follows, I introduce and demonstrate the combined use of the Atom 1.0 and Web Services Addressing 1.0 specifications as a functional replacement for the now defunct WS-Inspection. A basic understanding of both the Atom and WS-Addressing specifications is assumed and it is recommended that you have a copy of both specifications handy as a reference as you continue reading. (See Resources for links to the specifications.)
A note on the code accompanying this article: The example is based on the web services run-time embedded in IBM WebSphere® Application Server V6.0 (Application Server). While the concepts are easily adapted to other web services run-times, if you wish to run the code, you will need to install Application Server. See the Resources section for a link to a trial version that you can download at no charge.
The sample code uses a Java™ servlet to generate an Atom 1.0 document (Listing 1) containing one entry for each web service that has been deployed to the Application Server environment. Whenever a new web service is deployed, a new entry is added to the Atom feed. By periodically polling the feed for new entries, clients can detect new or revised services.
In order to provide clients all of the information they need to access new service endpoints, each of the entries in the feed will contain a WS-Addressing Endpoint Reference that describes the endpoint.
Listing 1. An Atom+WS-Addressing feed
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en"
xmlns="http://www.w3.org/2005/Atom"
xmlns:fh="http://purl.org/syndication/history/1.0">
<id>http://localhost:9085/wsatom/services.atom</id>
<title>Web Services on localhost</title>
<fh:incremental>false</fh:incremental>
<updated>2005-08-23T23:00:35Z</updated>
<link href="http://localhost:9085/wsatom/services.atom"
rel="self"
type="application/atom+xml"/>
<author>
<name>WebSphere</name>
<uri>http://localhost:9085/wsatom</uri>
</author>
<entry>
<id>tag:localhost,2005:/services/HelloWorld</id>
<title>HelloWorld</title>
<summary>Service 'HelloWorld' is available at
http://localhost:9085/wsatom/services/HelloWorld</summary>
<link href="http://localhost:9085/wsatom/services/HelloWorld"
rel="alternate"
title="Service Endpoint"/>
<link
href="http://localhost:9085/wsatom/services/HelloWorld?wsdl"
rel="alternate"
title="WSDL"
type="application/wsdl+xml"/>
<updated>2005-08-23T23:00:35Z</updated>
<content type="application/xml">
<EndpointReference
xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://localhost:9085/wsatom/services/HelloWorld
</Address>
</EndpointReference>
</content>
</entry>
</feed>
|
Before I discuss how this feed is generated, I should point out that the Atom document generated by the servlet is always a complete set of the services available on the server. If a particular entry for a service drops off of the feed, it means that the service is no longer deployed on the server. Further, no significance is given to the order in which the services appear in the feed -- new services could appear at any position in the collection.
Access the list of deployed services
The web services run-time embedded in Application Server has been implemented around the Web Services for J2EE version 1.0 specification (referred to as JSR-109 -- see Resources) that defines the programming and deployment model for web services in enterprise Java environments. The deployment model for JSR-109 is based on a declarative approach centered around a configuration file called webservices.xml.
According to the JSR-109 specification, webservices.xml "defines the set of web services that are to be deployed in a web services for J2EE enabled container." This translates roughly into "the webservices.xml file is where you need to look for the list of services that you are going to advertise in the Atom feed."
In a typical scenario, the webservices.xml file can be found most often in the /WEB-INF directory of a standard J2EE Web application. However, it is possible to find multiple webservices.xml files located throughout a Web application's classpath. Listing 2 shows the webservices.xml deployment descriptor for the sample application.
Listing 2. webservices.xml
<?xml version="1.0" encoding="UTF-8"?>
<webservices
xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
version="1.1"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd">
<webservice-description>
<webservice-description-name>HelloWorldService
</webservice-description-name>
<wsdl-file>WEB-INF/wsdl/HelloWorld.wsdl
</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/HelloWorld_mapping.xml
</jaxrpc-mapping-file>
<port-component>
<port-component-name>HelloWorld
</port-component-name>
<wsdl-port
xmlns:pfx="http://example.com">pfx:HelloWorld
</wsdl-port>
<service-endpoint-interface>com.example.HelloWorld
</service-endpoint-interface>
<service-impl-bean>
<servlet-link>com_example_HelloWorld
</servlet-link>
</service-impl-bean>
</port-component>
</webservice-description>
</webservices>
|
The webservices.xml format consists of a top-level <webservices> element
containing any number of child <webservice-description> elements -- one for each
web service that has been deployed. The contents of the <webservice-description>
element specifies:
- The name of services
- The URL of the Web Services Description Language (WSDL) document describing the service
- The mapping file that is used to associate native Java types with the appropriate XML representation
- A binding of the service to a specific Java implementation
Of this information, you should be primarily concerned with just the service name and the WSDL.
The process that will be implemented is quite simple:
- Parse all available webservices.xml files.
- For each webservice-description found, create a WS-Addressing Endpoint Reference for the service.
- For each Endpoint Reference, create an Atom Entry.
- Add each Atom Entry to the Atom feed.
All of the work for generating the Atom feed has been isolated to a single HTTP Servlet, outlined in Listings 3-6.
Listing 3. AtomServlet.java
package com.example.atom;
...
public class AtomServlet
extends HttpServlet
implements Servlet {
...
|
The first task -- handled by the init function shown in Listing 4 -- is the discovery of all available webservices.xml files. By default, check first in the Web application's WEB-INF directory. The JSR-109 deployment descriptors can also be found at various locations in a Web application's classpath,. In the sample implementation, searching the classpath for services is disabled by default.
Listing 4. Finding webservices.xml
public void init(
ServletConfig config)
throws ServletException {
super.init(config);
try {
webservicesdocs = new ArrayList();
File webservices =
new File(
getServletContext().getRealPath(
"WEB-INF/webservices.xml"));
DocumentBuilderFactory dbf =
DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
dbf.setNamespaceAware(true);
documentBuilder = dbf.newDocumentBuilder();
Document webservicesdoc =
documentBuilder.parse(webservices);
webservicesdocs.add(webservicesdoc);
if (INCLUDE_CLASSPATH) {
Enumeration enum =
Thread.currentThread().
getContextClassLoader().getResources(
"META-INF/webservices.xml");
for (;enum.hasMoreElements();) {
try {
URL url = (URL)enum.nextElement();
documentBuilder = dbf.newDocumentBuilder();
Document doc = documentBuilder.parse(url.openStream());
webservicesdocs.add(doc);
} catch (Exception e) {}
}
}
lastmodified = Calendar.getInstance();
lastmodified.setTimeInMillis(webservices.lastModified());
} catch (Exception e) {} }
...
|
Once the set of webservices.xml deployment descriptors have been discovered and parsed, you are ready to serve up requests for the Atom feed. The process -- shown in Listing 5 -- is simple: If the webservices.xml document has been modified, the Atom document containing the complete current set of Endpoint References is generated and returned to the client.
Listing 5. Getting the Atom feed
protected void doGet(
HttpServletRequest request,
HttpServletResponse response)
throws ServletException,
IOException {
String modsince =
request.getHeader("If-Modified-Since");
String lastmod =
httpdateformat(lastmodified);
if (modsince != null &&
modsince.equals(lastmod)) {
response.setStatus(
HttpServletResponse.SC_NOT_MODIFIED);
} else {
response.setContentType("application/atom+xml");
response.setCharacterEncoding("utf-8");
response.setHeader(
"Last-Modified",
httpdateformat(lastmodified));
Document doc = getAtom(request);
OutputFormat of = new OutputFormat(doc);
of.setOmitComments(true);
of.setOmitDocumentType(true);
of.setOmitXMLDeclaration(false);
of.setEncoding("utf-8");
of.setIndenting(false);
of.setPreserveSpace(false);
SerializerFactory factory =
SerializerFactory.getSerializerFactory(
Method.XML);
Serializer ser =
factory.makeSerializer(
response.getWriter(), of);
DOMSerializer domser = ser.asDOMSerializer();
domser.serialize(doc);
}
}
|
Generating the Atom document (Listing 6) is a simple matter of iterating
through all of the <webservice-description> elements found in the collection of
webservice.xml files parsed when the servlet was initialized. A feed is created,
and for each of the deployed services, an Atom entry is created.
Listing 6. Generating the Feed
private Document getAtom(HttpServletRequest request) {
Document feedDocument = documentBuilder.newDocument();
Element feed = createFeed(feedDocument, request);
NodeList nl =
webservicesdoc.getElementsByTagNameNS(
WAS,"webservice-description");
for (int n = 0; n < nl.getLength(); n++) {
Element service = (Element) nl.item(n);
feed.appendChild(
createEntry(
feedDocument,
service,
request));
}
return feedDocument;
}
private Element createFeed(
Document doc,
HttpServletRequest request) {
...
}
private Element createEntry(
Document doc,
Element service,
HttpServletRequest request) {
...
}
...
}
|
Once the servlet has been implemented, it is deployed to the Web application containing the web services and given a URL mapping. An HTTP GET request to the servlet URL yields the generated Atom document (Listing 7).
Listing 7. http://localhost:9085/wsatom/services.atom
<?xml version="1.0" encoding="utf-8"?>
<feed xml:lang="en"
xmlns="http://www.w3.org/2005/Atom"
xmlns:fh="http://purl.org/syndication/history/1.0">
<id>http://localhost:9085/wsatom/services.atom</id>
<title>Web Services on localhost</title>
<fh:incremental>false</fh:incremental>
<updated>2005-08-23T23:00:35Z</updated>
<link href="http://localhost:9085/wsatom/services.atom"
rel="self"
type="application/atom+xml"/>
<author>
<name>WebSphere</name>
<uri>http://localhost:9085/wsatom</uri>
</author>
<entry>
<id>tag:localhost,2005:/services/HelloWorld</id>
<title>HelloWorld</title>
<summary>Service 'HelloWorld' is available at
http://localhost:9085/wsatom/services/HelloWorld</summary>
<link href="http://localhost:9085/wsatom/services/HelloWorld"
rel="alternate"
title="Service Endpoint"/>
<link
href="http://localhost:9085/wsatom/services/HelloWorld?wsdl"
rel="alternate"
title="WSDL"
type="application/wsdl+xml"/>
<updated>2005-08-23T23:00:35Z</updated>
<content type="application/xml">
<EndpointReference
xmlns="http://www.w3.org/2005/08/addressing">
<Address>http://localhost:9085/wsatom/services/HelloWorld
</Address>
</EndpointReference>
</content>
</entry>
</feed>
|
Once the Atom feed has been deployed, clients can subscribe to the feed using their favorite Atom 1.0-enabled feed readers, such as SharpReader, as shown in Figure 1. They can also programmatically access the feed, making use of the embedded WS-Addressing Endpoint Reference.
Figure 1. http://localhost:9085/wsatom/services.atom in SharpReader
The example presented here was designed as a simple illustration of how Atom 1.0 can be combined with WS-Addressing to solve, in a simple way, the problem of discovering when new web services are available without requiring the invention of yet-another-XML-format.
| Description | Name | Size | Download method |
|---|---|---|---|
| Atom Web Services Sample Code | ws-atomwascode.zip | 18 KB | HTTP |
Information about download methods
Learn
- Atom 1.0 Specification -- Find the internet working draft on the IETF Web site.
- WS-Addressing 1.0 - Core -- Find the Candidate Recommendation Draft on the W3C Web site.
- Atom Publishing Format and Protocol -- Learn more about the Working Group.
- Web Services Inspection Language Draft -- Find the specification on developerWorks.
- Web Services for J2EE (JSR-109) specification -- Find the latest version on the Java Community Process Web site.
- Feed History extension -- Read the current version of the specification utilized in the demo.
Get products and technologies
- WebSphere Application Server version 6.0 -- Download a no-charge trial version from developerWorks.
James Snell is a member of IBM's Emerging Technologies Toolkit team. He has spent the past few years focusing on emerging web services technologies and standards, and has been a contributor to the Atom 1.0 specification. He maintains a weblog focused on emerging technologies at http://www.ibm.com/developerworks/blogs/page/jasnell.




