Open Session In View not working (locator?)

86 views
Skip to first unread message

Yan

unread,
Dec 30, 2013, 2:17:07 PM12/30/13
to google-we...@googlegroups.com, Yan.X...@questdiagnostics.com
Hi there, 

I am integrating GWT 2.5.1 with Spring 3.0 backend.  Run into a problem that OSIVP should fix but it is not. 

A parent object contains a list of children objects, both are EntityProxy. On client side, I update the child proxy and my Server side API simply saves the parent.  On the server side, my updates to the child object disappears by the time server business logic is invoked.  My transaction starts and commits in business service layer. I have already used one single entity manager instance per request by using ThreadLocal.

Without using OSIVP, I did observe if I explicitly start a transaction in my request factory servlet when request comes in, and then commit the transaction in the servlet at the end, the problem is fixed. Therefore, I have to group everything under the same transaction (inside servlet, rather than in service layer), in addition to use one single entity manager pre request, is that correct?

Everyone said that the fix is to use OSIVP, however, I do not see it is fixing the problem afterwards. For whatever reason, using OSIVP does not have the same effect. 

1) In my EntityLocator class, how do I get entityManager?   Some has posted this code, this is what I used. But, does not it start a new entity manager rather than using what is attached to the thread?

private void init() {
        HttpServletRequest request = RequestFactoryServlet.getThreadLocalRequest();
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
        EntityManagerFactory entityManagerFactory = context.getBean(EntityManagerFactory.class);
        entityManager = entityManagerFactory.createEntityManager();
        // then cache this entityManager in locator instance
    }

2) In my DAO class, do I need to declare my entity manager as extended like this?  That is what I did. 

@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;

3) How does Spring OpenEntityManagerInViewFilter start a transaction? I do not see it is happening in its source code, other than registering entity manager to current thread.  I think that is my problem. If somehow a transaction is started before the locator method is called, I would have been fine. 

I wish someone has a sample project illustrates all this.

Thanks,
Yan

Thomas Broyer

unread,
Dec 30, 2013, 6:51:52 PM12/30/13
to google-we...@googlegroups.com, Yan.X...@questdiagnostics.com


On Monday, December 30, 2013 8:17:07 PM UTC+1, Yan wrote:
Hi there, 

I am integrating GWT 2.5.1 with Spring 3.0 backend.  Run into a problem that OSIVP should fix but it is not. 

A parent object contains a list of children objects, both are EntityProxy. On client side, I update the child proxy and my Server side API simply saves the parent.  On the server side, my updates to the child object disappears by the time server business logic is invoked.  My transaction starts and commits in business service layer. I have already used one single entity manager instance per request by using ThreadLocal.

Without using OSIVP, I did observe if I explicitly start a transaction in my request factory servlet when request comes in, and then commit the transaction in the servlet at the end, the problem is fixed. Therefore, I have to group everything under the same transaction (inside servlet, rather than in service layer), in addition to use one single entity manager pre request, is that correct?

No. Transactions really should be scoped to the service methods at most.
 
Everyone said that the fix is to use OSIVP, however, I do not see it is fixing the problem afterwards. For whatever reason, using OSIVP does not have the same effect. 

1) In my EntityLocator class, how do I get entityManager?   Some has posted this code, this is what I used. But, does not it start a new entity manager rather than using what is attached to the thread?

private void init() {
        HttpServletRequest request = RequestFactoryServlet.getThreadLocalRequest();
        ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getSession().getServletContext());
        EntityManagerFactory entityManagerFactory = context.getBean(EntityManagerFactory.class);
        entityManager = entityManagerFactory.createEntityManager();
        // then cache this entityManager in locator instance
    }

You should call createEntityManager in a servlet filter prior to the RequestFactoryServlet, or call it in some helper class if you want it initialized lazily.
And you could store that EntityManager in the request's attributes rather than a ThreadLocal (but a ThreadLocal will work too).

That said, I don't know Spring, so there might be other ways to get at the EntityManager than calling createEntityManager and "caching" its result yourself.
Possibly something like ((EntityManagerHolder) TransactionSynchronizationManager.getResource(emf)).getEntityManager(), where "emf" is your singleton EntityManagerFactory.

This code is most likely why your app doesn't work: you're not actually using OSIV.
 
2) In my DAO class, do I need to declare my entity manager as extended like this?  That is what I did. 

@PersistenceContext(type=PersistenceContextType.EXTENDED)
private EntityManager em;

I suppose so (I don't know Spring or JPA much)
 
3) How does Spring OpenEntityManagerInViewFilter start a transaction?

It doesn't, fortunately. 

Yan Zhou

unread,
Jan 1, 2014, 7:11:58 PM1/1/14
to google-we...@googlegroups.com
Thanks so much, 

I may have had misconceptions. Because I observed correct behavior when I started transaction in servlet, I assumed a transaction needs to be involved at that level. Apparently, I was using multiple entity manager instances, and when I start a transaction at servlet level, somehow the entity manager behaves correctly. But transaction is not the answer as you pointed out.

I was looking up EntityManager from JNDI in a servlet filter and store it in ThreadLocal, like the following shows.  Maybe that is _not_ the real entity manager, it is just an interface which may have different underlying EntityManager instances? Does anyone know?

em = (EntityManager) new InitialContext().lookup("java:comp/env/persistence/myapp");   // then store it in ThreadLocal 

This is now fixed, what fixed this is to switch my backend from Guice to Spring. I am sure that Guice is not the problem. But for some reason, when I use Spring configuration for entity manager lookup,  it IS using single entity manager instance even though I configured it for JNDI look up.  This is how I now use Spring to get entity manager:

<beans:bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<beans:property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" />
<beans:property name="dataSource" ref="dataSource" />
</beans:bean>

Anyone share any insight on this, why my previous approach did not work?

Thanks,
Yan


--
You received this message because you are subscribed to a topic in the Google Groups "Google Web Toolkit" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/google-web-toolkit/sMQhxKeeGOc/unsubscribe.
To unsubscribe from this group and all its topics, send an email to google-web-tool...@googlegroups.com.
To post to this group, send email to google-we...@googlegroups.com.
Visit this group at http://groups.google.com/group/google-web-toolkit.
For more options, visit https://groups.google.com/groups/opt_out.

Reply all
Reply to author
Forward
0 new messages