-
1. Re: Weld ignoring Servlets, and Google App Engine
alesj May 13, 2010 10:34 PM (in response to lhoriman.jeff-seam.infohazard.org)This is related GAE + Weld + Servlets issue.
For my playground app I hacked this workaround:
public class WeldServlet extends HttpServlet { /** The request handler */ private RequestHandler handler; @Override @SuppressWarnings("unchecked") public void init(ServletConfig config) throws ServletException { super.init(config); String wrapperClass = config.getInitParameter("request-handler"); if (wrapperClass == null) throw new IllegalArgumentException("Missing handler class parameter"); ServletContext context = config.getServletContext(); BeanManager manager = (BeanManager) context.getAttribute(BeanManager.class.getName()); if (manager == null) throw new IllegalArgumentException("No Weld manager present"); try { ClassLoader cl = RequestHandler.class.getClassLoader(); Class<?> tmp = cl.loadClass(wrapperClass); if (RequestHandler.class.isAssignableFrom(tmp) == false) throw new ServletException("Illegal handler class, wrong type: " + tmp); Class<RequestHandler> clazz = (Class<RequestHandler>) tmp; InjectionTarget<RequestHandler> it = manager.createInjectionTarget(manager.createAnnotatedType(clazz)); CreationalContext<RequestHandler> cc = manager.createCreationalContext(null); handler = it.produce(cc); it.inject(handler, cc); } catch (ServletException e) { throw e; } catch (Exception e) { throw new ServletException(e); } } protected final void handle(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { handler.handle(req, resp); } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { handle(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { handle(req, resp); } }
-
2. Re: Weld ignoring Servlets, and Google App Engine
lhoriman.jeff-seam.infohazard.org May 14, 2010 2:56 AM (in response to lhoriman.jeff-seam.infohazard.org)
Ales Justin wrote on May 13, 2010 22:34:
This is related GAE + Weld + Servlets issue.Funny, I starred your issue earlier today.
RequestHandler is your own custom interface, right? I don't have that luxury because I'm using GWT rpc servlets, which must actually extend GWT's RemoteServiceServlet. I need to get Weld to register a servlet for injection one way or another. I'm going to try doing it manually.
It looks like there's a lot of code in WeldBootstrap that I should be able to follow and figure out where the exclusion is being made for servlets... but I'm lost. Can someone tell me roughly where the exclusion is being made? There aren't any javadocs on internal methods :-(
Thanks,
Jeff -
3. Re: Weld ignoring Servlets, and Google App Engine
nickarls May 14, 2010 7:31 AM (in response to lhoriman.jeff-seam.infohazard.org)in
org.jboss.weld.bootstrap.AbstractBeanDeployer
there is a method
isTypeManagedBeanOrDecoratorOrInterceptor(WeldClass<?>)
that does something like
!servletApiAbstraction.SERVLET_CLASS.isAssignableFrom(javaClass)
which might be the offender.
Can you use an extension + SPI to make injection available?
-
4. Re: Weld ignoring Servlets, and Google App Engine
lhoriman.jeff-seam.infohazard.org May 17, 2010 4:02 AM (in response to lhoriman.jeff-seam.infohazard.org)
Nicklas Karlsson wrote on May 14, 2010 07:31:
Can you use an extension + SPI to make injection available?It doesn't look like there is a convenient way to surgically edit that behavior out, but it wasn't too hard to take Ales' code and make it into a generic CDIProxyServlet:
package test; import java.io.IOException; import java.util.Iterator; import java.util.logging.Logger; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.InjectionTarget; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServlet; /** * <p>Servlet which proxies to another servlet which was loaded using CDI and thus receives * proper dependency injection. You can use this on containers (like GAE) which do not support * CDI for Servlets.</p> * * <p>Use an init-param which defines the actual class of the servlet to load.</p> */ public class CDIProxyServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** */ @SuppressWarnings("unused") private static final Logger log = Logger.getLogger(CDIProxyServlet.class.getName()); /** */ public static final String PROXY_FOR_INIT_PARAM_NAME = "realServletClass"; /** The actual, CDI-managed servlet we wrap */ HttpServlet actual; /** */ @Override @SuppressWarnings("unchecked") public void init() throws ServletException { BeanManager mgr = (BeanManager)this.getServletContext().getAttribute(BeanManager.class.getName()); //log.finest("BeanManager is " + mgr); String className = this.getServletConfig().getInitParameter(PROXY_FOR_INIT_PARAM_NAME); try { Class<?> clazz = Class.forName(className); Iterator<Bean<?>> it = mgr.getBeans(clazz).iterator(); if (it.hasNext()) { Bean<?> servletBean = it.next(); if (it.hasNext()) throw new ServletException("Too many managed beans for " + clazz); this.actual = (HttpServlet)servletBean.create((CreationalContext)mgr.createCreationalContext(servletBean)); } else { InjectionTarget targ = mgr.createInjectionTarget(mgr.createAnnotatedType(clazz)); CreationalContext cc = mgr.createCreationalContext(null); this.actual = (HttpServlet)targ.produce(cc); targ.inject(this.actual, cc); //log.fine("Injected " + this.actual); } } catch (ClassNotFoundException e) { throw new ServletException(e); } } /** */ @Override public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { this.actual.service(req, res); } }
Big thanks to both of you. I now have CDI working more-or-less as advertised with Resteasy and GWT services in GAE.
-
5. Re: Weld ignoring Servlets, and Google App Engine
pmuir May 19, 2010 1:50 PM (in response to lhoriman.jeff-seam.infohazard.org)
Nicklas Karlsson wrote on May 14, 2010 07:31:
inorg.jboss.weld.bootstrap.AbstractBeanDeployer
there is a methodisTypeManagedBeanOrDecoratorOrInterceptor(WeldClass<?>)
that does something like!servletApiAbstraction.SERVLET_CLASS.isAssignableFrom(javaClass)
which might be the offender.This is a bug in Weld. Please file an issue and we will fix (in fact, I thought we had an open issue, but I can't find it).
-
7. Re: Weld ignoring Servlets, and Google App Engine
pmuir May 20, 2010 12:40 PM (in response to lhoriman.jeff-seam.infohazard.org)
Nicklas Karlsson wrote on May 19, 2010 13:57:
https://jira.jboss.org/browse/WELD-492 ?Yep, thanks Nik!