Thứ Tư, 25 tháng 7, 2018

Xử lý lỗi liên hoàn khi thực hiện Redirect Action trong Struts 2.x Framework

 

Tác giả: Nguyễn Hiếu Liêm

 

Mục đích: Nội dung bài này sẽ hướng dẫn xử lý lỗi liên hoàn trên các action trong các chức năng gọi lại các action khác khi xử lý thông qua cơ chế redirect Action trong Struts 2 framework. Ngoài ra, bài viết này cũng hướng dẫn việc trình bày lỗi trên lưới dữ liệu kết xuất cụ thể trên từng dòng của lưới thông qua định hướng tiếp cận là sử dụng JSON. Bài viết thể hiện sử kết hợp của Struts 2 Validation Framework với request của Http Protocol để gửi object lỗi qua request và thực hiện chuyển lỗi của action này cho action để từ đó action đón nhận sẽ xử lý báo lỗi. Để tiếp cận kỹ năng đã nêu, bài viết sẽ thực hiện xây dựng ứng dụng với 2 chức năng chính cơ bản là search và update và thực hiện việc validation dữ liệu trong quá trình update ngay trên lưới dưới dữ liệu.

 

Yêu cầu kiến thức cơ bản

·         Nắm rõ mô hình MVC2, Struts 1.x Framework, các khái niệm cơ bản của Struts 2.x Framework.

·         Nắm rõ những phương pháp cơ bản của lập trình hướng đối tượng bằng ngôn ngữ Java.

·         Nắm rõ những khái niệm lập trình web sử dụng JavaEE cùng những kiến thức về Servlet, JSP.

