Thứ Sáu, 27 tháng 1, 2012

JSF - Bài 1: Tính lương trước thuế




Center of Excellence


Bài 1
Tính lương trước thuế




Đây là bài đầu tiên trong loạt bài phát triển các ứng dụng web (web applications) dùng công nghệ JavaServer Faces (JSF). Để dễ dàng tiếp thu, bạn cần có kiến thức về lập trình hướng đối tượng bằng Java. Có thể tham khảo loạt bài lập trình hướng đối tượng bằng Java tại đây. Vạn sự khởi đầu nan. Bạn nên đọc và thực hành nhiều lần cho đến khi tự mình phát triển được giải pháp mà không cần nhìn vào bài.


I. Bài toán

Hãy phát triển một web application để tính lương chính thức (gross pay), hay còn được gọi là lương chưa trừ thuế, của một nhân viên biết rằng thông tin để tính lương bao gồm số giờ làm việc (number of hours worked, được qui tròn về một số nguyên không âm) và lương một giờ (hourly pay rate, là một số thực dương từ 6.00 trở lên, đơn vị là USD, đô-la Mỹ). Sau đây là công thức tính gross pay:

gross-pay = number-of-hours-worked x hourly-pay-rate

Dưới đây là màn hình giao diện (UI screen) mẫu.


Hình 1



II. Giải pháp

Đầu tiên ta thiết kế một user interface screen (UI screen) tĩnh dùng ngôn ngữ thuần XHTML, sau đó dùng JSF để bổ sung phần động, tức phần tương tác với người dùng (user), rồi phát triển mã (code) tính toán. Tuy nhiên, trước tiên ta cần tạo dự án (project) bằng việc dùng môi trường phát triển tích hợp (Integrated Development Environment – IDE) Netbeans. Phần phụ lục sẽ hướng dẫn việc tải (download) và cài đặt (install) IDE này.



1. Tạo JSF project

Kích (click) vào File menu, rồi chọn New Project... để chuyển sang cửa sổ New Project.

Hình 2

Chọn dự án (Choose Project) bằng cách chọn Java Web trong mục Categories, chọn tiếp Web Application trong mục Projects, rồi click Next để chuyển sang bước đặt tên và xác định vị trí lưu trữ (Name and Location).

Hình 3

Nhập tên dự án vào ô Project Name, ở đây ta đặt là PaymentJSF. (Có thể thay đổi vị trí lưu trữ của project bằng cách click vào nút Browse.) Click Next để chuyển sang bước chọn server (Server and Settings).


Hình 4

Chọn GlassFish Server 3.1 cho mục Server, chọn Java EE 6 Web cho mục Java EE Version, rồi nhớ chọn Enable Contexts and Dependency Injection. Sau đó click Next để chuyển sang bước chọn Frameworks.

Hình 5

Chọn JavaServer Faces rồi click Finish.


Hình 6



2. Thiết kế UI screen

Sau khi tạo xong project, NetBeans chủ động tạo sẵn trang (page) index.xhtml.

Hình 7

Nhận xét rằng NetBeans đã sử dụng các thẻ (tag) JSF cho phần đầu (head) và phần thân (body) của index.xhtml page. Ta có thể quay về sử dụng những thẻ thuần XHTML như sau

Hình 8

Kế đến, ta đặt lại tiêu đề cho page.

Hình 9

Để xem nhanh biểu diễn của page trong trình duyệt web (web browser), ta kích phải (right-click) vào bên trong page, rồi chọn View.

Hình 10

Đến đây ta tổ chức các ô nhập và ô xuất bên trong. Ta áp dụng <h:outputText>  cho ô xuất Gross pay nhằm ngăn không cho user thay đổi nội dung ô này.


Hình 11a

Thêm vào đó là những hoa thđđể nhắc nhuser, những giá trị phải nhập


Hình 11b
 
Bên dưới <fieldset> block, ta nhóm hai nút lệnh (buttons) bên trong <div> block: Compute Gross Pay để user có thể yêu cầu application thực hiện việc tính toán, và Clear để xóa nội dung bên trong các ô nhập lẫn ô xuất.

Hình 12

Để tăng tính thẩm mỹ cho page, ta yêu cầu browser khi trình bày phần body, phải chừa trống lề (margin) trái lẫn lề phải một khoảng bằng 20% chiều ngang của browser (Hai giá trị 0 có nghĩa là ta không thay đổi phần trên cũng như phần dưới của page).

Hình 13

Kế đến, ta sắp cho ngay ngắn các nhãn (label) bên trong <fieldset> block bằng cách qui định chiều rộng (width) của label là 170 pixels (điểm ảnh), không cho các thành phần khác lấn vào chiều rộng qui định này (thông qua thuộc tính float), và canh lề phải (right) cho label (thông qua thuộc tính text-align).

