5

I am using Spring 3.1 and have my DAO and service layer(transactional) written.

However in a special case to avoid a lazy init exception I have to make a spring mvc request handler method @transactional. But It is failing to attach transaction to that method. Method name is ModelAndView home(HttpServletRequest request, HttpServletResponse response). http://forum.springsource.org/showthread.php?46814-Transaction-in-MVC-Controller From this link it seems it is not possible to attach transaction (by default ) to mvc methods. Solution suggested in that link seems to be for Spring 2.5 (overriding handleRequest ). Any help will be reallyappreciated. Thanks

@Controller
public class AuthenticationController { 
@Autowired
CategoryService categoryService;    
@Autowired
BrandService brandService;
@Autowired
ItemService itemService;

@RequestMapping(value="/login.html",method=RequestMethod.GET)
ModelAndView login(){       
    return new ModelAndView("login.jsp");       
}   
@RequestMapping(value="/home.html",method=RequestMethod.GET)
@Transactional
ModelAndView home(HttpServletRequest request, HttpServletResponse response){
    List<Category> categories = categoryService.readAll();
    request.setAttribute("categories", categories);     
    List<Brand> brands = brandService.readAll();
    request.setAttribute("brands", brands);     
    List<Item> items = itemService.readAll();
    request.setAttribute("items", items);
    Set<Image> images = items.get(0).getImages();
    for(Image i : images ) {
        System.out.println(i.getUrl());
    }
    return new ModelAndView("home.jsp");    
}
Subin Sebastian
  • 10,870
  • 3
  • 37
  • 42

3 Answers3

4

You'll need to implement an interface so that Spring has something it can use as a Proxy interface:

@Controller
public interface AuthenticationController {
  ModelAndView home(HttpServletRequest request, HttpServletResponse response);
}

@Controller
public class AuthenticationControllerImpl implements AuthenticationController {

@RequestMapping(value="/home.html",method=RequestMethod.GET)
@Transactional
@Override
ModelAndView home(HttpServletRequest request, HttpServletResponse response){
.....
}
}
Kieran
  • 5,906
  • 3
  • 24
  • 34
  • Using springBoot 1.2.3.RELEASE with spring 4.1.6.RELEASE I encounter exactly the opposite: If the controller (@RequestMapping) formally implements an interface, spring creates a JdkDynamicAopProxy (which starts up without errors but the dispatcher servlet does not find the entry points for the URL mappings at runtime). If the controller does NOT formally implement an interface, a CglibAopProxy is generated, and everything works perfectly. The CGLib does not need to be an explicit dependency, as opposed to the comment of chrismarx below. – Heri Aug 06 '15 at 12:30
4

Spring will implement the transactional logic using JDK dynamic proxies, these rely on proxied classes implementing suitable interfaces. It's also possible to use CGLib proxies which don't require interfaces.

There is a nice article about this link

BartoszMiller
  • 1,245
  • 1
  • 15
  • 24
  • I think this is the better answer, Spring will attempt to create the cglib proxies for the controller if you dont specify an interface, and as long as cglib is on the classpath, this all just works, and you dont need to deal with changing anything. I ran into problems with @requestmapping trying to get the controller with interface to work – chrismarx May 20 '15 at 13:10
  • This link had been changed to https://spring.io/blog/2012/05/23/transactions-caching-and-aop-understanding-proxy-usage-in-spring . – DEWA Kazuyuki - 出羽和之 Nov 26 '19 at 07:34
0

I'm not sure this applies to your case but if you are using separate DI contexts you should also consider how Spring weaves aspects.

Spring will only apply @Transactional semantics to beans in the same DI context where @EnableTransactionManagement or <tx:annotation-driven/> is used.

So if you define your transaction configuration in the root context, only beans in that context are covered, which typically means only business services. You'll need to re-enable transaction management in any child context where you also use @Transactional.

Ref: Spring AOP - How to make aspects defined in a parent context work in child contexts?