Below is my solution which is based on a similar ServletFilter from the
SpringFramework. You will need to set the entityManagerFactory before using
this. I normall have that configured in spring and get a reference to this
filter bean from the context.
package com.revolsys.restlet;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceException;
import org.apache.log4j.Logger;
import org.restlet.Filter;
import org.restlet.data.Request;
import org.restlet.data.Response;
import org.springframework.dao.DataAccessResourceFailureException;
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
import org.springframework.orm.jpa.EntityManagerHolder;
import
org.springframework.transaction.support.TransactionSynchronizationManager;
public class OpenEntityManagerFilter extends Filter {
private static final Logger logger =
Logger.getLogger(OpenEntityManagerFilter.class);
private EntityManagerFactory entityManagerFactory;
protected int beforeHandle(Request request, Response response) {
if (TransactionSynchronizationManager.hasResource(entityManagerFactory))
{
request.getAttributes().put(this.toString(), Boolean.TRUE);
} else {
logger.debug("Opening JPA EntityManager in OpenEntityManagerFilter");
try {
EntityManager em = entityManagerFactory.createEntityManager();
TransactionSynchronizationManager.bindResource(entityManagerFactory,
new EntityManagerHolder(em));
} catch (PersistenceException ex) {
throw new DataAccessResourceFailureException(
"Could not create JPA EntityManager", ex);
}
}
return super.beforeHandle(request, response);
}
protected void afterHandle(Request request, Response response) {
Map<String, Object> attributes = request.getAttributes();
if (attributes.get(this.toString()) != Boolean.TRUE) {
EntityManagerHolder emHolder =
(EntityManagerHolder)TransactionSynchronizationManager.unbindResource(entityManagerFactory);
logger.debug("Closing JPA EntityManager in OpenEntityManagerFilter");
EntityManagerFactoryUtils.closeEntityManager(emHolder.getEntityManager());
}
}
public EntityManagerFactory getEntityManagerFactory() {
return entityManagerFactory;
}
public void setEntityManagerFactory(EntityManagerFactory
entityManagerFactory) {
this.entityManagerFactory = entityManagerFactory;
}
}
On Wed, Feb 18, 2009 at 6:45 AM, Jerome Louvel <[email protected]>wrote:
> Hi guys,
>
> This is such a hook available. See the ConnectorService#afterSend method:
>
> http://www.restlet.org/documentation/snapshot/api/org/restlet/service/ConnectorService.html#afterSend(org.restlet.resource.Represent<http://www.restlet.org/documentation/snapshot/api/org/restlet/service/ConnectorService.html#afterSend%28org.restlet.resource.Represent>
> ation)
>
> Hope this helps!
>
> Best regards,
> Jerome Louvel
> --
> Restlet ~ Founder and Lead developer ~ http://www.restlet.org
> Noelios Technologies ~ Co-founder ~ http://www.noelios.com
>
>
> -----Message d'origine-----
> De : Michael Terrington [mailto:[email protected]]
> Envoye : mercredi 18 fevrier 2009 12:23
> A : [email protected]
> Objet : Re: Managing a JPA/Hibernate session
>
> Hi Peter,
>
> I recently encountered this problem myself. I ended up creating a
> Representation wrapper that would close my EM after the call to write.
> The code [1] is part of restlet-jpa [2].
>
> Regards,
> Michael.
>
> [1] -
> http://trac.sarugo.org/restlet-jpa/browser/trunk/src/main/java/org/sarugo/restlet/jpa/TransactionFilter.java
>
> [2] - http://trac.sarugo.org/restlet-jpa/
>
> On Wed, Feb 18, 2009 at 10:22 AM, Peter Becker <[email protected]>
> wrote:
> > 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
> >
>
> ------------------------------------------------------
>
> http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=1185212
>
> ------------------------------------------------------
>
> http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=1186386
>
------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=1186497