Level: Intermediate James Snell (jasnell@us.ibm.com), Software Engineer, IBM
07 Oct 2005 Advertise Web services using the new Atom 1.0 Syndication Format combined with the Web Services Addressing specification.
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 approach
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.
Generate 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) {
...
}
...
}
|
The end result
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
Wrap-up
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.
Download | Description | Name | Size | Download method |
|---|
| Atom Web Services Sample Code | ws-atomwascode.zip | 18 KB | HTTP |
|---|
Resources Learn
Get products and technologies
About the author  | 
|  | 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/dw_blog.jspa?blog=351. |
Rate this page
|