Search code examples
jsflogginglog4jejb

Logging logged-in user ID from JSF session in EJB service layer


I'm actually using log4j as a logger. The logger is used in all the application layers (controller, service, dao, etc). All the layers under the controller layer are also used by a non-JSF app.

When my JSF app is running, how can I get the logged user id in the logger when there is an exception, for instance, in the service layer? The logged-in user is actually stored in the JSF session.

Note : My question is probably related to How to get the name of the logged in user in JSF service in GlassFish which seems to conclude that it is not possible.


Solution

  • When using homegrown authentication with manually putting the logged-in user in the HTTP session, you'd really have to pass it along yourself as a method argument as the service layer is supposed to be unaware of any frontend specifics such as the HTTP session (i.e., it's forbidden to import/use anything from javax.faces.*, javax.servlet.*, javax.ws.*, etc in the service layer).

    When using container managed authentication via j_security_check or request.login(), it's available by EJBContext#getCallerPrincipal(). The EJBContext is in turn just injectable via @Resource. Here's an usage example in a logging interceptor.

    @Resource
    private EJBContext ejbContext; // You can also inject SessionContext.
    
    @AroundInvoke
    public Object log(InvocationContext invocationContext) {
        String username = ejbContext.getCallerPrincipal().getName();
        // ...
    }
    

    Note that it's never null and defaults to "anonymous" when non-logged-in.

    Additional advantage of container managed authentication is that you can put security restriction annotations like @RolesAllowed on service methods. How to use container managed authentication is in turn however a story apart. Start here: How to handle authentication/authorization with users in a database?