Hình 14

Sau đó ta canh lề trái cho hai buttons để chúng thẳng hàng với các ô nhập xuất ở trên.

Hình 15



3. Dùng JSF để bổ sung phần động

Sau khi kết thúc phần thiết kế UI screen tĩnh, ta tiến hành bổ sung phần động bằng JSF để thực hiện phần tương tác với user. Phần động bao gồm việc tạo managed bean (hay còn gọi là backing bean, tức đối tượng làm nhiệm vụ hỗ trợ), sau đó ràng buộc (bind) web page với managed bean.

3.1. Tạo managed bean

Managed bean là một Java class chuyên biệt, đóng vai trò là cầu nối giữa phần giao tiếp với user (UI) và phần tính toán (model) bên trong application.

Hình 16

Ta tạo managed bean tên là Index để hỗ trợ cho index.xhtml bằng cách right-click vào Source Packages, chọn New, rồi chọn Other... để chuyển sang New File window.

Hình 17

Chọn JavaServer Faces ở bảng Categories: bên trái, sau đó chọn JSF Managed Bean ở bảng File Types: bên phải, rồi click Next để chuyển sang bước đặt tên và xác định vị trí lưu trữ (Name and Location).

Hình 18

Nhập Index vào ô Class Name:, nhập controller vào ô Package:, và chọn request trong ô Scope:, rồi click Finish. (Trong một số trường hợp, request được thay bằng một chọn lựa khác. Với application này, request là chọn lựa thích hợp.)

Hình 19

Hình 20

Quan sát Index managed bean, ta thấy đây là một Java class với hai phụ chú (annotation) là @Named@RequestScoped (do ta đã chọn request trong ô Scope:), đồng thời managed bean còn có một phương thức tạo đối tượng phi tham biến (no-arg constructor).

Đến đây ta tiến hành xem xét các thành phần tương tác với người dùng (UI components) bên trong index.xhtml để quyết định xem managed bean cần có những trường (field) nào. Ở đây index.xhtml có ba loại UI components: input, output, và nút lệnh (button).



3.1.1. Tạo fields cho input components

Application của ta cần hai giá trị nhập từ user, đó là number of hours workedhourly pay rate, vì vậy ta cần có hai fields kèm theo getter/setter tương ứng bên trong managed bean.

Hình 21

Lưu ý là đối với các fields trong managed bean, ta không dùng kiểu dữ liệu nguyên thủy (primitive data type) mà dùng kiểu đối tượng (object type). Chẳng hạn ở đây, thay vì dùng int, ta đã dùng Integer cho hoursWorked. Cũng vậy, ta đã dùng Double cho hourlyPayRate, thay vì dùng double. Ngoài ra, ta không tạo thêm bất kỳ constructor nào khác.

Khi yêu cầu NetBeans phát sinh getter và setter cho fields, right-click bên trong class, chọn Insert Code...

Hình 22

Chọn Getter and Setter...

Hình 23

Đánh dấu fields, rồi click Generate.

Hình 24

Hình 25



3.1.2. Tạo field cho output component

Application của ta chỉ có một output component đó là gross pay. Đối với output component, ta chỉ cần getter (không cần setter) bên trong managed bean.

Hình 26



3.1.3. Tạo phương thức (methods) cho buttons

Đối với mỗi button, ta tạo một method trong managed bean.

Hình 27

Chú ý rằng kiểu kết quả trả về (return data type) của computeGrossPay() bên trong Index managed bean là void (thay vì double), bởi vì với cách phát triển managed bean như trên, kết quả tính toán sẽ được lưu vào grossPay field, và index.xhtml sẽ truy xuất đến field này thông qua getter của nó.



3.2. Ràng buộc web page với managed bean

Trước tiên ta cần áp dụng <h:form>block cho bộ phận nào của index.xhtml page có chứa những thành phần tương tác với user.

Hình 28



3.2.1. Ràng buộc input components với managed bean

Đối với input components, ta thay <input> tag bằng JSF tag tương ứng là <h:inputText> kèm theo thuộc tính (attribute) value.

Hình 29



3.2.2. Ràng buộc output component với managed bean

Đối với output component, ta không cần dùng JSF tag mà chỉ cần bổ sung value attribute vào <input> tag.

Hình 30



3.2.3. Ràng buộc buttons với managed bean

Ta thay <input> tag bằng JSF tag tương ứng là <h:commandButton> kèm theo thuộc tính (attribute) action với lệnh gọi computeGrossPay()clear() bên trong managed bean.

Hình 31



3.2.4. Phát triển clear()

