10

Well, i have a Class with @Service annotation and some strange occurrs: When i put the annotation @Transaction in some method i can't start tomcat server, i got error: "Can not autowired..." in another class when i use my @Autowired, but when i remove the @Transaction all works fine.

My class header is:

@Service(value = "caixaBO")
public class CaixaBOImpl extends BasicBOImpl {

And my method signature is:

@Transactional(propagation = Propagation.REQUIRED)
public void movimentarCaixaPaciente(String descricao, double valor,
        Paciente paciente) {

When i use @Autowired CaixaBOImpl caixaBO, i got error in tomcat initialized because the annotation @Transaction.

EDIT 1:

1 - I have transactionManager in applicationContext.xml, look:

<!-- Configuracao do gerente de transacoes do Spring -->
    <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="entityManagerFactory" />
    </bean>

2 - I have CGLIB in pom.xml, look:

<dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib-nodep</artifactId>
            <version>2.2.2</version>
        </dependency>

EDIT 2

My stack trace:

Grave: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'pedidoProteseBO': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.com.odontonew.financeiro.bo.CaixaBOImpl br.com.odontonew.odonto.bo.PedidoProteseBOImpl.caixaBO; nested exception is java.lang.IllegalArgumentException: Can not set br.com.odontonew.financeiro.bo.CaixaBOImpl field br.com.odontonew.odonto.bo.PedidoProteseBOImpl.caixaBO to com.sun.proxy.$Proxy36
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:288)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:293)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:290)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:192)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:895)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:425)
    at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:282)
    at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:204)
    at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
    at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4701)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5204)
    at org.apache.catalina.core.StandardContext$1.call(StandardContext.java:5199)
    at java.util.concurrent.FutureTask.run(FutureTask.java:262)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at java.lang.Thread.run(Thread.java:724)
Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private br.com.odontonew.financeiro.bo.CaixaBOImpl br.com.odontonew.odonto.bo.PedidoProteseBOImpl.caixaBO; nested exception is java.lang.IllegalArgumentException: Can not set br.com.odontonew.financeiro.bo.CaixaBOImpl field br.com.odontonew.odonto.bo.PedidoProteseBOImpl.caixaBO to com.sun.proxy.$Proxy36
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:508)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:84)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:285)
    ... 20 more
Caused by: java.lang.IllegalArgumentException: Can not set br.com.odontonew.financeiro.bo.CaixaBOImpl field br.com.odontonew.odonto.bo.PedidoProteseBOImpl.caixaBO to com.sun.proxy.$Proxy36
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:164)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:168)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:741)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:504)
    ... 22 more
Shelly
  • 1,035
  • 5
  • 27
  • 51

2 Answers2

6

There are two situations I can think of that might cause this

  1. You haven't declared a TransactionManager and therefore @Transactional advice cannot be applied.
  2. Your @Autowired target is declared as a field of type CaixaBOImpl and you don't have CGLIB libraries on your classpath for Spring to create class proxies. As such, it creates JDK Proxies which it fails to inject because the types don't match. You can get the CGLIB libraries here. Or you can change the @Autowired target field to type BasicBOImpl. This will be a problem if you are injecting other beans of type BasicBOImpl in your application without qualifying them with an id.

It seems that even though you have the CGLIB proxies, Spring is using JDK proxies anyway. Change your tx:annotation-driven declaration to

<tx:annotation-driven proxy-target-class="true" /> 
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • So, i have answer for you 2 question in my post edit. Read please. – Shelly Oct 27 '13 at 22:45
  • @user2776409 Please post your exception stack trace. and the injection target. – Sotirios Delimanolis Oct 27 '13 at 22:55
  • I posted my stack trace. – Shelly Oct 27 '13 at 23:02
  • Good, it's work. But i didn't understand this concept. WHat is JDK and Spring Proxies, how this works ? – Shelly Oct 27 '13 at 23:07
  • @user2776409: see http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/aop.html#aop-introduction-proxies and http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/aop.html#aop-understanding-aop-proxies – JB Nizet Oct 27 '13 at 23:09
  • @user2776409 In addition to the recommended readings that JB posted, you should also familiarize yourself with the JDK's [`Proxy`](http://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html) class. The javadoc states: `A proxy class extends java.lang.reflect.Proxy.` Therefore, the object that Spring is trying to inject is of type `Proxy`, not `CaixaBOImpl`, although it will be of type `BasicBOImpl` because that is an interface. – Sotirios Delimanolis Oct 27 '13 at 23:23
0

We encountered a similar problem and we used a "hack" that seems to be working. Simply make your class implement some interface. It worked for us - let me know if it works for you too.

Ron Sher
  • 181
  • 8