Netbeans: Facelet

Tôi xin giới thiệu một ví dụ nhỏ về Facelete trong netbeans, bạn cần chuẩn bị một số thứ sau:

  • Netbeans 5.5.1

  • NBFaceleteSupportPlugin

  • MySQL 5(hay csdl nào mà bạn có cũng được)

  • Driver

  • Sun Server

  1. Tạo netbeans project

  • New Project

  • Web \ Web application

  • Next

  • Project name : Facelet

  • Server : Sun Java Application Server

  • Next

  • Framework: Facelets

  • Finish

Poject của chúng ta đã sẵn sàng và bạn có thể run để test Facelet. Tiếp theo ta sẽ tạo một Persistence Unit

  • Chuột phải chọn new file / Folder

  • Trong phần Persistence chọn Persistence Unit

  • Next

  • Trong phần Persistence Unit Name ta để mặc định

  • Ta chỉ sửa phần Data Source đế csdl mà ta dùng

  • Chọn Create cho Table Generation Strategy

  • Finish

Tiếp theo, ta tạo một entity

  • new File / Folder

  • Phần Persistence chọn Entity Class

  • Ta đặt tên cho class là Run

  • Package com.bds.entity

  • Finish

Ta cần thêm một số thuộc tính sau

@Temporal(value = TemporalType.DATE)

private Date dateOfRun;

private String location = "";

private int totalHours;

private int totalMinutes;

private int totalSeconds;

private int avgHr;

private float distance;

private String environment = "";


Và đừng quên tạo getter, setter nhé bạn.

Tạo JSF Page

  • new File/Folder

  • Trong phần Persistence chọn JSF Pages From Entity Class

  • Chọn và add entity class Run

  • Next

  • Ta sẽ lưu trong package com.bds.web

  • Finish

Đến đây thì project của ta chạy không được, bởi vì một Facelet Project chỉ chạy các file jsf có đuôi .xhtml. Việc của chúng ta cần làm đơn giản là thay các trang JSF thành xhml và theo cấu trúc Facelet. Tôi sẽ hiện thực trên trang List, và các bạn sẽ làm phần còn lại nhé.

Trước tiên ta sẽ tạo trang navigation

  • Chuột phải vô phần Web Pages chọn new File/Folder

  • Trong phần Web, chọn Facelets Simple File

  • Next

  • Đặt tên : navigation

  • Finish

Có nội dung

<p>

<div class="navitems"><a href="List.jsf">Show all Runs</a></div>

<div class="navitems"><a href="../index.jsp">Home</a></div>

</p>

File template.xhtml của ta có nội dung như sau

<?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:ui="http://java.sun.com/jsf/facelets">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<title>Running around.....</title>

<link href="../css/default.css" rel="stylesheet" type="text/css" />

</head>

<body>

<h1>

<ui:insert name="title">Running around.....</ui:insert>

</h1>

<div id="navi">

<ui:insert name="navigation">

<ui:include src="navigation.xhtml"></ui:include>

</ui:insert>

</div>

<div id="content">

<ui:insert name="content">Hmmm, where is the content?</ui:insert>

</div>

</body>

</html>


Trong trang List.xhtml, ta sẽ kéo thả những thành phần chính ( composition, define, view và form), mục đích của phần này là nó sẻ hiện thực cho ta các không gian tên phù hợp. Sau đó ta chỉ việc copy từ List.jsp qua:

<?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:ui="http://java.sun.com/jsf/facelets"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html">

<body>

<ui:composition template="../template.xhtml">

<ui:define name="content">

<f:view>

<h:messages errorStyle="color: red" infoStyle="color: green" layout="table"/>

<h1>Listing Runs</h1>

<h:form>

<h:commandLink action="#{run.createSetup}" value="New Run"/>

<br />

<h:dataTable value='#{run.runs}' var='item' border="1" cellpadding="2" cellspacing="0">

<h:column>

<f:facet name="header">

<h:outputText value="Id"/>

</f:facet>

<h:commandLink action="#{run.detailSetup}" value="#{item.id}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="DateOfRun"/>

</f:facet>

<h:outputText value="#{item.dateOfRun}">

<f:convertDateTime type="DATE" pattern="MM/dd/yyyy" />

</h:outputText>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="Location"/>

</f:facet>

