Announcement Announcement Module
Collapse
No announcement yet.
Multiple Hibernate Entity Interceptors? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multiple Hibernate Entity Interceptors?

    Hello.

    I'm trying to set up two different Entity Interceptors for hibernate using the LocalSessionFactoryBean. It seems that the LocalSessionFactoryBean only allows for one interceptor. Can I use the ProxyFactoryBean to add more? I currently have the following setup:

    <bean id="catalogDS" class="org.springframework.jndi.JndiObjectFactoryB ean">
    <property name="jndiTemplate">
    <ref bean="wlJndiTemplate"/>
    </property>
    <property name="jndiName">
    <value>${jndi.appname}/Catalog</value>
    </property>
    </bean>

    <bean id="CatalogTransactionManager" class="org.springframework.orm.hibernate.Hibernate TransactionManager">
    <property name="sessionFactory">
    <ref local="com.stormhq.entity.CatalogSessionFactory"/>
    </property>
    </bean>

    <!-- my own hibernate interceptor for dirty entity detection -->
    <bean id="unsavedBeanInterceptor" class="com.stormhq.util.HibernateUnsavedEntityInte rceptor"/>

    <bean id="com.stormhq.entity.CatalogSessionFactory" class="org.springframework.orm.hibernate.LocalSess ionFactoryBean">
    <property name="dataSource">
    <ref bean="catalogDS"/>
    </property>
    <property name="entityInterceptor"><ref bean="unsavedBeanInterceptor"/></property>
    <property name="mappingResources">
    <list>
    <value>com/stormhq/entity/Category.hbm.xml</value>
    <value>com/stormhq/entity/ProductGroup.hbm.xml</value>
    <value>com/stormhq/entity/ProductSKUImpl.hbm.xml</value>
    <value>com/stormhq/entity/attributes/Attribute.hbm.xml</value>
    <value>com/stormhq/entity/attributes/AttributeGroup.hbm.xml</value>
    <value>com/stormhq/lookups/LookupTableImpl.hbm.xml</value>
    </list>
    </property>
    <property name="hibernateProperties">
    <props>
    <prop key="hibernate.dialect">net.sf.hibernate.dialect.O racle9Dialect</prop>
    <prop key="hibernate.show_sql">true</prop>
    </props>
    </property>
    <!-- <property name="schemaUpdate"><value>true</value></property> -->

    </bean>


    <bean id="com.stormhq.entity.dao.CategoryDao" class="org.springframework.transaction.interceptor .TransactionProxyFactoryBean">
    <property name="target"><ref local="com.stormhq.entity.dao.CategoryDAOImpl"/></property>
    <property name="transactionManager"><ref local="CatalogTransactionManager"/></property>
    <property name="transactionAttributes">
    <props>
    <prop key="add*">PROPAGATION_REQUIRED</prop>
    <prop key="update*">PROPAGATION_REQUIRED</prop>
    <prop key="load*">PROPAGATION_REQUIRED</prop>
    </props>
    </property>
    </bean>


    Thank you.

  • #2
    Hibernate SessionFactory allows for using only one entityInterceptor per session.
    If you need to use two entityInterceptors, I suppose they are mutually exclusive so they are not to be used with the same session as Hibernate states, you can create and register a generic entityInterceptor that proxy your base interceptors depending on the usecase.

    Comment


    • #3
      Thanks for the reply.

      They are mutually exclusive, but which interceptor is chosen is determined by the type of entity being used by hibernate and the method call being used. I have 1 interceptor which is used to determine if an entity is saved or not (overrides onSave() and isUnsaved() ) and another one for proxying object creation which overrides instantiate(). I could combine these two since they don't conflict with eachother but that would not be a very elegant solution.


      So you're suggesting that I should create a 3rd object which programatically passes off control to one of the existing interceptors? That would work, but it also seems like a closed solution. Adding new interceptors would require code changes which I'd like to avoid. ProxyFactoryBean allows for a list of interceptors to be registered, but I'm not sure if that could somehow be wrapped around the LocalSessionFactoryBean.

      Comment


      • #4
        but which interceptor is chosen is determined by the type of entity being used by hibernate and the method call being used
        just wondering, how do you manage this when using Hibernate without Spring?

        Comment


        • #5
          Originally posted by irbouho
          but which interceptor is chosen is determined by the type of entity being used by hibernate and the method call being used
          just wondering, how do you manage this when using Hibernate without Spring?
          I haven't tried it without spring.

          Comment


          • #6
            AFAIK, Hibernate SessionFactory allows for using only one entityInterceptor per session.
            Code:
               Session openSession&#40;Connection connection, Interceptor interceptor&#41;;
            
               Session openSession&#40;Interceptor interceptor&#41;;

            Comment


            • #7
              A Session can only have one entity interceptor, so indeed, if you need more, with or without Spring, you need some sort of mechanism (such as a wrapper) that delegates to one or another...

              Comment


              • #8
                Originally posted by Colin Sampaleanu
                A Session can only have one entity interceptor, so indeed, if you need more, with or without Spring, you need some sort of mechanism (such as a wrapper) that delegates to one or another...
                Could that wrapper be a ProxyFactoryBean? I notice that LocalSessionFactoryBean doesn't expose a getEntityInterceptor method, but HibernateTransactionManager does. Could interceptors be used to add advice to getEntityInterceptor() in HibernateTransactionManager to provide this functionality?

                Comment


                • #9
                  I don't know if you really need to use ProxyFactoryBean, since the Hibernate entity Interceptor is just an interface. The wrapper could just be a bean which implements that interfaces and takes a list of the real interceptors, and when it is invoked, delegates to the appropriate one. Ultimately it depends on how that decision is being made, which I guess is a programmatic one... ProxyFactory may help you if you actually need to get at the call context to make the decision...

                  Comment


                  • #10
                    I see how that would work, but I'm trying to think more long term where we may want to have more than just 2 interceptors and be able to wire them up using IoC instead of programmatically.

                    I guess the uber-interceptor could be wired with IoC and do this... but I was hoping there might be a pre-existing spring feature which would make it easier.

                    Comment


                    • #11
                      rmangi,

                      If I understand what you said, deciding what interceptor to use depends on the entity and method called.

                      So lets configure our interceptors as plain POJOs
                      Code:
                        <bean id="interceptor1" class="Interceptor1"/> 
                        <bean id="interceptor2" class="Interceptor2"/> 
                        ...
                      Now we create the uber-interceptor with a property of type map that holds the (entity, interceptor) pairs
                      Code:
                        <bean id="myInterceptor" class="MyInterceptor">
                          <property name="interceptors">
                            <entry key="entity1"> 
                             <value>interceptor1</value>
                            </entry> 
                            <entry key="entity2"> 
                             <value>interceptor2</value>
                            </entry> 
                          <property>
                        </bean>
                      myInterceptor will lookup the interceptor to be used for each call using the interceptors map:

                      Code:
                        public class MyInterceptor implements Interceptor, Serializable &#123;
                      
                          private map interceptors;
                          //getters and setters
                      
                          ...
                      
                          public void onDelete&#40;Object entity,
                                               Serializable id,
                                               Object&#91;&#93; state,
                                               String&#91;&#93; propertyNames,
                                               Type&#91;&#93; types&#41; &#123;
                              Interceptor interceptor = resolveInterceptor&#40;entity&#41;;
                              if &#40;interceptor != null&#41;
                                interceptor.onDelete&#40;entity, id, state, propertynames, types&#41;;
                          &#125;
                      
                          ...
                      
                          //interceptor resolver
                          private Interceptor resolveInterceptor&#40;Object entity&#41; &#123;
                            //uses property interceptors, if not found returns null
                            ...
                            return interceptor;
                          &#125;
                        &#125;
                      I did not try this solution before, but It seems extensible.

                      Comment


                      • #12
                        Yes, that's pretty much where I'm headed right now. I'd like it to be smart enough to be aware of which methods a particular interceptor is overriding to avoid extra method calls (although they would be quick if they just return null). I'd also like it to be able to call two interceptors in the case where there may be more than 1 interceptor interested in a particular method call (not currently the case, but in the interest of the best possible solution...)

                        None of this is rocket science, it just seems like a duplication of a lot of the functionality offered in other packages in spring, but not available for the hibernate entity interceptors. That's really my reason for asking about this.

                        Thanks,

                        Rick

                        Comment


                        • #13
                          This may be useful:
                          http://www.hibernate.org/92.html
                          http://wiki.opensymphony.com/display...ng+Interceptor

                          Comment


                          • #14
                            Thanks. Good to see others have thought about this problem.

                            Comment

                            Working...
                            X