简体   繁体   English

具有日志记录和嵌套EJB调用的EJB拦截器

[英]EJB interceptor with logging and nested EJB calls

I'm trying to apply general logging for EJB calls via an interceptor. 我正在尝试通过拦截器为EJB调用应用通用日志记录。 This logging should log the security principal for a bean. 此日志记录应记录Bean的安全主体。 The approach uses MDC and pushes the principal to the MDC and removes it, when the method call is finished. 当方法调用完成时,该方法使用MDC并将主体推送到MDC并将其删除。

However this approach fails, when a EJB method call is made within an EJB. 但是,当在EJB中进行EJB方法调用时,此方法失败。 See the demo code below. 请参阅下面的演示代码。 Is there any solution or a better aproach that tackles this problem? 是否有任何解决方案或更好的方法来解决这个问题?

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");
        }
    }
}

Now I try to use this with session beans as follows: 现在我尝试使用会话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.");

and bean 2: 和豆2:

@Stateless
@Interceptors(LoggingInterceptor.class)
public class Bean2 {

    private static Logger logger = Logger.getLogger(Bean2.class);

    public String doMore() {
        logger.debug("Step in Bean2.");

When Bean2 is called directly the logging works: 直接调用Bean2时,日志记录工作:

23:53:00,093 DEBUG [Bean2] [testuser] Step in Bean2. 

However when calling Bean1 the second log statement doesn't have the user anymore, as the UserKey has been removed from the MDC by the finally-Block of the Interception of 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.

You could store the previous principal name before proceeding in the interceptor. 您可以在继承拦截器之前存储先前的主体名称。

@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);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM