I have a web application implemented using Spring and Hibernate. A typical controller method in the application looks like the following:
@RequestMapping(method = RequestMethod.POST)
public @ResponseBody
Foo saveFoo(@RequestBody Foo foo, HttpServletRequest request) throws Exception {
// authorize
User user = getAuthorizationService().authorizeUserFromRequest(request);
// service call
return fooService.saveFoo(foo);
}
And a typical service class looks like the following:
@Service
@Transactional
public class FooService implements IFooService {
@Autowired
private IFooDao fooDao;
@Override
public Foo saveFoo(Foo foo) {
// ...
}
}
Now, I want to create a Log
object and insert it to database every time a Foo
object is saved. These are my requirements:
- The
Log
object should containuserId
from the authorisedUser
object. - The
Log
object should contain some properties from theHttpServletRequest
object. - The save operation and log creation operation should be atomic. I.e. if a foo object is saved in the object we should have a corresponding log in the database indicating the user and other properties of the operation.
Since transaction management is handled in the service layer, creating the log and saving it in the controller violates the atomicity requirement.
I could pass the Log
object to the FooService
but that seems to be violation of separation of concerns principle since logging is a cross cutting concern.
I could move the transactional annotation to the controller which is not suggested in many of the places I have read.
I have also read about accomplishing the job using spring AOP and interceptors about which I have very little experience. But they were using information already present in the service class and I could not figure out how to pass the information from HttpServletRequest
or authorised User
to that interceptors.
I appreciate any direction or sample code to fulfill the requirements in this scenario.