Page 1 of 2 12 LastLast
Results 1 to 10 of 13

Thread: OpenEntityManagerInViewFilter not working

  1. #1

    Default OpenEntityManagerInViewFilter not working

    Hi @all,

    I know that this issue has been posted a bunch of times before, thus before of asking I was googling and searching in this forum for this topic without success in terms of finding something useful for solving my issue. I have decided to ask because probably my problem is due to a configuration mistake that I am not able to realize by myself.

    So this is my scenario: Spring MVC 3, Spring Web Flow 2, JPA 2, Hibernate 3 and Spring Data. I use both MVC and SWF depending on the functionality, there are some complex wizards that with SWF are easier to implement. I am also using the AOP Spring's transactions manager.

    This is my configuration:

    • In the web.xml file I am trying to set up the OpenEntityManagerInViewFilter so as I have read this is the filter to use for implementing the open session in view pattern:

    Code:
    	
    	<filter>
    		<filter-name>oemInViewFilter</filter-name>
    		<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    		<init-param>
    			<param-name>entityManagerFactoryBeanName</param-name>
    			<param-value>entityManagerFactory</param-value>
    		</init-param>
    	</filter>
    	
    	<filter-mapping>
    		<filter-name>oemInViewFilter</filter-name>
    		<url-pattern>/</url-pattern>
    	</filter-mapping>
    • At the same time, in dispatcher-servlet.xml I am setting up the PersistenceContext in flowScope:

    Code:
    	<flow:flow-executor id="flowExecutor" flow-registry="flowRegistry">
    		<flow:flow-execution-listeners>
    			<flow:listener ref="jpaFlowExecutionListener" />
    		</flow:flow-execution-listeners>
    	</flow:flow-executor>
    	
    	<bean id="jpaFlowExecutionListener" class="org.springframework.webflow.persistence.JpaFlowExecutionListener">
    		<constructor-arg ref="entityManagerFactory" />
    		<constructor-arg ref="transactionManager" />
    	</bean>
    • Transaction management is configured this way:

    Code:
    	<!-- To conduct transactions, we declare a JPA transaction manager that collaborates with the JPA EntityManager produced by the factory -->
    	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    		<!-- Reference to the entity manager factory defined in dal-context.xml -->
    		<property name="entityManagerFactory" ref="entityManagerFactory" />
    	</bean>
    	
    	<!-- Declaration of an AOP advice that defines transactional policies (beans that should be advised), referencing the transaction manager previously declared -->
    	<tx:advice id="txAdvice" transaction-manager="transactionManager">
    		<tx:attributes>
    			<tx:method name="find*(..)" propagation="SUPPORTS" isolation="DEFAULT" read-only="true" />
    			<tx:method name="save*(..)" propagation="REQUIRED" isolation="DEFAULT" />
    			<tx:method name="delete*(..)" propagation="REQUIRED" isolation="DEFAULT" />
    			<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" />
    		</tx:attributes>
    	</tx:advice>
    	
    	<!-- Definition of the pointcut for the previously declared advice by using and AspectJ expression -->
    	<aop:config>
    		<!-- AspectJ pointcut expression -->
    		<aop:pointcut id="blPointCut" expression="execution(public * ie.i2e2.greenmode.bl.bo.impl.*.*(..))" />
    		<!-- Maps the pointcut to the transaction's advice -->
    		<aop:advisor advice-ref="txAdvice" pointcut-ref="blPointCut" />
    	</aop:config>
    • And finally, database access and entity manager factory are configured like this;

    Code:
    	<!-- JDBC based datasource definition (TODO: should be changed to JNDI datasource) -->
    	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    		<property name="driverClassName" value="org.hsqldb.jdbcDriver" />
    		<property name="url" value="jdbc:hsqldb:mem:gmtest" />
    		<property name="username" value="sa" />
    		<property name="password" value="" />
    	</bean>
    	
    	<!-- Provide specifics about the particular JPA implementation to use, in this case Hibernate -->
    	<bean id="jpaVendorAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    		<property name="database" value="HSQL" />
    		<property name="showSql" value="false"/>
    		<property name="generateDdl" value="true"/>
    		<property name="databasePlatform" value="org.hibernate.dialect.HSQLDialect" />
    	</bean>
    	
    	<!-- Configuration of a JPA container-managed entity manager, wired with datasource and vendor adapter properties -->
    	<bean id="entityManagerFactory" class= "org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    		<!-- Reference eto the previously defined datasource -->
    		<property name="dataSource" ref="dataSource" />
    		<!-- Reference eto the previously defined JPA vendor adapter -->
    		<property name="jpaVendorAdapter" ref="jpaVendorAdapter" />
    		<!-- Spring will try to automatically register DAO and domain objects to into a default persistence unit of JPA, acording to the value defined -->
    		<property name="packagesToScan" value="ie.i2e2.greenmode.dal" />
    	</bean>
    	
    	<!-- Adds an advisor to any bean that’s annotated with @Repository so that any platform-specific exceptions are caught and then rethrown as one of Spring’s unchecked data access exceptions -->
    	<bean class="org.springframework.orm.hibernate3.HibernateExceptionTranslator"/>
    FlowScoped PersistenceContext is working fine inside web flows, so I don't get a LazyInitializationException when calling lazy initialized objects. I would like to have the same behavior in pages rendered from a standard Spring MVC controller.

    Isn't it working for me because I am mixing MVC and SWF? Or maybe the reason is that I am using a transaction manager instead of a the EntityManagerFactory directly, that is what the OpenEntityManagerInViewFilter requires for its initialization?

    Lots of questions come to my mind and I am driving crazy trying to finde the proper way of configuring my scenario.

    Any ideas?

    Thanks in advance guys!

  2. #2

    Default

    Hi again,

    I have just realized that open entity in view works fine for MVC controllers if I configure the OpenEntityManagerInViewFilter this way;

    Code:
    	<filter>
    		<filter-name>oemInViewFilter</filter-name>
    		<filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
    		<init-param>
    			<param-name>entityManagerFactoryBeanName</param-name>
    			<param-value>entityManagerFactory</param-value>
    		</init-param>
    	</filter>
    	
    	<filter-mapping>
    		<filter-name>oemInViewFilter</filter-name>
    		<url-pattern>/*</url-pattern>
    	</filter-mapping>
    The difference the URL pattern; befor was "/" and now is "/*". The problem is that with this configuration any SWF flow no longer works, getting the next exception:

    Code:
    java.lang.IllegalStateException: No value for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@59a04a1b] bound to thread [http-8080-3]
    	at org.springframework.transaction.support.TransactionSynchronizationManager.unbindResource(TransactionSynchronizationManager.java:209)
    	at org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter.doFilterInternal(OpenEntityManagerInViewFilter.java:153)
    	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    	at java.lang.Thread.run(Thread.java:680)
    Another possibility I have tried is to removing the FlowScoped PersistenceContext configuration and the result is that flows are working but I get a LazyInitializationException if a lazy initialized object is retrieved from inside the flow.

    The question is: Is not possible to have the open session in view behavior both in Spring MVC controllers and SWF? If its possible, which is my mistake?

    Thanks.

  3. #3
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,629

    Default

    There is quite a difference between the to it isn't both OpenSessionInView but rather OpenEntityManagerInView and OpenEntityManagerInConversation the behaviors are quite different. The problem is that the filter is invoked always and this eagerly associates a entity manager with the current thread and as such that basically breaks the OpenEntityManagerInConversation because there is already one bound.

    A solution would be to instead of using the filter to use the interceptor and only attach it to the HandlerMapping that needs it (so basically everything but the FlowHandlerMapping).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  4. #4

    Default

    Marten Deinum,

    Thanks a lot for your prompt answer, that makes senses.

    Yeah, you are completely right, there are notable nuances between OpenSessionInView, OpenSessionInView and OpenEntityManagerInConversation.

    I took into consideration the option of using the interceptor instead of the filter, but I believe have read that the use of the filter is recommended over the interceptor. Isn't it?

    Anyway I will try it!

    Another probably option would be the one discussed in http://forum.springsource.org/showth...-Webflow/page2. What do you think?

    Regards.
    Last edited by alejandrogarciaseco; Jul 27th, 2012 at 09:35 AM.

  5. #5

    Default

    I have tried the interceptor but the result is the same than the case when I configure both the OpenEntityManagerInViewFilter and the FlowScoped PersistenceContext:

    Code:
    java.lang.IllegalStateException: No value for key [org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean@248a9705] bound to thread [http-8080-2]
    	at org.springframework.transaction.support.TransactionSynchronizationManager.unbindResource(TransactionSynchronizationManager.java:209)
    	at org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor.afterCompletion(OpenEntityManagerInViewInterceptor.java:107)
    	at org.springframework.web.servlet.handler.WebRequestHandlerInterceptorAdapter.afterCompletion(WebRequestHandlerInterceptorAdapter.java:68)
    	at org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletion(DispatcherServlet.java:1241)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:968)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
    	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
    	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
    	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
    	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
    	at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
    	at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
    	at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
    	at java.lang.Thread.run(Thread.java:680)
    My interceptor is configured this way:

    Code:
    	<mvc:interceptors>
    		<bean id="openEntityManagerInViewInterceptor" class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor">
    			<property name="entityManagerFactory" ref="entityManagerFactory" />
    		</bean>
    	</mvc:interceptors>
    is that correct?

    Thank you.

    Regards.

  6. #6
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,629

    Default

    You have now basically the same setup your interceptor is invoked for every handler mapping including the web flow one. YOu should configure it in such a way that it only is configured for the HandlerMapping that detects the (@)Controllers.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  7. #7

    Default

    Yep, thats it.

    Now the question would be how to configure the OpenEntityManagerInViewInterceptor in that way... I am currently trying to find out the way of making it either detect only the controllers annotated with @Controller or just ignore the web flow's handler. Does anybody has idea?

    Thanks.

    Regards.

  8. #8
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,629

    Default

    You would have to manually add the HandlerMappings needed (probably RequestMappingHandlerMapping and FlowHandlerMapping and only register it with the RequestMapping one).
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

  9. #9

    Default

    Hi Marten,

    I was looking for information about you mentioned in your last post. Do you mean doing something like this?:

    Code:
    	<bean id="handlerMapping" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping">
    		<property name="interceptors">
    			<bean id="openEntityManagerInViewInterceptor" class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor">
    				<property name="entityManagerFactory" ref="entityManagerFactory" />
    			</bean>
    		</property>
    	</bean>
    I understand that what I should do is register manually the RequestMappingHandlerMapping in order to defining only for this one the OpenEntityManagerInViewInterceptor. I guess that there is nothing to do with the FlowHandlerMapping so I leave declared it as it was initially:

    Code:
    	<!-- The FlowHandlerMapping helps DispatcherServlet to knowing that it should send flow requests to Spring Web Flow -->
    	<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
    		<property name="flowRegistry" ref="flowRegistry" />
    	</bean>
    Even doing what I have described above it doesn't work. Am I wrong? Is there something else missing?

    Thanks.

    Regards.

  10. #10
    Join Date
    Jun 2006
    Location
    The Netherlands
    Posts
    13,629

    Default

    Something like that should work, make sure that you remove the mvc:interceptors and the filter.

    Also if you are using the mvc:annotation-driven you also need to use the correct name for the RequestMappingHandlerMapping (else you might end up with 2 instances as the mvc namespace also registers one). I don't recall the name (you can look in the debug log and find the generated name for the bean and copy paste it). Either that or do a full manual configuration of the mvc:annotation-driven.
    Marten Deinum
    Java Consultant / Pragmatist / Open Source Enthousiast / Author


    Pro Spring MVC: With Web Flow
    Conspect

    Have you read the reference guide.
    Use the [ code ] tags, young padawan

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •