Tải bản đầy đủ (.pdf) (96 trang)

Khởi đầu với JavaServer Faces 1.2, Phần 2: Vòng đời, phép chuyển đổi, duyệt tính hợp lệ, và trình nghe pha của JSF pdf

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (1.4 MB, 96 trang )

Khởi đầu với JavaServer Faces 1.2, Phần 2: Vòng đời, phép chuyển đổi, duyệt
tính hợp lệ, và trình nghe pha của JSF
Richard Hightower, CTO, ArcMind
Tóm tắt: Loạt bài hướng dẫn bao gồm cách làm thế nào để bắt đầu khởi động
công nghệ Java™ Server Faces (JSF), một khung công tác phía máy chủ, cung cấp
một cách tiếp cận dựa vào thành phần để phát triển giao diện người dùng web.
Phần 1 dẫn bạn bắt đầu với một tổng quan JSF 1.2 và một ứng dụng cơ bản. Phần
tiếp theo này sẽ làm cho bạn nắm vững các tính năng cao cấp hơn của JSF: các
trình duyệt tính hợp lệ, các trình chuyển đổi và trình nghe pha tùy biến theo yêu
cầu. Cùng với hướng dẫn này bạn sẽ hiểu rõ về vòng đời của ứng dụng JSF.
Trước khi bạn bắt đầu
Về loạt bài này
Giới thiệu mở đầu về công nghệ Java™ Server Faces (JSF), một khung công tác
thành phần giao diện người dùng phía máy chủ cho các ứng dụng web dựa trên
Java. Loạt bài này dành cho các nhà phát triển, những người mới bắt đầu tìm hiểu
JSF và muốn tiến nhanh — không chỉ với JSF, mà với cả việc sử dụng các thành
phần JSF để giảm công sức. Loạt bài này trình bày chỉ những điều cốt yếu, với rất
nhiều ví dụ.
JSF là một môi trường phát triển GUI khá truyền thống, giống như AWT, SWT,
và Swing. Một trong những lợi ích chính của nó là nó làm cho việc phát triển Web
dễ dàng hơn bằng cách giao những công việc khó khăn cho các nhà phát triển
khung công tác, chứ không phải cho các nhà phát triển ứng dụng. Cứ cho là bản
thân JSF phức tạp hơn nhiều so với các khung công tác Web khác, nhưng sự phức
tạp này được che giấu không để cho các nhà phát triển ứng dụng biết. Phát triển
các ứng dụng Web trong JSF dễ dàng hơn nhiều so với hầu hết các khung công tác
khác: nó đòi hỏi viết mã ít hơn, ít phức tạp hơn, và ít việc cấu hình hơn.
Nếu bạn đang thực hiện phát triển Java phía máy chủ, JSF là khung công tác dễ
nhất để tìm hiểu. Nó được định hướng để tạo các ứng dụng Web (không chỉ là các
trang web). Nó cho phép bạn tập trung vào việc mã hóa Java của bạn mà không
cần đối phó với các đối tượng yêu cầu, các đối tượng phiên, các thông số yêu cầu,
hoặc đối phó với các tệp tin XML phức tạp. Với JSF, nhiều thứ thực hiện nhanh


hơn so với các khung công tác Web Java khác.


Về hướng dẫn này
Về hướng dẫn này Phần 1 đã để lại. Nếu bạn là người mới bắt đầu với JSF, hoặc
chỉ muốn ôn lại, thì hãy đọc bài đã đăng đầu tiên trước khi bạn bắt đầu phần này.
Thậm chí nếu bạn là một người chuyên nghiệp về JSF già dặn, có một hay hai khả
năng được đánh giá cao thì điều đó cũng sẽ giúp bạn.
Mặc dù hỗ trợ công cụ là một lợi ích chính của JSF, bạn sẽ không sử dụng các
công cụ ưa thích hay sự hỗ trợ của IDE trong hướng dẫn này. Hướng dẫn này đề
cập những điểm cốt yếu, với thông tin nền tảng để tiếp tục trình bày và để giữ cho
bạn cách học tập có hiệu quả việc sử dụng JSF để xây dựng các ứng dụng Web.