<h:outputText value="#{item.location}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="TotalHours"/>

</f:facet>

<h:outputText value="#{item.totalHours}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="TotalMinutes"/>

</f:facet>

<h:outputText value="#{item.totalMinutes}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="TotalSeconds"/>

</f:facet>

<h:outputText value="#{item.totalSeconds}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="AvgHr"/>

</f:facet>

<h:outputText value="#{item.avgHr}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="Distance"/>

</f:facet>

<h:outputText value="#{item.distance}"/>

</h:column>

<h:column>

<f:facet name="header">

<h:outputText value="Environment"/>

</f:facet>

<h:outputText value="#{item.environment}"/>

</h:column>

<h:column>

<h:commandLink value="Destroy" action="#{run.destroy}">

<f:param name="id" value="#{item.id}"/>

</h:commandLink>

<h:outputText value=" "/>

<h:commandLink value="Edit" action="#{run.editSetup}">

<f:param name="id" value="#{item.id}"/>

</h:commandLink>

</h:column>

</h:dataTable>

</h:form>

</f:view>

</ui:define>

</ui:composition>

</body>

</html>


Tương tự tạo:

  • New.xhtml

  • Edit.xhtml

  • Details.xhtml

Hoàn tất và run.

Đọc tiếp >>

Cao Trong Hien

Netbeans: Xắp xếp và phân trang trong EJB

trong bài này tôi dùng Netbeans Visual Web Pack, và database TRAVEL. Trong bài này có 2 phần 1) Enterprise application dùng Ejb. 2) Web application hiển thị dữ liệu.

  1. Tạo EJB modul

    tạo ejb project:

  • new project

  • Enterprise / Ejb modul

  • next

  • project name : TravelEjb

  • Server Sun, Java EE Version J2EE 5

  • Finish

Tạo entity class:

  • new file and folder

  • Persistent/ Entity Class from database

  • Create datasource

  • add datasource

  • chọn bảng PERSON

  • next

  • tạo persistent Unit

  • Create

  • Finish

Tạo stateless sessionbean

  • new Session Bean

  • EJB Name: Person, package: com.travel.servise

  • Ta sẽ tạo cả Remote và Local

  • Ta cần thêm 2 thư viện: ToplinkEssentials(có sẵn trong netbeans), Dataprovider.jar(netbeans-home/rave2.0/modules/ext)

  • Trong class PersonBean.java, chuột phải chọn Add Business Method. Ta cần 2 phương thức getPersons(), getcount()

  • Code như sau

public List getPersons(int startPosition, int maxResult, SortCriteria[] sc) {

String query = "select object(o) from Person as o";

if(sc != null){

query = query + " " + "order by " + " " + "o."+sc[0].getCriteriaKey();

if(!sc[0].isAscending()){

query = query + " desc";

}

}

Query q = em.createQuery(query);

q.setMaxResults(maxResult);

q.setFirstResult(startPosition);

return q.getResultList();

}

/* Count */

public int getCount() {

Query q = em.createQuery("select count(o) from Person as o ");

Long count = (Long)q.getSingleResult();

if(count != null){

return count.intValue();

}

return 0;

}


Build

  1. Tạo Web modul

    ta sẽ tạo một visual web application:

  • new project

  • Web/ Visual Web Application

  • Next

  • Project name: TravelWeb

Thêm lib TravelEjb vô TravelWeb

Tạo DataProvider:

  • Tạo class PersonDP

  • Chuột phải lên code chọn Enterprise Resource / call Enterprise Bean

  • Chọn bean Person

  • Thêm vào các phương thức sau: refreshDP(), getRowCount(), next(), previous()

  • Thêm vào 2 thuộc tính: startPosition and maxresults

  • Như sau:

    public class PersonDP extends ObjectListDataProvider{

    /* controls page size*/

    private int maxresults =5;

    /* starting row*/

    private int startPosition;

    /** Creates a new instance of PersonDP */

    public PersonDP() {

    /* needed by netbeans editor */

    setObjectType(Person.class);

    }

    /* fetch a fresh list of persons from ejb layer*/

    public void refreshDP(){

    clearObjectList();

    setList(lookupPersonBean().getPersons(getStartPosition(),getMaxresults(),null));

    }

    /* Fetch sorted list of persons from ejb layer*/

    public void refreshDP(SortCriteria[] sc){

    clearObjectList();

    setList(lookupPersonBean().getPersons(getStartPosition(),getMaxresults(),sc));

    }

    /* find count */

    public int getRowCount() throws DataProviderException {

    if(Beans.isDesignTime()){

    return 5;

    }

    return lookupPersonBean().getCount();}

    public int getMaxresults() {

    return maxresults;

    }

    public void setMaxresults(int maxresults) {

    this.maxresults = maxresults;}

    public int getStartPosition() {

    return startPosition;

    }

    public void setStartPosition(int startPosition) {

    this.startPosition = startPosition;

    refreshDP();

    }

    public void setLastPosition() {

    startPosition = (lookupPersonBean().getCount()/maxresults) * maxresults;

    refreshDP();

    }

    /*move to next page*/

    public void next(){

    if(startPosition + maxresults <= lookupPersonBean().getCount()){

    startPosition = startPosition + maxresults;

    }

    refreshDP();

    }

    public void previous(){

    if(startPosition <>

    startPosition = startPosition - maxresults;

    }

    if (startPosition <>

    startPosition =0;

    }

    refreshDP();

    }

    /* Helper for calling ejb service . Created by netbeans*/

    private PersonLocal lookupPersonBean() {

    try {

    Context c = new InitialContext();

    return (PersonLocal) c.lookup("java:comp/env/ejb/PersonBean");

    } catch(NamingException ne) {

    Logger.getLogger(getClass().getName()).log(Level.SEVERE,"exception caught" ,ne);

    throw new RuntimeException(ne);

    }

    }

    }

Ta sẽ thự hiện phần view như sau:

  • Mở page1.jsp

  • Kéo Table trong Palette\Basic

  • Thêm vào SessionBean1 thuộc tính persondp kiểu PersonDP(khởi tạo luôn)

  • Build TravelWeb và TravelEjb

  • Restart netbeans

  • Mở Page1

  • Chuột phải lên table chọn table layout

  • Get Data Form chọn persondp

  • Trong tab Option chọn Show Clear Sort Button


Tạo EJBTableSorter.java

  • Tạo class EjbTableSorter.java

  • tạo trường ejbTableSorter trong SessionBean1(khởi tạo luôn)

    public class EjbTableSorter implements TableDataSorter , Serializable {

    /** Creates a new instance of EjbTableSorter */

    public EjbTableSorter() {

    }

    protected SortCriteria sortCriteria[];

    protected Locale sortLocale;

    /** Creates a new instance of EjbSorter */

    public EjbTableSorter(SortCriteria sortCriteria[], Locale sortLocale) {

    this.sortCriteria = sortCriteria;

    this.sortLocale = sortLocale;

    }

    public void setSortCriteria(SortCriteria[] sortCriteria) {

    this.sortCriteria = sortCriteria;

    }

    public SortCriteria[] getSortCriteria() {

    return sortCriteria;

    }

    public void setSortLocale(Locale locale) {

    this.sortLocale= locale;

    }

    public Locale getSortLocale() {

    return this.sortLocale;

    }

    /* returns sorted list of keys. Gets frersh sorted list of objects from ejb layer*/

    public RowKey[] sort(TableDataProvider provider, RowKey[] rows) throws DataProviderException {

    if(!Beans.isDesignTime()){

    PersonDP persondp = (PersonDP)provider;

    persondp.refreshDP(sortCriteria);

    System.err.println(" Executed sort EjbSorter.java");

    return persondp.getRowKeys(rows.length,null);

    }

    return provider.getRowKeys(rows.length,null);

    }

    }

Kết nối xắp xếp với trang

  • Mở page1 lên

  • Trong phần Layout chọn TableRowGroup1, chuột phải chọn Property Bindings

  • Chọn All radio

  • Trong khung bên trái chọn TableDataSorter

  • Trong khung bên phải chọn SessionBean1 \ ejbSorter

  • Close

Tạo button cho phân trang

  • Mở page1

  • Kéo GroupPanel vào page

  • Kéo 4 button như bên

  • Double vào button để đến phương thức hiện thực action cho button. Ta thêm lần lượt các phương thức sau vào từng button:

    <<: getSessionBean1().getPersondp().setStartPosition(0);

    < : getSessionBean1().getPersondp().previous();

    > : getSessionBean1().getPersondp().next();

    >>: getSessionBean1().getPersondp().setLastPosition();

  • Deloy Travel Ejb

  • Run Travel Web.

