The Atom service document is how a service tells you know what is available. Each service represents one or more workspaces, which represent one or more collections. The collections contain the individual resources. For example, you can retrieve the Blogapps service document at http://local hosts:8080/roller/app (see Listing 1).
Listing 1. The service document
<?xml version="1.0" encoding="UTF-8"?>
<app:service xmlns:app="http://purl.org/atom/app#"
xmlns:atom="http://www.w3.org/2005/atom">
<app:workspace>
<atom:title>AdminBlog</atom:title>
<app:collection
href="http://localhost:8080/roller/app/adminblog/entries">
<atom:title>Weblog Entries</atom:title>
<app:categories app:fixed="yes"
app:scheme="http://localhost:8080/roller/adminblog/">
<atom:category atom:term="/General" atom:label="General" />
<atom:category atom:term="/Status" atom:label="Status" />
</app:categories>
<app:accept>entry</app:accept>
</app:collection>
<app:collection
href="http://localhost:8080/roller/app/adminblog/resources">
<atom:title>Media Files</atom:title>
<app:accept>image/*</app:accept>
</app:collection>
</app:workspace>
<app:workspace>
...
</app:workspace>
</app:service>
|
From this document, you can create a servlet that includes a sidebar that shows all of the services and feeds available, along with links to their HTML versions.
The first step is to create the basic servlet, including space for the sidebar (see Listing 2).
Listing 2. The basic servlet
package com.backstop.atom;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;
public class SideBarServlet extends javax.servlet.http.HttpServlet
implements javax.servlet.Servlet {
String APPNS = "http://purl.org/atom/app#";
String AtomNS = "http://www.w3.org/2005/atom";
String AtomNS2 = "http://www.w3.org/2005/Atom";
protected void doGet(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().print(
"<div style='width:25%; float: right;'>");
Document doc = URLContents.getContentsAsXMLDoc(
"http://localhost:8080/roller/app" );
Element root = (Element)doc.getDocumentElement();
NodeList workspaces = root.getElementsByTagNameNS(APPNS,
"workspace");
for (int i = 0; i < workspaces.getLength(); i++){
Element thisWorkspace = (Element)workspaces.item(i);
response.getWriter().print(
"<div style='border: 1px solid green; padding: 5px;'>");
String wsTitle =
thisWorkspace.getElementsByTagNameNS(AtomNS,
"title").item(0).getTextContent();
response.getWriter().print(
"<h3 class='wstitle'>"+wsTitle+"</h3>");
response.getWriter().print("</div>");
}
response.getWriter().print("</div>");
}
}
|
The class includes all of the import statements you'll need, as well as variables representing the needed namespaces. (Blogapps has a slight bug in that the service document has a slightly incorrect namespace; until that is fixed, you'll need to declare both versions: http://www.w3.org/2005/atom and http://www.w3.org/2005/Atom.)
The next step is to add the actual workspaces to the sidebar. To do that, loop through the workspace elements in the document. All of these documents are password-protected in the Blogapps server, so to keep things simple, I moved their actual retrieval to a separate utility class, URLContents. You can find it in the source code for this article. (If you wind up doing this retrieval on your own, make sure that you set your DocumentBuilderFactory to be namespace-aware.)
Once you have the XML Document object, you can loop through each of the workspace
elements, and create a div on the page for each of them. For each one, extract the text of the title element and place it on the page, as you can see in Figure 1.
Figure 1. The workspaces
Now look at adding the collections.
Adding the collections to the page involves much the same process. Once you have the individual workspace, you can retrieve each of its collections (see Listing 3).
Listing 3. Looping through the collections
...
response.getWriter().print(
"<h3 class='wstitle'>"+wsTitle+"</h3>");
NodeList collections =
thisWorkspace.getElementsByTagNameNS(APPNS, "collection");
for (int j = 0; j < collections.getLength(); j++){
Element thisCollection = (Element)collections.item(j);
String colTitle =
thisCollection.getElementsByTagNameNS(AtomNS,
"title").item(0).getTextContent();
String feedURL = thisCollection.getAttribute("href");
response.getWriter().print(
"<h4 class='collection'>"+colTitle);
response.getWriter().print(" -- <a href='"+feedURL+
"'><img border='0' src='images/feed-icon.gif' /></a>");
response.getWriter().print("</h4>");
}
response.getWriter().print("</div>");
}
response.getWriter().print("</div>");
}
}
|
For each collection, you do a little bit more than just display the title, though. Each collection element also includes an href attribute, representing the location of the Atom feed for the collection. To take advantage of this, extract this information and add a feed icon, linking it to the feed's URL. The result should look something like Figure 2.
Figure 2. Adding the feeds
You can also add an indication of the categories of content covered by each collection (see Listing 4).
Listing 4. Adding categories
...
response.getWriter().print(" -- <a href='"+feedURL+
"'><img border='0' src='images/feed-icon.gif' /></a>");
response.getWriter().print("</h4>");
NodeList categories =
thisCollection.getElementsByTagNameNS(AtomNS,
"category");
if (categories.getLength() > 0){
response.getWriter().print(
"Categories in this collection: ");
}
for (int k = 0; k < categories.getLength(); k++){
Element thisCategory = (Element)categories.item(k);
String catName = thisCategory.getAttributeNS(AtomNS,
"label");
if (k > 0){
response.getWriter().print(", ");
}
response.getWriter().print(catName);
}
}
response.getWriter().print("</div>");
}
response.getWriter().print("</div>");
}
}
|
The result looks like Figure 3.
Figure 3. Adding categories
The final step is to include a link to the HTML representation of the information. Unfortunately, that information does not actually exist in the service document. To retrieve it, you will have to look at the feed itself (see Listing 5).
Listing 5. Retrieving the feed information
...
for (int j = 0; j < collections.getLength(); j++){
Element thisCollection = (Element)collections.item(j);
String colTitle =
thisCollection.getElementsByTagNameNS(AtomNS,
"title").item(0).getTextContent();
String feedURL = thisCollection.getAttribute("href");
String webURL = getWebURL(feedURL);
response.getWriter().print(
"<h4 class='collection'><a href='"+webURL+"'>"+>
colTitle+"</a>");
...
}
response.getWriter().print("</div>");
}
response.getWriter().print("</div>");
}
private String getWebURL(String feedURL){
String webURL = "";
Document doc = URLContents.getContentsAsXMLDoc(feedURL);
Element root = (Element)doc.getDocumentElement();
NodeList links = root.getElementsByTagNameNS(AtomNS2, "link");
for (int i = 0; i < links.getLength(); i++){
Element thisLink = (Element)links.item(i);
if (thisLink.getAttribute("rel").equals("alternate") &&
thisLink.getParentNode().equals(root)){
webURL = thisLink.getAttribute("href");
}
}
return webURL;
}
}
|
In this case, you retrieve the feed URL from the service document, and then retrieve that actual document, which includes a link element, such as <link rel="alternate" href="http://localhost:8080/roller/adminBlog" /> representing the HTML version of data represented by the feed. You can then add that information to the sidebar. The final result looks like Figure 4.
Figure 4. Adding categories
The service document is more than just an opportunity for introspection; with careful planning, you can use it to provide actual content and links to content.
| Description | Name | Size | Download method |
|---|---|---|---|
| Atom sidebar samples | x-atomsidebar-source.zip | 3KB | HTTP |
Information about download methods
Learn
-
An overview of the Atom 1.0 Syndication Format (James Snell, developerWorks, August 2005): See how this popular Web content syndication format stacks up.
-
Getting to know the Atom Publishing Protocol (James Snell, developerWorks, October - December 2006): Find out about the Atom API in this three-part series:
- Part 1: Create and edit Web resources with the Atom Publishing Protocol: Explore a high-level overview of the protocol and its basic operation and capabilities.
- Part 2: Put the Atom Publishing Protocol (APP) to work: Learn to use APP to interact with a number of real-world deployed applications.
- Part 3: Introducing the Apache Abdera project: Start to implement Atom-enabled apps using a new open-source project, called Abdera, currently under incubation at the Apache Software Foundation.
-
RSS and Atom in Action (Dave Johnson, Manning Publications, July 2006): If you prefer something more physical, take a look at this book about the blog technologies of news feed formats and publishing protocols and how to put these building blocks together. (Blogapps was put together for this book.)
-
Atom 1.0 specification: Read about this XML-based Web content and metadata syndication format.
-
Atom 1.0 compatible software: Visit the Atom Working Group's Wiki for a list of known Atom 1.0 feed consumers.
-
Use the Atom format for syndicating news and more (Uche Ogbuji, developerWorks, May 2004): Read more on this XML-based standard, format, and API for the interchange and cross-reference of Web metadata.
-
developerWorks XML zone: Find hundreds more XML resources.
-
IBM XML certification: Find out how you can become an IBM-Certified Developer in XML and related technologies.
-
XML technical library: See the developerWorks XML Zone for a wide range of technical articles and tips, tutorials, standards, and IBM Redbooks.
-
developerWorks technical events and webcasts: Stay current with technology in these sessions.
- The technology bookstore: Browse for books on these and other technical topics.
Get products and technologies
- The Blogapps server: Download the server in this collection of useful RSS and Atom utilities and examples.
-
IBM trial software: Build your next development project with trial software available for download directly from developerWorks.
Discuss
- Participate in the discussion forum.
-
XML zone discussion forums: Participate in any of several XML-centered forums.
-
developerWorks blogs: Check out these blogs and get involved in the developerWorks community.
Nicholas Chase has been involved in Web site development for companies such as Lucent Technologies, Sun Microsystems, Oracle, and the Tampa Bay Buccaneers. Nick has been a high school physics teacher, a low-level radioactive waste facility manager, an online science fiction magazine editor, a multimedia engineer, an Oracle instructor, and the Chief Technology Officer of an interactive communications company. He is the author of several books, including XML Primer Plus (Sams).
Comments (Undergoing maintenance)





