weld 1.1 breaks when working with proxied groovy objects
jeff.howard Jan 18, 2011 6:07 PMI've been working on a webapp that uses weld 1.0 and includes quite a bit of groovy code (using groovy 1.7.6) and I've run into a show stopper while attempting to move to weld 1.1. It appears that the weld proxy mechanism in 1.1 does not work well (or at all) with groovy object proxies. A very simple example is included below. This same code works perfectly in 1.0.x.
First, the web bean (groovy):
@Named("testBean") @SessionScoped class TestBean1 implements Serializable{ @Inject InjectedClass test1 // proxied java class @Inject InjectedGroovy test2 // proxied groovy class public TestBean1(){ } public void doSomeAction(AjaxBehaviorEvent event){ System.out.println("Action called") try{ new ProcessorClass().doSomeStuff(test1) } catch (Exception e){ System.out.println("Failed test1") } try{ new ProcessorClass().doSomeStuff(test2) } catch (Exception e){ System.out.println("Failed test2") } } }
The simple processor groovy class. Simply prints the message to the console:
class ProcessorClass { void doSomeStuff(InjectedClass c){ System.out.println(c.message) } void doSomeStuff(InjectedGroovy c){ System.out.println(c.message) } }
Some facelet code to use the web bean:
<h:form id="form"> <h:commandButton value="Click me" type="button"> <f:ajax listener="#{testBean.doSomeAction}"/> </h:commandButton> </h:form> #{testBean.test1.message}<br/> #{testBean.test2.message}
The injected java object (test 1):
@Named @SessionScoped // Session scoped to force weld proxy public class InjectedClass implements Serializable { public String getMessage(){ return "Message from injected java"; } }
The injected groovy object (test2):
@Named @SessionScoped // session scoped to force weld proxy class InjectedGroovy implements Serializable{ String message = "Message from injected groovy" }
The initial load of the facelets page works fine. The EL expressions render as expected yielding
Message from injected java
Message from injected groovy
Clicking the button in the facelet causes testBean.doSomeAction to execute. This is where things break down.
Action called Message from injected java Failed test2
The exception stacktrace is as follows:
java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:88) at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233) at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1600) at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3305) at InjectedGroovy.getProperty(InjectedGroovy.groovy) at org$jboss$weld$bean-flat-ManagedBean-class_InjectedGroovy_$$_WeldClientProxy.getProperty(org$jboss$weld$bean-flat-ManagedBean-class_InjectedGroovy_$$_WeldClientProxy.java) at org.codehaus.groovy.runtime.callsite.PogoGetPropertySite.getProperty(PogoGetPropertySite.java:47) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:241) at ProcessorClass.doSomeStuff(ProcessorClass.groovy:16) at ProcessorClass$doSomeStuff$0.call(Unknown Source) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at TestBean1.doSomeAction(TestBean1.groovy:32) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) at java.lang.reflect.Method.invoke(Unknown Source) at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:329) at org.jboss.el.util.ReflectionUtil.invokeMethod(ReflectionUtil.java:342) at org.jboss.el.parser.AstPropertySuffix.invoke(AstPropertySuffix.java:58) at org.jboss.el.parser.AstValue.invoke(AstValue.java:96) at org.jboss.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276) at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43) at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56) at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:102) at com.sun.faces.facelets.tag.jsf.core.AjaxBehaviorListenerImpl.processAjaxBehavior(AjaxHandler.java:447) at javax.faces.event.AjaxBehaviorEvent.processListener(AjaxBehaviorEvent.java:109) at javax.faces.component.behavior.BehaviorBase.broadcast(BehaviorBase.java:98) at javax.faces.component.UIComponentBase.broadcast(UIComponentBase.java:764) at javax.faces.component.UICommand.broadcast(UICommand.java:296) at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:781) at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1246) at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:77) at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:97) at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114) at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293) at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:190) at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291) at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:769) at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:698) at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:891) at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:690) at java.lang.Thread.run(Unknown Source)
To summarize, the proxied java object works as expected but the proxied groovy object cannot be used outside of the bean into which it was injected. Have you guys seen this behavior before? As it stands now, I cannot use Weld 1.1 without rewriting a large amount of groovy code as straight java.
Thanks for looking at this!
--jeff howard