I have a Java EE project with a lot of beans and processing. I was asked to log every dangerous operation that a user can do, i.e. deleting a document. I have a log method in userServices bean, so a call like this:
userService("is deleting the document with id: "+documentId);
will work, the bean will use jpa to store user, date, time and message in the log table. Anyway with this method I have to add the injection
@EJB private UserService userService;
in every EJB where I want to log something, and I really don't like it. I'm trying to use annotations and interceptor to do something like that:
@Stateless
@Interceptors(LogUserInterceptor.class)
@LogUserModuleName("Documents")
class DocumentServices implements DocumentServiceRemote {
[...lot of code...]
@Override
@LogUserDangerousOperation("Delete a document")
public deleteDocument(int id) {
}
}
In my interceptor I combine the class annotation and the method annotation to create a message (in this case: "Document: Delete a document") and then I call userService.log(message). The advantage is I only have to annotate methods and class, without have to inject UserService bean programmatically call it. It's working fine, but the obvious point is that I have no way to pass the id of the document the user is deleting, so I cannot log "Document: Delete document 12345".
Is there a way to do it without injecting UserServices bean in almost every bean of my project?
Try using CDI Interceptors instead of EJB interceptors. They are much more powerful and flexible.
All you have to do is to declare them in beans.xml like this:
Create annotation binding @Logger and create LoggerInterceptor like described in documentation.