2016-02-23 1 views
0

Я пишу приложение, основанное на весенней загрузке. В моем коде у меня есть класс менеджера UManager, в котором есть метод save. Внутри этого метода принимают участие два действия. Первый сохраняет некоторые данные с помощью другого Менеджера, а второй сохраняет данные, данные в методе сохранения. Теперь, когда одно из двух действий может потерпеть неудачу, они должны быть отменены. Я предполагаю, что использование аннотации @Transactional обеспечило бы то, что мне нужно, как если бы одно из двух действий потерпело неудачу, вся транзакция будет отброшена и никаких изменений не будет сделано для базы данных.Как получить метод внутри класса @Component для @Transactional?

@Component 
public class UManager { 

    @Autowired 
    AManager aManager; 

    @Autowired 
    URepository uRepository; 

    ... some stuff happening here 

    @Transactional 
    public U save(UBuilder uBuilder) { 
      aManager.save(something); 
      uRepository.save(uBuilder.build()); 
    } 
} 

Как только я добавить @Transactional аннотацию к методу сохранения, приложение не в состоянии запуска. Я получаю следующее сообщение об ошибке:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bController': Injection of autowired dependencies failed; 

Что я делаю неправильно или я что-то упускаю?

РЕДАКТИРОВАТЬ: Это StackTrace:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'bController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: UManager BController.uManager; nested exception is java.lang.IllegalArgumentException: Can not set UManager field BController.uManager to com.sun.proxy.$Proxy102 
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) ~[spring-beans-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) ~[spring-context-4.2.4.RELEASE.jar:4.2.4.RELEASE] 
at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118) ~[spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:764) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at org.springframework.boot.SpringApplication.doRun(SpringApplication.java:357) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at org.springframework.boot.SpringApplication.run(SpringApplication.java:305) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1124) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1113) [spring-boot-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at RApplication.main(RApplication.java:44) [classes/:na] 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_72] 
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_72] 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_72] 
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_72] 
at org.springframework.boot.maven.AbstractRunMojo$LaunchRunner.run(AbstractRunMojo.java:467) [spring-boot-maven-plugin-1.3.1.RELEASE.jar:1.3.1.RELEASE] 
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_72] 

EDIT 2: RApplication:

import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.scheduling.annotation.EnableScheduling; 
import org.springframework.transaction.annotation.EnableTransactionManagement; 
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 

@SpringBootApplication 
@EnableScheduling 
@EnableTransactionManagement 
public class RApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(RaumbuchungApplication.class, args); //this is the line mentioned in the stacktrace 
    } 
} 

UManager:

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Component; 
import org.springframework.transaction.annotation.Transactional; 

import de.mischok.hfmw.raumbuchung.data.URepository; 
import de.mischok.hfmw.raumbuchung.types.U; 
import de.mischok.hfmw.raumbuchung.types.UBuilder; 

@Component 
public class UManager { 

    @Autowired 
    URepository uRepository; 

    @Transactional 
    public U save(UBuilder uBuilder){ 

    } 
} 

BController:

import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Controller; 
import org.springframework.web.bind.annotation.RequestMapping; 
import UManager; 

@Controller 
@RequestMapping("my/Path") 
public class BController { 

    @Autowired 
    UManager uManager; 
} 

Это важные части кода, так как другие части не участвуют в этой проблеме.

+0

У вас есть еще одна ошибка журнала, чтобы показать нам? – pleft

+0

Действительно ли это ваш код или ваши службы/репозитории также реализуют интерфейсы? –

ответ

2

Если вы не используете конфигурацию XML весеннюю, но у вас есть Application класс (я предполагаю RApplication из StackTrace вас в курсе), которая делает конфигурацию убедитесь пояснением @EnableTransactionManagement

например:

@Configuration 
@ComponentScan 
@EnableAutoConfiguration 
@EnableJpaRepositories 
@EnableTransactionManagement 
public class Application { 
    //rest code goes here 
} 

РЕДАКТИРОВАТЬ Ошибка показывает, что прокси-объект не удался, вы должны autwire интерфейс класса (UManager), который вы хотите ввести не сам класс.

например.

Изменить UManager класс для реализации интерфейса (и, конечно, объявить любые публичные методы UManager к интерфейсу тоже)

public class UManager implements IUManager 

и в вашем bController классе autowire интерфейс не класс

public class BController { 
    @Autowired 
    IUManager uManager; 
} 
+0

Благодарим вас за быстрый ответ. Я добавил аннотацию '@ EnableTransactionManagement', которую вы рекомендовали моему классу« RApplication », но единственная вещь, отличная от предыдущей, - это строка, в которой ошибка возникает в« RApplication »(я поставил оба в сочетании с изменением с 44 до 46) , Есть ли что-то еще, вы бы предложили попробовать? – daniel

+0

Можете ли вы обновить свой вопрос, включая полный код 'RApplication',' UManager' и 'BController'? – pleft

+0

@elefasGR использует Spring boot, и это уже позволяет все, что вы пытаетесь включить (снова) вручную. Поэтому это не решит проблему. –

0

Вы должны создать Менеджер транзакций первого, как показано ниже:

<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
    <property name="dataSource" ref="dataSource"/> 
</bean> 

А затем сделать его аннотацию приводом, указав следующее:

<tx:annotation-driven transaction-manager = "txManager" /> 

Теперь вы должны быть в состоянии использовать @Transactional ,

+0

Благодарим вас за быстрый ответ. Но как я могу это сделать без наличия beans.xml? Я использую весеннюю загрузку, и поэтому у меня ее нет. – daniel

0

Обнаруженная ошибка выглядит так, как будто это из другого компонента, который пытается выполнить Autowire UManager. Я не эксперт по весне, но когда вы положили Transactional, вы сделали его DAO типа Component, и поэтому вы должны объявить bean как bean-фасоль, как bean вместо Component. Существует больше различий между различными аннотациями в What's the difference between @Component, @Repository & @Service annotations in Spring?.

Смежные вопросы