Đọc tiếp >>

Cao Trong Hien

Những điểm mới trong jsf 1.2: Phần 1

Hôm nay tôi xin giới thiệu những điểm mới trong JSF 2. Mà trong đó việc dùng chung với JSP Framework là một thành tựu quan trọng nhất của JSF 2, được phát triển thông qua JSR 252. Thêm nữa là jsf có những đặc tính dễ dùng hơn. Tôi xin nói về những điểm chủ yếu sau:

1.Sử dụng chung với công nghệ JSP.
2.Dễ dàng tạo một message.
3.Tính năng lưu trạng thái.
4.Tắt tính năng tạo id cho component.
5.setPropertyActionListener cho tag.

1.Sử dụng chung với JSP
Cái chính của sự xung khắc nhau giữa JSF và JSP là sự khác nhau về life cycle mà cả 2 hỗ trợ. JSP chỉ có một life cycle trong suốt quá trình tạo trang. JSF thì nó đuợc chia làm nhiều phần, khi component tạo, dữ liệu được xử lý, sau đó là thể hiện lên trang. Tuy nhiên, một trang JSF không nhất thiết phải dịch toàn bộ lập tức. Kết quả cho thấy, dùng JSF component trong trang JSP thỉnh thoảng là nguyên nhân của sự thể hiện sai thứ tự, trạng thái component bị mất, và còn nhiều lỗi khác.
Tôi xin nói về một số thay đổi trong JSF để ta có thể sử dụng đồng thời JSF và JSP.

1.Ta có thể dùng JSF component bên trong thẻ forEach của JSTL.
2. Cải tiến trong việc tạo tree trộn.
3.Cải tiến cách viết EL một cách thống nhất.
1.1 Dùng JSF component trong forEach của JSTL.
Được minh hoạ trong đoạn code sau:














Item Name Item Price Item Quantity



1.2 Cải tiến trong việt tạo tree trộn.
Trộn JSP với JSF thường ra kết quả không như ta mong muốn. Ví dụ đoạn code sau, Hi sẽ xuất hiện sau What's your name?.



What's your name?

Vậy nếu ta đổi thứ tự hai dòng thì sao? JSF phục thuộc vào cấu trúc cây của JSP. Vì JSP dịch ngay lập tức dòng text trong kho JSF chỉ dịch khi đến dòng đóng panelGroup. Vậy là sao để Hi nằm truớc What's your name?
Vấn đề này đuợc giải quyết trong JSF 2, và giải quyết như sau:
Tạo và dịch của component tree chia làm 2 bước để ngăn dịch tức thời của JSP
Thuộc tính rendersChildren được set thành true trên tất cả các component.
Những dòng text tĩnh trong component được lưu tạm thời thành một UIInput component và đặt vào trong tree.
Quản lý trạng thái được chuyểntừ ViewTag vào trong ViewHandle

1.2 Cải tiến cách viết EL một cách thống nhất.
Cả trong JSP và JSF điếu có cách viết EL một cách thống nhất. Vì vậy nếu bạn có mở rộng một bộ thẻ của JSF phải thay ValueBinding thành ValueExpression, thay MethodBinding thành MethodExpression.

2.Dễ dàng tạo một message.
Và đã thay đổi như thế nào:
Một tập hợp các chuẩn message mới.
Thêm vào 3 thuộc tính mới requiredMessage, converterMessage và validatorMessage cho input component.
Thuộc tính label trong input component
Thẻ resource-bundle khai báo bundle cho application.
2.1 Một tập hợp chuẩn messages mới.
Dùng cho validator và convertor
2.2 Thêm 3 thuộc tính requiredMessage, converterMessage và validatorMessage.
Ý nghĩ thì tuỳ thuộc vào cách dùng, ví dụ: bạn dung validator nói rằng userId phải có 8 ký tự và một cái khác nói rằng password chỉ cho 9 kí tự. Nhưng bạn muốn dùng 1 validator. với validatorMessage.
2.3 Thuộc tính label trong input.
Giúp ta thông báo lỗi một cách rỏ ràng hơn. Ví dụ tôi có một input BIRTH_DATE, tôi sẽ dùng label để thông báo lỗi như sau:
{2}: "{0}" could not be understood as a date.