Các mục tiêu
Trong hướng dẫn này sẽ: tiếp tục nhìn tổng quan về các tính năng của JSF và học
cách làm việc với tất cả các thành phần JSF; xây dựng một ứng dụng đơn giản
quản lý các mối giao tiếp — một danh sách liệt kê CRUD cơ bản (tạo, đọc, cập
nhật, xóa); sau khi tìm hiểu về vòng đời của ứng dụng JSF, cải tiến ứng dụng này
với các trình chuyển đổi (converter) và các trình duyệt tính hợp lệ (validator).
Hướng dẫn này uốn khúc với một chút hương vị về lập trình JSF cao cấp: tạo một
khung công tác duyệt tính hợp lệ mức đối tượng bằng cách sử dụng một trình nghe
pha.


Ai nên tìm hiểu hướng dẫn này?
Nếu bạn là người mới bắt đầu tìm hiểu JSF, hướng dẫn này để dành cho bạn. Ngay
cả khi bạn đã sử dụng JSF nhưng chưa thử nghiệm các tính năng JSF 1.2 hoặc chỉ
sử dụng các công cụ GUI để xây dựng các ứng dụng JSF, bạn sẽ có khả năng học
hỏi được rất nhiều từ cả hai hướng dẫn trong loạt bài này.



Các yêu cầu tiên quyết
Hướng dẫn này được viết cho các nhà phát triển Java có kinh nghiệm ở mức bắt
đầu tới mức trung cấp. Bạn cần phải có hiểu biết chung về cách sử dụng ngôn ngữ
Java, cùng với một số kinh nghiệm phát triển giao diện đồ họa người dùng (GUI).


Các yêu cầu hệ thống
Để chạy các ví dụ trong hướng dẫn này, bạn cần có một môi trường phát triển Java
(JDK) và Maven Apache. Nó giúp để có một IDE Java. Các tệp tin dự án Maven
và các tệp tin dự án trong Eclipse Java EE và Web Tools Project (WTP) được
cung cấp. Xem Tải về để nhận được mã ví dụ. Hãy truy cập vào trang web sách
hướng dẫn của tác giả (xem Tài nguyên) để biết thêm thông tin về cách làm thế
nào để chạy các ví dụ này.
Ứng dụng CRUD JSF mẫu
Phần này giới thiệu một ứng dụng CRUD đơn giản mà bạn sẽ xây dựng trong các
phần tiếp sau để tìm hiểu về:
 Từng thành phần HTML tiêu chuẩn của JSF
 Tạo các trình biến đổi tùy biến
 Làm việc với các trình duyệt tính hợp lệ
 Làm việc với các trình nghe pha

Một ứng dụng quản lý các mối giao tiếp
Ứng dụng mà bạn sẽ xây dựng trong phần này là một ứng dụng quản lý giao tiếp
có cấu trúc giống như ứng dụng máy tính bỏ túi trong Phần 1. Như bạn có thể thấy
trong Hình 1, ứng dụng này là một danh sách CRUD tiêu chuẩn. Nó không yêu
cầu các quy tắc dẫn hướng do toàn bộ ứng dụng sử dụng chỉ một khung nhìn đơn
(trang contacts.jsp).


Hình 1. Ứng dụng mẫu quản lý các mối giao tiếp


Hình 2 Cho thấy lưu đồ cơ sở của ứng dụng:

Hình 2. Ứng dụng mẫu quản lý các mối giao tiếp, sơ đồ liên kết


Ứng dụng CRUD này bao gồm các phần tử sau đây:
 ContactController: Trình điều khiển JSF
 Contact: Đối tượng mô hình để mô tả thông tin về các mối giao tiếp
 ContactRepository: Đối tượng mô hình để tạo, đọc, cập nhật, và xóa các đối
tượng Contact
 contacts.jsp: Trang JavaServer Pages (JSP) để bố trí cây thành phần JSF
quản lý các giao tiếp
 faces-config.xml: Cấu hình JSF, nơi bạn khai báo ContactController và
ContactRepository như là các bean quản lý và nội xạ ContactRepository và
ContactController


Trình điều kiển giao tiếp (ContactController)
ContactController hậu thuẫn trang contacts.jsp. Listing 1 hiển thị mã cho
ContactController:

Listing 1. ContactController

package com.arcmind.contact.controller;

import java.util.List;


import javax.faces.application.FacesMessage;
import javax.faces.component.UICommand;
import javax.faces.component.UIForm;
import javax.faces.context.FacesContext;

import com.arcmind.contact.model.Contact;
import com.arcmind.contact.model.ContactRepository;

