1 2 Previous Next 20 Replies Latest reply on Jan 3, 2010 3:12 PM by kva

    Ambiguous resolution

    kva

      I started off using a weld sample generated via the maven archetypes.


      Then I added some functionality to create new widgets


      @Named
      public class WidgetCreator
      {
         @Inject
         @WidgetRepository
         EntityManager widgetRepository;
      
         @Inject
         private Widget newWidget;
      
         @Model
         @Produces
         Widget getNewWidget() {
            return new Widget();
         }
      
         public void persist() {
            widgetRepository.persist(newWidget);
         }
      



      Why does this lead to an ambiguous resolution?


      I went on to add names like this




      @Named
      public class WidgetCreator
      {
         @Inject
         @WidgetRepository
         EntityManager widgetRepository;
      
         @Inject
         @Named("newWidget")
         private Widget newWidget;
      
         @Model
         @Produces
         @Named("newWidget")
         Widget getNewWidget() {
            return new Widget();
         }
      
         public void persist() {
            widgetRepository.persist(newWidget);
         }
      



      This gives an exception when submitting the form and invoking the persist method.




      java.lang.IllegalArgumentException: Unknown entity: be.sample.Widget_$$_javassist_15
           at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:311)
           at be.sample.WidgetCreator.persist(WidgetCreator.java:28)
      



      It all looked pretty darn simple... Does any of this make sense?


      I am also confused by this sentence in the spec:



      entity beans are by nature non-contextual objects and may not be injected into other objects.


      This is exactly what many examples do (e.g. the logged in user to name just one).


      Some guidance would be appreciated.

        • 1. Re: Ambiguous resolution
          gavin.king

          The ambiguity is between the Widget bean, and the getNewWidget() producer method. You need to add a qualifier on getNewWidget().


          "Entity beans" refers to EJB 2.x-style entity beans. It does not refer to JPA entities, which are never called entity beans in the specs.

          • 2. Re: Ambiguous resolution
            kva

            So all JPA entities become components because they are managed beans and thus are candidates for resolution even if they do not carry a @Name annotation? This is not the case in Seam is it?

            • 3. Re: Ambiguous resolution
              meetoblivion

              if your JPA module has a beans.xml in it, then that is correct. 

              • 4. Re: Ambiguous resolution
                gavin.king

                Kristof Vanbecelaere wrote on Dec 30, 2009 14:04:


                So all JPA entities become components because they are managed beans and thus are candidates for resolution even if they do not carry a @Name annotation? This is not the case in Seam is it?


                Right, but note that it is extremely easy to write a portable extension that changes this behavior:



                public class EntitiesAreNotBeans implements Extension {
                
                    void vetoEntity(@Observes ProcessAnnotatedType<?> pat) {
                        if ( pat.getAnnotatedType().isAnnotationPresent(Entity.class) ) {
                            pat.veto();
                        }
                    }
                
                }



                This is actually quite a useful little trick.

                • 5. Re: Ambiguous resolution
                  kva

                  Yes, using this extension the code works even without the qualifiers.


                  Care to tell me how to get around to the exception due to the persisting of the proxy?


                  java.lang.IllegalArgumentException: Unknown entity: be.sample.Widget_$$_javassist_15
                  



                  This is something that works in Seam, so I guess some unwrapping happens when a JPA entity is used to satisfy an @In-marked field.

                  • 6. Re: Ambiguous resolution
                    nickarls

                    Use a dependent-scoped Widget (they're not proxied)

                    • 7. Re: Ambiguous resolution
                      kva

                      Not a good idea if you want to refer to this bean from EL as each EL expression would get a new instance. I dropped the portable extension mentioned above and dropped the producer method. I added a @Name on the Widget class so the view can use that instance to post to.


                      Now the persist() no longer complains about the entity passed in. Only, I do not see an insert statement happening. I thought this meant that no transaction is active.


                      I tried making the WidgetCreator a SFSB to enjoy CMT but that did not make a difference either. Trying to inject the UserTransaction fails as well with be.sample.WidgetCreatorBean not bound.


                      I don't understand how the DocumentEditor in the spec can actually work if there is no Weld-managed persistency and the bean itself is not an EJB either.


                      I think I am missing some basic point here.


                      Is there a sample that actually does a persist?

                      • 8. Re: Ambiguous resolution
                        nickarls

                        If you have the dependent scoped entity injected into a request- or session scoped bean, it will share the lifecycle of the containing bean.

                        • 9. Re: Ambiguous resolution
                          nickarls

                          You would of course EL-ref it as #{bean.entity} and not as #{entity}

                          • 10. Re: Ambiguous resolution
                            kva

                            Thanks for correcting my understanding.


                            There is conflicting wording in the spec in section 6.4



                            It is re-
                            used if the bean EL name appears multiple times in the EL expression, but is never reused when the EL expression is
                            evaluated again, or when another EL expression is evaluated.


                            Seems to suggest that #{bean.entity.a} and #{bean.entity.b} in the same page would both use a different instance of entity.

                            • 11. Re: Ambiguous resolution
                              nickarls

                              My interpretation:


                              If you have a depedent-scoped @Named entity you will have different instances of entity in all cases but



                              1. if you have multiple refs to it in the same EL expression

                              2. it's injected somewhere else (and hence follows that beans lifecycle)



                              In your case bean.entity will be the same in both cases since bean is the same in both cases.

                              • 12. Re: Ambiguous resolution
                                kva

                                Right, after you mentioned the ref ought to start out with #{bean.entity} it made more sense. I had used a name on the producer method.


                                I would like to understand more about why the persist() operation does not actually cause an insert. I would also like more detail about how the DocumentEditor code snippet in the spec could work.


                                My understanding (probably flawed) is that the only way to get persistency to work (SMPC being absent) is to use CMT and thus ones component must be a session bean.


                                So I would really like to see a working JPA sample (beyond a simple query).

                                • 13. Re: Ambiguous resolution
                                  kva

                                  This must be a case of JBAS-7526.

                                  • 14. Re: Ambiguous resolution
                                    nickarls

                                    Tried something like


                                       @Inject @MyDB private EntityManager db;
                                       @Inject private UserTransaction ut;
                                    
                                       ...
                                    
                                       ut.begin();
                                       db.persist(myEntity);
                                       ut.commit();
                                    


                                    1 2 Previous Next