Sunday, December 6, 2009

Embracing Atom with CXF

Until recently, it has been possible to write an AtomPub JAX-RS application in CXF by using Abdera Feed or Entry classes like this :



public class AtomPubResource {

@GET
@Path("/feed")
public Feed getCollection() {
// create Feed as needed
}

@GET
@Path("/feed/{id}")
public Entry getEntry(@PathParam("id") int id) {
// get individual entry
}

@POST
@Path("/feed")
public void addEntry(Entry entry) {
// update collection
}

// etc
}


Going this route gives users the most control over how a given feed is initialized and how entries have the actual content captured. Some frameworks provide JAXB-based classes for dealing with Atom primitives such as feeds and entries - I am not quite keen on extending CXF JAXRS in a similar way, after all, what it can give a user apart from introducing alternative foreign classes into their main application code ?

With the addition of AtomPojoProvider provider and Atom-specific extensions few more options are now available for CXF users to start playing with Atom (note the provider and extensions code may still get changed).

To start with, users can now simply do :


@Path("/store")
public class BookStore {

private Books books = new Books();

@GET
@Path("/books")
@Produces(
{
"application/xml",
"application/json",
"application/atom+xml;type=feed"
})
public Books getBooks() {
return books;
}

@GET
@Path("/books/{id}")
@Produces(
{
"application/xml",
"application/json",
"application/atom+xml;type=entry"
})
public Book getBook(@PathParam("id") int id) {
return books.getBook(id);
}

@POST
@Consumes(
{
"application/xml",
"application/json",
"application/atom+xml;type=entry"
})
public void addBook(Book book) {
books.addBook(book);
}

// etc
}


What happens here is that you continue write your Java JAX-RS code, the way you may often do, without introducing any direct dependencies on the Atom-specific classes, and just experimenting at the same time with implementing an AtomPub application on top of your collection classes like Books. Starting with AtomPub and Atom is now as simple as updating Produces and Consumes values and registering an AtomPojoProvider.
As long as your Books class has default collection setter and getter methods, getBooks and setBooks returning and accepting a List of Book instances in this case, and happy with some of default Feed and Entry properties, that is all that needs to be done.

The next step is to tell the AtomPojoProvider the names of the collection getters and setters on individual classes such as Books.

The next step is to register Feed and/or Entry builders which can help AtomPojoProvider with setting various Feed and Entry properties, still without introducing direct dependencies in your main code.

Finally, you can take the complete control with registering Feed or Entry writers or readers. This option is similar to having Abdera Feed or Entry classes in your main application code except that these providers will let you deal with these classes outside of the main application code.

CXF users will now have plenty of options for writing AtomPub applications on top of the JAX-RS runtime. Give it a try and enjoy !

2 comments:

Roby said...

How to enable the ATOM provider in cxf2-2-6? I tried:




It give out:WARNING: No message body writer has been found for response class FOMEntry.

Generic Cialis said...

Interesting article, I was looking for something like this, thanks for sharing, it is very useful.