Announcement Announcement Module
Collapse
No announcement yet.
@Transactional and OSIV configuration Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • @Transactional and OSIV configuration

    Cannot get @Transactional to work with OSIV configuration

    I have been struggling with this for two days, pouring over the forums and now feel as if I'm chasing my tail.
    I have a CRUD application that uses Spring 2.5, Hibernate 3.
    I have been using the OSIVInterceptor with flushModeName="FLUSH_AUTO", and singleSession="true". Most of the controllers extend SimpleFormController and have the property sessionForm=true.

    I recently discovered that having the sessionForm = true was causing data issues when the users toggle between two tabs in one browser. This issue is documented here in the API for AbstractFormController.
    So my next attempt to solve the issue was to set sessionForm to the default value, sessionForm = false.
    However, on Submit, the Hibernate session would flush the session and save the "dirty" command object even if validation failed, sometimes causing
    a SQLException(for instance an empty field). This is discussed in this forum post.

    So I've been trying to figure out the best practice for OSIV or just something that will work for my project.
    What I came up with from reading the forum and various blogs (no official examples here for OSIV and transactions) is that I need to have sessionForm=false for Controllers to eliminate the data issues.
    Furthermore, for the OSIV config, I need to set FLUSH_MODE="NEVER" to prevent the auto Hibernate flush on validation failure. I'd also like to keep the singleSession = "true" as I think this might minimize some code refactoring in my project.

    Since I'm setting the flush mode to never, I now need to implement transactions at a more granular level, the service level, which I had not been doing but instead relying on the FLUSH_MODE=AUTO to close the transaction at the end of the request. This is where I am running into an issue.

    I have added the <tx:annotation-driven/> line to my application-context.xml. I have also added @Transactional to all of my service level managers
    at the class level.

    I keep seeing similar errors to this upon application startup:
    Code:
    2009-10-13 17:15:12,542 [FrameworkServlet.java:244] ERROR  - Context initialization failed
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lessonController' defined in ServletContext resource [/WEB-INF/lp-servlet.xml]: Cannot resolve reference to bean 'lpUtilities' while setting bean property 'lpUtilities'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'lpUtilities' defined in ServletContext resource [/WEB-INF/lp-servlet.xml]: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (6) are:
    PropertyAccessException 1: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.IpgManager] for property 'ipgManager'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.IpgManager] for property 'ipgManager': no matching editors or conversion strategy found
    PropertyAccessException 2: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.ConceptManager] for property 'conceptManager'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.ConceptManager] for property 'conceptManager': no matching editors or conversion strategy found
    PropertyAccessException 3: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.UnitManager] for property 'unitManager'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.UnitManager] for property 'unitManager': no matching editors or conversion strategy found
    PropertyAccessException 4: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.ArcManager] for property 'arcManager'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.ArcManager] for property 'arcManager': no matching editors or conversion strategy found
    PropertyAccessException 5: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.LessonManager] for property 'lessonManager'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy6] to required type [org.schoolsys.lp.service.managers.LessonManager] for property 'lessonManager': no matching editors or conversion strategy found
    PropertyAccessException 6: org.springframework.beans.TypeMismatchException: Failed to convert property value of type [$Proxy8] to required type [org.schoolsys.lp.service.managers.StageManager] for property 'stageManager'; nested exception is java.lang.IllegalArgumentException: Cannot convert value of type [$Proxy8] to required type [org.schoolsys.lp.service.managers.StageManager] for property 'stageManager': no matching editors or conversion strategy found
    	at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:274)
    Why can I not inject my managers into the LPUtilities class?
    It is not a Controller class but that shouldn't matter right?



    Will post the relevant configuration details in separate post as this was too long for one post.
    Last edited by litmusunit; Oct 14th, 2009, 11:59 AM. Reason: more information

  • #2
    Followup with Config Files...

    lp-servlet.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
    		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
    		http://www.springframework.org/schema/context 
            http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    <!-- NEW CONTROLLERS -->
    
    	
    	<bean id="lessonController" class="org.schoolsys.lp.web.controllers.LessonController">
    		<property name="lessonManager" ref="lessonManager"/>
    		<property name="lpUtilities" ref="lpUtilities"/>
    		<property name="editableFormView" value="lesson/lessonDetail"/>
    		<property name="readOnlyFormView" value="lessonV"/>
    		<property name="successView" value="lesson/lessonDetail"/>
    		<property name="sessionForm" value="false"/>
    		<!-- <property name="bindOnNewForm" value="true"/> -->
    		<property name="validator" ref="lessonValidator"/>
    	</bean>
    ...numerous other controllers
    <!-- END NEW CONTROLLERS -->
    
    	<bean id="lpUtilities" class="org.schoolsys.lp.utilities.LPUtilities">
    		<property name="ipgManager" ref="ipgManager"/>
    		<property name="conceptManager" ref="conceptManager"/>
    		<property name="unitManager" ref="unitManager"/>
    		<property name="arcManager" ref="arcManager"/>
    		<property name="lessonManager" ref="lessonManager"/>
    		<property name="stageManager" ref="stageManager"/>
    		<property name="dropdownDao" ref="dropdownCategoryDao"/>
    	</bean>
    
        	<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
            <property name="interceptors">
                <list>
                    <ref bean="openSessionInViewInterceptor" />
                </list>
            </property>
    	<property name="mappings">
                  ...mappings here...
            </property>
    	<property name="order"><value>0</value></property>
    	</bean>
    <!-- NOTE!!! The ResourceBundleViewResolver(for Velocity) HAS to be BEFORE InternalResourceViewResolver(for JSP). See Spring documentation for details -->
    <bean id="velocityConfig" class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
      <property name="resourceLoaderPath" value="/WEB-INF/velocity/"/>
      <property name="velocityProperties">
        <props>
          <prop key="velocimacro.library">/utilities/macros.vm</prop>
        </props>
      </property>
    </bean>	
    <bean id="velocityViewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
      <property name="basename" value="views"/>
    </bean>
    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
            <property name="prefix" value="/WEB-INF/jsp/"></property>
            <property name="suffix" value=".jsp"></property>
    </bean>
        
        
    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
            <property name="basename"><value>messages</value></property>
    </bean>  
    <!-- END MAIN SPRING CONFIG -->
    </beans>
    application-context.xml
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-2.0.xsd
           http://www.springframework.org/schema/tx 
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    
        ....dwr config...
        ...compass config...
        
        	<!-- MANAGERS SECTION -->
    ...more managers here....	
    	
    	<bean id="lessonManager" class="org.schoolsys.lp.service.managers.LessonManager">
    	<property name="lessonDao" ref="lessonDao"/>
    	<property name="ipgDao" ref="ipgDao"/>
    	<property name="arcDao" ref="arcDao"/>
    	<property name="assessmentDao" ref="assessmentDao"/>
    	<property name="stageDao" ref="stageDao"/>
    	<property name="resourceDao" ref="resourceDao"/>
    	<property name="lessonTeksDao" ref="lessonTeksDao"/>
    	<property name="relatedLessonTeksDao" ref="relatedLessonTeksDao"/>
    	<property name="nonCoreLessonTeksDao" ref="nonCoreLessonTeksDao"/>
    	<property name="lessonElpsDao" ref="lessonElpsDao"/>
    	<property name="elpsStudentExpectationDao" ref="elpsStudentExpectationDao"/>
    	<property name="teksStudentExpectationDao" ref="teksStudentExpectationDao"/>
    	<dwr:remote javascript="AjaxLessonManager"></dwr:remote>
    	</bean>
    	<!-- END MANAGERS SECTION -->
    	
    	<!-- VALIDATORS -->
    	<bean id="lessonValidator" class="org.schoolsys.lp.web.validators.LessonValidator"></bean>
    	<!-- END VALIDATORS -->
    
    	<!-- DAO SECTION -->
        <bean id="lessonDao" class="org.schoolsys.lp.db.dao.LessonDao">
        	<property name="sessionFactory">
        		<ref bean="sessionFactory" />
        	</property>
        </bean>
    ...more DAOs here    
        <!-- END DAO SECTION -->
        <!-- HIBERNATE STUFF -->
        <!-- LocalSessionFactoryBean loads one or more HIbernate mapping XML files to produce a Hibernate Session Factory -->
        <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"><ref local="dataSource"/></property>
        <property name="mappingResources">
                <list>
               		<value>/orm/Lesson.hbm.xml</value>
                            ...more hbm config here....
                </list>
        </property>
        <property name="hibernateProperties">
                <props>
                    <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
                    <prop key="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</prop>
                    <prop key="hibernate.max_fetch_depth">3</prop>
                    <!-- turned off 8-09, rely on log4j generated logs instead -->
                    <prop key="hibernate.show_sql">true</prop>
                    <!-- kas 12-08 had to add next 3 lines to solve clob hanging issue(Bug 430) -->
                    <prop key="hibernate.order_updates">true</prop>
    				<prop key="hibernate.jdbc.batch_size">0</prop>
    				<prop key="hibernate.jdbc.use_scrollable_resultsets">false</prop>
    				<!-- end clob issue -->
                </props>
        </property>
        
        <property name="lobHandler"><ref bean="oracleLobHandler"/></property>
    	</bean>
    	<!-- END HIBERNATE STUFF -->
    	
    	<!-- BEGIN JDBCTEMPLATE SETUP - this should ONLY be used for READ ONLY report queries -->
    	<bean id="simpleJdbcTemplate" class="org.springframework.jdbc.core.simple.SimpleJdbcTemplate">
       		<constructor-arg><ref bean="dataSource"/></constructor-arg>
    	</bean>
    	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
       		<constructor-arg><ref bean="dataSource"/></constructor-arg>
    	</bean>
    
        <bean id="dataSource"
        	class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
        	<property name="jndiName" value="java:comp/env/jdbc/schemaname" />
    		<property name="resourceRef">
    			<value>true</value>
    		</property> 
        </bean>
      	<bean id="openSessionInViewInterceptor" class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor">
      		<property name="flushModeName">
      			<value>FLUSH_NEVER</value>
      		</property>
      		<property name="sessionFactory">
      			<ref bean="sessionFactory"/>
      		</property>
      		<property name="singleSession">
      		  		<value>true</value>
      		</property>
    
      	</bean>
    	 <!-- Transaction manager for a single Hibernate SessionFactory (alternative to JTA) -->
    	<tx:annotation-driven/>
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    		<property name="sessionFactory"><ref local="sessionFactory"/></property>
    	</bean>
    	   	<!-- NativeJdbcExtractor -->
    <bean id="nativeJdbcExtractor"
    class="org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor"
    lazy-init="true"/>
    
    <!-- LobHandler for Oracle JDBC drivers -->
    <bean id="oracleLobHandler" class="org.springframework.jdbc.support.lob.OracleLobHandler" lazy-init="true">
    <property name="nativeJdbcExtractor"><ref local="nativeJdbcExtractor"/></property>
    </bean>
    
    </beans>

    snippet from LPUtilities.java
    Code:
    package org.schoolsys.lp.utilities;
    ...more imports here...
    import org.schoolsys.lp.service.managers.ArcManager;
    import org.schoolsys.lp.service.managers.ConceptManager;
    import org.schoolsys.lp.service.managers.IpgManager;
    import org.schoolsys.lp.service.managers.LessonManager;
    import org.schoolsysd.lp.service.managers.GenericManager;
    import org.schoolsys.lp.service.managers.StageManager;
    import org.schoolsysd.lp.service.managers.UnitManager;
    
    public class LPUtilities implements LPUtilitiesInterface{
    	
    	private IpgManager mIpgMan;
    	private ConceptManager mConceptMan;
    	private UnitManager mUnitMan;
    	private ArcManager mArcMan;
    	private LessonManager mLessonMan;
    	private StageManager mStageMan;
    
    	private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(LPUtilities.class);
    ...more code here..
    	public void setIpgManager(IpgManager ipgMan) {
    		 mIpgMan = ipgMan;
    		
    	}
    
    	public void setConceptManager(ConceptManager cm) {
    		 mConceptMan = cm;
    		
    	}
    
    	public void setUnitManager(UnitManager unitMan) {
    		 mUnitMan = unitMan;		
    	}
    
    	public void setArcManager(ArcManager am) {
    		 mArcMan = am;		
    	}
    
    	public void setLessonManager(LessonManager lessMan) {
    		 mLessonMan = lessMan;		
    	}
    
    	public void setStageManager(StageManager stageMan) {
    		mStageMan = stageMan;
    	}	
    }
    Last edited by litmusunit; Oct 14th, 2009, 10:54 AM.

    Comment


    • #3
      Update...

      UPDATE: when I removed LPUtilities from the mix, I received the same error trying to inject the managers into LessonController, so it has nothing to do with LPUtilities. Also LessonManager implements a couple of
      service level interfaces. If I take out the "implements xInterface" in the LessonManager, then the initialization of the LessonController works. However, most of my Manager implement some interface so this won't work. One more hint is that if I set <tx:annotation-driven proxy-target-class="true"/> the application builds successfully but then grinds to a halt on the 2nd or 3rd page rendering.

      Wondering if this has to do with the fact that my service object I'm annotating as @Transactional implements >1 Interface....
      Last edited by litmusunit; Oct 14th, 2009, 04:55 PM.

      Comment


      • #4
        Resolution?

        a)I could not ever get @Transactional or xml configured transactions to work. My hunch is that this is due to a bug discussed here in JIRA where a Class that implements >1 Interface will not play nicely with the proxies created. If someone would like to confirm this, I would really appreciate it.

        b)I stepped back from trying to implement service level transactions, and reimplemented sessionForm=true in the Controller configs and also reset the OSIV config to flushModeName="FLUSH_AUTO", and singleSession="true", all of which had been working nicely for me before I discovered the issue of multiple tabs/windows in same browser confusing the session command objects.

        I solved the issue of two tabs/windows in one browser confusing command objects, by overriding the Spring method that sets the command name in the session Therefore if Foo1 is loaded in one window and then Foo2 is loaded in a separate window, then the user saves Foo1, the code now grabs packagename.Foo.1 instead of packagename.Foo, ensuring that the correct object is retrieved from the session. I realize this introduces a bit of memory management and we now need to be aware how many objects are getting
        created in the session. For read only objects, the objects are still loaded in as just packagename.Foo, but for editable objects I append the appropriate
        unique Key. In our system, the number of users editing vs. viewing is low so this seems plausible.

        Code in Controllers:
        Code:
        	@Override
        	protected String getFormSessionAttributeName(HttpServletRequest request) {
        	String objectId = (String)request.getParameter("id");
        	String commandName = super.getFormSessionAttributeName()+"."+objectId;
        	return commandName;
        	}

        Comment

        Working...
        X