Why We Shouldn't Make a Spring MVC Controller @Transactional

Why we shouldn't make a Spring MVC controller @Transactional?

TLDR: this is because only the service layer in the application has the logic needed to identify the scope of a database/business transaction. The controller and persistence layer by design can't/shouldn't know the scope of a transaction.

The controller can be made @Transactional, but indeed it's a common recommendation to only make the service layer transactional (the persistence layer should not be transactional either).

The reason for this is not technical feasibility, but separation of concerns. The controller responsibility is to get the parameter requests, and then call one or more service methods and combine the results in a response that is then sent back to the client.

So the controller has a function of coordinator of the request execution, and transformer of the domain data to a format the client can consume such as DTOs.

The business logic resides on the service layer, and the persistence layer just retrieve / stores data back and forth from the database.

The scope of a database transaction is really a business concept as much as a technical concept: in an account transfer an account can only be debited if the other is credited etc., so only the service layer that contains the business logic can really know the scope of a bank account transfer transaction.

The persistence layer cannot know what transaction it's in, take for example a method customerDao.saveAddress. Should it run in it's own separate transaction always? there is no way to know, it depends on the business logic calling it. Sometimes it should run on a separate transaction, sometimes only save it's data if the saveCustomer also worked, etc.

The same applies to the controller: should saveCustomer and saveErrorMessages go in the same transaction? You might want to save the customer and if that fails then try to save some error messages and return a proper error message to the client, instead of rolling back everything including the error messages you wanted to save on the database.

In non transactional controllers, methods returning from the service layer return detached entities because the session is closed. This is normal, the solution is to either use OpenSessionInViewor do queries that eager fetch the results the controller knows it needs.

Having said that, it's not a crime to make controllers transactional, it's just not the most frequently used practice.

What is the benefit of using @Transactional in Controller layer on spring MVC application

There is no reason to use the annotation @Transactional in the @Controller.

There is a simple reason not to do this: best practice. A @Controller should not be aware of data persistence in a MVC logic, only the Service layer.

Also Spring recommends not to annotate whole classes only certain methods, this is also a good practice so you can mantain easily your application.

Making Spring 3 MVC controller method Transactional

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){
.....
}
}


Related Topics



Leave a reply



Submit