Reputation: 467
I am very new to spring and java. I have been using mostly springsource.org to try and work my way through creating a spring 3 MVC web application. I have it working where I can grab information and display it with the controllers and managers.
Now I am working on the functionality to edit the information and save it back to the database. I added the @Transactional
annotation to my save function inside my service class and now I am receiving an UnsatisfiedDependencyException
. Being very new, I am not sure what to do to clear it. I added a bean for my EventsManager but I didn't think that would be necessary since Annotations were suppose to remove the need for extensive xml config files. I was not sure where the error is so I am posting my source code. Thank you for taking the time to assist me with my problem.
Full Exception:
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 Class:
@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 Class :
@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);
}
}
Trimmed down version of my Dao class:
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");
}
}
Application Context :
<?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" />
Upvotes: 1
Views: 2720
Reputation: 871
It looks like the autowire annotation is getting confused, but I can't be sure.
The dependency you've stated in your EventsController is a dependency on the concrete EventsManager class and not on the interface IEventsManager, which is better practice i.e. code to interfaces. Spring uses some smarts to auto wire your beans, like autowiring by type and autowiring by name. For example (and I am simplifying) spring will check the bean container for a type that matches or a name that matches. I would have assumed the autowiring by type worked with concrete types, but there may be some idiosyncrasies firing here.
I would recommend:
Also, it looks like you're specifying some of your beans twice. When you use the @Service annotation and do a component scan of that package, you don't need to specify it again in your context file. So your "EventsManager" bean has been defined twice, but I'm not sure this is causing your dependency problem.
Upvotes: 1