·         Nắm vững cơ chế vận hành của RequestDispatcher và Filter, cách sử dụng Filter như là Controller trong mô hình MVC2 (có thể xem thêm bài viết về Filter tại đây: http://www.kieutrongkhanh.net/2017/06/topic-su-dung-filter-nhu-la-controller.html).

·         Nắm rõ cách sử dung annotation kết hợp cấu hình struts.xml để xây dựng web application với Struts 2.x Framework (tham khảo tại địa chỉ: http://www.kieutrongkhanh.net/2017/07/video-su-dung-annotation-ket-hop-cau.html).

·         Nắm rõ cách thực hiện validation dữ liệu với annotation và trình bày message động dùng file properties với Struts 2.x Framework (tham khảo tại địa chỉ: http://www.kieutrongkhanh.net/2017/07/video-su-dung-annotation-ket-hop-cau.html).

·         Nắm rõ và đã xây dựng mô hình ứng dụng thao tác với các chức năng cơ bản của ứng dụng web, cụ thể ở đây là chức năng update hay delete (tham khảo tại địa chỉ http://www.kieutrongkhanh.net/2016/08/xay-dung-ung-dung-web-su-dung-mvc2-ket.htmlhttp://www.kieutrongkhanh.net/2016/10/video-delete-va-update-tren-luoi-voi.html hay http://www.kieutrongkhanh.net/2017/01/video-tiep-tuc-hoan-thien-chuc-nang-cho.html )

 

Yêu cầu tool sử dụng

·         IDE: Netbeans 8.x (Recommendation 8.2).

·         JDK 6 update 22, JDK 7 update 51, JDK 8 update 66.

·         Server: Tomcat 6.0.26, Tomcat 7.x, Tomcat 8.x.

·         DBMS: SQL Server 2005 đến SQL Server 2016.

·         IDE Netbeans phải cài đặt plugin hỗ trợ Struts 2 Framework (Cụ thể bài này sử dụng Struts 2.3.15 – download tại địa chỉ http://plugins.netbeans.org/plugin/39218 ).

 

Thư viện hỗ trợ

·         Driver kết nối database SQLServer (sqljdbc.jar hay sqljdbc4.jar – địa chỉ download https://docs.microsoft.com/en-us/sql/connect/jdbc/microsoft-jdbc-driver-for-sql-server?view=sql-server-2017 ).

·         Struts 2.x Framework (Struts 2. 3. 15 – download tại địa chỉ https://archive.apache.org/dist/struts/binaries/ ).

·         Thư viện Gson phiên bản 2.3.1 hỗ trợ serialize và deserialize các đối tượng Java trở thành JSON và ngược lại (gson-2.3.1.jar – địa chỉ download https://sourceforge.net/projects/gson23/ ).

Định hướng trong việc validation lỗi trên một action được redirect đến một Action để thực hiện refresh giao diện trình bày kết quả

·         Chúng ta định hướng việc xử lý lỗi theo mục đích đã nêu trên theo một chức năng cụ thể để có thể hình dung ra cơ chế hoạt động của việc xử lý

·         Ở đây, với chức năng update hay delete trực tiếp trên lưới dữ liệu thì chúng ta cần phải thực hiện việc cập nhật giao diện lưới dữ liệu hay refresh mới sau khi chức năng update và delete thành công hay thất bại theo nghĩa là gọi lại chức năng search.

·         Chúng ta xét đến trường hợp khi thực hiện việc update hay delete mà có lỗi phát sinh do lỗi nhập liệu của user chẳng hạn thì chức năng update hay delete không thể thực hiện ở phía server và lỗi phải được đưa trình bày cho người dùng. Tuy nhiện, trong mọi trường hợp lỗi của action update được catch và chúng ta cần phải gọi chức năng search để refresh lại giao diện nghĩa là chuyển action từ update action sang search action để trình bày kết quả. Trong trường hợp này, search action không có lỗi vì search chỉ là search dữ liệu và trình bày. Chính vì điều đó, chúng ta phải kích hoạt lỗi để đón nhận lỗi từ action update sang action search.

·         Mô hình bên dưới sẽ thể hiện hướng tiếp cận mà chúng ta sẽ xây dựng khi validation dữ liệu khi action ban đầu tạo lỗi những sẽ trình bày tại result của action thứ 2

·         Định hướng kỹ thuật trong quá trình implement như sau

o   Đầu tiên, để sử dụng cơ chế Validation của Struts 2.x Framework chúng ta cần extends ActionSupport ở cả action update và search. Sau đó sử dụng Annotations để khai báo các Validators cho các fields mà cần bắt validation của action update.

o   Tiếp theo, chúng ta thực hiện tạo một object để lưu lại các giá trị mà người dùng nhập trước khi chức năng được thực hiện để hỗ trợ bắt validation trong quá trình xử lý và truyền đi

o   Kích hoạt việc báo lỗi bằng việc override các phương thức của Struts2 Validation Framework theo cơ chế cụ thể với các hàm validate và hasError của Validation Aware và Validateable. Và lỗi sẽ được chuyển đổi từ object thành dạng JSON để transfer giữa các action với nhau

o   Tại action cuối cùng, kích hoạt errors thông qua việc override hàm validate trong action cuối  cùng đưa toàn bộ message lỗi vào action tiếp theo và kích hoạt phương thức xử lý execute của action này nhằm định hướng đến result trình bày lỗi trong kết quả xử lý được hỗ trợ của Struts2 Validation Framework.

o   Xử lý việc trình bày message cụ thể tại dòng báo lỗi trên giao diện

Để hiện thực cụ thể các định hướng nêu trên, chúng ta sẽ thực hiện xây dựng ứng dụng theo yêu cầu như sau

·         Ứng dụng yêu cầu người sử dụng đăng nhập vào hệ thống với username và password được cung cấp.

·         Nếu đăng nhập  thành công với vài trò là staff (role = 1), hệ thống sẽ tự động chuyển đến trang search dành cho staff.

·         Ngược lại, nếu user đăng nhập không thành công, hệ thống sẽ chuyển sang trang invalid.

·         Khi đăng nhập thành công, user sẽ được phép search sản phẩm theo tên hoặc ID. Kết quả search được trình bày dưới dạng lưới.

·         Staff được phép update mô tả, giá, số lượng và tình trạng mua bán của sản phẩm trực tiếp trên lưới kết quả search.

·         Dữ liệu của mô tả được yêu cầu bắt buộc nhập, giá và số lượng phải là số và bắt buộc phải nhập. Nếu có lỗi xảy ra, thông báo lỗi sẽ xuất hiện trên lưới kết quả search chính xác tại ngay dòng mà người dùng không nhập đúng yêu cầu.

·         Database được sử dụng trong bài viết này có tên ValidationDemoDB. Bao gồm 2 tables là tbl_Usertbl_Product có cấu trúc như hình mô tả bên dưới

·         Dữ liệu mẫu trong database dùng để kiểm thử trong bài như sau

 

Các bước thực hiện

·         Bước 1: Tạo project

o   Tạo mới project Java Web Application với tên Struts2ValidationDemo.

o   Lưu ý chọn Java EE 6 Web, server Apache Tomcat 8.x, add Struts 2.x Framework

·         Bước 2: Cấu hình kết nối CSDL

o   Thực hiện cấu hình datasource kết nối DB động.

o   Chỉnh sửa tập tin context.xml trong thư mục META-INF

o   Bổ sung việc mapping data souce vào tập tin web.xml trong thư mục WEB-INF

o   Tạo thư viện hỗ trợ kết nối CSDL với class utilities với tên là DBConnection.java

·         Bước 3: Thực hiện chức năng Login với authenticate trên DB đã nêu ở trên

o   Tạo tập tin login.html trong thư mục Web Pages

o   Thực hiện cấu hình welcome page cho trang login với khai báo welcome-file trong tập tin web.xml là rỗng và cấu hình trong tập tin struts.xml như sau

o   Tạo trang invalid, với đường link quay về welcome page

§  Lưu ý: Với một vài trình duyệt như Chrome, nếu để href=”” (chuỗi rỗng) thì khi click sẽ load lại trang hiện hành, vì vậy để gọi lại “action rỗng” để quay về welcome page, chúng ta sẽ dùng một dấu chấm (href=“.”) có nghĩa là trỏ đến thư mục hiện hành (ở đây là thư mục có tên khai báo trong context path của ứng dụng).

o   Tạo trang search.jsp.

o   Tạo DTO để chứa thông tin của user khi login vào hệ thống, ứng với bảng tbl_User ở database.

o   Tạo DAO với method checkStaffLogin với mục đích kiểm tra đăng nhập với role = 1 (staff), return giá trị true/false, và field currentUser với getter để lưu thông tin của user đăng nhập thành công.

o   Lưu ý: Sau khi kiểm tra đăng nhập thành công thì chúng ta không cần lưu lại password của user ở session nên có thể đặt lại password là một số bất kỳ nào đó.

o   Tạo LoginAction để xử lý action login.

o   Thêm welcome cho trang search.jsp

o   Lưu ý: import struts 2 taglib.

o   Tạo LogoutAction để xử lý action logout.

o   Thêm logout cho trang search.jsp

o   Clean and Build, Deploy và test thử ứng dụng.

o   Chúng ta hoàn thành chức năng Login.

·         Bước 4: Thực hiện chức năng Search.

o   Bổ sung form search cho trang search.jsp

o   Tạo trang error.html

o   Tạo DTO để chứa thông tin của sản phẩm khi search thành công, ứng với bảng tbl_Product ở database.

o   Tạo DAO với method searchProduct, tìm kiếm sản phẩm theo tên hoặc ID, và field searchResults với getter để lưu danh sách các sản phẩm tìm được.

o   Tạo SearchProductAction để xử lý action search.

o   Trình bày kết quả hiển thị lên trên lưới dữ liệu tại trang search.jsp.

o   Clean and Build, Deploy và test thử ứng dụng.

o   Chúng ta vừa hoàn thành chức năng Search.

·         Bước 5: Thực hiện chức năng Update.

o   Bổ sung thêm form và các control hỗ trợ chức năng update trên trang search.jsp

o   Bổ sung thêm method updateProduct trong Tbl_ProductDAO, cập nhật mô tả, giá, số lượng và tình trạng mua bán của sản phẩm có productId tương ứng, return giá trị true/false.

o   Tạo UpdateAction để xử lý action update.

o   Clean and Build, Deploy và test thử ứng dụng.

o   Chúng ta hoàn thành chức năng Update.

·         Bước 6: thực hiện validation dữ liệu trên 03 field description, price và quantity theo đặc tả yêu cầu và ứng dụng các nội dung tiếp cận mà chúng ta đã đề cập ở phần đầu bài viết này

o   Đầu tiên, để sử dụng cơ chế Validation của Struts 2.x Framework chúng ta cần extends ActionSupport ở cả action update và search. Sau đó sử dụng Annotations để khai báo các Validators cho các fields của action update.

o   Lưu ý

§  Để bắt lỗi nhập chữ vào giá trị price hay quantity, chúng ta sẽ thay đổi đón nhận parameters bằng kiểu String và xử lý sau ở phương thức validate().

§  Để cho ứng dụng có tính flexible hơn thì chúng ta sẽ lưu các message thông báo lỗi trong file properties đặt bên ngoài code (cách tạo file properties có thể tham khảo tại địa chỉ: http://www.kieutrongkhanh.net/2017/07/video-su-dung-annotation-ket-hop-cau.html )

o   Tiếp theo, chúng ta thực hiện tạo một class có tên  là ProductFieldsValue để lưu các giá trị mà người dùng nhập trên các control để thực hiện chức năng update.

o   Chúng ta thực hiện import thư viện Gson hỗ trợ thao tác với JSON.

§  Đầu tiên click phải chuột vào Libraries chọn Add JAR/Folder…

§  Chọn đường dẫn đến gói gson-2.3.1.jar

§  Chọn Open và kiểm tra lại trong thư mục Libraries đã xuất hiện gói
gson-2.3.1.jar

o   Tiếp tục thực hiện thêm field errorJsonString ở action update để lưu lại JSON string được tạo ra và thực hiện override phương thức validate() với các nội dung tổng quát như sau

§  Chúng ta lưu lại toàn bộ thông tin về sản phẩm đang bị nhập lỗi trong một object. Sau đó, chúng ta chuyển object đó thành chuỗi JSON và đặt tạm vào một fieldError giả tên là “product” nhằm để phân biệt lỗi của chính xác sản phẩm này.

§  Cuối cùng, chúng ta lấy toàn bộ fieldErrors chuyển thành chuỗi JSON và gán vào field errorJsonString đã thêm ở trên.

o   Chúng ta thêm một field cũng tên errorJsonString  ở action search để đón nhận giá trị từ action update truyền sang sau khi update được xử lý.

o   Tiếp theo, chúng ta cấu hình việc báo lỗi khi action update được xử lý sẽ chuyển sang result input với việc bổ sung các annotation tương ứng ở action update. Tham số bổ sung bao gồm thực hiện redirectAction đến action search, truyền các parameters sang search Action với các giá trị searchValue để gọi lại lưới kết quả search và đối tượng chứa đựng lỗi với tên errorJsonString nếu có lỗi xảy ra.

o   Tại action search, chúng ta sẽ đón nhận object lỗi và xử lý ở phương thức validate() với nội dung như sau

§  Chúng ta thực hiện dịch ngược từ JSON string thành Map<String, List<String>>. Đây là tập lỗi chứa tất cả message lỗi nhận được từ action update.

§  Sau đó, chúng ta thực hiện duyệt toàn bộ object lỗi và đưa lỗi cho Struts2  Validation Framework xử lý bằng cách sử dụng phương thức addFieldError. Công việc này sẽ hỗ trợ chúng ta chuyển toàn bộ lỗi của action update cho action search với mục đích yêu cầu Validation Framework hỗ trợ handle chúng ta một phần trình bày lỗi ở giao diện.

§  Chúng ta nên thêm một field mới cho action search với tên là fieldsValue để lưu lại thông tin về sản phẩm đang có lỗi (kiểu dữ liệu là ProductFieldsValue)

§  Chúng ta lấy chuỗi JSON từ fieldError giả có tên “product” đã nói ở phần trên và dịch ngược để có lại giá trị của fieldsValue.

§  Cuối cùng, chúng ta gọi lại phương thức excute() để thực hiện lại chức năng search với mục đích refresh lại lưới dữ liệu mà chúng ta đã nhìn thấy trước khi thực hiện update.

§  Lưu ý: Nội dung try và catch trong phần gọi phương thức this.execute() chúng ta sẽ không có bất kỳ phần xử lý lỗi nào cả vì ở đây, chúng ta chỉ gọi lại phương thức excute() với mong muốn lấy lại danh sách kết quả search của người dùng (danh sách này đã được truy xuất trước đây và trình bày trên lưới kết quả trước khi chúng ta nhấn nút update nếu có lỗi xảy ra) và bỏ qua các lỗi mà chúng ta đã xử lý

o   Bổ sung result input với annotation cho action search để kích hoạt việc trình bày lỗi với Struts2 Validation Framework sau những bước chúng ta đã cấu hình ở trên.

o   Thực hiện cập nhật hỗ trợ trình bày lỗi ở trang search.jsp với mục tiêu đưa lỗi đến chính xác dòng mà người sử dụng nhập sai gây nên lỗi. Các nội dung xử lý như sau

§  Chúng ta lấy tất cả fieldErrors (getFieldErrors()) gán vào biến có tên fieldErrors với kiểu dữ liệu là Map<String, List<String>>. Mỗi entry trong Map sẽ có key là fieldName (tên của field có lỗi) và value là một list các message lỗi của field đó.

§  Tại mỗi control, chúng ta thực hiện kiểm tra nếu productId tại dòng đó trùng với productId của sản phẩm có lỗi (fieldsValue.productId == productId) thì in ra dòng thông báo lỗi ở ngay trên control và đặt value cho control đúng bằng những gì người dùng đã nhập ở action update. Ngược lại, chúng ta sẽ lấy giá trị đang có trong DB.

§  Message thông báo lỗi tương ứng với mỗi control/field sẽ được lấy từ biến #fieldErrors. Ví dụ với câu lệnh #fieldErrors[‘description’][0] tương đương với #fieldErrors.get(‘description’).get(0), chúng ta sẽ lấy ra được message lỗi đầu tiên của field “description”.

o   Clean and Build, Deploy và test thử ứng dụng.

o   Chúng ta đã thực hiện xử lý lỗi thành công với update và báo lỗi từng dòng tương ứng trên ứng dụng với description.

o   Chúng ta cập nhật thêm xử lý lỗi đối với nhập chữ vào giá trị price hay quantity.

§  Chúng ta bổ sung đoạn xử lý ở phương thức validate() của action update.

o   Thực hiện cập nhật thêm key cho file properties.

o   Clean and Build, Deploy và test thử ứng dụng.

o   Chúng ta đã hoàn tất xử lý lỗi trên tất cả các fields theo yêu cầu đặc tả

·         Cấu trúc thư mục project sau khi hoàn thành tất cả các chức năng như sau

 

Chúc mừng quý vị đã hoàn tất vấn đề xử lý lỗi và truyền lỗi trên các action bằng kỹ thuật sử dụng JSON để gửi object lỗi từ action này sang action khác để cuối cùng trình bày lỗi ở action cuối cùng.

Hy vọng bài viết sẽ giúp quý vị nâng cao kiến thức và hiểu rõ hơn về cơ chế Validation của Struts 2.x Framework, cũng như giải quyết được một bài toán thực tế.

Rất mong nhận được sự góp ý chân thành của quý vị về chủ đề này.

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

Đăng nhận xét