Идентификатор корреляции EJB3

Сейчас мои коллеги работают над подсистемой логирования и хотят связать отдельные операции, инициированные каким-то бизнес-методом. Например, если метод из bean-компонента A вызывает какой-то метод из bean-компонента B, а затем из bean-компонента C, было бы здорово узнать, чем бизнес-методы в bean-компоненте B и bean-компоненте C выполняют некоторые действия для метода из bean-компонента A. Особенно было бы здорово узнать, известно, что методы из B и C выполнили некоторую единицу работы для конкретного вызова bean-компонента A.

Итак, вопрос в том, как связать эти единицы работы в нечто общее? Очевидно, что использовать аргументы метода для привязки некрасиво!

А также я думаю, что пора задать еще один вопрос, достаточно близкий к предыдущему. Что, если я хочу передать некоторую контекстную информацию от bean-компонента A другим bean-компонентам, которые вызываются из A? Что-то вроде учетных данных безопасности и принципала безопасности? Что я могу сделать? Может быть, вопросы, которые я задавал, - это какая-то плохая практика?


person gkuzmin    schedule 19.02.2012    source источник


Ответы (2)


Похоже, хороший пример использования mdc, доступного в как Logback, так и Log4J. По сути, вы прикрепляете некоторое пользовательское значение к потоку, и все сообщения журнала, поступающие из этого потока, могут прикреплять это значение к сообщению.

Я думаю, что лучшим способом реализовать это в EJB будет перехватчик :

public class MdcInterceptor {

    @AroundInvoke
    public Object addMdcValue(InvocationContext context) throws Exception {
        MDC.put("cid", RandomStringUtils.randomAlphanumeric(16));
        try {
            return context.proceed();
        } finaly {
            MDC.remove("cid");
        }
    }
}

Теперь все, что вам нужно сделать, это добавить:

%X{user}

к вашему шаблону ведения журнала (logback.xml или log4j.xml).

Смотрите также

person Tomasz Nurkiewicz    schedule 19.02.2012
comment
Спасибо! Я посмотрю это завтра. - person gkuzmin; 20.02.2012
comment
Это должно работать, пока вы используете локальные EJB. Как только вы начнете использовать Remote EJB, все методы, основанные на ThreadLocal, перестанут работать. - person Bogdan; 24.02.2012
comment
Вероятно, вы имели в виду %X{cid} вместо %X{user}. - person alesch; 10.11.2017

Для получения контекстной информации общего назначения можно использовать TransactionSynchronizationRegistry. Это может выглядеть примерно так:

@Stateless
public class MyBean {

    @Resource
    TransactionSynchronizationRegistry registry;

    @AroundInvoke
    public Object setEntryName(InvocationContext ic) throws Exception {
        registry.putResource(NAME, "MyBean");
        return ic.proceed();
    }
}

@Stateless
public class MyBean2 {

    @Resource
    TransactionSynchronizationRegistry registry;

    public void doJob() {
        String entryName = (String)registry.getResource(NAME);
        ...
    }
}

Я считаю, что обычно это реализуется с использованием переменных ThreadLocal. как обычно каждая транзакция сопоставляется с одним потоком на серверах приложений. Поэтому, если TransactionSynchronizationRegistry не реализован в вашей AS (например, в JBoss 4.2.3) или вам нужен инструмент более низкого уровня, вы можете напрямую использовать переменные ThreadLocal.

Кстати, я думаю, что утилиты MDC используют то же самое под прикрытием.

person Wacław Borowiec    schedule 21.02.2012