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

Reply via email to