Частичные запросы JSF 2 не используют FacesContext с фабрики

#ajax #jsf #jsf-2 #mojarra #facescontext

#ajax #jsf #jsf-2 #mojarra #facescontext

Вопрос:

Похоже, что частичные запросы не используют экземпляры контекста faces, которые создаются FacesContextFactory реализациями.

Вот код в UIViewRoot#processDecodes , который указывает на то же самое

 if (context.getPartialViewContext().isPartialRequest() amp;amp;
    !context.getPartialViewContext().isExecuteAll()) {
    context.getPartialViewContext().processPartial(PhaseId.APPLY_REQUEST_VALUES);
} else {
    super.processDecodes(context);
}
  

Похоже, что PartialViewContext хранит в себе реализацию FacesContextImpl по умолчанию и использует ее для вызова методов жизненного цикла. (Обратите внимание, что метод processPartial не принимает объект контекста, потому что он использует свой собственный, сохраненный внутри)

Это ошибка или этот код там по определенной причине?

Спасибо

Комментарии:

1. Это как-то вредит вашей логике или вам просто любопытно?

2. мне нужно использовать FacesContext, который я создаю с фабрики, для извлечения некоторой дополнительной информации, которая установлена в переменных его экземпляра. технически говоря, я все еще мог бы получить необработанные значения из карты запросов, если бы захотел, но это было бы просто странно

Ответ №1:

FacesContext экземпляры уникальны для каждого потока, и FacesServlet создает a ThreadLocal<FacesContext> в начале запроса при получении FacesContext (который является контрактом на FacesContextFactory#getFacesContext) ) и удаляет его в конце ответа, связанного с запросом HTTP-сервлета (путем вызова FacesContext#release ).

Всякий раз, когда вы выполняете FacesContext#getCurrentInstance() в своем коде JSF, вы всегда будете получать один и тот же экземпляр на протяжении всей обработки запроса / ответа HTTP-сервлета.

Что касается метода UIViewRoot#processDecodes , я действительно не вижу ни одной строки, которая, вероятно, могла бы указывать на то, что метод использует свой собственный созданный экземпляр, а не переданный. Какая строка заставила вас так подумать?

Это видно из FacesServlet#service метода, который он создает FacesContext из FacesContextFactory , вот выдержка из FacesServlet#service метода, который показывает это —

 // Acquire the FacesContext instance for this request
FacesContext context = facesContextFactory.getFacesContext
   (servletConfig.getServletContext(), request, response, lifecycle);

// Execute the request processing lifecycle for this request
try {
 ...
} catch (FacesException e) {
 ...
}
finally {
 // Release the FacesContext instance for this request
 context.release();
}
  

Учитывая это, я не чувствую, что UIViewRoot#processDecodes могу иметь FacesContext экземпляр, который не из FacesContextFactory .

Поскольку вы говорите, что вы установили некоторые дополнительные параметры для FacesContext , которые возвращаются из FacesContextFactory , это означает, что у вас есть своя пользовательская реализация FacesContextFactory , если это так, то вы уверены, что ваш экземпляр введен в FacesServlet , а не mojarra com.sun.faces.context.FacesContextFactoryImpl (если вы используете mojarra)?

Комментарии:

1. более подробно изучив код, я понял, что моя пользовательская реализация FacesContextFactory, в свою очередь, делает delegate.getFacesContext() это, вызывает фабрику по умолчанию и инициализирует PartialViewContext через ExceptionHandlerFactoryImpl#getExceptionHandler. Я думаю, что в качестве решения мне нужно было бы вызвать ctx.setExceptionHandler(exceptionHandlerFactory.getExceptionHandler()); , прежде чем я вызову делегат. Позвольте мне проверить и вернуться

Ответ №2:

Вот как я заставил это работать. Ниже приведен код в моей пользовательской faces context factory

 public FacesContext getFacesContext(Object context, Object request, Object response, Lifecycle lifecycle) throws FacesException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;

    ExternalContextFactory externalContextFactory = (ExternalContextFactory) getFactory(FactoryFinder.EXTERNAL_CONTEXT_FACTORY);
    ExternalContext externalContext = externalContextFactory.getExternalContext(context, request, response);

    // CustomFacesContext extends from FacesContextImpl
    CustomFacesContext facesContext = new CustomFacesContext(externalContext, lifecycle);

    ExceptionHandlerFactory exceptionHandlerFactory = (ExceptionHandlerFactory) getFactory(FactoryFinder.EXCEPTION_HANDLER_FACTORY);
    ExceptionHandler exceptionHandler = exceptionHandlerFactory.getExceptionHandler();
    facesContext.setExceptionHandler(exceptionHandler);
}