Announcement Announcement Module
Collapse
No announcement yet.
OpenEntityManagerInViewFilter not working Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 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
    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.

    Comment


    • #3
      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).

      Comment


      • #4
        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, 09:35 AM.

        Comment


        • #5
          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.

          Comment


          • #6
            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.

            Comment


            • #7
              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.

              Comment


              • #8
                You would have to manually add the HandlerMappings needed (probably RequestMappingHandlerMapping and FlowHandlerMapping and only register it with the RequestMapping one).

                Comment


                • #9
                  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.

                  Comment


                  • #10
                    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.

                    Comment


                    • #11
                      Yes, I removed the mvc:interceptors tag for avoiding conflicts, anyway thanks for the tip.

                      I am using mvc:annotation-driven just for avoiding a full manual configuration, I am not sure if it could be a discouraged practice... So I am trying to look for the way of customizing the mvc:annotation-driven configuration. One option could be defining the RequestMappingHandlerMapping with the proper name according to the bean created by the mvc:annotation-driven, as you said; at the moment I wasn't able to find that bean name in the application's log using DEBUG and TRACE logging levels.

                      Now I am looking for a solution like this: http://scottfrederick.blogspot.com/2...nnotation.html

                      Any idea?

                      Thanks.

                      Comment


                      • #12
                        Well it seems that in cases of needing to customize the configuration provided by mvc:interceptors, it is recommended the usage of a BeanPostProcessor, I have read the same here: http://vard-lokkur.blogspot.com/2010...g-default.html

                        What do you think Marten? Does it make sense for you?

                        Thanks

                        Regards.

                        Comment


                        • #13
                          I didn't work neither, this was the set up:
                          • Bean post processor's code:
                          Code:
                          package ie.i2e2.greenmode.web.configuration;
                          
                          import org.springframework.beans.BeansException;
                          import org.springframework.beans.factory.config.BeanPostProcessor;
                          import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor;
                          import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
                          
                          public class MvcConfigurationPostProcessor implements BeanPostProcessor {
                          
                          	private OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor;
                          	
                          	@Override
                          	public Object postProcessAfterInitialization(Object bean, String beanName)
                          			throws BeansException {
                          		if (bean instanceof RequestMappingHandlerMapping) {
                          			Object [] interceptors = new Object [1];
                          			interceptors [0] = openEntityManagerInViewInterceptor;
                          			
                          			((RequestMappingHandlerMapping) bean).setInterceptors(interceptors);
                          		}
                          		
                          		return bean;
                          	}
                          
                          	@Override
                          	public Object postProcessBeforeInitialization(Object bean, String beanName)
                          			throws BeansException {
                          		return bean;
                          	}
                          
                          	public OpenEntityManagerInViewInterceptor getOpenEntityManagerInViewInterceptor() {
                          		return openEntityManagerInViewInterceptor;
                          	}
                          	public void setOpenEntityManagerInViewInterceptor(
                          			OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor) {
                          		this.openEntityManagerInViewInterceptor = openEntityManagerInViewInterceptor;
                          	}
                          
                          }
                          • Corresponding Spring configuration:
                          Code:
                          	<bean id="openEntityManagerInViewInterceptor" class="org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor">
                          		<property name="entityManagerFactory" ref="entityManagerFactory" />
                          	</bean>
                          	
                          	<bean id="mvcConfigurationPostProcessor" class="ie.i2e2.greenmode.web.configuration.MvcConfigurationPostProcessor">
                          		<property name="openEntityManagerInViewInterceptor" ref="openEntityManagerInViewInterceptor" />
                          	</bean>
                          At the moment I give up, I cannot spend more time on this...

                          If anybody has any clue please make me know, thank you for your help Marten.

                          Regards.

                          Comment

                          Working...
                          X