Paul,

correct me if I am wrong, but I believe your solution suffers from the same 
problem as mine: if there is still data to fetch during the processing of a 
representation object (as it happens on the write(..) method of the 
TemplateRepresentation of the Freemarker extension), then you will get 
exceptions from the persistence layer.

By using the ConnectorService the JPA sessions lives long enough to include 
the call to the write(..) method.

  Peter



Paul Austin wrote:

> 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

------------------------------------------------------
http://restlet.tigris.org/ds/viewMessage.do?dsForumId=4447&dsMessageId=1189325

Reply via email to