Phương thức clear() liên quan đến việc xóa nội dung bên trong các ô nhập và xuất, tức liên quan đến các UI components, nên ta phát triển code ngay bên trong managed bean.

Hình 32



4. Phát triển code tính toán

Đây là phần tính toán độc lập với tầng giao diện với người dùng (presentation tier hay view). Ta gọi tầng này là business logic hay model tier. Sự độc lập này sẽ giúp ta dễ dàng tái dụng (reuse) business logic cho những applications khác. Chẳng hạn, nếu yêu cầu của bài toán bây giờ không phải là giao diện web, mà phải là giao diện trên một máy tính đơn (desktop computer) hay trên một thiết bị di động, ta chỉ cần tạo lại UI screen, còn business logic thì vẫn giữ nguyên.

Hình 33

Code của Payment class cùng với class kiểm thử (unit test) tương ứng sẽ như sau

Hình 34

Hình 35



5. Kết nối managed bean với model

Sau khi đã phát triển và kiểm thử thành công phần tính toán, ta trở về managed bean để triệu gọi lệnh tính toán và lưu kết quả vào grossPay field.

Hình 36

Đến đây, ta có thể thi hành application bằng cách triển khai (deploy) project lên máy chủ web (web server). Trong Projects window, right-click vào tên project rồi chọn Run.

Hình 37

Ta nhập dữ liệu cho Number of hours workedHourly pay rate rồi nhấn phím Enter hoặc click Compute Gross Pay button để xem kết quả tính toán.

Hình 38

Để xóa số liệu trên form, ta click Clear button.



6. Kiểm tra tính hợp lệ của dữ liệu nhập

6.1. Xử lý trường hợp để trống ô nhập

Khi thi hành application, nếu user để trống ô Number of hours worked hoặc Hourly pay rate, application sẽ tung ngoại lệ NullPointerException. Để buộc user phải nhập dữ liệu (data), ta bổ sung required="true" attribute vào <h:inputText> tag.

Hình 39

Ngoài ra, ta muốn thông báo lỗi phải nằm cạnh vị trí xảy ra lỗi để giúp user dễ dàng sửa sai. Ta đặt cạnh mỗi <h:inputText> một <h:message> tag. Nhờ id attribute của <h:inputText>for attribute của <h:message> mà JSF biết được thông báo nào dành cho (for) thành phần nào (id).

Hình 40

Ta có thể thay đổi nội dung của thông báo lỗi bằng cách thêm requiredMessage attribute vào <h:inputText>.

Hình 41



6.2. Xử lý trường hợp nhập data không đúng yêu cầu

Đến đây, application vẫn chưa có khả năng bắt lỗi nếu user nhập vào một giá trị âm cho Number of hours worked. Ta phải lồng <f:validateLongRange> vào trong <h:inputText>, đồng thời bổ sung validatorMessage attribute. Ở đây ta qui định rằng số giờ làm việc tối thiểu (minimum) phải từ 0 trở lên.

Hình 42

Đối với trường hợp của Hourly pay rate, ta lồng <f:validateDoubleRange> vào <h:inputText> và qui định rằng lương một giờ phải từ 6.00 USD trở lên.

Hình 43

Khi user nhập data vô nghĩa, chẳng hạn abc, application sẽ tự động phát ra một thông báo lỗi. Nếu muốn thay đổi nội dung của thông báo lỗi, ta có thể thêm converterMessage attribute vào <h:inputText>.

Hình 44


7. Xóa form ở phía browser bằng JavaScript

Bây giờ hãy thi hành application, rồi nhập vào một giá trị cho Number of hours worked, chẳng hạn 10. Nhưng giả định rằng thật sự thì ta muốn nhập 40, chứ không phải 10. Ta muốn xóa hết để nhập lại từ đầu bằng việc click Clear button. Nhưng sau khi click, data không được xóa mà thay vào đó là yêu cầu không được để trống ô Hourly pay rate! Dĩ nhiên đây là kết quả không mong muốn. Để bỏ qua giai đoạn kiểm tra tính hợp lệ của data (data validation) khi user clicks Clear button, ta bổ sung attribute immediate=”true”.


Hình 45


Đến đây khi thi hành application, nhập 10 cho Number of hours worked, rồi click Clear, ta không còn nhận được thông báo lỗi nữa, nhưng số 10 vẫn không được xóa! Thật ra thì giá trị đó đã được xóa ở phía server thông quan clear(), nhưng chưa được xóa ở phía browser.

Để xử lý tình huống này, ta bổ sung một hàm (function) viết bằng ngôn ngữ JavaScript. Right-click Web Pages, chọn New, rồi chọn Other... để chuyển sang New File window.

Hình 46

