Skip to main content

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

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

All information submitted is secure.

  • Close [x]

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.

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

All information submitted is secure.

  • Close [x]

Getting to know the Atom Publishing Protocol, Part 3: Introducing the Apache Abdera project

Create Atom-enabled apps with Abdera, a new open-source project

James Snell (jasnell@us.ibm.com), Software Engineer, IBM, Software Group
Photo of James M Snell
James Snell is a member of IBM's WebAhead development lab focusing on the prototype development of pre-emerging software technologies and standards for IBM's own use. His research and development interests cover a broad range of current technology trends including Atom, AJAX, REST, Open Source, personal publishing systems, semantic Web and situational applications. He is an active committer to the Apache Abdera project, currently in incubation and tasked with the creation of a high-performance, functionally complete implementation of the Atom Syndication Format and Atom Publishing Protocol standards.

Summary: 

Earlier articles in this series provided an overview of the Atom Publishing Protocol and described the various ways it is being utilized in real world applications. This article begins to demonstrate how you can start to implement Atom-enabled applications using a new open-source project, called Abdera, currently under incubation at the Apache Software Foundation.

This discussion assumes that you have read the Atom Format specification and that you are familiar with syndication in general (see Resources for links). All of the examples are provided in Java code and a sample Eclipse project containing all of the code samples is provided for download.

View more content in this series

Date:  12 Dec 2006
Level:  Intermediate
Also available in:   Chinese  Russian

Activity:  35641 views
Comments:  

Getting started

Before you begin, ensure that you have the current version of Apache Abdera installed. The source is available in the Apache Subversion repository at http://svn.apache.org/repos/asf/incubator/abdera/java/branches/0.2.1-incubating/. To retrieve the source, first make sure you have the subversion client and issue the command:

> svn co http://svn.apache.org/repos/asf/incubator/abdera/java/branches/0.2.1-incubating/

Once you download the source image, you can build Abdera using Ant version 1.6.5 or higher.

> cd trunk
> ant -f build/build.xml dist

After the build completes, the compiled jars and dependencies are located in a newly created "dist" directory. To run the examples, you need to have the following jars in your classpath. Not all of the examples require all of the jars in the dependencies list:

Table 1. Jars required to run the examples
Abdera (dist)Dependencies (dist/lib)
  • abdera.client.0.2.0-incubating.jar
  • abdera.core.0.2.0-incubating.jar
  • abdera.parser.0.2.0-incubating.jar
  • abdera.protocol.0.2.0-incubating.jar
  • axiom-api-1.0.jar
  • axiom-impl-1.0.jar
  • commons-codec-1.3.jar
  • commons-httpclient-3.0.1.jar
  • commons-logging-1.0.4.jar
  • geronimo-activation_1.0.2_spec-1.1.jar
  • log4j-1.2.12.jar
  • stax-1.1.2-dev.jar
  • stax-api-1.0.jar
  • jaxen-1.1-beta-7.jar

Getting started

The Abdera project consists of a collection of individual modules, each of which is listed alphabetically in the following table. Of these, the core, dependencies and parser modules are the most important and most frequently used:

Table 2. The Apache Abdera Project Modules
ModuleDescriptionDependencies
buildAnt build for the entire projectApache Ant 1.6.5+
clientAtom Publishing Protocol Clientcore, parser, protocol, commons-codec-1.3.jar, commons-httpclient-3.0.1.jar
coreFeed Object Model interfacesJava Activation Framework
dependenciesCommon dependencies for all modules 
extensionsFeed syntax and protocol extensionscore, protocol, json-1.0.jar
parserStAX and Axiom-based default Feed Object Model (FOM) implementationcore, axiom-api-1.0.jar, axiom-impl-1.0.jar, stax-1.1.2-dev.jar, stax-api-1.0.jar, jaxen-1.1-beta-7.jar, commons-logging-1.0.4.jar, log4j-1.2.12.jar, wstx-asl-2.0.5.jar
protocolCommon Atom Publishing Protocol codecore, parser
securityXML Digital Signature and Encryption supportcore, parser, xmlsec-1.3.0.jar, Bouncy Castle JCE implementation
serverAtom Publishing Protocol server implementationcore, parser, protocol, Servlet API

