1 2 Previous Next 15 Replies Latest reply on Oct 6, 2010 6:43 AM by amazur

    SelectOneMenu entity not valid

    norad2

      I have a page that is used for creating new Addresses entities.
      One of the properties of an Addresses is another entity called IpBank.


      
      @Entity
      
      @Name("addresses")
      
      @Table(name = "ADDRESSES")
      
      public class Addresses implements java.io.Serializable {
      
      
           private Integer addressId;
      
           private String addressName;
      
           private IpBank ipBank;
      
           private Integer ipOctet;
      
           .
      
           .
      
           .
      
           
      
           @ManyToOne(fetch = FetchType.LAZY)
      
           @JoinColumn(name = "IP_BANK_ID", nullable = false)
      
           @NotNull
      
           public IpBank getIpBank() {
      
                return this.ipBank;
      
           }
      
      
           public void setIpBank(IpBank ipBank) {
      
                this.ipBank = ipBank;
      
           }
      
           
      
           .
      
           .
      
           .
      
      }
      
      



      I want to provide a select one menu to be used during an Addresses creation.
      The following code shows the available IpBanks but when I select one and try to save
      I get a Faces Message saying that the value is not valid.


      
      08:45:43,496 INFO  [lifecycle] WARNING: FacesMessage(s) have been enqueued, but may not have been displayed.
      
      sourceId=createAddressForm:ipBankDecoration:j_id48[severity=(ERROR 2), summary=(value is not valid), detail=(value is not valid)]
      
      
      
      




      
      <h:selectOneMenu value="#{addresses.ipBank}" required="true">
      
          <s:selectItems value="#{ipBanks}" 
      
                        var="ipbank"
      
                   label="#{ipbank.ipRange}" 
      
           noSelectionLabel="Please Select..."/>
      
          <s:convertEntity />
      
      </h:selectOneMenu>
      
      



      Here is the bean that provides the ipBanks list.


      
      @Stateful 
      
      @Name("IpBankHome")
      
      public class IpBankHomeBean implements IpBankHome {
      
      
          @PersistenceContext(type=EXTENDED)
      
          private EntityManager em;
      
          
      
          @DataModel
      
          private List<IpBank> ipBanks;
      
      
           
      
          @Factory("ipBanks")
      
          public void getIpBanks() {
      
               ipBanks = em.createQuery("select i from IpBank i").getResultList();
      
          }
      
      
          @Destroy @Remove                                                                      
      
          public void destroy() {}
      
          
      
      }
      
      




      And the bean used to save a new address:


      
      @Stateful 
      
      @Name("AddressesHome")
      
      public class AddressesHomeBean implements AddressesHome {
      
      
          @Logger private Log log;
      
      
          @PersistenceContext(type=EXTENDED)
      
          private EntityManager em;
      
          
      
          @In(required=false)
      
          @Out(required=false)
      
          private Addresses addresses;
      
          
      
          @Begin
      
          public void createAddress() {
      
               addresses = new Addresses();
      
          }
      
          
      
          @End
      
          public void saveAddress() {
      
               em.persist(addresses);
      
               log.info("New address (address id #{address.addressId} created");
      
          }
      
          
      
          @Destroy @Remove                                                                      
      
          public void destroy() {}
      
          
      
      }
      
      



      Can anyone spot what I am doing wrong here?

        • 1. Re: SelectOneMenu entity not valid
          wrzep

          Hi Dan,


          Have you tried to follow solutions from this thread ?


          Cheers,
          -Pawel

          • 2. Re: SelectOneMenu entity not valid
            norad2

            I browsed through the forum for all SelectOneMenu posts. That one had to do with using multiple entity managers and the fix seemed to have to do with disabling one of them? That isn't really the issue I am having

            • 3. Re: SelectOneMenu entity not valid
              mcgilbertus

              I think it is because of the @DataModel annotation; s:selectItems accept a List, try replacing @DataModel with @Out

              • 4. Re: SelectOneMenu entity not valid
                norad2

                Switching to @Out gives the same result.


                The problem isn't that the Select One Menu does not display values, the values all display just fine.


                The problem is that when I select one of the values, the validation determines that the value is not valid.


                • 5. Re: SelectOneMenu entity not valid
                  vladimir.kovalyuk

                  I have to tell you bad news.


                  I've just debugged UISelectOne component and it works as follows
                  validateValue() method // Ensure that the value matches one of the available options. It calls matchValue() method in order to do that: it obtains <s:selectItems> items and corces them to the selected value and then check whether corced value is equal to selected value.  And it faults for one case - when selected instance entity is not of expected class (Address here) but Address_$$_java_assist1 class and compared item is of Address type.


                  So the problem is in ExpressionFactory.coerceToType(Object,Class<?>) implementaion that throws IllegalArgumentException that states than it can't convert Address to its supertype (actually Address_$$_java_assist1).


                  I don't see work around that :(

                  • 6. Re: SelectOneMenu entity not valid
                    vladimir.kovalyuk

                    Forgot to mention that Address_$$_java_assist1 is a proxy class introduced by Hibernate that loads lazy fetched parts of object on actual invocation.


                    It explains why symptoms are not constantly reproducible.

                    • 7. Re: SelectOneMenu entity not valid
                      vladimir.kovalyuk

                      I realized that validation is ok when object is completely loaded and there is nothing left to lazy-load.
                      I tried to add join in query and it started to work.


                      So for the discussed entity I'd suggest to re-write method as follows:


                          @Factory("ipBanks")
                          public void getIpBanks() {
                               ipBanks = em.createQuery("select i from IpBank i left join i.somePropertyItFetchesLazily").getResultList();
                          }
                      


                      • 8. Re: SelectOneMenu entity not valid
                        vladimir.kovalyuk

                        What coerceToType() does specifically? It demands instance to be completely loaded. But entity can be complex and making sure that it is completely loaded can be unnecessary expensive.


                        Could someone provide me with the sources of EL?

                        • 9. Re: SelectOneMenu entity not valid
                          norad2

                          I would be curious to see the code you've written to test this (if I am correct in guessing thats what you did).


                          This is my ipBank entity:


                          
                          @Entity
                          
                          @Name("ipBank")
                          
                          @Table(name = "IP_BANK")
                          
                          public class IpBank implements java.io.Serializable {
                          
                          
                               private static final long serialVersionUID = 1L;
                          
                               
                          
                               private BigDecimal ipBankId;
                          
                               private String ipRange;
                          
                               private Set<Addresses> addresseses = new HashSet<Addresses>(0);
                          
                          
                               public IpBank() {
                          
                               }
                          
                          
                               public IpBank(BigDecimal ipBankId, String ipRange) {
                          
                                    this.ipBankId = ipBankId;
                          
                                    this.ipRange = ipRange;
                          
                               }
                          
                               public IpBank(BigDecimal ipBankId, String ipRange,
                          
                                         Set<Addresses> addresseses) {
                          
                                    this.ipBankId = ipBankId;
                          
                                    this.ipRange = ipRange;
                          
                                    this.addresseses = addresseses;
                          
                               }
                          
                          
                               @Id
                          
                               @Column(name = "IP_BANK_ID", unique = true, nullable = false, precision = 22, scale = 0)
                          
                               @NotNull
                          
                               public BigDecimal getIpBankId() {
                          
                                    return this.ipBankId;
                          
                               }
                          
                          
                               public void setIpBankId(BigDecimal ipBankId) {
                          
                                    this.ipBankId = ipBankId;
                          
                               }
                          
                          
                               @Column(name = "IP_RANGE", nullable = false, length = 256)
                          
                               @NotNull
                          
                               @Length(max = 256)
                          
                               public String getIpRange() {
                          
                                    return this.ipRange;
                          
                               }
                          
                          
                               public void setIpRange(String ipRange) {
                          
                                    this.ipRange = ipRange;
                          
                               }
                          
                               @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "ipBank")
                          
                               public Set<Addresses> getAddresseses() {
                          
                                    return this.addresseses;
                          
                               }
                          
                          
                               public void setAddresseses(Set<Addresses> addresseses) {
                          
                                    this.addresseses = addresseses;
                          
                               }
                          
                          
                          }
                          
                          



                          I tried changing the query to:


                          
                              @Factory("ipBanks")
                          
                              public void getIpBanks() {
                          
                                   ipBanks = em.createQuery("select distinct i from IpBank i left join i.addresseses").getResultList();
                          
                              }
                          
                          
                          



                          but that did not work

                          • 10. Re: SelectOneMenu entity not valid
                            vladimir.kovalyuk

                            Changing query in not enough. Try to override equals() (and hashCode() as well).


                            PS I did nothing special with your code - just added your classes to my application. The difference would be in components.xml - I configured Seam to employ Seam-managed persistence contexts.


                            If problem persists have a look at the thread pointer in the first reply - EntityConverter requires to use the same classloader and entitymanager for selected value and items.

                            • 11. Re: SelectOneMenu entity not valid
                              damianharvey.damianharvey.gmail.com

                              The IllegalArgumentException with coerceToType issue can be remedied by either:



                              • setting your FetchType to EAGER; or

                              • upgrading your JSF to 1.2_08



                              I'm not sure that it is specific to your problem but it does sound very similar.


                              Cheers,


                              Damian.

                              • 12. Re: SelectOneMenu entity not valid
                                vladimir.kovalyuk

                                Damian, thank you for ideas but it's not the case. I use JSF 1.2_04 shipped with JBOSS AS.
                                FetchType is actually LAZY, what makes JPA generate proxies AFAIK.
                                As I see there are several potential problem with proxies. The greatest one is when developers forget to override equals() method.  And one more potential problem - when implementing equals() we can't rely on field's values and should use getters if @Id annotation applied to getter like in the classes above.
                                I'm still not sure whether items have to be completely loaded. It works without joins for now, but didn't work some time ago.


                                I'd recommend to add some lines to Seam reference manual with recomendations how to avoid potential problems.

                                • 13. Re: SelectOneMenu entity not valid
                                  lbertrand

                                  Did someone find the solution because I have exactly the same problem ?
                                  Thanks

                                  • 14. Re: SelectOneMenu entity not valid

                                    Does anyone tried upgrading JSF to 1.2_8?


                                    How to upgrade in JBOSS 4.2.2?

                                    1 2 Previous Next