0

I need to log all update operations from my rest resources and store to a Database log table.

The idea is to store info like:

  • logged user
  • operation description about updated / saved entity
  • updated fields and reference key

My application is Java EE8 compatible, it uses REST / EJB and CDI stuff.

At first I thought of dealing all this stuff on EJB side, however the exposed services don't need to have logged user on the method signature, so adding it would result on a forcing..

Is there any way to send user information, that is normally retrieved by webrequest (we use a session token model authentication) and inject through EJB ?

Fabrizio Stellato
  • 1,727
  • 21
  • 52
  • 1
    What do you mean by "inject through ejb"? And maybe entitylisteners help (we use them too) https://stackoverflow.com/questions/10765508/cdi-injection-in-entitylisteners – Kukeltje Nov 13 '19 at 11:11
  • The entitylistener may help indeed, however the main question is: How to get logged user info from EJB, which is actually retrieved from HttpServletRequest on the REST side? – Fabrizio Stellato Nov 13 '19 at 11:25

2 Answers2

0

If your session management is setup correctly, you can just inject the session context via:

@Resource
SessionContext sessionContext;

Then:

sessionContext.getCallerPrincipal().getName()

is your logged in user.

mtj
  • 3,381
  • 19
  • 30
0

As mentioned before, SessionContext.getCallerPrincipal().getName() doesn't work as authentication mechanism does not provide it.

After some tries I found this:

On EJB side

@RequestScoped
public class UserInfo {

    private String userId;

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        if (this.userId != null) throw new UncheckedException("cannot infer userid twice");
        this.userId = userId;
    }
}

On REST side

@Inject
UserInfo userInfo;

void userAuthenticated(...) {

    String userId = ... // get userid from access token through **WebRequest** object

    userInfo.setUserId(userId);

}

Side note

I honestly would have preferred to inject userid on UserInfo constructor but I was not allowed doing this as WebRequest object does not belong to EJB context

Alternative way

Move all the logging process to REST side by using a Response filter.

Example code:

@Provider
public class LoggingFilter implements ContainerResponseFilter {


    @Context
    HttpServletRequest webRequest;

    @Context
    ResourceInfo resinfo;

    @Inject
    LoggingService loggingService;


    @Override
    public void filter(ContainerRequestContext containerRequestContext, ContainerResponseContext containerResponseContext) {

        final Method resourceMethod = resinfo.getResourceMethod();

        if (resourceMethod.isAnnotationPresent(Loggable.class) && containerResponseContext.getStatusInfo().getFamily() == Response.Status.Family.SUCCESSFUL) {

            // get all method's info and log to database ...

        }
    }
Fabrizio Stellato
  • 1,727
  • 21
  • 52