The core module, whose packages are listed in the following table, defines what Abdera calls the "Feed Object Model", a set of interfaces used for parsing, creating and manipulating Atom documents that is modeled after the Atom Syndication Format specification:

Table 3. The packages of the Abdera "core" module
PackageDescription
org.apache.abderaMain package containing a single "Abdera" object
org.apache.abdera.factoryDefines the Factory interface that creates new Feed Object Model object instances
org.apache.abdera.filterDefines interfaces to filter Atom documents during the parse
org.apache.abdera.modelDefines the primary interfaces to work with Atom Feed and Entry documents. The model also includes support to work with Atom Publishing Protocol Service and Category documents.
org.apache.abdera.parserDefines the Parser interface that creates new Feed Object Model object instances from XML documents
org.apache.abdera.utilProvides a variety of utility classes targeted primarily at developers looking to extend or replace Abdera's default parser and factory implementations
org.apache.abdera.writerDefines the Writer interfaces used to serialize Feed Object Model object instances
org.apache.abdera.xpathDefines the interfaces for using XPath to navigate the Feed Object Model

After you download and build the Abdera source, take a moment, if necessary, to familiarize yourself with the API by browsing through the Javadoc documentation that the build generates (located in the $ABDERA_HOME/dist/docs directory created).

Creating entries and feeds

The two primary functions of Abdera's Feed Object Model are to make it easy to both produce and consume Atom Feed and Entry documents.

To create an Atom document starts by acquiring an instance of org.apache.abdera.factory.Factory and setting the properties of the feed or entry. Listing 1 illustrates the creation of a simple Atom Entry Document:


Listing 1. Creating a simple Atom Entry Document
Abdera abdera = new Abdera();
Factory factory = abdera.getFactory();
    
Entry entry = factory.newEntry();
entry.setId("http://example.org/foo/entry");
entry.setUpdated(new java.util.Date());
entry.setTitle("This is an entry");
entry.setContentAsXhtml("This <b>is</b> <i>markup</i>");
entry.addAuthor("James");
entry.addLink("http://www.example.org");
    
entry.writeTo(System.out);
    

This example illustrates all of the key characteristics of the Feed Object Model.

  • First, you create an instance of org.apache.abdera.Abdera, which provides a top-level entry point to initialize and access various key subcomponents like the Abdera Parser and Factory.
  • Second, you acquire an instance of org.apache.abdera.factory.Factory. This is the interface that bootstraps the creation of all Feed Object Model objects.
  • Third, you create a new instance of org.apache.abdera.model.Entry using the Factory. The two most frequently used methods on the Factory interface are the newEntry() and newFeed() methods.
  • Finally, you serialize the Atom document out to an OutputStream using the default Abdera Writer.

The output from Listing 1 is shown in Listing 2. Note that the XML namespace declarations, date formats, and proper serialization of atom:content elements is handled automatically by the Feed Object Model implementation. However, the serialized output is not that easy to read due to the lack of line breaks and indentation:


Listing 2. The created Atom Entry Document
<entry xmlns="http://www.w3.org/2005/Atom"><id>http://example.org/foo/entry</id><updated>
2006-09-04T19:27:01.068Z</updated><title type="text">This is an entry</title><content
type="xhtml"><div xmlns="http://www.w3.org/1999/xhtml">This <b>is</b> 
<i>markup</i></div></content>
<author><name>James</name></author><link href="http://www.example.org"/></entry>
    

Serializing without whitespace and line breaks is an optimization designed to make the transfer of the documents more efficient. As an alternative, you can use a prettyxml writer to insert line breaks and indents:


