3 Replies Latest reply on Mar 1, 2008 5:48 PM by youngm

    Seam and Spring integration with proxied beans

    davidintx.david.dsheth.com

      I looked at the two ways to share a hibernate session between spring and seam--configure it in spring and use it in seam, or configure it in seam and use it in spring.  I chose the former, because I have other spring beans that need a spring configured data source. 


      However, when I attempt to start the application, I get the following error:



      java.lang.IllegalArgumentException: value of context variable is not an instance of the component bound to the context variable: serviceEntities

      I've searched for other people with this error, and it seems to come up when they have a seam project that is hot deployed, and thus have old jars lying around, or they have a seam component with the same name as a jsp variable, neither of which applies here. I'm thinking that the underlying issue is that the serviceEntities bean is actually a proxied bean, wrapped in order to provide transaction management, and that somehow throws off the seam/spring integration.  Does anyone know if that indeed the case, and if so, is there a known workaround?


      Here's the bean configuration:


        <bean id="serviceEntities" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <seam:component/>
          <property name="transactionManager">
            <ref bean="transactionManager"/>
          </property>
          <property name="proxyInterfaces">
            <value>com.company.IEntitiesService</value>
          </property>
          <property name="proxyTargetClass">
              <value>true</value>
          </property>
          <property name="target">
            <bean class="com.company.service.entities.HibernateEntitiesService">
              <property name="sessionFactory">
                <ref bean="sessionFactory"/>
              </property>
            </bean>
          </property>
          <property name="transactionAttributes">
            <props>
              <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
          </property>
        </bean>




      and here's the components.xml


      <?xml version="1.0" encoding="UTF-8"?>
      <components xmlns="http://jboss.com/products/seam/components"
                  xmlns:core="http://jboss.com/products/seam/core"
                  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                  xmlns:persistence="http://jboss.com/products/seam/persistence" 
                  xmlns:spring="http://jboss.com/products/seam/spring"
                  xmlns:transaction="http://jboss.com/products/seam/transaction"
                  xsi:schemaLocation=
                      "http://jboss.com/products/seam/core http://jboss.com/products/seam/core-2.0.xsd
                       http://jboss.com/products/seam/spring http://jboss.com/products/seam/spring-2.0.xsd
                       http://jboss.com/products/seam/components http://jboss.com/products/seam/components-2.0.xsd
                       http://jboss.com/products/seam/transaction http://jboss.com/products/seam/transaction-2.0.xsd
                       http://jboss.com/products/seam/persistence http://jboss.com/products/seam/persistence-2.0.xsd">
                        <core:init transaction-management-enabled="true" debug="true"/>
          <core:manager conversation-timeout="120000"
                        concurrent-request-timeout="500"
                        conversation-id-parameter="k"/>
          <spring:context-loader>
              <spring:config-locations>
              <value>/WEB-INF/spring-dbContext.xml</value>
              <value>/WEB-INF/spring-serviceContext.xml</value>
              <value>/WEB-INF/spring-cacheContext.xml</value>
              <value>/WEB-INF/spring-schedulerContext.xml</value>
              <value>/WEB-INF/spring-acegiContext.xml</value>
              </spring:config-locations>
          </spring:context-loader>
          <persistence:managed-hibernate-session name="seamManagedHibernateSession" auto-create="true" session-factory="#{sessionFactory}"/>
          <transaction:hibernate-transaction session="#{seamManagedHibernateSession}"/> 
      </components>
      

        • 1. Re: Seam and Spring integration with proxied beans
          keithnaas

          Are you able to run your application in debug mode and set a breakpiont on the line where this is thrown?



          private static Object getInstance(String name, boolean create, Object result) {
              .....
                         throw new IllegalArgumentException( "value of context variable is not an instance of the component bound to the context variable: " + name  +
                                  ". If you are using hot deploy, you may have attempted to hot deploy a session or " +
                                  "application-scoped component definition while using an old instance in the session.");
              ....
          }




          There are two variables to examine while in the breakpoint: result and component.  What Class is component.getBeanClass() and what Class is result?  If the types appear to be the same, the next thing to check is to make sure their ClassLoader's are compatible.  What is component.getBeanClass().getClassLoader() and result.getClassLoader()? 


          • 2. Re: Seam and Spring integration with proxied beans
            davidintx.david.dsheth.com

            Thanks for the input.  I ran it under a debugger, and found out the following:


            component.getBeanClass shows a class of org.springframework.transaction.interceptor.TransactionProxyFactoryBean


            result shows a class of HibernateEntitiesService_$$_javassist_2


            I'm guessing that the component.getBeanClass should probably be returning the proxied version of the targeted spring bean, instead of the TransactionProxyFactoryBean, and because it's not, I'm seeing the error.


            This seems like it might be something to put in jira, as an enhancement request to the ioc functionality, to let it work with proxied beans.

            • 3. Re: Seam and Spring integration with proxied beans
              youngm

              In this case I believe you need to specify the class attribute in seam:component:


              seam:component Docs


              As a side note I noticed that you're using Hibernate transactions (transaction:hibernate-transaction) configured in Seam but attempting to also use Spring Transactions in Spring.  You might run into transaction mismatch problems.  Review the section on Spring managed transactions and persistence contexts in the manual and make sure you have spring persistent/transactions and seam persistence/transactions configured correctly.


              Mike