Announcement Announcement Module
Collapse
No announcement yet.
OSIV in a non-web application Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • OSIV in a non-web application

    I recently inherited a standalone java application where the prior developer ran into trouble with LazyInitializationException. We were on a short schedule, so he opted to use lazy="false" in the .hbm files. While that allowed development to continue, it makes maintenance difficult because we also have a web application that uses the same database tables and we use the OSIV interceptor in the app-servlet.xml file. We want to use the same .hbm.xml files as much as possible for obvious reasons. Since this module is not a web application, I don't have a servlet definition file. We are using the Spring framework and have various definition files (dao, services, etc.).

    I really want to use the OSIV interceptor but don't know where to plug in the reference to its bean. Can anyone provide guidance?

    Thanks.

  • #2
    To clarify, our web application uses a reference to the bean openSessionInViewInterceptor within the 'interceptors' property of the urlMapping bean within our servlet.xml file.

    Since we don't have a servlet, we don't have url mapping, etc. How would I map this interceptor into a standalone spring application?

    Comment


    • #3
      Similar problem...

      Hey Randy. I'm having a similar problem trying to use an existing Dao proejct (that extends HibernateDaoSupport) from within a Spring-managed Quartz environment.

      There are three projects: dao, quartz, and web-admin. The web-admin project is a Spring MVC web app, that successfully uses the OSIV interceptor when interacting with the Dao. The Quartz project has no interface, and therefore cannot use OSIV. I've tried everything I can think of to replicate the behavior of the OSIV, with no luck.

      The additional complication (in my case), results from the fact that the actual Quartz Job bean is not initialized from the applicationcontext, so I can't create a org.springframework.orm.hibernate3.HibernateInterc eptor around the actual job, only around the Dao instance methods (since they are configured in context.xml).

      However, a HibernateInterceptor may work for you. Check it:
      Code:
          <!-- interceptor -->
          <bean id="hibernateInterceptor" class="org.springframework.orm.hibernate3.HibernateInterceptor">
              <property name="sessionFactory">
                  <ref bean="sessionFactory"/>
              </property>
          </bean>
      
          <!-- My class that needs a Hibernate session. -->
          <bean id="myClassThatNeedsASession" class="org.springframework.aop.framework.ProxyFactoryBean">
              <property name="proxyInterfaces">
                  <value>com.swampgas.example.MyClass</value>
              </property>
              <property name="interceptorNames">
                  <list>
                      <value>hibernateInterceptor</value>
                  </list>
              </property>
              <property name="target">
                  <bean class="com.swampgas.example.MyClassImpl">
                      <property name="hibernateTemplate">
                          <ref bean="hibernateTemplate"/>
                      </property>
                  </bean>
              </property>
          </bean>
      Then, from within your MyClassImpl, you can call any number of session-based hibernate methods without worrying about LIE (supposedly. like I said, I can't get it to work in my particular case). The sesison is opened prior to your method being executed (by the interceptor), then closed when the method completes execution.

      If you want to get fancy, you could use a org.springframework.transaction.interceptor.Transa ctionInterceptor, and wrap our methods up in a Transaction. Useful when one session-dependant class calls methods in another. Mark your methods as @Transactional, and (again, supposedly), away you go!

      Anyhoo, if you, (or anyone else) manage to get this working, let me know. LazyInit is driving me frickin' BONKERS.

      Good luck.

      Comment


      • #4
        Same problem...

        I ran into this issue as well.

        Our system is divided into two major "application" and "kernel" layers. Each layer hosts of a number of different services & components all deployed and wired together via spring. The kernel layer defines mechanism and the application layer defines policy. There is also a web-layer which calls into applications & kernel components to do configuration, monitoring..etc. At the moment, everything is running in-process.

        To promote loose coupling, we generate ApplicationEvent(s) within the kernel layer which are processed asynchronously (on different thread pool threads) up in the application layer by whoever cares about them. The event handlers often call back down into kernel services which do use @Transactional but with no outer session available, I had LIE problems. At the same time, I did not want the application level event handlers to define an outer transaction scope and I also didn't want to put REQUIRES_NEW on all service methods in the kernel layer.

        This is how the system is structured and this problem has nothing do with web interfaces or views. I wanted OSIV functionality inside the application event handlers. There are valid arguments against OSIV but I personally feel OSIV is necessary to get the full productivity benefit(s) of using an ORM in the first place.

        First, I tried annotating the event handler with
        @Transactional(propagation=Propagation.NEVER) but that didn't work. The transaction manager still didn't bind a hibernate session for me. I'm not sure why but I didn't really look into it.

        My solution also uses the HibernateInterceptor. I defined the interceptor and configured it with the same settings as the OSIV filter.


        Code:
        <bean id="hibernateSessionAdvice" class="org.springframework.orm.hibernate3.HibernateInterceptor">
        	<property name="sessionFactory"><ref local="sessionFactory"/></property>
        	 <property name="flushModeName" value="FLUSH_NEVER"/>
        	 <property name="exceptionConversionEnabled" value="false"/>
        </bean>
        Then I created a marker annotation I can stick on any method where I want the hibernate interceptor to run.

        Code:
        package com.tvrc.as.support.spring;
        
        public @interface HibernateSession {
        
        }
        I added an aop:config entry to tie the advice to any methods marked with the annotation.

        Code:
         <aop:config>
           <aop:advisor pointcut="@annotation(com.tvrc.as.support.spring.HibernateSession)" advice-ref="hibernateSessionAdvice"/>
         </aop:config>
        Finally, I just annotate event handlers where I'd like OSIV functionality.

        Code:
        @HibernateSession
        public void onApplicationEvent(ApplicationEvent arg0) {
        		//Call kernel services that define transactions
                      //Session is available to avoid LIE
        }
        Spring is creating the application event listeners and wiring them all up so everything works well.

        Comment

        Working...
        X