Listing 3. Serializing with the prettyxml writer
Writer writer = abdera.getWriterFactory().getWriter("prettyxml");
writer.writeTo(entry, System.out);    
    

The result of which is output that is a bit easier on the eyes:


Listing 4. Pretty XML output
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.org/foo/entry</id>
  <updated>2006-09-04T19:28:58.237Z</updated>
  <title type="text">This is an entry</title>
  <content type="xhtml">
    <div xmlns="http://www.w3.org/1999/xhtml">This <b>is</b> <i>markup</i></div>
  </content>
  <author>
    <name>James</name>
  </author>
  <link href="http://www.example.org"/>
</entry>
    

Be careful using the prettyxml writer as it can cause a number of unintended side-effects. For instance, using the writer to serialize an Atom Feed or Entry that contains an XML Digital Signature might cause the signature to become invalid.

Listing 5 illustrates the creation of an Atom Feed Document. As one might expect, the process is identical to creating an Atom Entry Document:


Listing 5. Creating a simple Atom Feed Document
Abdera abdera = new Abdera();
Factory factory = abdera.getFactory();
    
Feed feed = factory.newFeed();
feed.setId("http://example.org/foo");
feed.setUpdated(new java.util.Date());
feed.setTitle("This is a feed");
feed.addLink("http://www.example.org");
feed.addLink("http://www.example.org/foo", "self");
    
Entry entry = factory.newEntry();
entry.setId("http://example.org/foo/entry");
entry.setUpdated(new java.util.Date());
entry.setTitle("This is an entry");
entry.setContentAsXhtml("This <b>is</b> <i>markup</i>");
entry.addAuthor("James");
entry.addLink("http://www.example.org");
    
feed.addEntry(entry);
  
Writer writer = abdera.getWriterFactory().getWriter("prettyxml");
writer.writeTo(feed, System.out);
    


Listing 6. The created Atom Feed Document
<?xml version='1.0' encoding='UTF-8'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.org/foo</id>
  <updated>2006-09-04T19:31:45.286Z</updated>
  <title type="text">This is a feed</title>
  <link href="http://www.example.org"/>
  <link href="http://www.example.org/foo" rel="self"/>
  <entry>
    <id>http://example.org/foo/entry</id>
    <updated>2006-09-04T19:31:44.695Z</updated>
    <title type="text">This is an entry</title>
    <content type="xhtml">
      <div xmlns="http://www.w3.org/1999/xhtml">This <b>is</b>
<i>markup</i></div>
    </content>
    <author>
      <name>James</name>
    </author>
    <link href="http://www.example.org"/>
  </entry>
</feed>
    

Abdera's Feed Object Model interfaces follow the Atom Syndication Format schema very closely, making it natural for developers who are familiar with the RFC 4287 specification to produce valid Atom documents. However, it is important to point out that the implementation does not perform any validation of the input. For instance, RFC 4287 requires that all atom:entry and atom:feed elements contain exactly one atom:id element whose value is a normalized IRI. Abdera, however, does not throw an exception if a developer tries to create and serialize an entry or feed that does not contain an atom:id or that contains multiple atom:ids. Developers are responsible for ensuring that the documents they produce are valid. With the FeedValidator, you can check the validity of Atom documents.

Adding extensions to documents

The Feed Object Model includes the ability to work with extensions to the Atom format without requiring developers to first write modules that implement those extensions. For example, Listing 7 illustrates how to add an element "foo" in the "tag:example.org,2006:/namespaces" namespace to an entry. Listing 8 illustrates the serialized result:


Listing 7. Adding an extension element
QName extensionQName = 
  new QName("tag:example.org,2006:/namespaces", "foo", "f");
Element element = entry.addExtension(extensionQName);
element.setAttributeValue("foo", "bar");
element.setText("fooBar");
    


