JSF 2: h: ссылка и получение данных

#jsf-2 #jpa-2.0 #glassfish-3

#jsf-2 #jpa-2.0 #glassfish-3

Вопрос:

Если у меня есть h:dataTable в books.xhtml, предоставляющий список записей, и я хочу просмотреть конкретную запись, затем добавить или отредактировать эту запись, в настоящее время у меня есть это:

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

Я обнаружил, что мне нужно включить, <f:param> чтобы показать CSS-статус нажатой ссылки; в противном случае, если у меня его нет <f:param> , каждый раз, когда я нажимаю на ссылку, отображаемую тегами h: link в приведенных выше кодах, все ссылки изменяются на CSS-статус нажатой.

Кроме того, я где-то читал о getrowdata() , но мне не удалось заставить его работать. Является ли это лучшей альтернативой использованию <f:param> ?

Я попробовал getrowdata() метод в моем классе BookBean следующим образом:

 private DataModel<BookModel> books;
private BookModel currentBook;

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

и в bookview.xhtml у меня есть это:

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

но я получаю сообщение об ошибке о том, что свойство не найдено. Извините, что задаю этот вопрос, но я все еще не понимаю некоторых мощных функций JSF 2. Может быть, какой-нибудь эксперт, который понимает использование h:link и getrowdata , пожалуйста, объяснит мне в терминах непрофессионала или, возможно, с каким-нибудь базовым примером кода. Спасибо.

ОБНОВЛЕНИЕ: изменены классы на основе приведенных ниже предложений @BalusC. Класс BookModel является:

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

   // getters and setters here
 }
  

Класс BookService выглядит следующим образом:

 @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);
    }
}
  

Класс BookBean является:

 @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;
    }
 }
  

Запуск класса BookBean, описанного выше, вызвал эту ошибку: 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 . На данный момент я застрял именно на этом.

К вашему сведению: моя среда разработки — Glassfish 3.1, Apache OpenJPA 2.1 и JSF 2.1.0 (поставляется в комплекте с Glassfish)

Комментарии:

1. Я понятия не имею, что вы имеете в виду под «статусом CSS» и в чем именно заключается проблема. CSS — это просто язык стилизации, который никоим образом не должен влиять на функциональность JSF. Не могли бы вы, пожалуйста, пояснить?

2. @BalusC: CSS-статус , о котором я упоминал выше, связан с a:visited . Я надеюсь, что это прояснит любое недоразумение. 🙂

Ответ №1:

В коде есть два недостатка:

  • h:link Запускает запрос GET, а не POST-запрос. DataModel#getRowData() Здесь также бесполезно, поскольку вы не можете присоединять действия компонента к компонентам, которые запускают запрос GET.

  • <h:dataTable value="#{BookBean.view}"> С public String view() не имеет смысла. Значение datatable должно быть набором элементов, а не методом действия компонента.


Я понимаю, что вы хотите получить ссылку на каждый элемент книги в таблице, которая указывает на некоторую страницу сведений об элементе книги. Исправьте страницу сведений следующим образом:

bookview.xhtml

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

И BookBean следующим образом:

 @ManagedBean
@RequestScoped
public BookBean {

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

    private BookModel currentBook;

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

    // ...
}
  

@ManagedProperty Будет установлен параметр запроса GET. @PostConstruct Будет предварительно загружена нужная книга на основе параметра.

Пожалуйста, обратите внимание, что это не имеет ничего общего с шаблоном получения ПОСЛЕ перенаправления.

Комментарии:

1. Отличный ответ! Хотя вопрос был очень неясным. @user463053 — Взгляните на BaluC balusc.blogspot.com/2010/06 /… опубликуйте отличный пример CRUD. Особенно для правильного использования getRowData(). @BaluC — Кстати, говоря о статусе CSS, я полагаю, он имел в виду теги привязки, к которым ко всем его ссылкам применяется стиль a: visited.

2. @BalusC: Да, вы правильно поняли, чего я хочу достичь. Я попробовал предложенные вами изменения выше, и я столкнулся с этой ошибкой: 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 . Извините, я должен был упомянуть, что я использую OpenJPA в своем первоначальном сообщении. Я обновил свой первоначальный пост дополнительной информацией, чтобы показать вам, что я пытаюсь сделать.

3. @BalusC: Я удалил тег post-redirect-get и обновил сообщение другими тегами, которые, я надеюсь, более тесно связаны с моим вопросом.

4. Согласно вашей правке, очистите / перестройте / повторно разверните / перезапустите ваше веб-приложение / сервер.

5. @BalusC: Я закрываю Eclipse, удаляю каталог сборки проекта, удаляю каталог проекта в eclipseApps каталоге Glassfish, запускаю Eclipse, создаю проект, запускаю Glassfish — но все та же ошибка. Согласно моему обновлению выше, id это первичный ключ, который, я думаю, требуется для EntityManager#find метода. Может ли это быть проблемой OpenJPA? Я также выполнил поиск по сообщению об ошибке, но ничего полезного не появилось.