Доступ к параметрам контекста сервлета из расширения CDI - PullRequest
4 голосов
/ 26 августа 2011

Я пытаюсь написать расширение CDI, которому нужен доступ к параметрам контекста, определенным в web.xml через <context-param>.Я думаю, что есть два способа сделать это:

  • Каким-то образом получить ServletContext и позвонить getInitParameter()
  • Вручную проанализировать web.xml

К сожалению, мне нужен ServletContext для обоих решений, и получить его не представляется возможным.Проблема в том, что некоторые контейнеры запускаются CDI до создания ServletContext.И даже если ServletContext будет доступен до запуска CDI, похоже, нет никакого способа получить к нему доступ с расширения CDI.Я экспериментировал с ServletContextListener, который хранит ServletContext в статическом ThreadLocal.Кажется, это работает нормально, но это приведет к утечке памяти, поскольку я не могу надежно очистить ThreadLocal.

Еще два комментария, прежде чем ответить:

  • Использование некоторых другихПодход к чтению параметров конфигурации (например, использование JNDI) не подходит для меня, поскольку я пытаюсь написать расширение CDI для интеграции со сторонней платформой.
  • Мне известно о том, что будетвероятно, нет решения этой проблемы, которая на 100% переносима между средами / контейнерами.Но я был бы счастлив, если бы нашел решение, которое работает в большинстве случаев.

Спасибо!:)

Ответы [ 3 ]

4 голосов
/ 23 ноября 2011

Я пытался сделать что-то похожее с общим контекстом с bean-компонентами CDI на JBoss 7.1. Хотя это не сработало для меня, я не уверен, что это текущее состояние JBoss7.1 вызвало проблемы, так что, возможно, оно будет работать для вас?

У меня при запуске было что-то, имеющее доступ к ServletContext (в моем случае JAX-RS Application, но, вероятно, для вас слушатель или сервлет), которое обращается к компоненту в области приложения и устанавливает ServletContext в нем.

Чтобы соединиться с миром CDI, я использовал рецепт из следующего URI для создания экземпляра компонента: http://docs.jboss.org/weld/reference/1.1.0.Final/en-US/html/extend.html#d0e4978

Соответствующий код выглядит примерно так:

@SuppressWarnings("unchecked")
public <T> T getBean(Class<T> instanceClass) throws NamingException 
{
    BeanManager beanManager 
        = (BeanManager) InitialContext.doLookup("java:comp/BeanManager");

    AnnotatedType<Object> annotatedType
        = (AnnotatedType<Object>) beanManager.createAnnotatedType(instanceClass);

    InjectionTarget<Object> injectionTarget 
        = beanManager.createInjectionTarget(annotatedType);

    CreationalContext<Object> context
        = beanManager.createCreationalContext(null);

    Object instance = injectionTarget.produce(context);

    injectionTarget.inject(instance, context);
    injectionTarget.postConstruct(instance);

    return (T) instance;
}

, который вы могли бы затем установить в bean-компонент, который выглядит следующим образом:

package some.package;

import javax.enterprise.context.ApplicationScoped;
import javax.servlet.ServletContext;

/** An application context, initialised on application startup. */
@ApplicationScoped
public class AppContext 
{

    private ServletContext servletContext;

    /** Return the servlet context for the current application. */
    public ServletContext getServletContext() 
    {
        return servletContext;
    }

    public void setServletContext(ServletContext servletContext)
    {
        this.servletContext = servletContext;
    }
}

с использованием фрагмента вроде:

getBean(AppContext.class).setServletContext(servletContext);

в вашем коде запуска. После этого вы сможете просто @Inject контекстить в любой конструкции CDI, в которой вы хотите ... при условии , что он запускается после инициализации вашего сервлета или как угодно.

Например:

@Inject
private AppContext appContext;

Мне будет любопытно, работает ли это в других ситуациях ...

0 голосов
/ 31 августа 2011

Как вы заметили, вы и Феми прокомментировали, что если ServletContext недоступен, вы не сможете получить от него что-либо (например, параметры инициализации). Чтение файла web.xml возможно, но наверняка это безумие и не будет переносимым, но вы всегда можете попробовать сделать это в вашем конкретном развертывании, вы можете получить пример чтения чего-л. Из WEB-INF здесь

0 голосов
/ 26 августа 2011

Не уверен, какой контейнер вы используете, но, по крайней мере, в JBoss вы можете просто вставить ServletContext , используя аннотацию.Разве это не сработает для вас, или я неправильно понимаю природу вашего расширения CDI?

РЕДАКТИРОВАТЬ: ах.Я никогда не использовал реализацию CDI, но было бы возможно создать ServletContextListener, который генерировал бы событие CDI с ServletContext в качестве одного из свойств события.Затем вы можете просто прослушать событие в вашем расширении и извлечь ServletContext.

...