Tuesday, March 2, 2010

Apache Wink - Dynamic Resources

Quite often people ask me what is so different about Apache Wink, and why another JAX-RS framework. Usually I answer that Apache Wink started in HP long before there was any REST open-source framework. It was developed internally for two years before joining Apache.

This may be interesting from historical point of view, but then people ask: so why should we use it now? Are there any unique features?
And the answer here is: yes, there are some unique features beyond the JAX-RS spec and this post will describe one of the most cool features (IMO) that Wink contains:

Dynamic Resources


The idea of Dynamic Resource is quite similar to Template pattern and it's simple: many resource classes have more or less the same logic. However, they manipulate different entities, so obviously they have different URLs.

Consider the following example: a resource that simply a facade to the database - it allows the CRUD operation and it uses Hibernate as the persistence layer.

So basically the template class will look something like this:

public class CrudResource {

private Session session;
@Context
private UriInfo uriInfo;

private Class clazz;

@GET
public Object getEntity(@PathParam("id") String id) {
return session.get(clazz, id);
}

@POST
public Response createEntity(Object newEntity) {
session.save(newEntity);
String id = newEntity.getId(); // this line will not compile, but the idea is that id is assigned by hibernate
URI location = uriInfo.getAbsolutePathBuilder().segment(String.valueOf(id)).build();
return Response.created(location).build();
}

@PUT
public void updateEntity(Object entity) {
session.update(entity);
}

@DELETE
public void delete(@PathParam("id") String id) {
session.delete(session.get(clazz, id));
}

}

Notice: This class doesn't contain the full logic, like transaction management, and won't even compile. It should provide the idea how to implement the "template" style resource and not how to really work with Hibernate or even Wink.

So as you can see, this class can basically perform the CRUD operations on any entity. It would be a pity, if for each entity, we'll need to extend this class just to assign a different path. And here come the Dynamic Resources. They allow to skip the @Path annotation and implement the DynamicResource interface instead (or extend from the AbstractDynamicResource class).

So now our resource will look something like this:
public class CrudResource extends AbstractDynamicResource  {
...
}

Now it's possible to create multiple instances of this class and assign it a different paths and other members (like 'clazz', which should hold the value of actual class).

Notice: Dynamic Resources can be returned only by Application.getSingletons() method. Thus these resources are actually singletons and must be coded accordingly (for example think about synchronization issues).

Spring Integration


Wink contains the Spring Integration extension. I won't describe its features here, but only want to mention the usage of Dynamic Resources with Spring.
First, Dynamic Resource can be defined and registered via Spring Context, thus you can create new resources using the same class, while updating the configuration only. Pretty nice feature, when you think about it.
Second, Dynamic Resources benefit from different scopes. Meaning, they may not be singletons anymore.

No comments: