我正在尝试通过拦截器为EJB调用应用通用日志记录。此日志记录应记录Bean的安全主体。当方法调用完成时,该方法使用MDC并将主体推送到MDC并将其删除。
但是,当在EJB中进行EJB方法调用时,此方法失败。请参阅下面的演示代码。是否有任何解决方案或更好的方法来解决这个问题?
public class LoggingInterceptor {
@Resource
protected SessionContext sessionCtx;
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Principal principal = sessionCtx.getCallerPrincipal();
if (principal != null) {
MDC.put("USER_KEY", principal.getName());
}
try {
return ctx.proceed();
} finally {
MDC.remove("USER_KEY");
}
}
}
现在我尝试将此用于会话bean,如下所示:
@Stateless
@Interceptors(LoggingInterceptor.class)
public class Bean1 {
private static Logger logger = Logger.getLogger(Bean1.class);
@Resource
Bean2 bean2;
public String doSomething() {
logger.debug("Step1.");
bean2.doMore();
logger.debug("Step2.");
和bean 2:
@Stateless
@Interceptors(LoggingInterceptor.class)
public class Bean2 {
private static Logger logger = Logger.getLogger(Bean2.class);
public String doMore() {
logger.debug("Step in Bean2.");
直接调用Bean2时,日志记录有效:
23:53:00,093 DEBUG [Bean2] [testuser] Step in Bean2.
然而,当调用Bean1时,第二个日志语句不再具有该用户,因为UserKey已被截取Bean2的finally-Block从MDC中删除:
23:53:00,093 DEBUG [Bean1] [testuser] Step1.
23:53:00,193 DEBUG [Bean2] [testuser] Step in Bean2.
23:53:00,293 DEBUG [Bean1] [] Step2.
答案 0 :(得分:2)
您可以在继承拦截器之前存储先前的主体名称。
@AroundInvoke
public Object intercept(InvocationContext ctx) throws Exception {
Principal principal = sessionCtx.getCallerPrincipal();
String previousPrincipalName = MDC.get("USER_KEY");
MDC.put("USER_KEY", principal == null ? "" : principal.getName());
try {
return ctx.proceed();
} finally {
MDC.put("USER_KEY", previousPrincipalName);
}
}