开发者

JSF 2: h:link and getrowdata

If I have a h:dataTable in books.xhtml providing a list of records and I want to view a particular record, then add or edit that record, currently I have this:

<h:dataTable #{BookBean.books}" var="books">
   <h:link outcome="bookview" value="#{books[1]}">
      <f:param name="id" value="#{books[2]}" />
   </h:link>
</h:dataTable>

I found out that I need to include <f:param> in order to show the CSS status of clicked link; otherwise if I don't have <f:param>, every time I clicked on a link rendered by h:link tags in the codes above, all links are changed to CSS clicked status.

Also, I read somewhere about the getrowdata() but I haven't been able to get it work. Is this a better alternative to using <f:param>?开发者_如何学Go

I have tried the getrowdata() method in my BookBean class as followed:

private DataModel<BookModel> books;
private BookModel currentBook;

public String view()
{
     currentBook = books.getRowData();
     return "bookview";
}

and in bookview.xhtml I have this:

<h:dataTable value="#{BookBean.view}" var="item">
    ... // render content here
<h:dataTable>

but I get an error about the property not found. Sorry for asking this question but I still don't understand yet some of the powerful features of JSF 2. Can some expert who understand the usage of h:link and getrowdata please explain to me in layman terms or perhaps with some basic code example. Thank you.

UPDATE: Changed classes based on @BalusC suggestions below. BookModel class is:

@Entity
public class BookModel implements Serializable
{
   private Long id;
   private String title;
   private String author;   

   // getters and setters here
 }

The BookService class looks like this:

@Stateless
public class BookService
{
    @PersistenceContext(unitName = "persistentUnit")
    protected EntityManager entityManager;

    public BookModel create() {
       return new BookModel();
    }

    public void delete(BookModel bookModel) {
       bookModel = entityManager.merge(bookModel);
       entityManager.remove(bookModel);
    }

    public BookModel update(BookModel bookModel) {
       return entityManager.merge(bookModel);
    }

    public BookModel find(Long id) {
       return entityManager.find(BookModel.class, id);
    }
}

The BookBean class is:

@ManagedBean(name = "bookBean")
@RequestScoped
public class BookBean implements Serializable
{
    @EJB
    private BookService bookService;

    @ManagedProperty(value = "#{param.id}")
    private Long id;

    private DataModel<BookModel> books;
    private BookModel currentBook;

    @PostConstruct
    public void init() {
        currentBook = bookService.find(id);
    }

    public BookModel getCurrentBook() {
       return currentBook;
    }

    public void setCurrentBook(BookModel currentBook) {
       this.currentBook = currentBook;
    }
 }

Running the BookBean class above caused this error: java.lang.IllegalStateException: WEB9031: WebappClassLoader unable to load resource [org.apache.openjpa.util.LongId], because it has not yet been started, or was already stopped. This is where I'm stuck at the moment.

FYI: My dev environment is Glassfish 3.1, Apache OpenJPA 2.1 and JSF 2.1.0 (that comes bundled with Glassfish)


There are two flaws in the code:

  • The h:link fires a GET request, not a POST request. The DataModel#getRowData() is not useful here either since you cannot attach bean actions to components which fire a GET request.

  • The <h:dataTable value="#{BookBean.view}"> with public String view() makes no sense. The datatable's value has got to be a collection of items, not a bean action method.


I understand that you want a GET link on every book item in the table which points to some detail page about the book item. Fix the detail page as follows:

bookview.xhtml

<h:outputText value="#{bookBean.currentBook.id}" />
<h:outputText value="#{bookBean.currentBook.author}" />
<h:outputText value="#{bookBean.currentBook.title}" />
...

And the BookBean as follows:

@ManagedBean
@RequestScoped
public BookBean {

    @ManagedProperty(value="#{param.id}")
    private Long id;

    private BookModel currentBook;

    @PostConstruct 
    public void init() {
        currentBook = bookDAO.find(id);
    }

    // ...
}

The @ManagedProperty will set the GET request parameter. The @PostConstruct will preload the right book based on the parameter.

Please note that this has nothing to do with POST-Redirect-GET pattern.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