9 Replies Latest reply on Jun 25, 2009 8:42 PM by boomerbrian.brian.abston.featurenotbug.com

    selectOneMenu and foreign keys issue in xxxList.xhtml

    sam-user

      Hello,
      I'm quite new to seam and I'm stuck with this issue for quite some time now.
      I have a database with 3 tables:


      TABLE AUTHORS 
      ( 
        AUTHOR_ID , 
        AUTHOR_NAME , 
        AUTHOR_SURNAME , 
        PRIMARY KEY (AUTHOR_ID) 
      );
      
      
      TABLE BOOK 
      ( 
        BOOK_ID , 
        BOOK_TITLE , 
        BOOK_AUTHOR , 
        BOOK_LANG , 
        BOOK_GENRE , 
        PRIMARY KEY , 
        FOREIGN KEY (BOOK_AUTHOR) REFERENCES AUTHORS (AUTHOR_ID) 
      );
      
      
      TABLE GENRES 
      ( 
        GENRE_ID , 
        GENRE_NAME , 
        PRIMARY KEY (GENRE_ID) 
      );



      Using seam-gen and reverse engineering I was able to generate an application and it works.
      Since BOOK_AUTHOR is a foreign key to the AUTHORS table, seam-gen didn't include this property in the search section of the BookList.xhtml
      I would like to add a dropdown listbox ( selectOneMenu) that gets populated from the AUTHORS table, allowing the user to select an existing author and use it as a search criteria.
      This is what I added to BooksList.xhtml


      <s:decorate template="layout/display.xhtml">
          <ui:define name="label">Author</ui:define>
          <h:selectOneMenu value="#{bookList.book.authors}"  >
             <s:selectItems value="#{authorsList.resultList}" var="_a" label="#{_a.authorName}"   noSelectionLabel="Select author ..." />  
             <s:convertEntity />
        </h:selectOneMenu>
      </s:decorate>





      I also added the following paramenter to BookList.page.xml




       <param name="bookAuthor" value="#{bookList.book.authors}" />



      And since there isn't a restriction in BookList.java class with regards to the auther property I added the following.




      "book.bookAuthors= #{bookList.book.authors} ",




      The problems is that this does not work. I played with the authorId property of the Author bean, but obviously with no success.
      I also read all the posts that seem releted to my issue, but none helped.


      This in theory should be a very easy task, but it's taking me a lot of time to figure out how to do it in seam, so any help would be highly appreciated.
      Thanks.

        • 1. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
          sam-user

          Just one addition:
          When I run the application with the above modifications I fet the following error message:



          SEVERE: /BookList.xhtml @46,78 value="#{bookList.book.authors.authorId}": Target Unreachable, 'authors' returned null on 'org.domain.book.entity.Book'



          • 2. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
            lvdberg

            Hi,


            The question you're raising is very common for people at our university coming from 'the DB-world'.


            you're trying to accsess an author id, starting the object tree from the Booklist. Be aware that you're doing objects here and - although possible with Sql - it is not so easy with objects.


            If this is a requirement, you could add a business method to the book class which provides you with has this book, that author.., looking it up in your set.


            Another issue is that Java doesn't has a notion of DB keys, That is taken care of by Hibernate. You should leave it to Hibernate (trust me, it really works!)



            Success Leo


            • 3. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
              sam-user

              Leo,
              thank you for the reply.
              I have to say that now I'm even more confused. I don't believe that such a common use case should be so dificult to implement in Seam.


              Since I just started with Seam (and Hibernate for that matter) I'm not sure I understand what you mean by




              ... you could add a business method to the book class which provides you with "has this book, that author..", ...


              and




              ... leave it to Hibernate ...

              Is it possible to give me some examples.
              Thanks you.

              • 4. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
                lvdberg

                I assume Seam-gen has created three classes for you:


                Book Authors and Genres and it also has created Queries and Home componenst and a lot of basic pages to view and edit.


                Suppose you have the result of the query for Books, which will undoublty be in BookList.


                So you have a


                List<Book> boobList 



                to work with.


                If I see it correctly you have an single Author related to your book or OneToOne so the reference an author (or its Id) You should do soemthing like this in code (assuming you have the book coming from the bookList and using the var b

                b.author.authorId


                You can't navigate from a List to a single objedct to a List to an object.


                So you should have something like:





                <s:decorate template="layout/display.xhtml">
                    <ui:define name="label">Author</ui:define>
                    <h:selectOneMenu value="#{_b.author}"  >
                       <s:selectItems value="#{authorsList.resultList}" var="_a" label="#{_a.authorName}"   noSelectionLabel="Select author ..." />  
                       <s:convertEntity />
                  </h:selectOneMenu>
                </s:decorate>
                






                The ID of the author (primary key in AUTHOR) is really not important in your JSF-page in this specific case because Seam (together with Hibernate and Faces) help you to map from a single entity (withs unique ID) to an object in the DB. That is what happens with the special convertEntity elemnt.


                If you'r curious how this works, take another page with a list and the convertEntity (for instance BookList) and open the source code. It will open up an impressive code page, but if you look for the SelectOneMenu you will see that Seam uses the primary keys as values for the items.


                Leo






                • 5. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
                  sam-user

                  But that's exactly what I have and I get this  ... Target Unreachable, 'authors' returned null  ... message
                  My understanding was that if I put this in my BookList.xhtml ( which is my search page in effect)




                  <s:decorate template="layout/display.xhtml">
                      <ui:define name="label">Author</ui:define>
                      <h:selectOneMenu value="#{bookList.book.authors}"  >
                         <s:selectItems value="#{authorsList.resultList}" var="_a" label="#{_a.authorName}"   noSelectionLabel="Select author ..." />  
                         <s:convertEntity />
                    </h:selectOneMenu>
                  </s:decorate>




                  the selected item is going to be an object which Id can be used in the search criteria as defined by the RESTRICTIONS in the BookList.java class.


                  It's a good idea, though, to take a look at the source code for the List page. I'll do that.


                  One more thought,though. If you really need the foreign key reletionship between tables only for the purpose of using one of the tables as a dictionary (many-to-one), is it really worth exposing this relationship to Seam/Hibernate. Would'n it be easier to have a simple column ( String, int or whatever) and populate the dictionary table in a dropdown list control that upon selection will assign the id of the selected item to the property.

                  • 6. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
                    lvdberg

                    Hi Ye,


                    You don't have the same, look closely





                    You have
                    
                    <h:selectOneMenu value="#{bookList.book.authors}"  >
                    
                    I suggest:
                    
                    <h:selectOneMenu value="#{_b.author}"  >
                    



                    And the relationship between entities is VERY visible to Seam/Hibernate. Seam handles these relationships transparently for you and simple tags like the convertEntity do the injecting from object in another object, without using key values. That's the beauty of Seam it hides all horrible and time consuming details


                    With Seam you can finally forget (but not ignore !!) the details and dedicate your time to the business logic.


                    Leo





                    • 7. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
                      sam-user

                      Ah, not sure where this _b comes from, though.
                      The strange thing is that when I use this approach in the case of "BookEdit" - it works and I'm able to persist the data.
                      Anyway, I think I finaly found the example I was looking for. For those of you that are looking how to implement this functionality - it's in the seam-bay example.


                      • 8. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
                        sam-user

                        OK, I finally figured this out. Ignore the previous post - the seam example seam-bay uses a diferent type of search and is not what I was looking for.
                        So here is the solution:


                        In the BookList.xhtml I added this section in the bookSearch form:




                        <s:decorate template="layout/display.xhtml">
                            <ui:define name="label">Author</ui:define>
                            <h:selectOneMenu value="#{bookList.book.authors.authorId}" >
                              <s:selectItems value="#{authorsList.resultList}" var="_a" label="#{_a.authorName}"  itemValue="#{_a.authorId}"    noSelectionLabel="Select author ..." />  
                         </h:selectOneMenu>
                        </s:decorate>



                        In my BookList.page.xml I added this:




                        <param name="bookAuthors" value="#{bookList.book.authors.authorId}" />



                        And in my BookList.java I added this restriction:




                        \"lower(book.authors.authorId) like concat(lower(#{bookList.author.authorId}),'%')\",




                        I also added this in BookList.java




                        private Authors author= new Authors();
                             
                        
                             public Book getBook() 
                             {
                                    book.setAuthors(author);
                                 return book;|
                             }
                        
                             public Authors getAuthor()
                             {
                                  return this.author;
                             }
                             
                             public void setAuthor(Authors author)
                             {
                                  this.author=author;
                             }





                        Note the first line in getBook()





                        book.setAuthors(author);

                        This effectively adds a new property to the BookList class with its gette and setter and assigns an empty Authors instance to the Book instanse. Without it I kept getting error messages saing Target unreachable.


                        I think this was what Leo was refereng to in his first reply but I didn't understand it. So now I do. :-)



                        This may not be the most elegant way of doing it, but at least it works.

                        • 9. Re: selectOneMenu and foreign keys issue in xxxList.xhtml
                          boomerbrian.brian.abston.featurenotbug.com

                          YE Neva wrote on Jun 10, 2009 12:25:


                          But that's exactly what I have and I get this  ... Target Unreachable, 'authors' returned null  ... message
                          My understanding was that if I put this in my BookList.xhtml ( which is my search page in effect)



                          I believe this is because your Entity Authors isn't a Seam component. You need to add something like @Name(authors) to your Entity. Seam Gen doesn't do this by default.