WARN: не удалось зарегистрировать обратный вызов

15: 11:14,676 WARN FacesRequestAttributes: 121 - Не удалось зарегистрировать обратный вызов разрушения [[email protected]1059fd6] для атрибута 'purchaseController', потому что FacesRequestAttributes не поддерживает такие обратные вызовы

Это сообщение предупреждения появляется в моем журнале. Для каждого управляемого bean всякий раз, когда он истекает. Он истекает через определенное время, потому что я использую MyFaces Orchestra.

Я определил org.springframework.web.context.request.RequestContextListener в моем web.xml, и у меня нет только jar spring только в моем пути к классам (т.е. не проблема с загрузкой классов)

В документах FacesRequestAttribute говорится:

ПРИМЕЧАНИЕ. В отличие от ServletRequestAttributes, этот вариант не поддерживает обратные вызовы уничтожения для облачных атрибутов, ни для области запроса, ни для области сеанса. Если вы полагаетесь на такие неявные обратные вызовы, рассмотрите возможность определения spring RequestContextListener в вашем web.xml.

purchaseController - фактически простой управляемый bean (не распространяющий ничего только на реализацию Serializable), аннотированный с помощью @Controller.

Update1:

Кажется, что повреждены beans в @Scope("request") и @Scope("session"). Поэтому я хотел знать, представляет ли этот сигнал опасность для правильного потока. То есть если что-то действительно нуждается в этих обратных вызовах. Если нет, я просто пропущу предупреждение с конфигурацией lo4j.

Обновление 2:

Я выкопал немного дальше, и кажется, что это происходит только иногда. Если используется прослушиватель, то RequestContextHolder.currentRequestAttributes() возвращает ServletRequestAttributes, а не FacesRequestAttributes. Таким образом, кажется, что иногда слушатель не работает и не устанавливает текущие атрибуты в RequestContextHolder.

Обновление 3:

Я отключил отладку для RequestContextListener, и вот результат:

07:21:31,518 DEBUG RequestContextListener:69 - Bound request context to thread: [email protected]
07:21:31,518 DEBUG RequestContextListener:89 - Cleared thread-bound request context: [email protected]
07:21:31,538  WARN FacesRequestAttributes:121 - Could not register destruction callback [[email protected]11aa152] for attribute 'org.apache.myfaces.orchestra.conversation.AccessScopeManager' because FacesRequestAttributes does not support such callbacks
07:21:31,541  WARN FacesRequestAttributes:121 - Could not register destruction callback [[email protected]1552393] for attribute 'localeController' because FacesRequestAttributes does not support such callbacks
....and so on, other request and session beans

Похоже, что запрос уничтожается до попытки доступа к beans. Это очень странно. Может ли это быть из-за проблемы в реализации контейнера сервлетов обработки прослушивателя?

Ответ 1

В javadoc FacesRequestAttributes мы можем прочитать:

Примечание: В отличие от ServletRequestAttributes, этот вариант не поддерживает обратные вызовы восстановления для облачных атрибутов, ни для области запроса или для области сеанса. Если вы полагаетесь на такие неявные обратные вызовы, рассмотрите определение Spring RequestContextListener в вашем web.xml.

И, действительно, метод registerDestructionCallback() FacesRequestAttributes не делает много чего:

public void registerDestructionCallback(String name, Runnable callback, int scope) {
    if (logger.isWarnEnabled()) {
        logger.warn("Could not register destruction callback [" + callback + "] for attribute '" + name +
                        "' because FacesRequestAttributes does not support such callbacks");
    }
}

Но я понимаю, что RequestContextListener (который вы объявили) позаботится об этом задании. Его метод requestDestroyed(ServletRequestEvent requestEvent) показан ниже:

public void requestDestroyed(ServletRequestEvent requestEvent) {
   ServletRequestAttributes attributes =
           (ServletRequestAttributes) requestEvent.getServletRequest().getAttribute(REQUEST_ATTRIBUTES_ATTRIBUTE);
   ServletRequestAttributes threadAttributes =
           (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
   if (threadAttributes != null) {
       // We're assumably within the original request thread...
       if (attributes == null) {
           attributes = threadAttributes;
       }
       RequestContextHolder.resetRequestAttributes();
       LocaleContextHolder.resetLocaleContext();
   }
   if (attributes != null) {
       attributes.requestCompleted();
       if (logger.isDebugEnabled()) {
           logger.debug("Cleared thread-bound request context: " + requestEvent.getServletRequest());
       }
   }
}

И если вы посмотрите на javadoc ServletRequestAttributes#requestCompleted():

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

Итак, я думаю, что вы можете безопасно пропустить WARN с конфигурацией log4j (возможно, подтвердите это с помощью небольшого отладочного сеанса).

Ответ 2

Я попробовал добавить

<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

как было предложено erhan14 на этом форуме .

И это предупреждение исчезло для меня. Надеюсь, что это поможет.