public class ContactController {
/** Contact Controller collaborates with contactRepository. */
private ContactRepository contactRepository;

/** The current contact that is being edited. */
private Contact contact = new Contact();

/** Contact to remove. */
private Contact selectedContact;

/** The current form. */
private UIForm form;

/** Add new link. */
private UICommand addNewCommand;

/** Persist command. */
private UICommand persistCommand;

/** For injection of collaborator. */
public void setContactRepository(ContactRepository contactRepository) {
this.contactRepository = contactRepository;

}

public void addNew() {
form.setRendered(true);
addNewCommand.setRendered(false);
persistCommand.setValue("Add");
}

public void persist() {
form.setRendered(false);
addNewCommand.setRendered(true);
if (contactRepository.persist(contact) == null) {
addStatusMessage("Added " + contact);
} else {
addStatusMessage("Updated " + contact);
}
}

public void remove() {
contactRepository.remove(selectedContact);
addStatusMessage("Removed " + selectedContact);
}

public void read() {
contact = selectedContact;
form.setRendered(true);
addNewCommand.setRendered(false);
addStatusMessage("Read " + contact);
persistCommand.setValue("Update");
}


private void addStatusMessage(String message) {
FacesContext.getCurrentInstance().addMessage(null,
new FacesMessage(FacesMessage.SEVERITY_INFO, message, null));
}

//most getter/setter omitted

}

Listing 1 tạo ra một GUI CRUD với chưa đến 74 dòng mã — không quá tệ có phải
không.ContactController được quản lý trong phạm vi, yêu cầu , do đó một Contact
mới được tạo ra khi một ContactController được khởi tạo. Ba thành phần — biểu
mẫu (form) (có kiểu là UIForm), addNewCommand (có kiểu là UICommand), và
persistCommand (có kiểu là UICommand) — được liên kết với ContactController.
Phương thức addNew() đảm bảo rằng:
 biểu mẫu (form) được bật lên để người sử dụng có thể nhập vào một giao
tiếp mới — form.setRendered(true)
 addNewCommand được tắt đi — addNewCommand.setRendered(false)
 nhãn của persistCommand được đặt là Add —
persistCommand.setValue("Add")
Phương thức persist() vừa xử lý cập nhật mối giao tiếp hiện có và vừa xử lý bổ
sung thêm mối giao tiếp mới bằng cách sử dụng contactRepository. Phương thức
persist() tắt form bật addNewCommand. Phương thức remove() loại bỏ mối giao
tiếp ra khỏi hệ thống bằng cách sử dụng contactRepository.
Phương thức read() sao chép selectedContact (có kiểu là Contact) vào một mối
giao tiếp. (Mối giao tiếp — cũng có kiểu là Contact — có giá trị liên kết với biểu
mẫu). Bạn có thể tự hỏi selectedContact bắt nguồn từ đâu. Nó được chọn khi
người dùng nhấn vào một mối giao tiếp trong danh sách các mối giao tiếp. (Hướng
dẫn này sẽ đề cập khi thảo luận về JSP.) Như trong Phần 1, addStatusMessage bổ

sung thêm các thông báo trạng thái để bạn có thể hiển thị chúng với
<h:messages>.


Khung nhìn các mối giao tiếp
Trang JSP sử dụng một <h:dataTable> (một thành phần không được giới thiệu
trong Phần 1), như hiển thị trong Listing 2:

Listing 2. contacts.jsp

<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ taglib uri=" prefix="h"%>
<%@ taglib uri=" prefix="f"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"

<html xmlns="
<head>
<title>Contacts</title>
<link rel="stylesheet" type="text/css"
href="<%=request.getContextPath()%>/css/main.css" />
</head>

<body>
<f:view>
<h4>Contacts</h4>

<h:messages infoClass="infoClass" errorClass="errorClass"
layout="table" globalOnly="true" />


<h:form>
<h:commandLink binding="#{contactController.addNewCommand}"
action="#{contactController.addNew}" value="Add New " />
</h:form>

<h:form binding="#{contactController.form}" rendered="false"
styleClass="form">

<h:inputHidden value="#{contactController.contact.id}" />
<h:panelGrid columns="6">
<% First Name %>
<h:outputLabel value="First Name" for="firstName" accesskey="f" />
<h:inputText id="firstName" label="First Name" required="true"
value="#{contactController.contact.firstName}" size="10" />
<h:message for="firstName" errorClass="errorClass" />