Giả sử bạn nhập older than the hills sẽ thông báo lỗi như sau
Birth Date: "older than the hills" could not be understood as a date.

2.3 Cấu hình resource-bundle.
Bạn có thể khai báo resource-bundle theo một cách mới

customMessages
resources.CustomMessages


Và sử dụng như sau

Đọc tiếp >>

Cao Trong Hien

,

Sử dụng công nghệ JavaServer Faces với Ajax

Sử dụng công nghệ JavaServer Faces với Ajax


  1. Đặt vấn đề

    Như chú ta đã biết, JSF cung cấp một tính năng vượt trội là giúp ta tự tạo một component bằng cách mở rộng một component.

    Ví dụ đưa ra là tạo một textfield nhập tên. Khi user bắt đầu nhập tên, ứng dụng sẽ dùng ajax thực hiện auto complete với tên mà user đang nhập.

    Vấn đề đặt ra ở đây là: làm sao ta có thể tích hợp ajax vào jsf.

    Và thông qua đó ta sẽ trả lời cho các câu hỏi sau:

  • Ajax request sẽ thi hành trong servlet controller hay đuợc quản lý bằng JSF life cycle.

  • Ta có thể dùng các components sẵn có của JSF để thi hành Ajax không.

  • Javascript sẽ nằm trong Java hay nằm trong file js.

  • Khai báo cấu trúc project

  • Đóng gói.

  1. Giải pháp

    Chúng ta có 3 giải pháp, nhưng bạn muốn dùng giải pháp nào? Hãy trả lời cho tôi các câu hỏi sau:

  • Bạn hiện thực một application mới hoàn toàn hay bạn chỉ viết một phần của ứng dụng đó.

  • Bạn có thể thêm javascript trực tiếp vào trang, hay thêm vào một bộ thẻ mới vào trang hay không.

  • Ajax code có tính reuse không.

Chúng ta sẽ thảo luận 3 giải pháp. Ở 2 giải pháp đầu tiên, ta sẽ hiện thực một component có javascript trong server component. Ở giải pháp 1: JSF life cycle sẽ quản lý Ajax request.

Giải pháp 2, thành phần tạo ra liên lạc với servlet, servlet này sẽ xử lý ajax request. Giải pháp 3, không yêu cầu tạo một component mới, tất cả ajax được xử lý bởi servlet được ta khai báo.


Giải pháp 1:

Tạo JSF Component xử lý ajax script trong client

Ta cần hiện thực một component với các yêu cầu sau:

  • Dịch html cho form.

  • Dịch link cho javascript quản lý sự kiện.

  • Xử lý Ajax request.

Theo các buớc sau:

  1. page được gọi. component được dịch ra mã html bởi AutoCompleteTextRenderer.

  2. Javascript gọi đến URL, faces/autocomplete-script là một hiện thực của FacesServlet, và được hiện thực bởi RenderPhaseListener

  3. User bắt đầu gõ, javascript gọi đến một hiện thực của FacesServlet .

  4. RenderPhaseListener xử lý tạo ra file xml, và trả về trên XMLHttpRequest

  5. XMLHttpRequest thi hành chức năng update html DOM phụ thuộc dữ liệu có trong file xml.

  6. Update button.


Ta cần hiện thực một tag căn bản sau:

completionMethod="#{AutoCompleteTextfield.completeCity}"
value="#{SessionBean.city}" required="true"
/>

Dĩ nhiên khi encode ta sẽ phaỉ encode javascript


Hiện thực sử lý cho ajax request

private void handleAjaxRequest(PhaseEvent event) {
FacesContext context = event.getFacesContext();
HttpServletResponse response =
(HttpServletResponse)context.getExternalContext().getResponse();
..
if ("complete".equals(action)) {
String method = request.getParameter("method");
try {
//get completion items
response.setContentType("text/xml");
response.setHeader("Cache-Control", "no-cache");
//Code to write XML response goes here...

event.getFacesContext().responseComplete();
return;
} catch (EvaluationException ee) {
ee.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}

Và cuối cùng, encode style cho đẹp.

Đọc tiếp >>

Cao Trong Hien

,