2014-11-07 3 views
1

У меня есть приложение JSF2, которое должно показывать страницу, в которой необходимо добавить число os элементов в списке. Пользователь хочет добавить эти элементы, установить некоторые их свойства и, наконец, сохранить их все вместе, в одной операции сохранения.Как сохранить список объектов в Java Server Faces 2

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

public class Item { 
    private long id; 
    private String name; 
    private Item previous; 

    public Item() { } 

    public Item(Item previousItem) { 
     this.previous = previousItem; 
    } 

    public long getId() { 
     return id; 
    } 
    public void setId(long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 

    public Item getPrevious() { 
     return previous; 
    } 

}

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

@ManagedBean 
public class ItemBean implements Serializable { 
    private static final long serialVersionUID = 1L; 

    private List<Item> items = new ArrayList<Item>(); 

    public List<Item> getItems() { 
     if(items.size()==0) { 
      items.add(new Item()); // adding the first item 
     } 
     return items; 
    } 

    public void setItems(List<Item> items) { 
     this.items = items; 
    } 

    public void addItem(Item previousItem) { 
     Item newItem = new Item(previousItem); 
     items.add(newItem); 
    } 

    public void save() { 
     ... 
    } 
} 

мнение является xhtml файл что выглядит следующим образом:

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" 
    xmlns:h="http://java.sun.com/jsf/html" xmlns:ui="http://java.sun.com/jsf/facelets"> 
<body> 
<ui:composition template="/templates/layout.xhtml"> 
<ui:define name="content"> 
<h2>Items</h2> 
<fieldset> 
    <legend>Items being added</legend> 
    <ui:repeat value="#{itemBean.items}" var="item"> 
    <div> 
     <h:outputLabel value="Item" for="name" /> 
     <h:inputHidden value="#{item.id}" /> 
     <h:inputText id="name" value="#{item.name}" /> 
     <h:commandLink action="#{itemBean.addItem(item)}">Add</h:commandLink> 
    </div> 
    </ui:repeat> 
</fieldset> 
<div class="options"> 
<h:commandButton action="#{itemBean.save}" value="Save"/> 
<div class="clear border-bottom"></div> 
</div> 
</ui:define> 
</ui:composition> 
</body> 
</html> 

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

Проблема в том, что я могу добавить второй элемент без проблем, но когда я нажимаю ссылку «Добавить» рядом со вторым элементом, страница перезаписывается одним отдельным элементом, как и в начале.

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

Update 1

меня спрашивали о том, какой объем используемой с этим компонентом. Это область по умолчанию (@RequestScoped). Я пытался избежать использования @SessionScoped ради масштабируемости, но в этом конкретном случае я не уверен, что у меня есть выбор. Любой, у кого больше опыта, может дать мне совет?

ответ

2

Какова область действия вашего ManagedBean?

Поскольку вы не опубликовали код персистентности, я полагаю, что список items существует только в зависимости от вашей жизни Бина. Это означает, что если ваш Bean равен @ViewScoped или @RequestScoped, ваши товары перестанут существовать после отправки вашей формы.

+0

Спасибо за ваш ответ! Область действия - '@ RequestScoped', которая по умолчанию предназначена для управляемых компонентов. Я собирался спросить именно об этом.Я понимаю, что бит был уничтожен после того, как представление построено и возвращено в браузер, однако в других случаях, когда я поддерживал один экземпляр, JSF был достаточно умен, чтобы установить свойство одного экземпляра в состояние, которое было на этой странице, и я был ожидая того же самого для коллекции. Поскольку компоненты '@ SessionScoped' уменьшают масштабируемость приложения, я пытался избежать его. Что ты говоришь? Использует '@ SessionScoped' мой единственный выбор в этом сценарии? – AlexSC

+0

@AlexSC Действительно, '@ SessionScoped' позволит вам сохранять ваши объекты на протяжении всего сеанса пользователя. Или вы можете сохранить свои объекты где-нибудь (sessionMap, файл, hibernate ...) – Thrax

+0

'@ NoneScoped' - это область по умолчанию для управляемых компонентов @AlexSC – kolossus

0

Вы должны использовать AJAX компонент, что-то вроде:

<fieldset id="list"> 
    <legend>Items being added</legend> 
    <ui:repeat value="#{itemBean.items}" var="item"> 
    <div> 
     <h:outputLabel value="Item" for="name" /> 
     <h:inputHidden value="#{item.id}" /> 
     <h:inputText id="name" value="#{item.name}" /> 
     <h:commandLink action="#{cargoBean.addItem(item)}"> 
      <f:ajax render="list" /> 
       Add 
     </h:commandLink> 
    </div> 
    </ui:repeat> 
</fieldset> 
+0

Спасибо за вашу попытку, но когда я добавил элемент '', и ссылка была снова видимой, но исходная проблема все еще происходит. Любое другое предложение? – AlexSC

0

Я не вижу никакой формы на странице Xhtml как:

<h:form> 
    <ui:repeat> 
     <h:inputBlabla/> 
    </ui:repeat> 
</h:form> 

форма необходима при использовании ч: поля ввода.

+0

Спасибо за ваш ответ. Это композиционный вид. Используемый шаблон имеет форму, поэтому здесь вы видите только одну часть всего представления. Я могу утверждать, что в финальном/составном виде есть форма. – AlexSC