-
1. Re: How to inject into a Servlet?
jfuerth Dec 21, 2012 3:38 PM (in response to jervisliu)Hi Jervis,
I have just tried the following:
1. Created a new cdi-quickstart project based on Errai 2.2.0.CR2
2. Added the following class:
package com.foo.erraicdi.server;
import java.io.IOException;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class InjectableServlet extends HttpServlet {
@Inject SimpleCDIService simpleCdiService;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/plain");
resp.getWriter().append("The injected service is " + simpleCdiService);
resp.getWriter().flush();
}
}
3. Added the following to src/main/jetty/WEB-INF/web.xml and src/main/jboss7/WEB-INF/web.xml
4. Executed "mvn clean package -Pjboss7"
5. Deployed the generated webapp at target/errai-cdi-with-servlet-injection.war in JBoss AS 7.1.1.Final
6. Went to http://127.0.0.1:8080/injectableServlet
And it was good. I got the message "The injected service is com.foo.erraicdi.server.SimpleCDIService@6755b6."
Then I tried in the embedded Jetty 6 that comes with GWT Dev Mode:
7. Executed "mvn clean package -Pjetty"
8. Executed "mvn gwt:run"
9. Visited http://127.0.0.1:8888/injectableServlet
And the injected value was missing. I got the message "The injected service is null."
So it seems that Weld was able to inject into servlets under AS7 but not under Jetty 6. There may be a weld configuration problem in the CDI quickstart project. I'm not sure. Are you experiencing this problem in the Dev Mode embedded Jetty server or in AS7?
Cheers,
Jonathan
-
2. Re: How to inject into a Servlet?
jfuerth Dec 21, 2012 4:01 PM (in response to jfuerth)Update:
I tried switching back to the standard weld-servlet listener (org.jboss.weld.environment.servlet.Listener) in web.xml, and now injection into the servlet is working properly in GWT Dev Mode's Jetty server.
It seems the problem of @Inject not working in the servlet was indeed due to a bug in Errai.
If your app works properly with org.jboss.weld.environment.servlet.Listener instead of org.jboss.errai.container.CDIServletStateListener, then this workaround should fix things for you.
I've filed ERRAI-462 to track this issue.
-Jonathan
-
3. Re: How to inject into a Servlet?
jervisliu Dec 22, 2012 2:17 AM (in response to jfuerth)Jonathan, thanks for the reply. I noticed that we have following comment in web.xml regarding CDIServletStateListener
<listener>
<!--
NOTE: The orig servlet listener has been patched,
until a solution to the bean validation problems in hosted mode is found.
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
-->
<listener-class>org.jboss.errai.container.CDIServletStateListener</listener-class>
</listener>
So what is this "bean validation problems" that org.jboss.errai.container.CDIServletStateListener patched for? The reason why I am asking is because if I switch back to org.jboss.weld.environment.servlet.Listener, Guvnor failed to start using mvn gwt:run, and I found following errors in the log, and they seemed to be related to bean validation:
00:00:02.013 [WARN] Failed startup of context org.jboss.errai.cdi.server.gwt.JettyLauncher$WebAppContextWithReload@6c6c5b8d{/,d:\svn\drools\guvnor-latest\guvnor-ng\guvnor-showcase\guvnor-webapp\target\guvnor-webapp-6.0.0-SNAPSHOT} org.jboss.weld.exceptions.DeploymentException: Exception List with 2 exceptions:
Exception 0 :
org.jboss.weld.exceptions.UnproxyableResolutionException: WELD-001436 Normal scoped bean class org.kie.guvnor.guided.rule.backend.server.util.BRDRTPersistence is not proxyable because it has a private no-args constructor private org.kie.guvnor.guided.rule.backend.server.util.BRDRTPersistence() - Managed Bean [class org.kie.guvnor.guided.rule.backend.server.util.BRDRTPersistence] with qualifiers [@Any @Default].
at org.jboss.weld.util.Proxies.getUnproxyableClassException(Proxies.java:224)
at org.jboss.weld.util.Proxies.getUnproxyableTypeException(Proxies.java:180)
at org.jboss.weld.util.Proxies.getUnproxyableTypesExceptionInt(Proxies.java:195)
at org.jboss.weld.util.Proxies.getUnproxyableTypesException(Proxies.java:169)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:147)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:163)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:382)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:367)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:380)
at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:182)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:543)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:513)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
at org.jboss.errai.cdi.server.gwt.JettyLauncher$WebAppContextWithReload.doStart(JettyLauncher.java:486)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.handler.RequestLogHandler.doStart(RequestLogHandler.java:115)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:222)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.jboss.errai.cdi.server.gwt.JettyLauncher.start(JettyLauncher.java:692)
at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:509)
at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1093)
at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:836)
at com.google.gwt.dev.DevMode.main(DevMode.java:311)
Exception 0 :
org.jboss.weld.exceptions.DeploymentException: WELD-001408 Unsatisfied dependencies for type [BuildService] with qualifiers [@Default] at injection point [[parameter 3] of [constructor] @Inject public org.kie.guvnor.projecteditor.backend.server.ProjectEditorServiceImpl(IOService, Paths, BuildService, Event<Messages>, KModuleEditorContentHandler, GroupArtifactVersionModelContentHandler)]
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:311)
at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:280)
at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:143)
at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:163)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:382)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:367)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:380)
at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:182)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:543)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:513)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
at org.jboss.errai.cdi.server.gwt.JettyLauncher$WebAppContextWithReload.doStart(JettyLauncher.java:486)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.handler.RequestLogHandler.doStart(RequestLogHandler.java:115)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:222)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.jboss.errai.cdi.server.gwt.JettyLauncher.start(JettyLauncher.java:692)
at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:509)
at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1093)
at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:836)
at com.google.gwt.dev.DevMode.main(DevMode.java:311)
at org.jboss.weld.bootstrap.Validator.validateBeans(Validator.java:394)
at org.jboss.weld.bootstrap.Validator.validateDeployment(Validator.java:367)
at org.jboss.weld.bootstrap.WeldBootstrap.validateBeans(WeldBootstrap.java:380)
at org.jboss.weld.environment.servlet.Listener.contextInitialized(Listener.java:182)
at org.mortbay.jetty.handler.ContextHandler.startContext(ContextHandler.java:543)
at org.mortbay.jetty.servlet.Context.startContext(Context.java:136)
at org.mortbay.jetty.webapp.WebAppContext.startContext(WebAppContext.java:1220)
at org.mortbay.jetty.handler.ContextHandler.doStart(ContextHandler.java:513)
at org.mortbay.jetty.webapp.WebAppContext.doStart(WebAppContext.java:448)
at org.jboss.errai.cdi.server.gwt.JettyLauncher$WebAppContextWithReload.doStart(JettyLauncher.java:486)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.handler.RequestLogHandler.doStart(RequestLogHandler.java:115)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.mortbay.jetty.handler.HandlerWrapper.doStart(HandlerWrapper.java:130)
at org.mortbay.jetty.Server.doStart(Server.java:222)
at org.mortbay.component.AbstractLifeCycle.start(AbstractLifeCycle.java:39)
at org.jboss.errai.cdi.server.gwt.JettyLauncher.start(JettyLauncher.java:692)
at com.google.gwt.dev.DevMode.doStartUpServer(DevMode.java:509)
at com.google.gwt.dev.DevModeBase.startUp(DevModeBase.java:1093)
at com.google.gwt.dev.DevModeBase.run(DevModeBase.java:836)
at com.google.gwt.dev.DevMode.main(DevMode.java:311)Thanks,
Jervis
-
4. Re: How to inject into a Servlet?
cbrock Dec 22, 2012 3:44 PM (in response to jervisliu)Those aren't Bean Validation errors.They are plain Weld errors that mean what they mean -- that is if you're enabling Weld to manage all classes in your application classpath (which is the default behaviour of Weld). If you're using a normal-scoped bean in CDI, you are required to make it proxyable. ie. You can't have an @ApplicationScoped bean which has a private constructor. This is simply not permitted by the spec, because it means that it cannot be proxied to handle narrower-scope injection as well as cycle resolution.
-
5. Re: How to inject into a Servlet?
jfuerth Jan 8, 2013 12:31 PM (in response to jervisliu)Hi Jervis,
Just following up on this: have you tried creating a public constructor for org.kie.guvnor.guided.rule.backend.server.util.BRDRTPersistence? It seems like that should solve the problem.
-
6. Re: How to inject into a Servlet?
jervisliu Jan 9, 2013 12:25 AM (in response to jfuerth)Yes, the workaround (using org.jboss.weld.environment.servlet.Listener) works once I fixed BRDRTPersistence. Though I am not sure what kind of bean validation problems I may run into if I switch back to use org.jboss.weld.environment.servlet.Listener?
Thanks,
Jervis
-
7. Re: How to inject into a Servlet?
jfuerth Jan 9, 2013 12:22 PM (in response to jervisliu)We investigated this thoroughly yesterday, and have determined that the CDIServletStateListener is no longer necessary. I tracked down the history and found out it was forked from Weld 1.0.0.Beta1! The only difference from the upstream Weld Listener class was that it skipped the validation phase at startup. But since then, the official Weld version has changed a lot. This explains why @Inject wasn't working in Servlets for you, and also why you weren't being warned about the unproxyable BRDRTPersistence class.
For the 2.2.0.Final release, all demos, archetypes, and documentation will be using org.jboss.weld.environment.servlet.Listener. We've removed CDIServletStateListener entirely in the Errai 3.0 branch.
-Jonathan
-
8. Re: How to inject into a Servlet?
jervisliu Jan 9, 2013 8:36 PM (in response to jfuerth)Thats all I need to know, thanks Jonathan!
Jervis