Spring 3 MVC: @Transactional добавлен в класс Service и теперь получает исключение - PullRequest
1 голос
/ 16 июня 2011

Я очень новичок в весне и Java. Я использовал в основном springsource.org, чтобы попытаться создать свой веб-приложение для MVC Spring 3. У меня это работает, где я могу получить информацию и отобразить ее с контроллерами и менеджерами.

Сейчас я работаю над функциональностью, чтобы редактировать информацию и сохранять ее обратно в базу данных. Я добавил аннотацию @Transactional к своей функции сохранения внутри класса обслуживания, и теперь я получаю UnsatisfiedDependencyException. Будучи очень новым, я не уверен, что нужно сделать, чтобы очистить его. Я добавил bean-компонент для своего EventsManager, но я не думал, что это будет необходимо, поскольку аннотации должны были устранить необходимость в расширенных конфигурационных файлах xml. Я не был уверен, где ошибка, поэтому я публикую свой исходный код. Спасибо, что нашли время помочь мне с моей проблемой.

Полное исключение:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'eventsController' defined in file [$Path\gov\mt\dphhs\epts\web\EventsController.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [gov.mt.dphhs.epts.services.EventsManager]: : No matching bean of type [gov.mt.dphhs.epts.services.EventsManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [gov.mt.dphhs.epts.services.EventsManager] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {}

Класс контроллера:

@Controller
public class EventsController {

    private EventsManager eventsManager;

    @Autowired
    public EventsController(EventsManager eventsManager){
        this.eventsManager = eventsManager;
    }

    @RequestMapping("/events/events")
    public String displayEvents(ModelMap map){

        map.addAttribute("allEvents", eventsManager.getAllEvents());

        int totalEvents = eventsManager.getAllEvents().size();
        map.addAttribute("totalEvents",totalEvents);

        map.addAttribute("eventsTitle" , totalEvents + " Events");

        return "events";
    }

    @RequestMapping("/events/eventForm")
    public String editEvents(@RequestParam("id") Long eventId, ModelMap map){

        Events event = eventsManager.getEventById(eventId);
        map.addAttribute("pageTitle" , "Edit Event");
        map.addAttribute("event",event);

        return "eventForm";
    }

    @RequestMapping("/events/newEvent")
    public String newEvent(ModelMap map){

        Events event = new Events();
        map.addAttribute("pageTitle" , "New Event");
        map.addAttribute("event",event);

        return "eventForm";
    }

    @RequestMapping("/events/submitEvent")
    public String handleEventForm(@ModelAttribute("event")
            Events event, BindingResult result){

        System.out.println("Event Name:" + event.getEventName() + " ID: " + event.getEvntId());

        if(event.getEvntId() == null)
        {
            eventsManager.save(event);
        }

        return "redirect:/events/events";
    }   
}

Класс обслуживания:

@Service("EventsManager")
public class EventsManager implements IEventsManager {


    private EventsDAO eventsDao;

    @Autowired
    public void EventsDAO(EventsDAO eventsDao) {
        this.eventsDao = eventsDao;
    }

    public List<Events> getAllEvents() {
        return eventsDao.findAll();
    }

    public Events getEventById(Long id) {

        return eventsDao.findById(id);
    }

    public void delete(Events event) {
        // TODO Auto-generated method stub

    }

    @Transactional
    public void save(Events event) {
        eventsDao.save(event);
    }

    public Events update(Events event) {

        return eventsDao.update(event);
    }

}

Урезанная версия моего класса Дао:

public class EventsDAO implements IEventsDAO {

    @PersistenceContext
    private EntityManager em;

    protected final Log logger = LogFactory.getLog(EventsDAO.class);

    public void save(Events entity) {
        System.out.println("in Dao to save an event");
        logger.info("saving Events instance");
        try {
            em.persist(entity);
            logger.info("save successful");
        } catch (RuntimeException re) {
            logger.error("save failed", re);
            throw re;
        }
    }

    public EntityManager getEm() {
        return em;
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

    public static IEventsDAO getFromApplicationContext(ApplicationContext ctx) {
        return (IEventsDAO) ctx.getBean("EventsDAO");
    }
}

Контекст приложения:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns:p="http://www.springframework.org/schema/p"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans 
                    http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                    http://www.springframework.org/schema/context
                    http://www.springframework.org/schema/context/spring-context-3.0.xsd 
                    http://www.springframework.org/schema/tx 
                    http://www.springframework.org/schema/tx/spring-tx.xsd">

<context:component-scan base-package="gov.mt.dphhs.epts" />

<bean id="viewResolver"
    class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    <property name="prefix" value="/WEB-INF/" />
    <property name="suffix" value=".jsp" />
</bean>

<bean id="entityManagerFactory"
    class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
    <property name="persistenceUnitName" value="EPTSTest3Pu" />
</bean>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />
<context:annotation-config />

<bean id="EventsManager" class="gov.mt.dphhs.epts.services.EventsManager" />

<bean id="SpecialGuestsDAO" class="gov.mt.dphhs.epts.repository.SpecialGuestsDAO" />

<bean id="GroupMembersDAO" class="gov.mt.dphhs.epts.repository.GroupMembersDAO" />

<bean id="GroupsDAO" class="gov.mt.dphhs.epts.repository.GroupsDAO" />

<bean id="EventNotificationsDAO" class="gov.mt.dphhs.epts.repository.EventNotificationsDAO" />

<bean id="EventListingsDAO" class="gov.mt.dphhs.epts.repository.EventListingsDAO" />

<bean id="EventGroupXrefDAO" class="gov.mt.dphhs.epts.repository.EventGroupXrefDAO" />

<bean id="EventsDAO" class="gov.mt.dphhs.epts.repository.EventsDAO" />

1 Ответ

1 голос
/ 17 июня 2011

Похоже, что аннотация autowire становится запутанной, но я не уверен.

Зависимость, которую вы указали в EventsController, является зависимостью от конкретного класса EventsManager, а не от интерфейса IEventsManager, что является лучшей практикой, т.е.Spring использует некоторые смарты, чтобы автоматически связывать ваши компоненты, например, автоматическое подключение по типу и автоматическое подключение по имени.Например (и я упрощаю), Spring проверит контейнер bean-компонента на тип, который соответствует, или имя, которое соответствует.Я бы предположил, что автопроводка по типу работает с конкретными типами, но здесь могут быть некоторые специфические особенности.

Я бы порекомендовал:

  • Использование IEventsManager в вашем контроллере и указание, чтоЗависимость типа в аргументе конструктора
  • Именование ваших пружинных бинов начальными буквами в нижнем регистре, например соглашение о именовании полей / переменных java (тогда spring может автоматически связываться по имени, сопоставляя аргумент конструктора "eventsManager" с "eventsManager"Spring Bean)

Кроме того, похоже, что вы указываете некоторые из ваших бобов дважды.Когда вы используете аннотацию @Service и выполняете сканирование компонентов этого пакета, вам не нужно указывать его снова в файле контекста.Таким образом, ваш компонент "EventsManager" был определен дважды, но я не уверен, что это вызывает вашу проблему с зависимостями.

...