I am working with Spring MVC
application.
I want to create new event:
fill data at page > controller handle this info > saving new event to DB
I have already created DAO layer and repository layer. But at some places, it behaves very strangely. I have created Java configuration for all repositories in the same way.
Here is Repositories Configuration snippet:
@Configuration
@ComponentScan({ "net.lelyak.edu.repository", "net.lelyak.edu.service" })
@Import({ DatabaseDAOConfiguration.class })
public class ApplicationConfiguration {
@Autowired
private UserDAO userDAO;
@Autowired
private EventDAO eventDAO;
@Autowired
private TicketDAO ticketDAO;
@Autowired
private AuditoriumDAO auditoriumDAO;
@Bean
public AuditoriumRepository auditoriumRepository() {
AuditoriumRepository auditoriumRepository = new AuditoriumRepository();
auditoriumRepository.setDao(auditoriumDAO);
return auditoriumRepository;
}
@Bean
public EventRepository eventRepository() {
EventRepository eventRepository = new EventRepository();
eventRepository.setDao(eventDAO);
return eventRepository;
}
I have faced strange behavior at the controller level.
Here is controller code snippet:
@Controller
@RequestMapping("events")
public class EventsController {
@Autowired
private AuditoriumRepository auditoriumRepository;
@Autowired
private EventRepository eventRepository;
@RequestMapping(path = "add", method = RequestMethod.POST)
public String addEvent(@RequestParam Map<String, String> allRequestParams) {
Event newEvent = new Event();
// get auditorium id from request
String auditoryIdString = allRequestParams.get("auditorium");
Long auditoryId = Long.parseLong(auditoryIdString);
Auditorium auditorium = auditoriumRepository.getById(auditoryId);
newEvent.setAuditorium(auditorium);
AuditoriumRepository is auto-wired fine.
Here is snippet from debug view:
but EventRepository isn't:
Configuration is the same for both. One repository is auto-wired fine, second fails. I am newly at Spring. I can't get a clue why does this happen?
Here is snippet of code from EventRepository:
public class EventRepository extends BaseRepository<Event, EventDAO> {
@Autowired
private AuditoriumRepository auditoriumRepository;
@Override
public int put(Event entity) {
auditoriumRepository.put(entity.getAuditorium());
return super.put(entity);
}
AuditoriumRepository code snippet:
public class AuditoriumRepository extends BaseRepository<Auditorium, AuditoriumDAO> {
@Override
public Auditorium preSave(Auditorium entity) {
return entity;
}
For saving new event to DB I have to use exactly EventRepository. It fails, of course, with following stack trace:
java.lang.NullPointerException
at net.lelyak.edu.repository.BaseRepository.put(BaseRepository.java:23)
at net.lelyak.edu.repository.EventRepository.put(EventRepository.java:20)
at net.lelyak.edu.repository.EventRepository$$FastClassBySpringCGLIB$$5de8d2a5.invoke()
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
I am using spring 4.2.4.RELEASE
on Windows 10.
UPDATE:
BaseRepository code snippet:
public abstract class BaseRepository<T extends BaseEntity, E extends BaseDAO<T>> {
private E dao;
public E getDao() {
return dao;
}
public void setDao(E dao) {
this.dao = dao;
}
public int put(T entity) {
return dao.save(preSave(entity));
}
I can't understand why with the same configuration and repository structure. One instance is auto-wired by Spring fine, but the second one fails. How to find the root of this problem? And some solution.
UPDATE 2:
I have tried recommended solution, and added next setter to EventRepository:
public void setAuditoriumRepository(AuditoriumRepository auditoriumRepository) {
System.out.println("EventRepository.setAuditoriumRepository");
this.auditoriumRepository = auditoriumRepository;
}
As log message show this setter is executed. But keep failing for the same reason.
How to solve this issue?
i saw your code and the problem is not related to Spring and autowiring process. The problem is in your save
method in BaseDAO class:
@Override
public Integer save(ENTITY entity) {
if (entity.getId() == null) {
insert(entity);
} else {
update(entity);
}
return null;
}
if you change the metod to return newly inserted/updated entity id it will work fine.
try to hardcode it just for test :
@Override
public Integer save(ENTITY entity) {
if (entity.getId() == null) {
insert(entity);
} else {
update(entity);
}
return 1;
}
and the problem is raised when you return null
from save
method then you are doing assignment in the EventsController
class which is:
int eventId = eventRepository.put(newEvent); //this is null
and throws NullPointerException
because you are trying to assign null
to primitive variable.