#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);
}