<% Last Name %>
<h:outputLabel value="Last Name" for="lastName" accesskey="l" />
<h:inputText id="lastName" required="true"
value="#{contactController.contact.lastName}" size="15" />
<h:message for="lastName" errorClass="errorClass" />
</h:panelGrid>
<h:panelGroup>
<h:commandButton binding="#{contactController.persistCommand}"
action="#{contactController.persist}" />
</h:panelGroup>
</h:form>
<h:form>
<h:dataTable value="#{contactController.contacts}" var="contact"

rowClasses="oddRow, evenRow"
rendered="#{not empty contactController.contacts}"
styleClass="contactTable" headerClass="headerTable"
columnClasses="normal,centered">
<h:column>
<f:facet name="header">
<h:column>
<h:outputText value="Name" />
</h:column>
</f:facet>
<h:outputText value="#{contact.lastName}, #{contact.firstName}" />
</h:column>
<h:column>
<f:facet name="header">
<h:column>
<h:outputText value="Action" />
</h:column>
</f:facet>
<h:panelGrid columns="2">
<h:commandLink value="remove"
action="#{contactController.remove}">
<f:setPropertyActionListener
target="#{contactController.selectedContact}" value="#{contact}" />

</h:commandLink>
<h:commandLink value="edit" action="#{contactController.read}">
<f:setPropertyActionListener
target="#{contactController.selectedContact}" value="#{contact}" />

</h:commandLink>

</h:panelGrid>
</h:column>

</h:dataTable>
</h:form>
</f:view>
</body>

</html>


<h:dataTable> là giá trị được liên kết để hiển thị các mối giao tiếp từ
contactController, khi sử dụng "#{contactController.contacts}". Mỗi mối giao tiếp
được ánh xạ vào bảng bằng cách sử dụng thuộc tính: var="contact". Trong
contacts.jsp, các kiểu dáng (style) oddRow và evenRow (được định nghĩa trong
một tệp tin CSS) được đặt vào trong thuộc tính rowClasses với
rowClasses="oddRow, evenRow". Điều này cho phép <h:dataTable> sử dụng các
kiểu dáng luân phiên cho các hàng trong bảng. Hãy kiểm tra tài liệu hướng dẫn
trực tuyến <h:dataTable> để tìm một danh sách đầy đủ về những cái có thể làm
với <h:dataTable> và các kiểu dáng, bởi vì <h:dataTable> có khá nhiều khả năng.
(Xem Tài nguyên để tìm liên kết đến JSF API Javadocs).
Bạn cũng có thể thiết lập một kiểu dáng cho toàn bộ <h:dataTable>
vớistyleClass="contactTable" hoặc cho vùng tiêu đề của nó với
headerClass="headerTable". Hoặc bạn có thể thực hiện các kiểu dáng luân phiên
tương tự như thế cho các cột bằng cách sử dụng thuộc tính columnClasses:
columnClasses="normal,centered". <h:dataTable> được thiết lập để nó không
hoàn trả nếu không có mối giao tiếp: rendered="#{not empty
contactController.contacts}"nào. Thành phần <h:dataTable> rất linh hoạt và dễ sử
dụng.
Bên trong <h:dataTable>, bạn sử dụng các <h:column> để hiển thị các giá trị theo

các thuộc tính. Mỗi cột định nghĩa một phần tiêu đề trong một thẻ <f:facet>. Một
facet là một thành phần tên mà các thành phần khác sử dụng. Vậy thì sau <f:facet>
và bên trong thành phần <h:column> bạn hãy sử dụng thành phần <h:outputText>
để đưa ra các thuộc tính firstName và lastName.
Mỗi hàng có một liên kết loại bỏ và một liên kết chỉnh sửa, mỗi liên kết sử dụng
một <h:commandLink>. commandLink loại bỏ được liên kết với phương thức
contactController.remove. Liên kết chỉnh sửa được liên kết với phương thức
contactController.read . Thuộc tính contactController.selectedContact được điền
bằng hàng hiện tại theo cách bạn cấu hình <f:setPropertyActionListener>.
<f:setPropertyActionListener> làm cho mối giao tiếp của hàng hiện tại được sao
chép vào selectedContact trước khi phương thức hành động được gọi.


Tệp faces-config.xml cho ứng dụng CRUD của các mối giao tiếp
Tệp tin faces-config.xml nối ContactRepository vào trong ContactController, như
hiển thị trong Listing 3:

Listing 3. faces-config.xml

