2012-05-28 2 views
1

Я разрабатываю сайт, используя стандартные компоненты Java EE, такие как JSF 2.0, CDI, EJB и JPA. Это на ранней стадии, поэтому навигация довольно проста. Проблема в том, что у меня есть трудности с сохранением некоторых данных при навигации.Запрос облачной навигации по страницам

Вот seminarController поддержки боб:

SeminarController.java

@Named 
@RequestScoped 
public class SeminarController { 
    @Inject 
    private SeminarDao seminarDao; 

    private int seminarID; 
    private Seminar seminar; 

    ... 
    // Getters and setters 
    ... 

    public Collection<Seminar> getSeminars() {...} 

    public Collection<Seminar> getUpcomingSeminars() {...} 

    public void initSeminar() { 
     seminar = seminarDao.findSeminar(seminarID); 
    } 

    public String save() { 
     seminarDao.save(seminar); 
     return "details"; 
    } 
} 

Первая страница в настоящее время только перечисляя некоторые семинары, которые предстоящие и может представлять interrest.

index.xhtml

<ul> 
     <ui:repeat value="#{seminarController.upcomingSeminars}" var="seminar"> 
      <li> 
       <h:link value="#{seminar.title}" outcome="details"> 
        <f:param name="id" value="#{seminar.seminarID}"/> 
       </h:link> 
       on 
       <h:outputText value="#{seminar.eventDate}"/> 
      </li> 
     </ui:repeat> 
    </ul> 

Как вы можете видеть, у меня есть список со ссылками, которые будут принимать меня к деталям, если я нажимаю ссылку. Я использую f:param, чтобы добавить идентификатор семинара в параметры HTTP-запроса.

На странице с подробными сведениями вы найдете более подробную информацию (конечно) о предстоящем семинаре. Семинар можно также отредактировать, нажав на ссылку.

details.xhtml

<f:metadata> 
    <f:viewParam name="id" value="#{seminarController.seminarID}"/> 
    <f:event type="preRenderView" listener="#{seminarController.initSeminar}"/> 
</f:metadata> 
<ui:define name="body"> 

    <h2>#{seminarController.seminar.title}</h2> 

    <p> 
     <strong>When:</strong> 
     #{seminarController.seminar.eventDate} 
    </p> 
    <p> 
     <strong>Where:</strong> 
     #{seminarController.seminar.address}, 
     #{seminarController.seminar.country} 
    </p> 
    ... 
    <p> 
     <h:link value="Edit" outcome="edit"> 
      <f:param name="id" value="#{seminarController.seminarID}"/> 
     </h:link> | 
     <h:link value="Back to List" outcome="index"/> 
    </p> 

До сих пор так хорошо, все работает отлично.

Теперь мы переходим по ссылке, чтобы редактировать семинар, и мы переходим на страницу редактирования. Мы по-прежнему используем f:param для идентификатора текущего семинара.

edit.xhtml

<f:metadata> 
    <f:viewParam name="id" value="#{seminarController.seminarID}"/> 
    <f:event type="preRenderView" listener="#{seminarController.initSeminar}"/> 
</f:metadata> 
<ui:define name="body"> 
    <h:form> 
     <h:messages title="Please correct the errors and try again."/> 
     <fieldset> 
      <h:panelGroup class="editor-label" layout="block"> 
       <h:outputLabel value="Seminar Title:" for="title"/> 
      </h:panelGroup> 
      <h:panelGroup class="editor-field" layout="block"> 
       <h:inputText id="title" value="#{seminarController.seminar.title}"/> 
       <h:message for="title" title="*"/> 
      </h:panelGroup> 
      ... 
      <p> 
       <h:commandButton value="Save" action="#{seminarController.save}"> 
        <f:param id="id" value="#{seminarController.seminar.seminarID}"/> 
       </h:commandButton> 
      </p> 
     </fieldset> 
    </h:form> 

Это где я начинаю есть проблемы. Я хочу вернуться к странице сведений, когда нажата кнопка «Сохранить». На странице сведений должен быть показан текущий семинар с обновленной информацией. Проблема в том, что при нажатии кнопки «Сохранить» объект seminar в seminarController равен null.

Когда визуализируется визуализация, объект семинара инициализируется и используется для отображения текущих значений в форме. Но когда нажата кнопка «Сохранить», объект семинара больше не существует в seminarController. И метод initSeminar также не называется.

Итак, вопрос в том, как я должен проектировать навигацию по дизайну и редактированию?

ViewScope не работает, так как при нажатии кнопки «Сохранить» я перехожу к новому виду. И ViewScope не существует при использовании CDI.

Любая помощь была бы признательна Вам!


Редактировать

Класс Семинар имеет несколько полей, которые не будут видны в форме.

Seminar.java

@Entity 
public class Seminar { 
    @Id 
    private int seminarID; 
    @Column 
    private String title; 
    @Column 
    private Date eventDate; // Date when the seminar occurs 
    @Column 
    private Date createdDate; // Not visible in forms 
    ... 
    // Some more fields and Getters/Setters 
} 

Edit2:

Я закончил тем, что делал это в SeminarController:

SeminarController.java

@PostConstruct 
public void init() { 
    if (FacesContext.getCurrentInstance().isPostback()) { 
     seminar = new Seminar(); 
    } else { 
     seminar = seminarDao.findSeminar(seminarID); 
    } 
} 

public void setSeminarID(int seminarID) { 
    if (this.seminarID != seminarID) { 
     seminar = seminarDao.findSeminar(seminarID); 
     this.seminarID = seminarID; 
    } 
} 

public String save() { 
    seminarDao.save(seminar); 
    return "details?faces-redirect=true&includeViewParams=true"; 
} 

И затем я добавил <h:inputHidden value="#{seminarController.seminarID}"/> в edit.xhtml.

The <f:event/> был соответственно изменен в details.xhtml и edit.xhtml вызвать метод init() вместо старого initSeminar().

Это похоже на работу, хотя я не очень нравится, что seminar объект создается с помощью new в пост-спине, а затем он будет перезаписан, когда seminarID создается.

ответ

2

Вы должны подготовить seminar до того, как будет выполнена фаза значений модели обновления. Событие предварительного рендеринга слишком поздно.

Одним из способов является создание @PostConstruct, где проверить, если текущий запрос является постбэком и если да, то precrate в Seminar так, что JSF имеет возможность ссылаться на свои сеттеров во время модели обновления значений фазы.

@PostConstruct 
public void init() { 
    if (FacesContext.getCurrentInstance().isPostback()) { 
     seminar = new Seminar(); 
    } 
} 

Я не уверен, что initSeminar() делает, но я думаю, вы также должны изменить его соответствующим образом, что он делает свою работу только if (!FacesContext.getCurrentInstance().isPostback()).

+0

ОК, я вижу вашу точку зрения. Когда я перейду от 'detail.xhtml' к' edit.xhtml', 'семинар' будет создан с использованием моего' initSeminar', который создает экземпляр 'семинара', используя' sessionID' и DAO. И когда я возвращаюсь из 'edit.xhtml'to' details.xhtml', я создаю 'семинар' в предложенном вами методе' init'. Я попробую и вернусь. Спасибо! – maba

+0

Проблема с этим решением заключается в том, когда я нажимаю Сохранить объект семинара не содержит всю информацию, полученную из исходного семинара, загруженного из базы данных. Мне нужен семинарID, чтобы я мог найти семинар из базы данных и изменить значения и сохранить обратно в базу данных. Имеет ли это смысл? – maba

+0

Используйте ''. – BalusC