JSF 2 Partial Requests не использует FacesContext с фабрики

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

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

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

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

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

Спасибо

2 ответа

Решение

FacesContext экземпляры уникальны для каждого потока, а FacesServlet создает 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 а не моджарры com.sun.faces.context.FacesContextFactoryImpl (если вы используете мохарру)?

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

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);
}
Другие вопросы по тегам