13 Replies Latest reply on Nov 20, 2008 3:43 PM by ivans

    selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null

    htrc

      I'm quite a beginner in seam, with the following problem.


      I have a jsf page showing a list of selectmanylistbox. The items are rss-articles received from a number of rss sources.
      My wish is to let the user select some of these articles, and then they should be saved to the database.
      The problem is that I have not yet persisted all the articles before showing them in the page, why I get the IllegalArgumentException, since the id is null.
      Do I have to persist all the articles before handling them in the jsf page?


      Here are my code:


      rss.xhtml:


      <h:selectManyListbox id="articles" value="#{articleController.selectedArticles}" rendered="#{articleController.selectedRssSources != null}" size="10" style="width:300px;">
                               <f:selectItems value="#{articleController.rssArticles}"/>
                               <s:convertEntity/>
                          </h:selectManyListbox>




      controller/bean:


      public List<SelectItem> getRssArticles() throws BusinessException {
           List<SelectItem> allArticles = new ArrayList<SelectItem>();
              for(RssSource rssSource : selectedRssSources) {
                  logger.debug("Selected rsssource: " + rssSource.getRssName() + ", id: " + rssSource.getId());
                  List<Article> articleList = articleService.getNewArticles(rssSource);
                  allArticles.addAll(mapArticleToSelectItem(articleList));
              }
              return allArticles;
          }


        • 1. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
          ivans

          I just got the same problem? Any solution or workaround?

          • 2. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
            josemlara

            if you return a list of SelectItem you don't need to use 



            <s:convertEntity/> 


            tag. try removing the tag. This is the fast method





            Other solution is using s:convertEntity and returning a list of Article in getRssArticles, but you must define:



            <component name="myEntityConverter"
                            class="org.jboss.seam.ui.converter.EntityConverter">
                            <property name="entityManager">#{yourEntityManagerName}</property>
            </component>




            in your components.xml.


            Sorry for my english, :-)

            • 3. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
              ivans

              Thanks, I tried the second solution but got into another problem.


              This is in components.xml



                   <component name="myEntityConverter"
                                   class="org.jboss.seam.ui.EntityConverter">
                                   <property name="entityManager">#{entityManager}</property>
                   </component>



              But i get this exception when creating myEntityConverter component:



              java.lang.RuntimeException: Could not create Component: myEntityConverter
              ...
              Caused by: java.lang.IllegalArgumentException: no such field: org.jboss.seam.ui.EntityConverter.entityManager



              Any idea?

              • 4. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                josemlara

                Can you copy the whole components.xml?

                • 5. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                  ivans

                  I forgot to say i am using seam 2.1


                  This is the relevant part of components.xml:



                       <transaction:entity-transaction entity-manager="#{entityManager}"/>
                  
                       <persistence:entity-manager-factory name="Bbb"/>
                  
                       <persistence:managed-persistence-context name="entityManager" 
                                                                       auto-create="true" 
                                                     entity-manager-factory="#{Bbb}"/>
                  
                       <security:identity authenticate-method="#{authenticator.authenticate}"/>
                  
                       <component name="myEntityConverter"
                                       class="org.jboss.seam.ui.EntityConverter">
                                       <property name="entityLoader">#{entityManager}</property>
                       </component>
                  



                  org.jboss.seam.ui.converter.EntityConverter doesn't exist int seam 2.1 and org.jboss.seam.ui.EntityConverter doesn't have a field called entityManager, it only has entityLoader which is AbstractEntityLoader that extends PersistenceController.


                  The problem I am having (as far as I can understand) is that convertEntity doesn't work because entities that are in selectItems are not managed by my entityManager and that is where convertEntity would look for them.


                  So is there a solution to get entityManager to manage these entities but without persisting them? Or am I even thinking in the right direction?

                  • 6. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                    josemlara

                    Try this:


                    <component name="org.jboss.seam.ui.EntityConverter">
                              <property name="entityManager">#{entityManager}</property>
                    </component>




                    • 7. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                      ivans

                      I still get the same exception:


                      java.lang.RuntimeException: Could not create Component: org.jboss.seam.ui.EntityConverter
                      ...
                      Caused by: java.lang.IllegalArgumentException: no such field: org.jboss.seam.ui.EntityConverter.entityManager
                      



                      • 8. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                        ivans

                        Should creating my own component (EntityConverter) solve the problem?


                        I cannot understand why it would help.


                        And btw: thank you very much for trying to help :)

                        • 9. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                          ivans

                          I just read in the documentation of <s:convertEntity> this line that looks important: The converter works with any managed entity.


                          And that is the problem. I have had convertEntity work before with managed entities but what about unmanaged ones (for example newly created but not yet persisted entities)?


                          I think my question now becomes: is there a way to show those (unmanaged) entities in a selectOneMenu?


                          Thanks

                          • 10. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                            josemlara

                            you are right. It seems that the problem is unmanaged entities...


                            Well if you want to show unmanaged entities in a selectOneMenu, you can create a List of SelectItems, and the value of the selectOneMenu will be a String (the id of the entity).

                            • 11. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                              ivans

                              Thanks but :(.


                              That means that i cannot bind my objects field directly to a list of objects. I would have to create a new transient property (String) in my entity and bind that to a list of SelectItems. Then i would have to find that object in a list using that transient property and then assign that value to a property in my object? Isn't there an easier way?


                              • 12. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                                josemlara

                                Then try found anything on the direction you said before... Using a converter with unmanaged entities

                                • 13. Re: selectitems: java.lang.IllegalArgumentException: Id and clazz must not be null
                                  ivans

                                  Thanks for the suggestion: I finally got this working using a custom converter. Don't know if it is ideal but it works. :)


                                  Here are the important parts of code if someone is interested..


                                  Ant thanks again Jose. :)



                                  @Name("unmanagedEntityConverter")
                                  @Converter
                                  @BypassInterceptors
                                  public class UnmanagedEntityConverter implements javax.faces.convert.Converter,
                                            Serializable {
                                  
                                       private static final long serialVersionUID = -1867717842379618493L;
                                  
                                       private Map<String, Object> unmanagedEntityLookup = new HashMap<String, Object>();
                                  
                                       public Object getAsObject(FacesContext facesContext, UIComponent cmp,
                                                 String value) {
                                            if (value == null) {
                                                 return null;
                                            }
                                            return unmanagedEntityLookup.get(value);
                                       }
                                  
                                       public String getAsString(FacesContext facesContext, UIComponent cmp,
                                                 Object value) {
                                            if (value == null) {
                                                 return null;
                                            }
                                            if (value instanceof String) {
                                                 return (String) value;
                                            }
                                            if (!(value instanceof UnmanagedIdentity)) {
                                                 throw new RuntimeException(
                                                           "Ha! Entity doesn't implement UnmanagedIdentity and cannot be used with unmanagedEntityConverter.");
                                            }
                                            UnmanagedIdentity umi = (UnmanagedIdentity) value;
                                            unmanagedEntityLookup.put(umi.getKey(), value);
                                            return umi.getKey();
                                       }
                                  
                                  }




                                  public abstract class UnmanagedIdentity {
                                  
                                       @Transient
                                       protected String key;
                                  
                                       @Transient
                                       protected static int counter = 0;
                                  
                                       protected String generateKey() {
                                            counter++;
                                            key = Integer.toString(counter);
                                            return key;
                                       }
                                  
                                       protected abstract Long getId();
                                  
                                       @Transient
                                       public String getKey() {
                                            return getId() != null ? getId().toString() : key;
                                       }
                                  }
                                  





                                  <f:converter converterId="unmanagedEntityConverter" />