|
From: aussiestaceus <aus...@ya...> - 2007-01-25 14:04:12
|
I am having a very peculiar problem and I was hoping all the Spring Gurus would have a simple answer for it. Problem: Transactions are not run properly when service is called as bean in the DispatcherServlet. Therefore no transaction checks are done on my hibernate-dao calls. Here are my config files: 1-applicationContext.xml [CODE]<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <!-- - Application context definition for Express on Hibernate. --> <beans> <bean id="exampleDataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName"><value>org.apache.derby.jdbc.EmbeddedDriver</value></property> <property name="url"><value>jdbc:derby:springexample;create=true</value></property> </bean> <bean id="exampleHibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="properties"> <props> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.dialect">net.sf.hibernate.dialect.DerbyDialect</prop> <prop key="hibernate.query.substitutions">true 'T', false 'F'</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.c3p0.minPoolSize">5</prop> <prop key="hibernate.c3p0.maxPoolSize">20</prop> <prop key="hibernate.c3p0.timeout">600</prop> <prop key="hibernate.c3p0.max_statement">50</prop> <prop key="hibernate.c3p0.testConnectionOnCheckout">false</prop> </props> </property> </bean> <!-- Hibernate SessionFactory --> <bean id="exampleSessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"><ref local="exampleDataSource"/></property> <property name="hibernateProperties"> <ref bean="exampleHibernateProperties" /> </property> <!-- Must references all OR mapping files. --> <property name="mappingResources"> <list> <value>Customer.hbm.xml</value> <value>Account.hbm.xml</value> </list> </property> </bean> <!-- Pass the session factory to our UserDAO --> <bean id="customerDAOTarget" class="springexample.hibernate.CustomerDAOImpl"> <property name="sessionFactory"><ref local="exampleSessionFactory"/></property> </bean> <bean id="transactionManager" class="org.springframework.orm.hibernate.HibernateTransactionManager"> <property name="sessionFactory"><ref bean="exampleSessionFactory"/></property> </bean> <bean id="userService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"><ref local="transactionManager"/></property> <property name="target"><ref local="customerDAOTarget"/></property> <property name="transactionAttributes"> <props> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="save*">PROPAGATION_REQUIRED</prop> <prop key="update*">PROPAGATION_REQUIRED</prop> <prop key="delete*">PROPAGATION_REQUIRED</prop> <prop key="search*">PROPAGATION_REQUIRED,readOnly</prop> <prop key="find*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean> </beans> [/CODE] 2-webapp-servlet.xml [CODE]<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping[COLOR="Red"][/COLOR]"> <property name="mappings"> <props> <prop key="/userService.rpc">userService</prop> </props> </property> </bean> </beans> [/CODE] [COLOR="Red"]As you can see I am refrencing the 'userService' bean from my applicationContext in my DispatcherServlet. The reason for doing this is so I can make RPC calls straight to the server over HTTP. Furthermore I want to avoid the need to make a controller class that makes simple pass-thru calls to my userService, especially when there is no need.(i.e UserLogic userService = (UserLogic)WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()).getBean("userService");[/COLOR] 3-web.xml [CODE]<?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd"> <web-app> <servlet> <servlet-name>webapp</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>webapp</servlet-name> <url-pattern>*.rpc</url-pattern> </servlet-mapping> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!--Hibernate Filter --> <filter> <filter-name>hibernateFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> </filter> <!--Hibernate Mapping--> <filter-mapping> <filter-name>hibernateFilter</filter-name> <url-pattern>*.rpc</url-pattern> </filter-mapping> </web-app> [/CODE] Ok so after loads of testing I have figured out for the transactions to work, I cant just reference the bean in the DispatcherServlet config file. I have to get the bean from the context, specifically I need to have <UserLogic userService =(UserLogic)WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext()).getBean("userService")>. Otherwise you start getting the following errors because Spring doesn't invoke AOP transactions for the method being called. [CODE]org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into FlushMode.AUTO or remove 'readOnly' marker from transaction definition[/CODE] So any ideas as far as referncing the service from the applicationContext and still have the TransactionProxyFactoryBean work as intended. Any help is greatly appreciated -- View this message in context: http://www.nabble.com/spring-hibernate-integration-with-DispatcherServlet-tf3108991.html#a8618523 Sent from the springframework-developer mailing list archive at Nabble.com. |