3 Replies Latest reply on Oct 30, 2009 3:13 PM by Huy Le

    AbstractProducerBean.checkReturnValue seems to check against the wrong injection point

    Huy Le Newbie

      Hi all,


      I was running a modified version of the numberguess example (embedded Jetty) and got the following exception which doesn't seem quite right:




      javax.enterprise.inject.IllegalProductException: Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans
      
      Producer: org.jboss.weld.bean-web-module-ProducerMethod-org.jboss.weld.examples.numberguess.FacesContextManager.getFacesContext()
      Injection Point: field org.jboss.weld.examples.numberguess.Game.maxNumber
           at org.jboss.weld.bean.AbstractProducerBean.checkReturnValue(AbstractProducerBean.java:201)
           at org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:287)
           at org.jboss.weld.context.AbstractMapContext.get(AbstractMapContext.java:104)
           at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.getProxiedInstance(ClientProxyMethodHandler.java:139)
           at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:97)
           at javax.faces.context.FacesContext_$$_javassist_7.getELContext(FacesContext_$$_javassist_7.java)
           at org.jboss.weld.examples.numberguess.Generator.getMaxNumber(Generator.java:38)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:597)
           at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:111)
           at org.jboss.weld.examples.numberguess.Generator_$$_javassist_6.getMaxNumber(Generator_$$_javassist_6.java)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
           at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
           at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
           at java.lang.reflect.Method.invoke(Method.java:597)
           at org.jboss.weld.introspector.jlr.WeldMethodImpl.invokeOnInstance(WeldMethodImpl.java:227)
           at org.jboss.weld.injection.MethodInjectionPoint.invokeOnInstance(MethodInjectionPoint.java:148)
           at org.jboss.weld.bean.ProducerMethod$1.produce(ProducerMethod.java:117)
           at org.jboss.weld.bean.AbstractProducerBean.create(AbstractProducerBean.java:286)
           at org.jboss.weld.context.DependentContext.get(DependentContext.java:62)
           at org.jboss.weld.BeanManagerImpl.getReference(BeanManagerImpl.java:899)
           at org.jboss.weld.BeanManagerImpl.getReference(BeanManagerImpl.java:945)
           at org.jboss.weld.BeanManagerImpl.getInjectableReference(BeanManagerImpl.java:967)
           at org.jboss.weld.injection.FieldInjectionPoint.inject(FieldInjectionPoint.java:78)
           at org.jboss.weld.util.Beans.injectBoundFields(Beans.java:683)
           at org.jboss.weld.util.Beans.injectFieldsAndInitializers(Beans.java:695)
           at org.jboss.weld.bean.ManagedBean$1$1.proceed(ManagedBean.java:195)
           at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:51)
           at org.jboss.weld.bean.ManagedBean$1.inject(ManagedBean.java:189)
           at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:115)
           at org.jboss.weld.context.AbstractMapContext.get(AbstractMapContext.java:104)
           at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.getProxiedInstance(ClientProxyMethodHandler.java:139)
           at org.jboss.weld.bean.proxy.ClientProxyMethodHandler.invoke(ClientProxyMethodHandler.java:97)
           at org.jboss.weld.examples.numberguess.Game_$$_javassist_5.getNumber(Game_$$_javassist_5.java)
           at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)



      The following modifications were made to the numberguess example:





      • Added a producer for FacesContext




      public class FacesContextManager implements Serializable {
      
           private static final long serialVersionUID = 5156835887786174326L;
           
           @Produces @RequestScoped
           public FacesContext getFacesContext() {
                return FacesContext.getCurrentInstance();
           }
      
      }




      • Inject an instance of FacesContext in Generator




      @ApplicationScoped
      public class Generator implements Serializable {
      
           ...
      
           @Inject
           private Instance<FacesContext> facesContextInstance;
      
           @Produces
           @MaxNumber
           int getMaxNumber() {
                final FacesContext facesContext = facesContextInstance.get();
                // This has no purpose other than to invoke a method on the proxy so that the proxy instance 
                // is retrieved via the producer method
                facesContext.getELContext();
                return maxNumber;
           }
           
           ...
      
      }




      • Max number is then injected into Game




      @Named
      @SessionScoped
      public class Game implements Serializable {
      
           ...
      
           @Inject
           @MaxNumber
           private int maxNumber;
      
           ...
      }





      Not sure if my analysis is correct, but it seems that:



      1. FieldInjectionPoint for maxNumber is set as the current injection point in BeanManagerImpl

      2. Producer method for maxNumber is invoked

      3. The getELContext method is invoked on the FacesContext proxy

      4. The getProxiedInstance method is invoked on ClientProxyMethodHandler which causes the producer method for FacesContext to be invoked

      5. The checkReturnValue on AbstractProducerBean is invoked, but it is checking the FacesContext return value against the injection point for maxNumber (since this is still the current injection point) an an IllegalProductException is thrown since maxNumber must be serializable (but not FacesContext)