Listing 8. An Entry Document with an extension element
<?xml version='1.0' encoding='UTF-8'?>
<entry xmlns="http://www.w3.org/2005/Atom">
  <id>http://example.org/foo/entry</id>
  <updated>2006-09-04T19:34:10.322Z</updated>
  <title type="text">This is an entry</title>
  <content type="xhtml">
    <div xmlns="http://www.w3.org/1999/xhtml">This is markup</div>
  </content>
  <author>
    <name>James</name>
  </author>
  <link href="http://www.example.org"/>
  <f:foo xmlns:f="tag:example.org,2006:/namespaces" foo="bar">fooBar</f:foo>
</entry>
    

Listing 9 shows a more practical example by adding elements from the OpenSearch version 1.1 specification to a feed:


Listing 9. Adding OpenSearch version 1.1 elements to an Atom Feed
final String OSURI = "http://a9.com/-/spec/opensearch/1.1/";
final QName TOTALRESULTS = new QName(OSURI, "totalResults");
final QName STARTINDEX = new QName(OSURI, "startIndex");
final QName ITEMSPERPAGE = new QName(OSURI, "itemsPerPage");
final QName QUERY = new QName(OSURI, "Query");
    
Feed feed = factory.newFeed();    
feed.addExtension(TOTALRESULTS).setText("4230000");
feed.addExtension(STARTINDEX).setText("21");
feed.addExtension(ITEMSPERPAGE).setText("10");
Element query = feed.addExtension(QUERY);
query.setAttributeValue("role", "request");
query.setAttributeValue("searchTerms", "New York History");
query.setAttributeValue("startPage", "1");
    

Flexible content options

A key differentiator of the Atom format relative to other syndication formats is its support for a broad and flexible range of content types. Atom entries can contain plain text, escaped HTML, well-formed XHTML, XML, any arbitrary character-based data, and Base64-encoded content. It is also possible for an Atom entry to reference content by URI. The Feed Object Model provides a simple means to work with each of these options. Listings 10 and 11 illustrate how to set the content of an entry as plain text:


Listing 10. Setting content as plain text
Entry entry = factory.newEntry();
entry.setContent("This <b>is</b> not <i>markup</i>");
    


Listing 11. A plain text content element
<content type="text">This &lt;b&gt;is&lt;/b&gt;not &lt;i&gt;markup&lt;/i&gt;</content>
    

When working with plain text content (Listing 10) and escaped HTML (Listing 12), it is important to note that the serialized content elements will be nearly identical (Listings 11 and 13). It is very important that processors of the generated feeds pay proper attention to the value of the content type attribute. When displaying the content in a feed reader, the plain text value in Listing 11 must be rendered as the unformatted literal string "This <b>is</b> not <i>markup</i>", while the escaped HTML in Listing 13 is rendered with formatting: "This is markup".


Listing 12. Setting content as escaped HTML
Entry entry = factory.newEntry();
entry.setContentAsHtml("This <b>is</b> <i>markup</i>");
    


Listing 13. An HTML content element
<content type="html">This &lt;b&gt;is&lt;/b&gt;
&lt;i&gt;markup&lt;/i&gt;</content> 
    

The preferred alternative to escaped HTML is for feed publishers to use well-formed XHTML fragments in their entries using the Entry interface's setContentAsXhtml method as shown in Listing 14:


Listing 14. Setting content as XHTML
Entry entry = factory.newEntry();
entry.setContentAsXhtml("This <b>is</b> <i>markup</i>");
    


Listing 15. An XHTML content element
<content type="xhtml">
  <div xmlns="http://www.w3.org/1999/xhtml">
    This <b>is</b> <i>markup</i>
  </div>
</content>
    

Abdera parses the XHTML input passed in to the setContextAsXHTML method to ensure that it is well-formed, but it does not check to make sure it is valid XHTML. Similarly, it is possible to set the content of the entry to any arbitrary, well-formed XML as shown in Listings 16 and 17:


Listing 16. Setting content as XML
Entry entry = factory.newEntry();
entry.setContent("<a><b><c><d>foo</d></c></b></a>", Content.Type.XML);
    


Listing 17. An XML content element
<content type="application/xml">
  <a>
    <b>
      <c>
        <d>foo</d>
      </c>
    </b>
  </a>
</content>
    

At times, simply marking character-based content as type="text" or type="html" is not enough. For instance, it is possible for an Atom entry to contain an entire HTML document. When type="html", however, the escaped markup contained in the content element must be appropriate for containing within an HTML DIV element. To include the entire document, the type attribute must specify the HTML media-type, as shown in Listings 18 and 19:


Listing 18. Using text-based media content
Entry entry = factory.newEntry();
entry.setContent(
  "<html>
    <head>
      <title>Foo</title>
    </head>
    <body>This is new</body></html>", 
  "text/html");
    


Listing 19: A text-based media content element

<content type="text/html">
&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Foo&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;This is new&lt;/body&gt; &lt;/html&gt;
</content>

      

If a feed publisher wishes to syndicate non-character based content, it must Base64-encode the content and use the content type attribute to specify the media type of the encoded binary data. To achieve this in Abdera, use the Java Activation Framework DataHandler interface. When a DataHandler is passed in as the content of an entry, Abdera automatically Base64-encodes the content:


Listing 20. Setting Base64-encoded binary content
Entry entry = factory.newEntry();
URL url = new URL("file:/home/jasnell/mozilla-firefox.png");
URLDataSource ds = new URLDataSource(url);
DataHandler dh = new DataHandler(ds);
entry.setContent(dh);
    


Listing 21. A content element with Base64-encoded data
<content type="image/png">iVBORw0KGgoAAAANSUhEUgAAA...</content>
    

Because of the natural inefficiencies of Base64 encoding and because there are times when including content directly with the Atom entry is not appropriate (for example, when syndicating streaming audio or video), it is possible to reference content by URI as seen in Listings 22 and 23:


Listing 22. Setting the src attribute on the content element
Entry entry = factory.newEntry();
URI uri = new URI("http://example.org");
entry.setContent(uri.toString(), "application/xhtml+xml");
    


Listing 23. A content element using the src attribute
<content type="application/xhtml+xml" src="http://example.org" />
    

Parsing Feed and Entry Documents

Abdera's second primary function is parsing Atom documents. This begins by acquiring an instance of a Parser and passing it an InputStream or Reader for the document to be parsed:


Listing 24. Parsing an Atom Feed Document
Abdera abdera = new Abdera();
Parser parser = abdera.getParser();
URL url = Listing7.class.getResource("/example.xml");
    
Document<Feed> feed_doc = parser.parse(url.openStream());
Feed feed = feed_doc.getRoot();
    

Because Abdera's default parser implementation uses a pull-oriented model to parse XML, calling the parse method on the Parser object does not fully consume the InputStream or Reader passed in to the method. The stream is consumed incrementally as the information in the document is requested. As one might expect, calling methods such as writeTo, clone, and so forth, causes the stream to be fully consumed. This might not be true of non-default implementations of the Parser interface.

Once the Document is parsed, developers can access the content of the feed using either the methods of the Feed Object Model API or by using XPath:


Listing 25. Navigating the Feed Object Model
System.out.println(feed.getBaseUri());
System.out.println(feed.getLanguage());
System.out.println(feed.getId());
System.out.println(feed.getTitle());
System.out.println(feed.getTitleType());
System.out.println(feed.getUpdated());
System.out.println(feed.getAlternateLinkResolvedHref());
System.out.println(feed.getSelfLinkResolvedHref());
    
List<Entry> entries = feed.getEntries();
   
for (Entry entry : entries) {
  
  System.out.println(entry.getId());
  System.out.println(entry.getTitle());
  System.out.println(entry.getTitleType());
  System.out.println(entry.getUpdated());
  System.out.println(entry.getAlternateLinkResolvedHref());
  System.out.println(entry.getEnclosureLinkResolvedHref());
  System.out.println(entry.getContent());
  System.out.println(entry.getContentType());
      
  Element element = entry.getExtension(
    new QName("tag:example.org,2006:/namespaces", "foo"));
  
  System.out.println(element.getText());
  
}
    

