Phát triển công cụ hỗ trợ biên dịch và kiểm thử trên hệ thống sakai
Trang 1KHOA KHOA HOC VÀ KỸ THUẬT MÁY TÍNH
BỘ MÔN KHOA HỌC MÁY TÍNH
………… o0o…………
LUẬN VĂN TỐT NGHIỆP
PHÁT TRIỂN CÔNG CỤ HỖ TRỢ BIÊN DỊCH VÀ
KIỂM THỬ TRÊN HỆ THỐNG SAKAI
Hội đồng: KHOA HỌC MÁY TÍNHGVHD: TS Nguyễn Hứa Phùng
KS Phan Nhật ThịnhGVPB: PGS Phan Thị TươiSVTH: Phan Văn Hòa 50600822
Lê Minh Hải 50600600
Tp Hồ Chí Minh, Tháng 6/2011
Trang 2LỜI CAM ĐOAN
Chúng tôi cam đoan rằng: ngoại trừ các kết quả tham khảo từ các công trình khác như đã ghi rõ trong phần tài liệu tham khảo của luận văn, các nội dung và công việc trình bày trong luận văn này cũng như các kết quả thu được do chính chúng tôi thực hiện và chưa
có phần nội dung nào trong luận văn này được sử dụng để lấy một bằng cấp ở trường này
và trường khác
TP HỒ CHÍ MINH, THÁNG 6/2011
PHAN VĂN HÒA
LÊ MINH HẢI
Trang 3LỜI CẢM ƠN
Chúng tôi xin chân thành cảm ơn thầy Nguyễn Hứa Phùng và thầy Phan Nhật Thịnh, giáoviên hướng dẫn đề tài luận văn của chúng tôi, thầy đã tận tình hướng dẫn, chỉ bảo chúng tôi trong suốt thời gian thực hiện đề tài và giai đoạn đồ án môn học làm tiền đề cho đề tài luận văn này
Xin chân thành biết ơn sự tận tình dạy dỗ và truyền đạt kiến thức của tất cả quý thầy cô trường Đại học Bách Khoa, đặc biệt là các thầy cô trong khoa Khoa học và Kỹ thuật máy tính
Cuối cùng, xin gửi lời cảm ơn chân thành đến gia đình, bạn bè, những người luôn sát cánh, động viên, giúp đỡ chúng tôi trong suốt quá trình thực hiện đề tài này
TP HỒ CHÍ MINH, THÁNG 6/2011
PHAN VĂN HÒA
LÊ MINH HẢI
Trang 4TÓM TẮT LUẬN VĂN
Quyển luận văn này gồm 8 chương với nội dung cụ thể như sau
Chương 1: GIỚI THIỆU ĐỀ TÀI
Yêu cầu của doanh nghiệp đối với sinh viên dẫn đến yêu cầu thực hành của sinh viên trong quá trình học gia tăng Sự phát triển của đào tạo điện tử dẫn đến việc sử dụng hệ thống Sakai Tuy nhiên, các công cụ hiện nay của SAKAI chưa hỗ trợ các bài thực hành với các yêu cầu đặc trưng về việc biên dịch và kiểm thử của ngành Từ đó dẫn đến yêu của đề tài là phát triển công cụ hỗ trợ biên dịch và kiểm thử trong hệ thống SAKAI
Chương 2: CÁC KIẾN THỨC LIÊN QUAN
Giới thiệu về các kiến thức liên quan trong quá trình tìm hiểu và thực hiện nội dung luận văn
Chương 3: PHÂN TÍCH YÊU CẦU
Phân tích các yêu cầu đối với công cụ
Chương 4: THIẾT KẾ CÔNG CỤ CSLAB TRÊN DỰ ÁN SAKAI
Thiết kế các hoạt động, giao diện của công cụ
Chương 5: HIỆN THỰC CÔNG CỤ CSLAB
Trình bày cách hiện thực các thiết kế, mô tả về mã nguồn
Chương 6: KIỂM TRA HIỆU SUẤT HOẠT ĐỘNG CỦA TEST SERVER
Xác định khả năng tải của giải pháp khi có nhiều kết nối được thực hiện
Chương 7: TRIỂN KHAI CÔNG CỤ CSLAB
Cài đặt công cụ vào hệ thống SAKAI
Chương 8: TỔNG KẾT
Tổng kết các kết quả đạt được, những hạn chế của luận văn và hướng phát triển công cụ
Trang 5MỤC LỤC
CHƯƠNG I GIỚI THIỆU ĐỀ TÀI 1
1.1 Giới thiệu tổng quan 1
1.2 Nhiệm vụ đề tài 9
1.3 Đóng góp của luận văn 10
1.4 Cấu trúc luận văn 10
CHƯƠNG II CÁC KIẾN THỨC LIÊN QUAN 11
2.1 SSH trong JAVA 11
2.2 Giao thức HTTP 12
2.3 Servlet 17
2.4 Java Server Pages (JSP) 23
2.5 Java Server Jaces (JSF) 27
2.6 Spring 30
2.7 Maven 38
2.8 Mô hình 3 tầng của một hệ thống web 40
CHƯƠNG III PHÂN TÍCH YÊU CẦU 42
3.1 Mô tả hiện trạng và yêu cầu 42
3.2 Cấu trúc của hệ thống 46
3.3 Các phương hướng hiện thực quá trình biên dịch và kiểm thử 48
3.4 Các yêu cầu khác 49
3.5 Lựa chọn phương án và tính khả thi 51
3.6 Danh sách chi tiết các yêu cầu của người dùng (URS – User Requirement Specification) 52
CHƯƠNG IV THIẾT KẾ CÔNG CỤ CSLAB TRÊN DỰ ÁN SAKAI 55
4.1 Các chức năng chính 55
4.2 Cấu trúc công cụ CSLab 56
4.3 Hoạt động của công cụ CSLab 57
4.4 Thiết kế giao diện và hoạt động của các trang trong công cụ CSLab 71
CHƯƠNG V HIỆN THỰC CÔNG CỤ CSLAB 86
5.1 Package 86
5.2 Hệ thống các trang JSP 86
5.3 Hiệu ứng phụ 87
Trang 6CHƯƠNG VI KIỂM TRA HIỆU SUẤT HOẠT ĐỘNG CỦA TEST SERVER 91
6.1 Kế hoạch Test 91
6.2 Các kịch bản cần thực thi 92
6.3 Kết quả 93
CHƯƠNG VII TRIỂN KHAI CÔNG CỤ CSLAB 103
7.1 Cài đặt SAKAI và công cụ CSLAB vào SAKAI Server 103
7.2 Cài đặt dịch vụ SSH vào Test Server 108
7.3 Cấu hình cho Test Server 109
7.4 Các lưu ý khi sử dụng 111
CHƯƠNG VIII TỔNG KẾT 113
8.1 Các kết quả đạt được 113
8.2 Một số giới hạn 113
8.3 Các phương hướng phát triển 114
CÁC TÀI LIỆU THAM KHẢO 115
PHỤ LỤC I TRÌNH DIỄN QUÁ TRÌNH TẠO VÀ LÀM BÀI TRÊN CÔNG CỤ CSLAB 117
1 Giảng viên tạo bài thực hành 117
2 Sinh viên làm bài 123
PHỤ LỤC II SAKAI TOOL TUTORIAL 127
1 Giới thiệu 127
2 Backup và Restore Sakai 127
3 Sakai tool với JSF 128
4 Một số kinh nghiệm hữu ích 171
Trang 7MỤC LỤC HÌNH
1.1-1-Các tổ chức sử dụng SAKAI 7
2.1-1-Mô hình giao thức SSH 11
2.2-1-Mô hình giao thức HTTP 13
2.2-2-HTTP Header với phương thức GET 14
2.2-3-HTTP Header với phương thức POST 14
2.2-4-HTTP Request – Response (1) 15
2.2-5-HTTP Request – Response (2) 16
2.3-1-Response với các tài nguyên tĩnh 17
2.3-2-Response với các tài nguyên động 18
2.3-3-Request-Response với Servlet 19
2.3-4-Servlet Engine 21
2.3-5-Các bộ lọc và Servlet 22
2.4-1-Kết quả củvới mã nguồn JSP và HTML 24
2.4-2-Servlet và JSP trong Servlet Container 25
2.4-3-MVC bên trong thế giới của JSP và Servlet 26
2.5-1-JSF Components của iceFaces 28
2.5-2-JSF Components của MyFaces 28
2.5-3-Bảng so sánh các “thương hiệu” JSF 29
2.5-4-Mojarra và Apache MyFaces 29
2.6-1-Ví dụ Spring 33
2.6-2-Spring trong SAKAI 34
2.6-3-Kết quả khi thực hiện lệnh deploy của Maven 35
2.7-1-Eclipse Dependency Hierarchy 39
2.7-2-Eclipse Dependency Graph 40
2.8-1-Dòng thông tin trong kiến trúc 3 tầng 41
3.1-1-Quy Trình thực hiện bài Test của các hệ thống Test Online thông thường 42
3.1-2-Quy trình chấm bài đối với các môn lập trình 43
3.1-3-Quy trình chấm các bài Test bằng tay trong các môn lập trình 44
3.1-4-Quy trình thực hiện bài Test của các hệ thống Test Online mới hỗ trợ các môn lập trình 45
3.2-1-Cấu trúc hệ thống cũ và dòng chảy của toàn hệ thống 46
3.2-2-Cấu trúc hệ thống mới và dòng chảy của toàn hệ thống 47
4.1-1- Usecase Model 55
4.2-1-Cấu trúc Công cụ CSLab và hệ thống các máy chủ 56
4.3-1-Lược đồ tuần tự hoạt động của hệ thống 58
4.3-2-Vòng đời các đối tượng 61
4.3-3-Nội dung tập tin config 62
4.3-4-Nội dung tập tin mapping 63
4.3-5-Nội dung tập tin script 63
4.3-6-Thư mục lưu trữ dữ liệu của chương trình 64
4.3-7-Hoạt động của chương trình đối với giảng viên 66
Trang 84.3-8-Dòng chảy quá trình tạo bài thực hành 67
4.3-9-Hoạt động của chương trình đối với sinh viên 69
4.3-10-Dòng chảy quá trình sinh viên làm bài và kiểm tra kết quả 70
4.4-1-Trang chính của giảng viên 71
4.4-2-Trang chính của sinh viên 72
4.4-3-Trình thuật sĩ tạo/sửa bài thực hành – bước 1: thông tin tổng quan 74
4.4-4-Trình thuật sĩ tạo/sửa bài thực hành – bước 2: cung cấp các tập tin tham khảo 75
4.4-5-Trình thuật sĩ tạo/sửa bài thực hành – bước3: cung cấp các tập tin bài làm mẫu 75
4.4-6-Trình thuật sĩ tạo/sửa bài thực hành – bước 4: cung cấp thông tin về Test Server 76
4.4-7-Trình thuật sĩ tạo/sửa bài thực hành – bước 5: cung cấp thông tin đăng nhập 76
4.4-8-Trình thuật sĩ tạo/sửa bài thực hành – bước 6: cung cấp các tập tin chứa dòng lệnh cần thực thi 77
4.4-9-Thông tin tổng quan bài thực hành 81
4.4-10-Tình trạng bài thực hành 82
4.4-11-Trang làm bài của sinh viên 84
5.3-1-Date Time Picker 88
5.3-2-Code Highlighter 89
5.3-3-Sắp xếp dữ liệu theo cột StartOn 90
5.3-4-Sắp xếp dữ liệu theo cột Name 90
6.3-1-Báo cáo tổng quát cho quá trình Load Test 94
6.3-2-Load Test: Kịch bản 1 với 256MB bộ nhớ, 10 kết nối 95
6.3-3-Load Test: Kịch bản 2 với 256MB bộ nhớ, 10 kết nối 95
6.3-4-Load Test: Kịch bản 3 với 256MB bộ nhớ, 10 kết nối 96
6.3-5-Load Test: Kịch bản 1 với 512MB bộ nhớ, 10 kết nối 96
6.3-6-Load Test: Kịch bản 2 với 512MB bộ nhớ, 10 kết nối 97
6.3-7-Load Test: Kịch bản 3 với 512MB bộ nhớ, 10 kết nối 97
6.3-8-Báo cáo tổng quát cho quá trình Stress Test 98
6.3-9-Stress Test: Kịch bản 1 với 256MB bộ nhớ, 10 kết nối 99
6.3-10-Stress Test: Kịch bản 2 với 256MB bộ nhớ, 10 kết nối 99
6.3-11-Stress Test: Kịch bản 3 với 256MB bộ nhớ, 10 kết nối 100
6.3-12-Stress Test: Kịch bản 1 với 512MB bộ nhớ, 10 kết nối 100
6.3-13-Stress Test: Kịch bản 2 với 512MB bộ nhớ, 10 kết nối 101
6.3-14-Stress Test: Kịch bản 3 với 512MB bộ nhớ, 10 kết nối 101
Trang 9CHƯƠNG I CÁC KIẾN THỨC LIÊN QUAN
I.1 SSH trong JAVA
a Giao thức SSH: SSH hay Secure Shell là giao thức mạng dùng để trao đổi thông tin giữa hai thiết bị dưới một kên truyền bảo mật, thường được sử dụng trong các hệ thống Linux hay hệ thống Unix-based để đăng nhập tài khoản từ xa
Cách thức làm việc của SSH bao gồm 3 bước là:
xác định máy chủ thông qua việc trao đổi khóa
xác lập một phiên làm việc bảo mật được mã hóa từ khóa đồng bộ được traođổi ở bước trên
chứng thực người dùng
SSH được thiết kế để thay thế cho giao thức Telnet hay các giao thức đăng nhập tài khoản từ xa không bảo mật khác, khi mà password của user và data được gửi đi dưới dạng plain-text và có thể bị bắt được bởi các chương trình bắt gói thông tin trên mạng
2.1-1-Mô hình giao thức SSH
Trang 10 SSH sử dụng cơ chế mã hóa Public-key và Authentication để chứng thực người dùng
SSH thực thi các tính năng chính như đăng nhập tài khoản từ xa, thực thi command đồng thời hỗ trợ việc gửi / nhận tập tin qua các giao thức SCP hay SFTP Ngoài ra SSH còn hỗ trợ các giao thức khác như Tunneling, Port
Forwarding, X11
Cổng mặc định của giao thức SSH là 22
Phiên bản mới nhật của SSH hiện nay là phiên bản 2 nâng cao tính bảo mật (ví dụ: sử dụng cơ chế trao đổi khóa Diffie – Hellman, message authentication code để kiểm tra tính toàn vẹn ) hay thêm một số chức năng (chạy nhiều shell trong một kết nối SSH …)
b JSCH: thư viện SSH trong Java
JSch là thư viện Java hiện thực việc kết nối đến máy chủ SHH sử dụng giao thức SSH-2, được phát hành với dưới giấu phép BSD-type
Hỗ trợ giao thức SSH-2 với khả năng đăng nhập shell hay thực thi câu lệnh
từ xa
Hỗ trợ việc chứng thực user bằng phương pháp Authentication hay key
Public- Hỗ trợ các tính năng gửi / nhận tập tin qua giao thức SCP
Hỗ trợ các giao thức X11Port Forwarding
Phụ thuộc vào gói Java Cryptography Extension (JCE) – gói thư viện mã hóa chuẩn của Java
I.2 Giao thức HTTP
Trước khi tìm hiểu về các công nghệ lập trình ở mức cao hơn, hiểu về
phương thức mà web browser và và webserver trao đổi đem lại lợi ích khi ta tươngtác với đối tượng request/response cũng như giúp ích trong việc debug khi có lỗi xảy ra
Trang 11 HTTP là viết tắt của Hyper-Text Transport Protocol, một phương thức giao tiếp theo kiểu yêu cầu-đáp ứng(request-response) Trong các tình huống phổ biến máy khách(client) sẽ mở một kết nối đến máy chủ(server) và gửi đi một HTTP request cho một tài nguyên(resource) nào đó, máy chủ sẽ trả lời với một HTTP response Sau khi nhận được response từ máy chủ, máy khách đóng kết nối đã tạo.Phương thức này là sau mỗi lần trao đổi yêu cầu-đáp ứng, máy chủ hoàn toàn không nhớ gì về khách nên được gọi là không trạng thái(stateless) Đứng trên góc nhìn của máy chủ mọi yêu cầu từ máy khách đều là yêu cầu đầu tiên.
2.2-2-Mô hình giao thức HTTP
Thường một gói tin HTTP có các phần:
Phần mở đầu: Chỉ định đây là gói yêu cầu(request) hay đáp ứng(response)
Phần đầu đề(header): Chỉ định một số thông tin về độ lớn, kểu, bộ mã kí tự của nội dung gói tin
Thí dụ: GET /MyWebApp/index.html HTTP/1.1
Ở phần phương thức gồm có GET,POST,HEAD,PUT.Thông thường ta chỉ quan tâm đến GET và POST
Trang 12 Trong một yêu cầu HTTP GET, các thông tin từ phía máy khách được gắn vào đuôi của URL: http://SomeHost/WebApp/home?
name=PVH&pass=50600822
2.2-3-HTTP Header với phương thức GET
Nói cách khác thông tin từ phía khách được đính kèm trong URL Điều này
có khuyết điểm: thứ nhất là độ dài giới hạn của URL, thứ hai là URL thường được trình duyệt ghi nhớ vì vậy các thông tin nhạy cảm không được đảm bảo GET vì vậy thường dùng để yêu cầu các tài nguyên tĩnh, hình ảnh, HTML hoặc các file nhỏ
Trong Một yêu cầu HTTP POST các thông tin từ phía máy khách được đính kèm trong phần thân của gói HTTP POST khắc phục nhược điểm để lộ thông tin trên URL và hạn chế về độ dài thông tin cần truyền tải Nếu bạn muốn gửi một tập tin lên máy chủ(upload) bạn phải sử dụng phương thức POST
2.2-4-HTTP Header với phương thức POST
Đáp ứng HTTP:
Một điều ta cần lưu ý HTTP là stateless nghĩa la mỗi quá trình
request/response không được nhớ bởi HTTP server Nếu browser của bạn gửi
Trang 13liên tiếp nhiều request đến một server, server sẽ xem các request này la độc lập, không có liên hệ với nhau.
Một trong những cách tạo ra mối lien hệ giữa các request là sử dụng
Cookies Khi server nhận được một request từ browser, server sẽ trả lời bằng một response và đặt vào đó một header đặt biệt gọi là cookie Nếu Broswer có
hỗ trợ cookies, nó sẽ lưu cookie tìm được trong header và gửi kèm với các request từ sau đó.Server sẽ dựa vào đây để liên hệ các request với nhau mà ta gọi là session Tuy nhiên Server hoàn toàn không đòi hỏi việc browser gửi kèm cookie mà nó đã nhận, việc sử dụng cookie do server cung cấp hoàn toàn phụ thuộc vào browser
2.2-5-HTTP Request – Response (1)
Các request từ browser sau đó gửi kèm cookie(do server gửi ) trong header
Trang 142.2-6-HTTP Request – Response (2)
Tuy nhiên do việc gửi kèm cookie trong header là phụ thuộc vào browser và một số browser không hỗ trợ cơ chế này Một kĩ thuật khác dùng để duy trì session là “encode URL” Một session ID sẽ được gắn vào URL
Khi sử dụng Servlet bạn có thể trích header từ đối tượng HttpServletRequestbằng các method getHeader(), getHeaders(), getHeadernames() Hoặc gọi
getCookies để lấy về cookies và xử lí session
Trong JSP/Servlet tồn tại một đối tượng ngầm định của lớp HttpSession, bạn
có thể đặ các đối tượng mình muốn vào session hoặc xóa một đối tượng khỏi session, bạn cũng có thể gọi hàm invalidate( ) để hủy session
Một thành phần quan trọng khác của gói HTTP là MIME type trong header của gói Khi máy chủ trả lời cho trình duyệt phía người sử dụng, trình duyệt sẽ dựa vào thông tin MIME type này để quyết định cách xử lí và trình bày dữ liệu nhận được cho người sử dụng Mặc dù khi lập trình ứng dụng mạng(web
application), đa số gói tin được trao đổi chứa đựng kiểu thông tin là html/text tuy nhiên đôi khi bạn cần truyền tải dữ liệu dưới dạng nhị phân, thí dụ cho phép user
Trang 15tải một file từ Server Nếu bạn mở một mã nguồn của trang JSP bạn thường hay thấy:
<%@ page contentType="text/html; charset=UTF-8" %>
Chỉ thị trên thường nằm ở đầu trang JSP ở đây thông báo cho trình duyệt biết thông tin trả về là một văn bản HTML sử dụng mã Unicode(UTF-8)
I.3 Servlet
a Ứng dụng web (Web Application)
Trước khi đến với servlet, tôi xin nói sơ về web application Đơn giản mả nói đó làmột application mà người sử dụng có thể tương tác qua môi trường web.Thôngthường người sử dụng chỉ cần browser để có thể sử dụng application này Mọi lolắng về bảo trì, nâng cấp hoàn toàn không tồn tại phía người dùng Web applicationlàm việc theo cơ chế request-response như đã nói ở phần HTTP Protocol Browsergửi đến server một request cho mộ resource, resource này có thể là tĩnh (như filejpg, gif, pdf, html) hoặc động (JSP/Servlet) Chính những resource động đó làmcho web application trở nên linh động như mọi application trên máy của bạn
2.3-7-Response với các tài nguyên tĩnh
Trang 162.3-8-Response với các tài nguyên động
b Servlet
Servlet nói nôm na là một chương trình viết bằng Java chạy trên server với hai nhiệm vụ chính:
Nhận và xử lí request do client gửi đến
Tạo ra response để gửi đến client
Trong thế giới của Java, Servlet là cơ sở của mọi web application
Một web server sẽ có những thành phần phụ trách việc load và thực thi các servlets, những thành phần này gọi là servlet container hay servlet engine Có thể minh họa như sau :
Một browser gửi request đến web server, nếu đối tượng được request là một file HTML server sẽ trực tiếp trả lời bằng nội dung file này Nếu đối tượng đượcrequest là 1 sevlet, server sẽ gọi servlet container xử lí request này, servlet container sẽ đưa request này đến servlet và từ đó servlet thực thi các thao tác với
hệ thống file và database tạo ra một response phù hợp
Hiện nay có khá nhiều servlet container mà bạn có thể sử dụng : như Tomcatcủa Apache, Resin của Caucho Tech, JRun của Macromedia , WebLogoc của BEA, Webshpere của IBM, v v
Trang 172.3-9-Request-Response với Servlet
Thực tế thì trong lập trình web application ta chỉ sử dụng lớp HttpServlet được mở rộng từ Servlet.Định nghĩa một Servlet bằng cách tạo một lớp mới mở rộng HttpServlet và hiện thực phương thức doGet hoặc doPost (tương ứng với
Trang 18việc Servlet nhận xử lí GET/POST từ yêu cầu HTTP):
public class HelloWorld extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse
response)
throws ServletException, IOException {
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 " + "Transitional//EN\">\n" +
Trang 192.3-10-Servlet Engine
Hình “ 2.3 -10-Servlet Engine” chỉ có một đối tượng Servlet, trên thực tế một chương trình mạng của bạn chưa có thể chứa rất nhiều Servlet vậy làm sao Tomcat hoặc các Servlet container khác quyết định được request này dành cho Servlet nào? Servlet nào nên nhận đối tượng request do máy khách gửi đến? Đo
là lí do mỗi chương trình mạng đều kèm theo một mô tả triển khai (deployment descriptor) dưới dạng một văn bản XML, đó chính là tập tin web.xml Đọc và hiểu được web.xml là một trong những kĩ năng quan trọng trong lập trình ứng dựng mạng nhất là đối với những hệ thống phức tạp như Sakai, mỗi công cụ trênSakai có ít nhất một Servlet làm controller Dưới đây là một phần nội dung của
Trang 20 Tương tự bạn có thể có nhiều servlet và servlet mapping, nhưng một pattern> chỉ được ánh xạ cho một servlet, trong trường hợp có sự trùng lắp trong các biểu thức mô tả url-pattern, một số luật phân định độ ưu tiên sẽ được áp dụng Bạn có thể tham khảo trong một số tài liệu mô tả mục servlet mapping…
<url- Ngoại trừ Servlet bạn cũng cần để ý đến một lớp khác gọi là filter, lớp này đóng vai trò bộ lọc, chặn trước một tài nguyên nào đó, khi có yêu cầu đối với tài nguyên đó thì filter sẽ chặn, xử lí yêu cầu trước rồi mới đưa yêu cầu đó đến nơi phù hợp(servlet hoặc filter khác)
2.3-11-Các bộ lọc và Servlet
Trang 21 Các bộ lọc được chỉ định trong tập tin web.xml tương tự Servlet:
< filter-name > sakai.request </ filter-name >
< servlet-name > FacesServlet </ servlet-name >
< dispatcher > REQUEST </ dispatcher >
< dispatcher > FORWARD </ dispatcher >
< dispatcher > INCLUDE </ dispatcher >
</ filter-mapping >
I.4 Java Server Pages (JSP)
a Điểm yếu của Servlet là sự trộn lẫn giữa nội dung văn bản HTML và java, giữa
mã phục vụ cho thiết kế giao diện và mã logic của chương trình Làm sao bạn có thểkiểm soát được văn bản DOM của mình khi nó bị trộn lẫn trong mã nguồn cùng code java, bạn thử xem lại thí dụ mã nguồn của một Servlet đơn giản phía trên mục đích chỉ để in ra nội dung một văn bản HTML :
<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
mở và đóng một khu vực mà trong đó bạn có thể dùng mã Java Ngoài ra trong JSP bạn có thể trộn lẫn mã Java và HTML
Trang 22Mã JSP trên sẽ cho ra nội dung:
2.4-12-Kết quả củvới mã nguồn JSP và HTML
c Có một sự tiện lợi ở đây, thí dụ một lúc nào đó bạn cần duyệt qua một danh sách các đối tượng và in ra với một các thuộc tính của đối tượng đó, bạn chỉ cần viết mã HTML cho một đối tượng và đặt nó trong một vòng lặp
Chính sự tiện lợi đó đã làm mất đi mục đích của JSP, trong ví dụ trên bạn có thể kiểm soát được mã HTML được in ra do khối lượng mã nguồn nhỏ Với nhữngtrang JSP khoảng trăm dòng thì JSP cho thấy biểu hiện không khá hơn người an hem Servlet của mình là mấy Mặt khác trong môi trường công nghiệp, sự chuyên môn hóa và tách biệt về chức năng là phổ biến và cần thiết Đội thiết kế giao diện người dùng có thể không chuyên về Java, họ quen với cú pháp của các văn bản XML, điều này hoàn toàn hợp lí vì CSS, Javascript, Jquery … các công cụ để thiết
Trang 23kế giao diện thường theo quy luật xử lí các phần tử của cây XML thông qua các công cụ như SAX(Simple API for XML) Đó là lí do mà JSP cho phép bạn tạo ra
và sử dụng các miếng dán (custom tag)
Các miếng dán bao đóng mã java thành những cú pháp đúng theo chuẩn văn bản XML, tức là có miến dán mở <dán> và miếng dáng đóng </dán> hoặc kiểu viết rút gọn <dán/> cho một số trường hợp Tập hợp của nhiều miếng dán cùng phục vụ một miền chức năng nào đó gọi là thư viện miếng dán (taglib) JSTL (Java Standard Tag Lib) là một trong những tập hợp các bộ miếng dán ra đời sớm nhất và được sử dụng rộng rãi Mỗi bộ miếng dán sẽ sở hữu một URI dùng để khaibáo ở đầu trang khi sử dụng
2.4-13-Servlet và JSP trong Servlet Container
d Servlet + JSP + Design Pattern → MVC
Servlet mang đến một môi trường lý tưởng khi bạn lập trình chức năng, hoàntoàn như viết một application bình thường Trong khi đó JSP đem đến sự rõ ràng khi bạn thiết kế giao diện người dùng hoặc các template bắt mắt Mô hình MVC của design pattern chóng được áp dụng dựa trên các đặt điểm ưu thế riêng của Servlet, JSP và java bean Mô hình MVC(Model-View-Controller) hay còn gọi là Model -2 nhanh chóng được áp dụng rộng rãi
Servlet – chứa code logic điều khiển các dòng chảy của chương trình đóng vai trò Controller
Trang 24 Javabean – giữ các trạng thái của chương trình (vì HTTP là stateless), đóng vai trò Model
JSP – tạo ra các template và trình bày các dữ liệu đến người dùng, đóng vai trò View
2.4-14-MVC bên trong thế giới của JSP và Servlet
Theo đó nhiều framework đã ra đời ứng dụng mô hình này : Strut, Tapestry, SpringMVC, JSF, Velocity, Wicket…
Do tính chất của JSP cho phép trộn lẫn code logic(java) cùng với các tag (xml) , JSP dần được loại bỏ để đảm bảo tính độc lập và rõ ràng của lớp
presentation Các file JSP được thay thế bằng file *.vm(Velocity), *.xml (JSF 2.0),
*.html(Wicket) …
Hiểu được JSP/Servlet và lý thuyết design pattern giúp bạn làm quen và sử dụng các khung thức (framework) một cách dễ dàng Một khi bạn quen với một trong các framework trên , việc chuyển qua sử dụng các framework khác rất dễ dàng Thậm chí việc hiểu cách làm việc của Servlet bạn có thể sử dụng một cách linh hoạt nhiều framework trong cùng một webapp để có thể sử những dịch vụ tốt nhất mà mỗi khung thức cung cấp, trên thực thế trong sách Javaserver Faces In Action có chương hướng dẫn bạn tích hợp JSF và Strut, trong sách Spring In action chương cuối cũng hướng dẫn bạn tích hợp Spring MVC hoặc Spring Web Flow vào JSF…
Trang 25I.5 Java Server Jaces (JSF)
a Nếu bạn đã từng lập trình với JSP và Servlet hẳn bạn sẽ nhận ra điểm yếu trong lập trình web bằng Java Đôi khi những việc bạn đã làm rồi nhưng phải làm lại nhiều lần Khả năng tạo ra các thư viện riêng của JSP (taglib) tuy có thể giúp bạn sử dụng lại component nhưng đòi hỏi một quá trình implement và config rườm rà mất thời gian không kém Đặt biệt nếu bạn đã biết đến ASP.net với các thao tác drag-drop các component từ 1 toolbar tạo một trang web trong vài phút càng không khỏi
lo lắng cho sự nghiệp viết web với Java của mình trong một thế giới RAD
b FrameWork JSF ra đời mới mục đích xóa bỏ xóa bỏ yếu điểm đó Với JSF bạn cóthể tạo trang web từ các thư viện component một cách nhanh chóng, các IDE như Eclipse, Netbean,… cho phép bạn drag và drop các component vào trang web để tạogiao diện nhanh chóng
c Các thư viện component phong phú được cung cấp bởi nhiều nguồi khác nhau bởicác project :
d Sự phong phú của các thư viện JSF với các “thương hiệu” khác nhau tạo ra một
sự cạnh tranh và phát triển không ngừng Người sử dụng lựa chọn dựa trên số lượng component, sự phong phú về tính năng, vẻ bắt mắt của giao diện…
Trang 262.5-15-JSF Components của iceFaces
2.5-16-JSF Components của MyFaces
e Trong JSF 2.0 các phần thành phần viết sẵng được tính hợp cả Ajax, giống như tính năng auto postback của các phần tử ASP.net Có thể nói J2EE đang cố gắng trở
Trang 27thành đối trọng của ASP.net trong thế giới phát triển ứng dụng liên tục
(RapidApplicationDevelopment) với khung thức JSF đầy tiềm năng
f Dưới đây là một bảng so sánh về các tiện ích mà các “thương hiệu” JSF cung cấp:
2.5-17-Bảng so sánh các “thương hiệu” JSF
g Trong số trên có hai nhánh JSF lớn một do Sun (bây giờ là Oracle) thực hiện là
dự án Mojarra, một do Apache thực hiện là dự án Myfaces:
2.5-18-Mojarra và Apache MyFaces
h Sakai hỗ trợ cho cả hai dòng JSF này Ngoài ra cộng đồng Sakai thực hiện một bộcomponent dưới taglib có prefix là <sakai:> RSF cũng là một phiên bản của JSF
Trang 28được Cambridge “viết lại” Nếu bạn lên trang https:// confluence sakai project.org và search cụm từ JSF không có gì lạ nếu số lượng result vượt trội các công nghệ khác Tuy nhiên JSF trên Sakai cũng gây ra nhiều tranh cãi vì phiên bản mà sakai có thể
sử dụng là 1.01 do các dependency servlet-api và phiên bản của tomcat chưa cho phép sử dụng JSF 2.0 JSF 1.01 còn yếu trong việc phân tách các chức năng dẫn đến
sự rối loạn trên lớp giao diện(view) JSF rất mạnh, có thể làm được mọi thứ mà bạn muốn, nhưng khi nhìn vào các trang JSP của một tool có tầm cỡ (thí dụ Samigo) thì ngay cả người đã viết ra chưa hẳn đã biết mình đã làm gì Cộng đồng Sakai đã có khi nhận xét JSF chẳng qua là một phiên bản JSP với độ khó cao (“JSF, well that’s just hard JSP”) Hiện nay một số thành viên tâm huyết của Sakai chuyển sang sử dụng Wicket để nâng cấp các công cụ cho Sakai và kêu gọi các thành viên khác ủng
hộ cho Wicket, tuy nhiên JSF vẫn chiếm vai trò ngự trị trên hệ thống Sakai, mặt khác nhìn chung Wicket vẫn chưa được biết đến nhiều trong môi trường sản xuất
i Một số công cụ trên Sakai được hiện thực bằng JSF:
có thể hoạt động như EJB Spring đem đến sự đơn giản, độc lập cho các module phần mềm và giúp việc test phần mềm trở nên hiệu quả Công dụng của Spring rất
Trang 29phong phú và trong nhiều trường hợp khá phức tạp, ở đây tôi chỉ trình bày phần cơ bản nhất của Spring Framework, cơ chế Dependency Injection hay còn gọi là
và phần mà các sinh viên viết sẽ được lần lược thay thế vào trước khi chạy hành động đó là Dependency Injection (hay còn gọi là Inversion Of Control) Việc thay thế một module như thế không phải mới và đã tồn tại từ lâu nhưng Spring cung cấp một cơ chế injection gọn gàng hiệu quả và dễ quản lí
c IoC: vì sao gọi là Inversion Of Control(IoC)? Cái gì bị đảo ngược(inversed)? Trong cơ chế này một số khái niệm lập trình cũ bị thay đổi Khi bạn thiết kế một chương trình theo kiểu “lập trình thủ tục”, bạn sẽ nghĩ các dòng chảy của chương trình chạy theo một trình tự với những hàm chức năng được gọi bởi main, tuy nhiên khi sử dụng cơ chế injection, bạn hoàn toàn không lường trước chuyện gì xảy ra trong chương trình con mà bạn gọi, bạn không hề biết gì ngoài input và output được khai báo như interface của trình con Cụ thể đã có trương hợp một số assignment của các bạn sinh viên khi được gọi chạy bởi main thay vì thực hiện một số hàm chứcnăng như yêu cầu của đề bài thì đã đem đến chức năng tự động delete các folder trong hệ thống file của hệ thống(đương nhiên bài mà các sinh viên khác đã nộp cungtheo đó mà đi) hoặc thực hiện các hành vi mang tính phá bĩnh khác Mặt khác trong lập trình hướng đối tượng, đối tượng được bạn tạo ra trực tiếp bằng toán tử new và Class cần tạo, trong IoC đối tượng được tạo bởi nhà máy đậu(bean factory), trong
mã chương trình bạn chỉ thực hiện hành vi tìm và gắn kết đối tượng thông qua định danh , điều này làm mất đi tính năng kiểm tra kiểu tĩnh nếu lúc chạy đối tượng mangđịnh danh đó không tương thích với biến ở vế trái trong biểu thức gắn kết…
Trang 30d Bạn cần hiểu cơ chế hoặc ít nhât là cách sử dụng Spring để có thể sử dụng các tiện ích được chia sẻ trong hệ thống Sakai.Trước khi đến với mở rộng của Spring trong Sakai, bạn thử xem thí dụ đơn giản sau về sử dụng Spring:
Giả sử chúng ta viết một chương trình mô tả việc một sinh viên đi học, đầu tiên ta tạo một interface gọi là SinhVien với hai phương thức điHọc() và điThi(), đạt Interface này trong gói tên là api
System.out.println( "Em di hoc 100% Truoc khi den lop em doc
}
System.out.println( "De thi rat hay va thu vi" );
}
System.out.println( "Troi dep, em cup hoc mot bua, bua sau
}
System.out.println( "Nhin de thi cha hieu gi ca, chac hoc lai roi" );
Trang 31 Tạo một tập tin tên là sinhvien.xml(của tôi là E:/sinhvien.xml) với nội dung sau:
<?xml version= "1.0" encoding= "UTF-8" ?>
<beans xmlns= "http://www.springframework.org/schema/beans"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://www.springframework.org/schema/beans
http: //www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id= "thanhcong" class= "impl.SVChuyenCan" ></bean>
<bean id= "thatbai" class= "impl.SVLuoi" ></bean>
</beans>
Để ý mục <bean>…<bean> trong <beans> … </beans> thông số id sẽ được dùng để tìm và gắn kết đối tượng này khi chương trình chạy Nội dung dài dòng trong <beans> ( xmlns=….), để có được nội dung này bạn có thể lấy trong tài liệu mô tả(specification) đi kèm gói thư viện của Spring (điều này là phổ biến, với các framework có các tập tin xml khác bạn cũng làm điều tương tự thí dụ file hbm.xml hay config.xml của Hibernate )
Sau đây là hàm Main và kết quả chạy chương trình:
2.6-19-Ví dụ Spring
Trang 32 Bây giờ nếu có ai đưa cho bạn một lớp thực hiện nội dung SinhVien do họ viết khi này bạn sửa lại tập tin sinhvien.xml, chạy lại chương trình mà không cần dịch lại kết quả sẽ thay đổi Bạn có thể đảo thông số class và id trên thí dụ trên để kiểm tra.
e Spring trong Sakai:
Hệ thống Sakai phát triển và sử dụng mộ phiên bản mở rộng đặt biệt của Spring Đó cũng là một trong những niềm tự hào mà cộng đồng Sakai hay nhắc đến Như ta biết trong Spring các đối tượng được tạo ra bởi mộ “nhà máy” và sốngtrong một context, trong đó xảy ra các quá trình “gắn kết” (bean - wiring) lúc chương trình đang chạy Có thể nói nôm na các đối tượng tồn tại trong một tầm vực và trong lúc chạy chương trình có thể tìm đối tượng đó bằng định danh(id) hoặc lớp (nếu là nếu lớp chỉ có một đối tượng lúc chạy - singleton) Trong Spring nguyên thủy, môi trường mà các đối tượng tồn tại gọi là ngữ cảnh của chương trình(application context)
Hiển nhiên các đối tượng chỉ tồn tại trong tầm vực của một chương trình Vấn đề ở đây Sakai là một hệ thống bao gồm nhiều chương trình mạng(web
application) và việc chia sẻ một số đối tượng thí dụ SessionFactory của Hibernate dùng để tạo session và tương tác với cơ sở dữ liệu, BeanFactory của Spring,
UserdirectoryService,Tolmanager, CompnentManager vân vân là cần thiết Vì thế Cộng đồng Sakai phát triển một phiên bản mở rộng của Spring cho phép làm điều đó :
2.6-20-Spring trong SAKAI
Trang 33 Bạn sẽ thấy một số đối tượng được định nghĩa và tạo ra bởi một chương trình/ công cụ khác trên Sakai nhưng bạn lại có thể thực hiện hành vi dò tìm và gắn kết đối tượng đó với các tham khải của mình để sử dụng.
Nói có vẻ dài dòng, thực tế có lẽ bạn quan tâm hơn đến việc “xài sao?” Làmsao biết có những đối tượng nào tồn tại trong ngữ cảnh của hệ thống? Làm sao lấy được tham khảo của nó để sử dụng ?
Để ý mỗi công cụ trên Sakai có mã nguồn bao gồm các gói dự án con với tiếp vị ngữ api, impl, tool Ở ví dụ Spring phía trên, tôi đã cố tình đặt tên tương tự
để các bạn dễ liên tưởng Mỗi dự án con phụ trách một chức năng, trừ -tool là dự
án sử dụng kết quả từ tất cả các gói dự án khác để thực hiện chức năng hoành chỉnh của công cụ và cung cấp giao diện cho người sử dụng Với cách phát triển này các gói dự án được thực hiện, bảo trì , nâng cấp và kiểm thử một cách độc lập,chỉ cần đảm bảo các mô tả về cách giao tiếp giữa chúng
Nếu bạn vào tập tin pom.xml của mỗi dự án con trên và tìm mục
<deploy.target> …</deploy.target>
Bạn sẽ thấy các dự án khi chạy pha deploy của Maven sẽ có kết quả sau:
2.6-21-Kết quả khi thực hiện lệnh deploy của Maven
Khi bạn chạy lệnh “mvn clean install sakai:deploy”, là bạn đã liên tiếp chạy các
pha(phase) của Maven, clean sẽ xóa kết quả mà bạn đã “build” trước đó, install là dịch
và đóng gói kết quả thành file jar/war(tùy artifact-type mà bạn khai báo trong pom.xml)
chép kết quả này vào repository Cuối cùng sakai:deploy là chép các artifact trên từ
repository vào các địa chỉ được khai báo như trong file pom.Trong hình 2.6-3 bên dưới là
Trang 34thư mục chứa mã nguồn của công cụ Chat của Sakai, bên trên là thư mục C:/tomcat/ Cácđường nối thể hiện đích đến của các gói dự án con khi triển khai.
Trong số các thư mục trên, tập tin khai báo các đối tượng cho ngữ cảnh nằm trong “components” Thí dụ đây là tập tin component.xml của công cụ Tests & Quizzes của Sakai:
Cũng giống như ví dụ Spring mà tôi đưa ra bạn sẽ dùng chuỗi giá trị của id
để tìm và gắn kết đối tượng này vào một tham khảo và sử dụng
Có hai cách lấy được tham khải của một đối tượng trong context mà bạn đã biết id:
sử dụng api của ComponentManager: Trong mã chương trình dùng phương thức get(class) hoặc get(id) để lấy được tham khảo của đối tượng Đương nhiên bạn chỉ sử dụng get(class) khi biết chắc chỉ có một đối tượng lớp đó trong ngữ cảnh (singleton)
Trang 35 sử dụng cơ chế Dependency Injection: khai báo một tham khảo đến đối
tượng mà bạn muốn sử dụng như một thuộc tính của một lớp mà bạn tạo ra,
dùng tập tin xml nội bộ để gắn kết đối tượng trong ngũ cảnh vào thuộc tính đó
< managed-bean-scope > session </ managed-bean-scope >
< managed-property >
< description > User Directory Service </ description >
< property-name > userDirectoryService </ property-name >
< property-name > OhMyGod </ property-name >
< value > #{Components["PersistenceService"]} </ value >
</ managed-property >
</ managed-bean >
Trang 36 Việc bạn lấy về tham khảo của đối tượng này không mấy khó khăn, tuy nhiên nắm trên tay một đối tượng nhưng các công dụng của nó chỉ có đọc mã nguồn của lớp hoặc xem cách sử dụng từ các công cụ có sẵng Thí dụ bạn lấy về một api TypeFacadeQueries của Test & Quizzes, các phương thức của api này đềutrả về kiểu là List<???> sẽ khó lòng có ích nếu bạn không biết lớp của phần tử trong List, thật sự trong api và mã nguồn đều sử dụng List mà không khai báo rõ loại phần tử, bắt buộc bạn phải vào xem mã nguồn của các lớp liên quan hoặc
“mò” bằng bất cứ hình thức nào mà bạn có thể nghĩ ra
I.7 Maven
a Sakai project bao gồm nhiều project nhỏ hơn được bảo trì và phát triển bởi nhiều nhóm khác nhau Tuy nhiên các project này đôi khi phụ thuộc chồng chéo vào nhau,project này cung cấp dependencies cho project khác Việc quản lí tập trung các metadata,các dependencies cũng như các tập tin binary của project đã được dịch là cần thiết Maven được sử dụng trong việc quản lí các thông tin này
b Có phần tương tự như Ant hay Makefile, nhưng Maven đơn giản hóa việc quản lí project và dependencies trong các kho(Repository) Trong Repository không chỉ chứa các dependency mà còn kèm theo metadata của nó dưới dạng tập tin pom.xml Mỗi khi cần sử dụng một dependency bạn cần cung cấp các thong số để xác định dependency đó bao gồm ít nhất 3 thông số groupId, artifactId, version Bộ thông số này gọi là Maven Coordinate
c Một trong những tiện ích mà maven đem lại là cơ chế transitive dependency Khi bạn chỉ định một dependency cho project của mình, Maven sẽ tự đông tìm và add các dependency của dependency đó mà bạn không cần tự mình đi tìm rồi add vào- việc này tiết kiệm rất nhiều thời gian và đảm bảo các gói thư viện có version tương thích với nhau Bản thân bạn cũng có thể nhóm các dependency mà mình thường sử dụng thành 1 artifact để tiện cho việc sử dụng nhiều lần trong các project Một thí dụ
cụ thể về transitive dependencies:
Trang 37d Sau đây là một số ảnh minh họa về cơ chế nói trên, trong hình này eclipse được cài đặt m2eclipse plugin và project có tập tin pom khai báo như trên:
2.7-22-Eclipse Dependency Hierarchy
Bên tay trái là các dependency được chỉ định trong tập tin pom.xml của project, tay trái là kết quả của việc resolve dependency Bạn sẽ tiết kiệm rất nhiều thời gian cho việc tìm kiếm đủ danh sách dependency bên trái với đúng các
Trang 38version tương thích nhau Mặt khác nếu không có maven bạn sẽ phải tự quản lí các tập tin jar này và có thể tạo ra dư thừa và lãng phí trên máy tính của bạn.
Hình 2.7-2 là thanh(tab) Dependency Hierarchy, ngoài ra thanh pom.xml
là nội dung của tập tin pom của project này, Effective POM là nội dung tập tin
pom của project này merge với các tập tin pom cha, ông …v…v Nếu bạn mở mộtproject trong Sakai và xem effective pom bạn sẽ thấy tập tin pom rất dài và dễ dàng nhận ra được một phần trong đó là từ tập tin sakai-src/master/pom.xml
Ngoài ra m2eclipse còn cho phép bạn xem danh sách dependency và các mốiquan hệ một cách trực quan thông qua tab dependency Graph Hình sau đây minh họa bản đồ dependency của SakaiMonitor, một project nhỏ chúng tôi thử nghiệm
về chức năng thống kê số liệu từ Test & Quizz (Samigo) của Sakai:
2.7-23-Eclipse Dependency Graph
I.8 Mô hình 3 tầng của một hệ thống web
a Khác với mô hình 3 lớp ở trên, các tầng trong mô hình 3 tầng ở đây thể hiện cho
sự phân chia về mặt vật lý của một ứng dụng web, thường được thể hiện thành các file thực thi, thư viện hay thậm chí được tách ra trên các máy chủ khác nhau
b Ta có các tầng trong mô hình bao gồm
Tầng thứ nhất: tầng giao tiếp trực tiếp với người dùng, thường được hiểu như các trình duyệt web và các đoạn chương trình chạy ở phía người dùng
Tầng thứ hai: tầng xử lý các yêu cầu của người dùng gửi đến, thường được hiểu như máy chủ web và các ứng dụng phía máy chủ
Trang 39 Tầng thứ ba: tầng xử lý các quá trình bổ sung trước khi máy chủ trả về kết quả cho người dùng, thường được hiểu như các máy chủ ứng dụng khác, máy chủ
cơ sở dữ liệu
2.8-24-Dòng thông tin trong kiến trúc 3 tầng
c Trong mô hình đó, khi người dùng gửi một yêu cầu đến máy chủ web, máy chủ web sẽ xử lý các thông tin, gọi ứng dụng bên ngoài máy chủ khác rồi mới tổng hợp thành kết quả trả về cho người dùng Mọi luồng dữ liệu từ người dùng đều bắt buộc qua máy chủ web ở tầng thứ hai
Trang 40CHƯƠNG II THIẾT KẾ CÔNG CỤ CSLAB TRÊN DỰ ÁN SAKAI
II.1 Các chức năng chính
4.1-25- Usecase Model
Hình “ 4.1 -25- Usecase Model” mô tả các chức năng chính của chương trình
a Tổng quát
Quản lý nội dung bài thực hành
Lưu trữ và quản lý nội dung bài làm của sinh viên và kết quả trả về từ Test Server
b Về phía giảng viên
Xem danh sách tất cả bài thực hành
Tạo mới bài thực hành
Cấu hình quá trình biên dịch và kiểm thử cho bài thực hành
Xóa, sửa nội dung bài thực hành
Xem thông tin bài thực hành, tình trạng bài thực hành, thống kê
Xem bài làm, kết quả và tình trạng làm bài của sinh viên
c Về phía sinh viên
Xem danh sách và tình trạng các bài thực hành đang kích hoạt