Перехватчик EJB с регистрацией и вложенными вызовами EJB

Я пытаюсь применить общую регистрацию для вызовов EJB через перехватчик. Эта регистрация должна регистрировать субъект безопасности для бина. Подход использует 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");
        }
    }
}

Теперь я пытаюсь использовать это с сессионными компонентами следующим образом:

@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.");

и боб 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 был удален из MDC блоком finally перехвата Bean2:

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.

1 ответ

Решение

Вы можете сохранить предыдущее основное имя, прежде чем продолжить в перехватчике.

@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);
    }
}
Другие вопросы по тегам