Abdera Tips #2

The Abdera parser uses Apache Axiom and the StAX api under the covers. This means that Atom documents are parsed incrementally, providing significant memory and speed improvements over typically configured DOM parsers. This does, however, lead to some interesting issues. Take for instance, the following code taken from a test case added to Abdera by Ugo Cei:

  Abdera abdera = new Abdera();
  Factory factory = abdera.getFactory();
  Feed feed = factory.newFeed();
  feed.setTitle("Test");
  feed.setId("http://example.com/feed");
  Parser parser = abdera.getParser();
  Document<Entry> doc = parser.parse(this.getClass().getResourceAsStream("/entry.xml"));
  Entry entry = doc.getRoot();

  Link link = factory.newLink();
  link.setHref(entry.getId().toString());
  link.setRel(Link.REL_EDIT);
  entry.addLink(link);
  assertNotNull("Link is null", entry.getLink(Link.REL_EDIT));
  feed.addEntry(entry);
  assertNotNull("Link is null", entry.getLink(Link.REL_EDIT));
  for (Entry e : feed.getEntries()) {
    assertNotNull("Link is null", e.getLink(Link.REL_EDIT));
  }

At first glance this code appears to be perfectly reasonable. The problem, however, is that the underlying input stream is not fully consumed before the edits are made to the objects, which ends up leading to problems. For the next release of Abdera, we will be working on fixing this so that the stream is fully consumed before any edits are made. If you’re using the recently released 0.3.0, however, you need to throw in an entry.toString() immediately before the first attempt to modify the entry. This will ensure that the stream is fully parsed. The corrected code would look something like:

  Abdera abdera = new Abdera();
  Factory factory = abdera.getFactory();
  Feed feed = factory.newFeed();
  feed.setTitle("Test");
  feed.setId("http://example.com/feed");
  Parser parser = abdera.getParser();
  Document<Entry> doc = parser.parse(this.getClass().getResourceAsStream("/entry.xml"));
  Entry entry = doc.getRoot();

  entry.toString();
  // Update: I checked in a fix to the Abdera trunk that does not require serializing to a string
  // entry.complete()

  Link link = factory.newLink();
  link.setHref(entry.getId().toString());
  link.setRel(Link.REL_EDIT);
  entry.addLink(link);
  assertNotNull(”Link is null”, entry.getLink(Link.REL_EDIT));
  feed.addEntry(entry);
  assertNotNull(”Link is null”, entry.getLink(Link.REL_EDIT));
  for (Entry e : feed.getEntries()) {
    assertNotNull(”Link is null”, e.getLink(Link.REL_EDIT));
  }

Comments are closed.