Chọn Other ở mục bên trái, chọn tiếp JavaScript File ở mục bên phải, rồi click Next để chuyển sang bước đặt tên và xác định vị trí file.


Hình 47

Nhập clearInputTexts vào ô File Name:, và nhập web/resources vào ô Folder:, rồi click Finish.

Hình 48

Nhập đoạn code sau rồi nhấn Ctrl+S để lưu.

function clearInputTexts(form) {
    inputs = form.getElementsByTagName('input');
    for (i = 0; i < inputs.length; i++)
        if (inputs[i].type == 'text')
            inputs[i].value = '';
}

Trong index.xhtml, ta khai báo JavaScript function ở trên bằng cách bổ sung <script> tag.

Hình 49

Và cuối cùng, ta bổ sung attribute onclick với lệnh gọi JavaScript function.

Hình 50



III. Tổng kết

Bài viết đã trình bày các bước chính khi phát triển một web application với JSF:
  • Thiết kế một UI screen tĩnh dùng ngôn ngữ XHTML.
  • Bổ sung phần tương tác giữa user và application bằng một managed bean. Thay thế các thành phần tương tác XHTML bằng JSF tags.
  • Phát triển phần tính toán của application, độc lập với phần tương tác với user, sau đó kết nối với UI screen thông qua managed bean.
  • Đảm bảo user nhập data theo đúng yêu cầu.
  • Xóa form ở phía browser bằng JavaScript.


IV. Tài liệu tham khảo
  1. Gaddis T. (2010) Starting Out with Java From Control Structures Through Objects (4th edition), Pearson Education, Boston. Chương 1 và 2.
  2. Gibson A. (2010) Getting Started with Contexts and Dependency Injection and JSF 2.0, <http://netbeans.org/kb/docs/javaee/cdi-intro.html> (14 June 2010).
  3. Eric Jendrock, Ian Evans, Devika Gollapudi, Kim Haase, Chinmayee Srivathsa (2011) The Java EE 6 Tutorial, Basic Concepts, Fourth Edition, Addison-Wesley. Chapter 17.
  4. Tong K. K. I. (2009) Beginning JSFTM APIs and JBoss® Seam, Apress, New York. Chapters 1, 2, and 3.
  5. David R. Heffelfinger (2011) Java EE 6 Development with NetBeans 7, Packt Publishing. Chapter 4.
  6. Clear a form with JavaScript. http://www.electrictoolbox.com/javascript-clear-form/


V. Thuật ngữ tiếng Anh

annotation
phụ chú
application
ứng dụng
attribute
thuộc tính
backing bean
đối tượng đứng phía sau, hỗ trợ cho trang .xhtml
browser
trình duyệt web
business logic
phần tính toán của một ứng dụng
business logic tier
tầng tính toán của một ứng dụng
button
nút lệnh
click
kích nút chuột trái
code
mã lệnh
computer
máy tính
constructor
phương thức tạo đối tượng
converter
bộ chuyển đổi dữ liệu
data
dữ liệu
deploy
triển khai
download
tải
field
trường
form
thành phần tương tác với người dùng
function
hàm
IDE
xem Integrated Development Environment
install
cài đặt
Integrated Development Environment
môi trường phát triển tích hợp
JSF
JavaServer Faces
label
nhãn
managed bean
tạm xem backing bean
margin
lề
message
thông báo, thông điệp
method
phương thức
model tier
tầng tính toán của một ứng dụng
no-arg constructor
phương thức tạo đối tượng phi tham biến
Object-Oriented Programming
Lập trình Hướng Đối tượng
OOP
xem Object-Oriented Programming
package
gói
pixel
điểm ảnh
presentation
phần giao tiếp với người dùng của một ứng dụng
primitive data type
kiểu dữ liệu nguyên thủy
project
dự án
reuse
tái dụng
right-click
kích nút chuột phải
static
tĩnh
tag
thẻ
UI component
thành phần giao diện với người dùng
UI screen
màn hình giao diện
unit test
kiểm thử đơn vị
user
người dùng
user interface
phần giao diện với người dùng
validator
bộ kiểm tra tính hợp lệ của dữ liệu
window
cửa sổ



VI. Phụ lục. Hướng dẫn tải và cài đặt NetBeans IDE

Trước khi cài đặt NetBeans IDE, computer cần cài sẵn một phiên bản Java SE Development Kit (JDK).

Download phiên bản NetBeans mới nhất tại http://netbeans.org/downloads/index.html. Cần chọn cột Java EE hoặc All.


Sau khi đã download xong, ta chỉ cần double-click vào file vừa download và làm theo chỉ dẫn để cài đặt NetBeans vào computer.

Không có nhận xét nào:

Đăng nhận xét