Как реализовать в OSGi пакет, имеющий класс, который помещает значения в ThreadContext, чтобы эти значения были видны другим пакетам - PullRequest
0 голосов
/ 01 октября 2019

Чтобы подвести итог проблемы, у меня есть общий класс в комплекте, который используется по всему проекту. Этот класс является классом Aspect, который помещает значения в ThreadContext (log4j2), чтобы в нашем журнале были соответствующие сведения о сеансе в журналах.

Я обнаружил, что ThreadContext работает как переменная ThreadLocal. А поскольку OSGi имеет разные загрузчики классов для каждого пакета, вызывающие / пользователи значений ThreadContext вообще не могут видеть эти значения.

Ссылки:

Эффект ThreadLocals и параллельной загрузки классов https://stackoverflow.com/a/34738856/8136561

Я ожидаю, что все еще будет иметь пакет с общим кодом, но другие пакеты все еще смогут видеть значенияв ThreadContext. Я не уверен, возможно ли это вообще.

Редактировать: Добавлен пример кода

Bundle1 (Общий код)

@Configurable
@Aspect
public class AspectLogger {

    @Before("within(@org.springframework.stereotype.Controller *)")
    public void beforeControllerAdvice(JoinPoint joinPoint) {
        Object[] paramValues = null;
        paramValues = joinPoint.getArgs();
        Object request = null;
        for (Object arg : paramValues) {
            if (arg instanceof RenderRequest) {
                request = arg;
            } else if (arg instanceof ResourceRequest) {
                request = arg;
            } else if (arg instanceof ActionRequest) {
                request = arg;
            }
        }

        if (request != null) {
            String transactionID = UUID.randomUUID().toString();
            ThreadContext.put("transactionID", transactionID);
        }
    }
}

Пакет 2,3 ... n (Использование этого аспекта в качестве компонента)

<bean id="aspectLogger" class="shared.bundle.common.AspectLogger" />

Log4j2 конфигурация с использованием этого значения для дополнений регистратора (значения проблемпусто в логах)

<PatternLayout>
    <Pattern>%-5p | %d{yyyy-MM-dd HH:mm:ss} | [%t] %c{2} (%F:%L) [transactionID: %X{transactionID}] - %m%n</Pattern>
</PatternLayout>

С точки зрения отладчика, я вижу, что поток контроллера и аспект аспекта в основном совпадают. Но я все еще не получаю значения, я даже пробовал ThreadContext.get("transactionID") на уровне @Controller, но он пуст.

Ответы [ 2 ]

2 голосов
/ 02 октября 2019

Таким образом, причина проблемы заключается в том, что log4j внедряется в каждый военный файл, который затем развертывается в OSGi. Встроенные классы загружаются соответствующим пакетом. Так что они живут в разных загрузчиках классов.

Встраивание журналов - плохая идея в OSGi. Одна из причин заключается в том, что вы не можете иметь центральную конфигурацию регистрации. Другая причина - проблема, описанная выше.

Вы можете посмотреть на pax-logging или поддержку felix logback как на правильные решения для ведения журнала OSGi. Оба предоставляют API log4j.

В ваших war файлах вам нужно будет определить импорт для журналируемых пакетов API. Тогда все войны должны использовать ThreadContext из одного делегированного загрузчика классов, и проблема должна быть решена.

0 голосов
/ 01 октября 2019

ThreadLocals и загрузчики классов являются ортогональными. Использование разных загрузчиков классов для каждого пакета ничего не говорит о том, какие потоки могут вызывать классы, загруженные из этих пакетов. Поэтому, если вы установите ThreadLocal перед вызовом кода в другом пакете, этот код сможет видеть ThreadLocals потока.

...