Hello,
I'm using Restlet above a JPA persistence layer with Hibernate as provider.
That works reasonably well, but unfortunately I haven't found a way to
handle the persistence sessions properly.
What I would like to see is that a new session is opened whenever needed and
is closed after all request processing is done. This is my current attempt:
public class EntityManagerFilter extends Filter implements
EntityManagerSource {
private final EntityManagerFactory emf;
private final ThreadLocal<EntityManager> entityManagerTL = new
ThreadLocal<EntityManager>();
public EntityManagerFilter(Context context, Restlet next,
EntityManagerFactory emf) {
super(context, next);
this.emf = emf;
}
public EntityManagerFilter(Context context, EntityManagerFactory emf) {
super(context);
this.emf = emf;
}
public EntityManagerFilter(EntityManagerFactory emf) {
this.emf = emf;
}
public EntityManager getEntityManager() {
// we lazily initialize in case the entity manager is not actually
needed
// by a request
EntityManager entityManager = entityManagerTL.get();
if(entityManager == null) {
entityManager = emf.createEntityManager();
entityManagerTL.set(entityManager);
}
return entityManager;
}
@Override
protected void afterHandle(Request request, Response response) {
EntityManager entityManager = entityManagerTL.get();
if(entityManager!=null) {
entityManagerTL.remove();
assert entityManager.isOpen():
"Entity manager should only be closed here but must have
been closed elsewhere";
entityManager.close();
}
super.afterHandle(request, response);
}
}
This filter is attached as the root of the application, forwarding to the
router that does the main dispatch.
The approach works to some extent, but with a huge "but": most of the time I
produce TemplateRepresentations to render data with Freemarker. The
processing of those templates happens after the afterHandle(..) method of
the filter, which means that the session is closed and if the template uses
anything that is not eagerly fetched and the Java code hasn't used it will
get an exception from the persistence layer. That is actually a pretty
common case since a lot of the details of objects is needed only in the
template rendering.
Currently I work around that problem by explicitly loading objects in Java
code. I'd rather solve that problem properly, but I can't find a hook that
gets called after the write(..) method of the representations. Long intro,
short question: Is there such thing?
Thanks,
Peter
------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=1182479