<managed-bean>
<managed-bean-name>contactRepository</managed-bean-name>
<managed-bean-class>
com.arcmind.contact.model.ContactRepository
</managed-bean-class>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-name>contactController</managed-bean-name>
<managed-bean-class>
com.arcmind.contact.controller.ContactController

</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>contactRepository</property-name>
<property-class>
com.arcmind.contact.model.ContactRepository
</property-class>
<value>#{contactRepository}</value>
</managed-property>
</managed-bean>

Lưu ý rằng contactRepository nằm trong phạm vi ứng dụng và nó được nội xạ vào
trong contactRepository của contactController bằng cách sử dụng phần tử
<managed-property>. Kỹ thuật này cho phép bạn nội xạ các phụ thuộc/các trình
cộng tác vào trong trình điều khiển để hỗ trợ việc duy trì mô hình và khung nhìn
riêng biệt, và nó cho phép bạn nội xạ các đối tượng giả để sau này có thể được
thay thế bằng các đối tượng thực. Nhiều hơn một lần, tôi đã làm giả một đối tượng
mô hình như ContactRepository và sau đó thay thế nó bằng phiên bản thực sau khi
hoàn thành GUI.
Mô hình của ứng dụng là khá đơn giản, như hiển thị trong các Listings 4 và 5.
Listing 4 hiển thị lớp Contact:

Listing 4. Contact

package com.arcmind.contact.model;

public class Contact { private String firstName;
private String lastName; protected long id;

public Contact(String firstName, String lastName) {

this.firstName = firstName; this.lastName =
lastName; }

public Contact() { }

public String getFirstName() { return firstName; }

public void setFirstName(String firstName) {
this.firstName = firstName; }

public String getLastName() { return lastName; }

public void setLastName(String lastName) {
this.lastName = lastName; }

@Override public int hashCode() { final int prime =
31; int result = 1; result = prime * result + (int)
(id ^ (id >>> 32)); return result; }

@Override public boolean equals(Object obj) { if
(this == obj) return true; if (obj == null) return
false; if (getClass() != obj.getClass()) return
false; final Contact other = (Contact) obj; if (id
!= other.id) return false; return true; }

@Override public String toString() { return
String.format("Contact: %s %s", firstName,
lastName); }

public long getId() { return id; }


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

}

Listing 5 hiển thị lớp ContactRepository, để mô phỏng việc viết các mối giao tiếp
vào một cơ sở dữ liệu:

Listing 5. ContactRepository

package com.arcmind.contact.model;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;

public class ContactRepository {
private Map<Long, Contact> contacts = new LinkedHashMap<Long,
Contact>();
private static long counter = 1l;

public List<Contact> getContacts() {
return new ArrayList<Contact>(contacts.values());
}

public synchronized Contact persist(Contact contact) {
if (contact.id == 0) {
contact.id = counter++;
}

return contacts.put(contact.id, contact);
}

public synchronized void remove(Contact contact) {
contacts.remove(contact.id);
}

}

Những gì bạn có bây giờ là một ứng dụng CRUD khá cơ bản. Trong phần kế tiếp,
bạn sẽ xây dựng bên trên cơ sở này để tìm hiểu cách làm thế nào để sử dụng các
thành phần JSF khác nhau.
Làm việc với các thành phần JSF
Trong phần này, bạn sẽ sử dụng nhiều thành phần JSF để nâng cao ứng dụng
CRUD:
 <f:subview>
 <h:selectOneMenu>
 <h:selectOneRadio>
 <h:selectBooleanCheckbox>
 <h:selectManyCheckbox>
 <h:inputTextarea>

Hình 3 cho thấy các thành phần này xuất hiện trong GUI như thế nào:



Hình 3. Quản lý các mối giao tiếp với một số lượng lớn các thành phần JSF
phổ biến

Các khung nhìn phụ

Như bạn có thể hình dung, thật khó để bao gồm tất cả các thành phần JSF của bạn
trên một trang web. May mắn thay, bạn có thể phân chia các thành phần JSF theo
các khung nhìn riêng biệt bằng cách sử dụng một <f:subview>, như hiển thị trong
Listing 6:

Listing 6. Các khung nhìn phụ contacts.jsp

<body>
<f:view>
<h3>Contacts (2nd version)</h3>
<h:messages infoClass="infoClass" errorClass="errorClass"
layout="table" globalOnly="true" />

<h:form>
<h:commandLink binding="#{contactController.addNewCommand}"
action="#{contactController.addNew}" value="Add New " />
</h:form>

<f:subview id="form">
<jsp:include page="form.jsp" />
</f:subview>

