I am trying to implement a registration controller for the Rest API. I read about where to post @Transactional quite a bit. (Not at the DAO level, but at services, possibly organized). In my use case, I want not only services, but also a sleep mode check to use the same transaction.
This is the controller code:
@Autowired private UserService userService; @RequestMapping(method = RequestMethod.GET) @ResponseBody @Transactional public DefaultResponse register(@Valid RegisterIO registerIO, BindingResult errors) { DefaultResponse result = new DefaultResponse(); if (errors.hasErrors()) { result.addErrors(errors); } else { userService.register(registerIO); } return result; }
I wrote a custom contraint annotation that checks the registerIO parameter attribute. Both of these are validators and userService.register (registerIO); access to the database (check if the email address is used).
Therefore, I want both methods to use the same Hibernate session and transaction.
This approach leads to the following exception:
org.hibernate.HibernateException: No Session found for current thread org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:941)
The problem is the @Transactional annotation. When I put this annotation in the methods that will call the database, everything works, but the two transactions begin. I suspect that when I put it in the register method, the validation of the sleep mode validation is done before @Transactional starts the transaction for this method.
I developed the following functional workaround, but I am not happy with it. These codes do not use the @Valid annotation, but invoke the validator themselves:
@RequestMapping(method = RequestMethod.GET) @ResponseBody @Transactional public DefaultResponse register( RegisterIO registerIO, BindingResult errors) { DefaultResponse result = new DefaultResponse(); ValidatorFactory vf = Validation.buildDefaultValidatorFactory(); Validator validator = vf.getValidator(); Set<ConstraintViolation<RegisterIO>> valResult = validator.validate(registerIO);
I am trying to summarize my question: Using Spring MVC and Hibernate-Validation together with @Valid and @Transactional, how can I encapsulate an entire request in a single transaction?
Thanks:)