As an alternative to walking through and calling the various get methods on the feed and entry objects, developers can use XPath statements to navigate the parsed document as illustrated in Listing 26:


Listing 26. Navigating the Feed Object Model with XPath
Abdera abdera = new Abdera();
XPath xpath = abdera.getXPath();
    
System.out.println(xpath.valueOf("/a:feed/a:id", feed));
System.out.println(xpath.valueOf("/a:feed/@xml:base", feed));
System.out.println(xpath.valueOf("/a:feed/@xml:lang", feed));
System.out.println(xpath.valueOf("/a:feed/a:title", feed));
System.out.println(xpath.valueOf("/a:feed/a:title/@type", feed));
System.out.println(xpath.valueOf("/a:feed/a:updated", feed));
System.out.println(xpath.valueOf("/a:feed/a:link[not(@rel)]/@href", feed));
System.out.println(xpath.valueOf("/a:feed/a:link[@rel='self']/@href", feed));
    

In addition to the ability to select individual nodes, groups of nodes, text, boolean, and numeric values, standard XPath features, such as functions and axes, are also supported:


Listing 27. Using standard XPath functions
System.out.println(xpath.valueOf("count(//a:entry)", feed) + " entry");
System.out.println(xpath.valueOf("name(//a:entry/ancestor::*)", feed));
    

Selecting nodes using XPath returns Feed Object Model objects that can themselves be evaluated using XPath as illustrated in Listing 28. Note that instead of passing the feed in as the second argument of the valueOf function, as in the previous examples, the Div selected from the selectSingleNode method is passed in. The XPath is evaluated relative to whatever Feed Object Model element is passed in to the method:


Listing 28. Evaluating XPath statements against individual FOM objects
Div div = (Div) xpath.selectSingleNode(
  "//a:entry/a:content/x:div", feed, namespaces);
System.out.println(xpath.valueOf("namespace-uri()", div));
System.out.println(xpath.valueOf("x:p", div, namespaces));
    

Using XPath to navigate Abdera documents provides a number of advantages, especially to developers who work with extensions to the core format. For instance, with the xpath.booleanValueOf method, you can quickly determine whether or not a given feed or entry contains a particular extension element and it is generally more efficient than walking through the structure of the document using the various get methods and iterators.

Another important feature of the Feed Object Model is the ability to apply XSLT transforms to parsed documents and elements using the standard Java Transformation APIs. As with the XPath support, it is possible to apply XSLT transforms to any part of a parsed document:


Listing 29. Transforming Abdera documents with XSLT
Abdera abdera = new Abdera();
Parser parser = abdera.getParser();
    
URL url = Listing8.class.getResource("/example.xml");
URL xslt = Listing8.class.getResource("/example.xslt");
    
Document<Feed> feed_doc = parser.parse(url.openStream());
Document<Element> xslt_doc = parser.parse(xslt.openStream());
    
Source feed_source = new AbderaSource(feed_doc);
Source xslt_source = new AbderaSource(xslt_doc);
    
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer(xslt_source);
    
Result result = new StreamResult(System.out);
transformer.transform(feed_source, result);
    

The results of the transformation can be sent to any Result implementation supported by the Java Transformer API. In the example above, the results are simply going to stdout. It is possible to send the results directly to the Abdera parser to produce another document.

Atom Publishing support

When the Abdera project was launched, the stated goal of the project was to provide functionally complete implementations of both the Atom Syndication Format and the Atom Publishing Protocol. Thus far, this series has provided a fair amount of coverage of the support for the Syndication Format and has illustrated how to produce and consume feeds. The next installment will cover the Atom Publishing Protocol client and server support that is still currently being implemented. Listing 30 illustrates a simple example of Abdera's APP client:


Listing 30. A simple Atom Publishing Protocol client
Abdera abdera = new Abdera();
Client client = new CommonsClient(abdera);
RequestOptions options = client.getDefaultRequestOptions();
options.setIfModifiedSince(new java.util.Date());
options.setNoCache(true);
    
ClientResponse response = client.get("http://example.org/entries/1", options);
    
System.out.println(response.getStatus());
System.out.println(response.getStatusText());
System.out.println(response.getEntityTag());
System.out.println(response.getLastModified());
System.out.println(response.getContentType());
    
response.release();
    

Abdera and thread safety

Before wrapping up, you should know that most of the core Abdera components, such as the Abdera, Factory, and Parser objects, are thread-safe and stateless, making it possible to share instances efficiently across multiple threads. However, the Feed Object Model (FOM) objects they create are not thread-safe. For a variety of reasons, none of the FOM objects are synchronized. If you intend to allow multiple threads to access or modify Entry and Feed objects, you need to provide your own synchronization:


Listing 31. Non-synchronized concurrent modification to FOM Objects leads to unpredictable results
final Abdera abdera = new Abdera();
final Factory factory = abdera.getFactory();
final Entry entry = factory.newEntry();
    
final Thread[] threads = new Thread[100];
for (int n = 0; n < threads.length; n++) {
  final int i = n;
  threads[n] = new Thread(
    new Runnable() {
      public void run() {
        try {
          int s = (new java.util.Random(
            System.currentTimeMillis())).nextInt(10);
          Thread.sleep(s);
        } catch (InterruptedException e) {}
        try {
          IRI id = factory.newID();
          id.setValue("urn:thread:" + i);
          entry.setIdElement(id);
          System.out.println(i + "\t" + entry);  // unpredictable results
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    }
  );
}
    
for (Thread t : threads) t.start();
    


Listing 32. A sample of the invalid output from Listing 31
85    urn:thread:85
86    urn:thread:99
91    urn:thread:91
org.apache.axiom.om.OMException
     at org.apache.axiom.om.impl.llom.OMNodeImpl.insertSiblingBefore(OMNodeImpl.java:232)
     at org.apache.abdera.parser.stax.FOMElement._setChild(Unknown Source)
     at org.apache.abdera.parser.stax.FOMEntry.setIdElement(Unknown Source)
     at abdera.examples.atom.Listing11$1.run(Listing11.java:29)
     at java.lang.Thread.run(Thread.java:788)
87    urn:thread:87
88    urn:thread:88
    

Wrapping the entry modifications in a synchronization block is enough to resolve the issues. It is, however, recommended that FOM objects only ever be created and used by a single thread.

Looking forward

In this article, you looked at the core features of the Apache Abdera project including its Feed Object Model, XPath and XSLT support, extension handling and incremental parsing model. The next installment of this series introduces and demonstrates the support for the Atom Publishing Protocol currently being developed.



Download

DescriptionNameSizeDownload method
Sample Eclipse Project with the example codex-atompp3-code.zip39KB HTTP

Information about download methods


Resources

Learn

Get products and technologies

  • IBM trial software: Build your next development project with trial software available for download directly from developerWorks.

Discuss

About the author

Photo of James M Snell

James Snell is a member of IBM's WebAhead development lab focusing on the prototype development of pre-emerging software technologies and standards for IBM's own use. His research and development interests cover a broad range of current technology trends including Atom, AJAX, REST, Open Source, personal publishing systems, semantic Web and situational applications. He is an active committer to the Apache Abdera project, currently in incubation and tasked with the creation of a high-performance, functionally complete implementation of the Atom Syndication Format and Atom Publishing Protocol standards.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


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. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

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.

(Must be between 3 – 31 characters.)

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

 


Rate this article

Comments

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=XML, Java technology, Open source
ArticleID=182875
ArticleTitle=Getting to know the Atom Publishing Protocol, Part 3: Introducing the Apache Abdera project
publish-date=12122006
author1-email=jasnell@us.ibm.com
author1-email-cc=dwxed@us.ibm.com