<f:subview id="listing">
<jsp:include page="listing.jsp" />
</f:subview>

</f:view>
</body>

Bạn có thể sử dụng các <f:subview> trong trang cha mẹ hay trong trang bao gồm

(chứ không phải cả hai). Trong JSF 1.2 <f:subview> là tùy chọn. Trong các phiên
bản JSF cũ hơn, nó là bắt buộc. Một số các IDE hình như cũng chờ đợi các
<f:subview>, do đó bạn có thể cần sử dụng chúng ngay cả khi bạn đang sử dụng
JSF 1.2 hoặc phiên bản mới hơn.


Chọn một
Trong JSF, các thành phần được tách thành hai phần: thành phần JSF chính nó và
một trình hoàn trả có trách nhiệm hiển thị thành phần đó. Thành phần
UISelectOne có một số trình hoàn trả. Nó hậu thuẫn HtmlSelectOneListbox,
HtmlSelectOneMenu, và HtmlSelectOneRadio.
Ứng dụng quản lý các mối giao tiếp (phiên bản thứ 2) sử dụng
<h:selectOneMenu>. Để điều này hoạt động, bạn bổ sung thêm ba đối tượng mô
hình mới: Group (chỉ ra trong Listing 7), Thẻ (Tag), và ContactType. Bạn cũng
thêm hai đối tượng kho lưu trữ mới: GroupRepository và TagRepository, tương tự
như ContactRepository. ContactType không cần có một kho lưu trữ bởi vì nó là
một Bảng kê (Enum). Lớp Contact hiện nay có ba thuộc tính mới dành cho nhóm
có nó ở trong đó (được gọi là group), dành cho các thẻ có kết hợp với nó (tags), và
cuối cùng là dành cho kiểu của nó type.

Listing 7. Các khung nhìn phụ contacts.jsp/form.jsp

<% Group %>
<h:outputLabel value="Group" for="group" accesskey="g" />
<h:selectOneMenu id="group" validatorMessage="required"
value="#{contactController.selectedGroupId}">
<f:selectItems value="#{contactController.groups}" />
<f:validateLongRange minimum="1" />
</h:selectOneMenu>
<h:message for="group" errorClass="errorClass" />


Lưu ý rằng selectOneMenu sử dụng thuộc tính giá trị để liên kết selectOneMenu
với selectedGroupId. Phần thân của selectOneMenu chứa một <f:selectItems>, đó
là giá trị liên kết với thuộc tính các nhóm: value=#{contactController.groups}.
Bạn tạo ra một danh sách các nhóm trong bean phía sau. Mã cho thuộc tính
selectedGroupId và thuộc tính các nhóm có trong Listing 8:

Listing 8. Xây dựng một danh sách của các nhóm

public class ContactController {

private GroupRepository groupRepository;

private Long selectedGroupId;

public List<SelectItem> getGroups() {
List<Group> groups = groupRepository.list();
List<SelectItem> list = new ArrayList<SelectItem>(groups.size()+1);
list.add(new SelectItem(Long.valueOf(-1L), "select one"));
for (Group group : groups) {
SelectItem selectItem = new SelectItem(group.getId(), group.getName());
list.add(selectItem);
}
return list;
}
//Other getter/setters removed


Thuộc tính các nhóm (groups) trả về một danh sách các SelectItem. Lớp
SelectItem được sử dụng để biểu diễn một mục trong một danh sách. Nó được cả

hai thành phần UISelectMany và UISelectOne sử dụng. Lưu ý rằng phương thức
getGroups sử dụng groupRepository, đây là một đối tượng kho lưu trữ, được nội
xạ như contactRepository để nhận một danh sách các nhóm. The groupRepository
quản lý các đối tượng Group . Một Group đại diện cho một nhóm. Một Contact đại
diện một mối giao tiếp. Phương thức getGroups() tạo ra một danh sách các
SelectItem bằng cách sử dụng thuộc tính group.id như là một giá trị và thuộc tính
group.name như là một nhãn.
Lưu ý rằng bạn thêm một SelectItem "chọn một" với giá trị là -1. Bạn sử dụng giá
trị này để xác định một mục có được lựa chọn không. Nếu nó không được lựa
chọn, bạn chọn mục chưa được chọn bằng cách sử dụng <f:validateLongRange
minimum="1" /> ở trong selectOneMenu (xem lại Listing 7). Cũng cần chú ý rằng

×