A basic Restlet-JPA consists of three distinct components: The persistence application, the entity router and entity resources.

Persistence Application

The persistence application manages EntityManager instances and is the root of your Restlet-JPA application. Very little custom code is required here: just to supply an EntityManagerFactory and configure your routes.

Example:

public class FooApp extends PersistenceApplication {

  public FooApp() {
    super(Persistence.createEntityManagerFactory("foo");
  }

  @Override
  public Restlet createRoot() {
    EntityRouter router = getEntityRouter();
    router.attach("/foo/", FooCollection.class);
    router.attach("/foo/{id}", FooResource.class);
    return new TransactionFilter(router);
  }
}

Entity Router

The entity router maps requests to entity resources. It also allows for mapping of entity instances (objects) to URLs.

This class is provided by Restlet-JPA and customisation is not required.

Nested entity routers can be created to allow for complex routing requirements.

Example:

EntityRouter root = getEntityRouter();

EntityRouter fooRouter = new EntityRouter(root);
fooRouter.attach("", FooCollection.class);
fooRouter.attach("/{id}", FooResource.class);
// attach foo router with authentication
root.attach("/foo", new FooGuard(fooRouter));

EntityRouter barRouter = new EntityRouter(root);
barRouter.attach("", BarCollection.class);
barRouter.attach("/{id}", BarResource.class);
// attach bar router with authentication
root.attach("/bar", new BarGuard(barRouter));

return root;

Entity Resources

Resources attached to an entity router which are annotated @EntityResource are treated as entity resources. Entity resources implement the actual mapping from requests to entity instances (objects). There's no mandatory features of the entity resource (other than it being a Resource) - Restlet-JPA will simply not support some features if you don't provide them in your resource.

Optional Methods

If your resource provides the following methods, Restlet-JPA will use them for request to entity mapping.

public E getEntity()::

This method is used to retrieve an entity instance (object) given a request. The entity resource will be initialised (as if handling a request) then this method called to return the entity instance associated with the request.

public static Object getEntityParent(E entity)::

For nested entity routers, this method is called to check if the entity has a parent (which the root entity router might be able to resolve to a URL). This is used when mapping an entity to a URL.

public static Map<String, Object> getIdAttributes(E entity)::

Called to map an entity to the request attributes (the bits in braces in the route - /{id}). For entities which only map their @Id to one attribute, there's no need to provide this method. Provide this is you have a compound key or are using multiple attributes to map to entities.

Helper Classes

There are two helper classes provided that make providing entity lists and entity resources trivial. They are EntityCollection and EntityInstance. These rely on a simple converter framework for converting entities to/from representations.

EntityList Usage

A read-only list:

public class FooList extends EntityList<Foo> {

  @Override
  protected Query getJPAQuery() {
    return getEntityManager().createQuery("select f from Foo f");
  }

  @Override
  protected void initConverters() {
    try {
      getOutputConverters().add(
        new XTCConverter(getApplication(),
          "/pages/foo/list.xhtml"));
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

}

list.xhtml:

<!DOCTYPE html 
     PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
     "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"
	xmlns:ui="http://sarugo.org/xtc/ui"
	xmlns:c="http://java.sun.com/jsp/jstl/core">
<body>
<ui:composition template="../template.xhtml">
 <ui:param name="page" value="Foos" />
 <ui:define name="body">
  <c:if test="${empty resource.list}">No foos.</c:if>
  <c:if test="${!empty resource.list}">
   <ul>
    <ui:repeat var="foo" value="${resource.list}">
     <li><a href="${resource.application.getEntityURL(foo)}"><c:out value="${foo.name}" /></a></li>
    </ui:repeat>
   </ul>
   <c:if test="${resource.start != 1}">
    <a href="${resource.prevUrl}">&amp;laquo; Previous</a>
   </c:if>
   <c:if test="${resource.hasMore}">
    <a href="${resource.nextUrl}">Next &amp;raquo;</a>
   </c:if>
  </c:if>
 </ui:define>
</ui:composition>
</body>
</html>

EntityInstance Usage

A read-only entity resource:

@EntityResource(entity = Foo.class)
@EntityConverter(JSONConverter.class)
public class FooResource extends EntityInstance<Foo> {

  public FooResource(EntityFinder finder) {
    super(finder);
  }

}

Converters

Converters come in two flavours: InputConverters and OutputConverters. There are several trivial implementations of these provided. When supplied via @EntityConverter annotation, they must have a single-arg constructor taking a PersistenceApplication as the only argument. When supplied by the resource directly by overriding initConverters() any constructor may be used. Therefore the @EntityConverter is only useful for trivial converters (vs. those requiring runtime configuration, for example of template names).