Маловероятно, что это можно сделать программным способом из вашего приложения для управляемых компонентов всех областей. BalusC уже указал, как это сделать для управляемых bean-компонентов в области приложения.
Рассмотрев, как управляемые bean-компоненты регистрируются в Mojarra 2.1 (реализация JSF 2.1); Существует не так много элегантных опций, доступных для программной регистрации сеанса и запроса bean-объектов в области видимости. Проще говоря, вы либо должны вызывать специфические для реализации классы, либо вам придется создавать и уничтожать, т.е. управлять компонентами самостоятельно, а не полагаться на реализацию JSF для этого.
Заполнение областей запроса и сеанса компонентами (неуправляемым способом)
Примечание. Это называется "неуправляемым способом", поскольку вы создаете компоненты, а не контейнер. Аннотации типа @PostConstruct
и @PreDestroy
не будут работать, если вы не обработаете их сами и не вызовете соответствующие методы. Даже внедрение зависимостей не сработает.
Выражения EL всегда оцениваются во время выполнения, так что это дает вам достаточную возможность заполнить прицел бобами перед оценкой (что позволяет выстрелить себе в ногу, если у вас есть такая возможность). В Mojarra (и, возможно, в других реализациях JSF) распознаватель EL будет использовать службы ScopeHandler (или эквивалентного класса) для разрешения значений выражения EL. Мохарра использует классы ApplicationScopeHandler
, RequestScopeHandler
и SessionScopeHandler
для получения значений из разных областей.
Вы можете заполнить содержимое областей Сеанс и Запрос после того, как после создания нового сеанса или до обработки запроса реализацией JSF.
Заполнение области действия сеанса можно выполнить (в идеале, используя HttpSessionListener
), используя:
HttpSession session = request.getSession(false);
session == null ? null : session.setAttribute("<keyname>", new Bean());
keyname
должно соответствовать значениям, которые вы используете для ссылки на bean-компонент в выражениях EL.
Аналогичным образом вы можете заполнить область запроса (в идеале это делается в фильтре), используя:
ServletRequest request = ... // get the reference to the servlet request object
request.setAttribute("<keyname>", new Bean());
Если вам нужно понять, как это работает, вы должны взглянуть на классы com.sun.faces.context.SessionMap
, com.sun.faces.context.RequestMap
и com.sun.faces.context.ApplicationMap
, чтобы увидеть, как контекстные карты управляются внутри и используются SessionScopeHandler
, RequestScopeHandler
и ApplicationScopeHandler
классы, которые являются статическими внутренними классами класса ScopeManager
(еще один статический внутренний) класса com.sun.faces.mgbean.BeanManager
. Класс BeanManager
- это класс, который содержит регистрацию управляемых компонентов, а в следующем разделе обсуждается, как «взломать» процесс регистрации Mojarra.
Использование классов Mojarra для регистрации бинов
Регистрация управляемых bean-компонентов в реализации Mojarra выполняется методом public void register(ManagedBeanInfo beanInfo)
класса com.sun.faces.mgbean.BeanManager
. Нетрудно получить доступ к классу BeanManager
, используя только API-интерфейсы JSF или Servlet. Однако существует класс ApplicationAssociate
Мохарры, который создает экземпляр BeanManager
, и доступ к нему можно получить с помощью метода getCurrentInstance()
. Другой ответ Томаса уже демонстрирует, как программно зарегистрировать управляемый компонент:
ApplicationAssociate.getCurrentInstance().getBeanManager().register(...)
Существует оговорка с вышеуказанным подходом. Маловероятно, что этот подход будет работать в методе init Servlet
по той простой причине, что метод getCurrentInstance
использует переменную ThreadLocal для извлечения экземпляра ApplicationAssociate
. Локальная переменная потока инициализируется классом com.sun.faces.application.WebappLifecycleListener
, поэтому вы должны воспроизвести механизм, используемый классом WebappLifecycleListener
, для вызова метода ApplicationAssociate getInstance(ServletContext context)
, чтобы получить доступ к экземпляру ApplicationAssociate
. Поэтому следующий код может быть (поскольку я не пытался его использовать) лучше, если вы хотите использовать классы, специфичные для Мохарры:
ServletContext sc = ... //get the ServletContext reference;
ApplicationAssociate.getInstance(sc).getBeanManager().register(...)
Вы все равно должны остерегаться причуд, возникающих из-за этого механизма, поскольку вполне возможно, что некоторые классы и экземпляры Mojarra не были бы загружены или инициализированы до вашего сервлета. Поэтому я бы предложил загрузку, пытаясь настроить ваш сервлет со значением load-on-startup
, которое больше, чем значение, используемое FacesServlet
.