Announcement Announcement Module
Collapse
No announcement yet.
Getting JDK-proxy instead of cglib-proxy when not in appserver Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Getting JDK-proxy instead of cglib-proxy when not in appserver

    Dear all,

    I'm having an issue with a transactional class and <tx:annotation-driven transaction-manager="transactionManager"/>. The class does not implement any interfaces and thus should be proxied by cglib. This works as expected when running in JBoss, but I'm getting a JDKProxy when the JUnit tests run standalone. I'm using a slightly different setup (spring pitchfork) for the local tests so it's propably due to some configuration problems, but I can't spot any important differences.
    Of course I could create an interface (and it would be even a good idea), but first I want to understand the issue.
    I also tried proxy-target-class="true" which should force cglib proxied, but I'm still getting a JDKProxy (and a classcast exception in the consecution).

    The relevant part of the config should be:
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionM anager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>
    <bean id="MyBean" class="xxx.MyBean">
    <property name="datasource" ref="dataSource"/>
    </bean>

    MyBean inherits directly from Object.
    The logging output says:
    ...
    Bytecode provider name : cglib
    ...
    Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyC reator'
    Creating instance of bean 'org.springframework.aop.config.internalAutoProxyC reator' with merged definition [Root bean: class [org.springframework.aop.framework.autoproxy.Infras tructureAdvisorAutoProxyCreator]; scope=singleton; abstract=false; lazyInit=false; autowireCandidate=true; autowireMode=0; dependencyCheck=0; factoryBeanName=null; factoryMethodName=null; initMethodName=null; destroyMethodName=null]
    Eagerly caching bean 'org.springframework.aop.config.internalAutoProxyC reator' to allow for resolving potential circular references
    adding interceptors for proxyTargetClass=true; optimize=false; opaque=false; exposeProxy=false; frozen=false
    ...
    Adding transactional method [setYYY] with attribute [PROPAGATION_REQUIRES_NEW,ISOLATION_DEFAULT]
    Creating JDK dynamic proxy: target source is SingletonTargetSource for target object [xxx.MyBean@25ab07]

    Any idea why I'm not getting a cglib proxy?

    Thanks,
    Stefan

  • #2
    Change the returned element to Object (to eliminate the class cast exception) and try to see what interfaces does the instance implement:
    Code:
    Object myObject = (Object) context.getBean("mybean");
    for (int i = 0; i < myObject .getClass().getInterfaces().length; i++) {
    		    Object interface = myObject .getClass().getInterfaces()[i];
    		    System.out.println(interface );
    		}

    Comment


    • #3
      Standalone JUnit:
      interfaces=[interface org.springframework.jee.intercept.__ProxyControl, interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised]
      superclass=class java.lang.reflect.Proxy

      In JBoss:
      interfaces=[interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised, interface net.sf.cglib.proxy.Factory]
      superclass=class xxx.MyBean

      I forgot to mention that I'm using Spring 2.5 if that matters.

      Comment


      • #4
        Something interferes with Pitchfork (note org.springframework.jee.intercept.__ProxyControl).
        Please, post a test case reproducing the problem.

        Comment


        • #5
          (Sorry that I couldn't answer earlier)
          The trouble start when JeeEjbBeanFactoryPostProcessor is enabled.
          A sketch for a test case looks like that:
          Code:
          public class Main {
          	public static void main(String[] args) throws Exception {
          		ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("config.xml");
          		Object obj = ctx.getBean("TestBean");
          		System.out.println("interfaces="+Arrays.toString(obj.getClass().getInterfaces()));
          		System.out.println("superclass="+obj.getClass().getSuperclass());
          		System.out.println("superclass = "+obj.getClass().getSuperclass().getName());
          		TestBean tb = (TestBean)obj;
          	}
          }
          
          @Stateless
          @Local(Test.class)
          public class TestBean implements Test {
          	@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
          	public void sayHello() {
          		System.out.println("I say hello");
          	}
          }
          
          public interface Test {
          	public void sayHello();
          }
          
          <beans>
          	<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
          
          	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
          		<property name="entityManagerFactory" ref="entityManagerFactory" />
          	</bean>
          
          	<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
          		<property name="persistenceUnitName" value="test" />
          		<property name="persistenceXmlLocation" value="classpath:/META-INF/persistence-test.xml" />
          	</bean>
          
          	<bean id="TestBean" class="test.TestBean"/>
          </beans>
          As soon as you add <bean class="org.springframework.jee.ejb.config.JeeEjbBe anFactoryPostProcessor" /> to the xml config the superclass is java.lang.reflect.Proxy and no longer TestBean. Looks like a bug in pitchfork to me.

          Comment


          • #6
            I think the following replacement for the TestBean shows the issue better. The usage of an EJB component is not necessary (and you definitely should use the interface in those cases...):
            Code:
            public class TestBean  {
            	@Transactional(propagation=Propagation.MANDATORY)
            	public void sayHello() {
            		System.out.println("I say hello");
            	}
            }
            Without the JeeEjbBeanFactoryPostProcessor you get:
            interfaces=[interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised, interface net.sf.cglib.proxy.Factory]
            superclass=class test.TestBean

            And with it enabled you get:
            interfaces=[interface org.springframework.jee.intercept.__ProxyControl, interface org.springframework.aop.SpringProxy, interface org.springframework.aop.framework.Advised]
            superclass=class java.lang.reflect.Proxy

            Comment

            Working...
            X