Я пишу приложение CDI, которое работает на Tomcat. Я использую Tomcat 7.0.62 с Weld 2.2.12.Final как реализация CDI. Я использую CDI без JSF.Включенный сервлет с поддержкой CDI с ContextNotActiveException: WELD-001303:
Приложение состоит из сервлета диспетчера, который не поддерживает CDI. Диспетчер включает в себя вывод сервлета с поддержкой CDI для создания страницы.
Когда сервлет диспетчера и сервлет CDI находятся в одном и том же веб-приложении, работает нормально. Тем не менее, мне нужен сервлет CDI для работы в другом веб-приложении, поэтому Я использую кросс-контекст. Когда я включаю кросс-контекст, сервлет CDI производит выходные данные, пока не попытается получить доступ к компоненту @RequestScoped. Bean доступа не за исключением следующего:
org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
at org.jboss.weld.manager.BeanManagerImpl.getContext(BeanManagerImpl.java:708)
at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:90)
at org.jboss.weld.bean.ContextualInstanceStrategy$CachingContextualInstanceStrategy.getIfExists(ContextualInstanceStrategy.java:165)
at org.jboss.weld.bean.ContextualInstance.getIfExists(ContextualInstance.java:63)
at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:83)
...
Я попытался активации КДИ для диспетчера сервлета, а также, но это, похоже, не делать никакой разницы.
Мне кажется, что контекст запроса для сервлета CDI не настроен должным образом, когда сервлет CDI включен в отличие от приема запроса напрямую.
Я искал этот сайт, а также через Google, но не нашел подходящую проблему/решение . Я нашел параметр контекста tomcat «fireRequestListenersOnForwards =« true »' , который я применил к сервлету диспетчера, но это не повлияло.
Это проблема конфигурации? Может ли кто-нибудь дать понять, как это решить?
Буду очень признателен вам!
Справочная информация:
Фактическое применение имеющих проблемы большой, поэтому я конденсируется его вниз, чтобы получить к сущности разбитости. В результате у меня есть два военных файла. Первый файл войны содержит сервлет CDI и диспетчер (в коде, который я назвал его включенным). Второй файл войны содержит только сервлет диспетчера.
ИПР Servlet
ИПР Servlet есть файл context.xml в своей директории META_INF со следующим содержанием:
<?xml version="1.0" encoding="UTF-8"?>
<Context>
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>
Файл сервлет web.xml CDI содержит строки:
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>
<resource-env-ref>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
В каталоге WEB-INF для сервлетов CDI содержится файл beans.xml.
ИПР сервлетные бутстрап исполнение фасоли посредством использования BeanManager получены через JNDI поиск (это работает):
BeanManager bm = null;
try {
InitialContext context = new InitialContext();
try {
// "regular" naming
bm = (BeanManager) context.lookup("java:comp/BeanManager");
} catch(NameNotFoundException e) {
// try again with Tomcat naming
bm = (BeanManager) context.lookup("java:comp/env/BeanManager");
}
} catch (Exception e) {}
if (bm == null) {
writer.write("Couldn't look up the bean manager");
} else {
Set<Bean<?>> beans = bm.getBeans(EnclosingBean.class);
@SuppressWarnings("unchecked")
Bean<EnclosingBean> bean = (Bean<EnclosingBean>) bm.resolve(beans);
if (bean == null) {
writer.write("Couldn't get the bean");
} else {
EnclosingBean eb = (EnclosingBean) bm.getReference(bean, bean.getBeanClass(), bm.createCreationalContext(bean));
writer.write("finally here we are. Name is: ");
writer.write(eb.getName());
}
}
The (грузоотправитель) сервлет Includer
includer сервлет имеет context.xml в каталоге META-INF:
<?xml version="1.0" encoding="UTF-8"?>
<Context
path="/ExternalIncluderServlet"
docBase="ExternalIncluderServlet.war"
crossContext="true"
fireRequestListenersOnForwards="true">
<Resource name="BeanManager"
auth="Container"
type="javax.enterprise.inject.spi.BeanManager"
factory="org.jboss.weld.resources.ManagerObjectFactory" />
</Context>
Inclu дер сервлет смотрит контекст КДИ сервлета и получает RequestDispatcher следующим образом (это работает):
ServletContext sc = request.getServletContext();
ServletContext extsc = sc.getContext("/SimpleCDIServlet");
if (extsc == null) {
writer.println("<p>Couldn't get the external context.</p>");
} else {
RequestDispatcher rd = extsc.getRequestDispatcher("/CDIServlet");
if (rd == null) {
writer.println("<p>RequestDispatcher is null.</p>");
} else {
writer.println("<p>Got the RequestDispatcher.</p>");
rd.include(req, resp);
}
}
Результаты:
Когда я использую браузер для доступа к CDI сервлета непосредственно через URI: локальный: 8080/SimpleCDIServlet/CDIServlet Я получаю ожидаемый результат:
Simple CDI Servlet
finally here we are. Name is: InjectedBean
Если я получить доступ к CDI сервлет через диспетчерскую сервлета, расположенный в том же веб-приложение, что и CDI, он также работает. URI:/SimpleCDIServlet/IncluderServlet, выход:
Simple CDI Servlet Including Servlet
Will now include the CDI servlet ...
Got the RequestDispatcher.
Simple CDI Servlet
finally here we are. Name is: InjectedBean
Но если я включаю CDI сервлет из другого контекста, я не получаю впрыскиваемого имя боба на выходе и исключение было отмечено выше в журнале. URI:/ExternalIncluderServlet/IncluderServlet, выход:
CDI Servlet Includer
This servlet includes a CDI servlet in a different web app. It is not CDI enabled.
Got the RequestDispatcher.
Simple CDI Servlet
finally here we are. Name is:
Обратите внимание, что я не могу использовать диспетчер запросов вперед вместо того, чтобы включать в себя как оригинальный приложение включает в себя вывод из нескольких других сервлетов, а не только один. И открытие нового HTTP-запроса для каждого из них будет неэффективным, так как количество запросов будет умножено на количество включенных сервлетов, и это будет довольно уродливо .
Update: Я попробовал это на Tomee 1.7.2, а также на версии 8.5 WebSphere Application Server. Результаты приведены ниже.
WAS 8.5 Tomcat 7.0.62 Tomee 1.7.2 ======= ============= =========== CDI servlet direct access works works works Included by servlet works works works in same web app Included by servlet works broken broken in different web app
Чем больше я думаю об этом, тем больше я чувствую, что это действительно должно работать. Вы должны иметь возможность успешно использовать диспетчер запросов для включения вывода с сервлета с поддержкой CDI на Tomcat. Я надеюсь, что кто-то здесь может помочь мне разобраться, как заставить его работать.
А что на ...? Как вы фактически получаете контент, созданный вашим CDIServlet? Во-вторых: можете ли вы вызвать сервлет непосредственно из браузера (или инструмента HttpRequester), а не через фронт-контроллер? Успешно ли это работает? – Gimby
Привет, Гимби, Спасибо за ваш ответ. Я расширил фрагмент кода, а также добавил текст вывода программы. Если я напрямую обращаюсь к сервлету CDI, он работает. Он также работает, если я получаю доступ к сервлету CDI через сервлет диспетчера, расположенный в том же веб-приложении, что и портлет CDI. Это не удается. Когда я пытаюсь включить сервлет из другого контекста. –
Хороший вопрос. По сути, CDI/Weld не получает возможности инициализировать себя, когда кросс-контекст включен. Это на самом деле не кажется мне чем-то странным, так как в этом случае в CDIServlet не будет никакого фактического HTTP-запроса, чтобы слушатель CDI даже не стрелял. Техническое решение: выполните запрос HTTP ко второму сервлету, но мне интересно, есть ли для этого правильное решение. – Gimby