Chương 14. Phát triển mô đun bằng AI

📚 Mục lục sách

Đến chương này, bạn đã biết cách tạo trang, bài viết, chức năng và tích hợp dịch vụ bên ngoài. Nhưng nếu nhu cầu của bạn vượt ra ngoài những gì EzyPlatform có sẵn, bạn có thể tự phát triển mô đun (mô đun) riêng — và đăng lên Marketplace để chia sẻ hoặc kinh doanh.

Mô đun là gì?

Một Mô đun là một gói mở rộng độc lập, có thể cài vào hoặc gỡ khỏi EzyPlatform mà không ảnh hưởng đến phần còn lại của hệ thống. Bạn có thể gọi mô đun là plugin hay theme. Trong cuốn sách này nhiều lần nhắc tới mô đun, plugin hay theme nếu bạn cảm thấy khó hiểu bạn có thể coi chúng là một.

Trong EzyPlatform một mô đun có thể có nhiều thành phần tuỳ theo nhà phát triển có bao gồm vào mô đun hay không. Chúng bao gồm:

  • Admin plugin — thành phần chạy ở phía quản trị (Admin), chứa các màn hình cấu hình, quản lý dữ liệu, API riêng của mô đun; có thể tự khai báo mục menu trong sidebar Admin để người dùng truy cập.
  • Web plugin — thành phần chạy ở phía Website (nơi khách truy cập), chứa API và tính năng phục vụ người dùng cuối, ví dụ vòng quay may mắn, form đăng ký, widget hiển thị dữ liệu... Web plugin bổ sung tính năng cho website chứ không quyết định giao diện tổng thể — việc đó là vai trò của theme.
  • Theme (chủ đề giao diện) — định hình toàn bộ diện mạo của một website: màu sắc, font chữ, bố cục tổng thể. Việc phát triển theme khác với việc chỉnh sửa một trang đơn lẻ: bạn cần đảm bảo tính nhất quán xuyên suốt tất cả các trang, bài viết, và khu vực khác nhau của website.
  • Socket Plugin — thành phần chạy trong máy chủ realtime (socket) của EzyPlatform, xử lý logic dùng chung trong một zone nhưng không trực tiếp nhận yêu cầu (request) từ client — phù hợp cho các tác vụ nền hoặc logic realtime chia sẻ giữa nhiều app khác nhau.
  • Socket App — cũng chạy trong máy chủ realtime, nhưng là một ứng dụng độc lập mà client kết nối và gửi yêu cầu trực tiếp tới, tự quản lý người dùng, phòng (room) và trạng thái riêng — phù hợp để xây một tính năng realtime cụ thể, ví dụ phòng chat hay một trò chơi vòng quay may mắn.
Khi phát triển theme, hãy yêu cầu AI thiết lập trước một bộ quy tắc chung: bảng màu, font chữ, khoảng cách, kiểu nút bấm — rồi mới áp dụng cho từng trang cụ thể. Điều này giúp toàn bộ website đồng bộ và chuyên nghiệp hơn.

Khi mô tả yêu cầu phát triển mô đun cho AI, hãy làm rõ:

  • Mô đun giải quyết vấn đề gì, dành cho ai sử dụng.
  • Nó cần những màn hình quản trị (Admin) nào để cấu hình.
  • Nó cần hiển thị gì ở phía Website.
  • Nó có cần lắng nghe sự kiện nào từ hệ thống không.
  • Nó có cần tính năng thời gian thực (realtime) hay không — nếu có, chọn Socket Plugin hay Socket App tuỳ theo client có cần kết nối trực tiếp hay không.

Khi nào cần tự phát triển mô đun?

Tư tưởng của EzyPlatform là đơn giản hoá công nghệ cho mọi người, nên phần lõi và các mô đun do EzyPlatform cùng các nhà phát triển khác cung cấp sẵn được thiết kế theo hướng Low Code và No Code khá mạnh — đủ dùng cho phần lớn nhu cầu phổ thông mà không cần viết một dòng code nào. Với AI và Vibe Coding, khả năng tuỳ biến từ những mô đun có sẵn lại càng mạnh mẽ hơn. Vậy nên trước khi quyết định tự phát triển một mô đun mới, bạn hãy trả lời các câu hỏi sau — nếu câu trả lời là "có" cho ít nhất một trong số đó, tự phát triển mô đun là lựa chọn hợp lý.

  • EzyPlatform và các mô đun có sẵn đang thiếu tính năng mà bạn cần, và không có cách nào cấu hình (Low Code/No Code) để đạt được.
  • Bạn cần một tính năng đặc thù cho riêng nghiệp vụ của mình mà không mô đun có sẵn nào đáp ứng được.
  • Bạn muốn đóng gói một bộ tính năng để tái sử dụng cho nhiều website khác nhau, thay vì code lại từ đầu mỗi lần.
  • Bạn muốn phát triển một sản phẩm để bán trên Marketplace của EzyPlatform.

Đóng gói và bán trên chợ thế nào?

Sau khi mô đun hoàn thiện, bạn có thể đóng gói thành một gói (một tập tin zip) theo chuẩn mà EzyPlatform đưa ra bằng lệnh ezy.sh package (xem chi tiết ở phần "Hướng dẫn khởi tạo dự án mô đun" bên dưới). Sau đó, để đăng bán trên Marketplace, bạn cần:

  • Truy cập ezyplatform.com và tạo tài khoản nhà phát triển.
  • Khởi tạo một dự án trên Marketplace và tải lên gói zip vừa đóng gói.
  • Mô tả rõ ràng mô đun dùng để làm gì, giải quyết vấn đề gì.
  • Ảnh chụp minh họa (screenshot) giao diện thực tế.
  • Thêm tài liệu hướng dẫn sử dụng từ cơ bản đến chi tiết.

Cài đặt môi trường cục bộ

Phát triển mô đun khác với việc tạo trang hay bài viết qua giao diện Admin: bạn cần một môi trường lập trình Java chạy ngay trên máy để AI có thể sửa code, build và chạy thử trước khi cài vào hệ thống thật. Gồm 5 bước, mỗi bước bạn chỉ cần đưa prompt tương ứng cho AI Assistant (Claude Code, Codex...) — nó sẽ tự kiểm tra và cài đặt giúp bạn.

Bước 1: Cài đặt JDK 8

EzyPlatform chạy trên nền Java, nên cần đúng JDK 8 (không phải bản mới hơn). Sau khi cài, biến môi trường JAVA_HOME phải trỏ đúng đến thư mục cài đặt.

📋 Prompt mẫu — Cài JDK 8
Máy tôi đang chạy {Windows / macOS / Linux}. Hãy kiểm tra máy tôi đã cài JDK 8 chưa (lệnh java -version).
Nếu chưa có hoặc đang là bản khác, hướng dẫn tôi tải và cài JDK 8 từ Oracle hoặc Eclipse Adoptium, rồi khai báo biến môi trường JAVA_HOME trỏ đến đúng thư mục cài đặt.
Sau khi cài xong, đưa tôi lệnh để xác nhận java -version và JAVA_HOME đã đúng. Nếu bạn không đủ quyền ghi tập tin, hãy hướng dẫn tôi điền thủ công.

Đây là các biến môi trường của tôi khi dùng lệnh cat ~/.zshrc để xem:

📄 ~/.zshrc
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export PATH=$PATH:$JAVA_HOME/bin

Và đây là phiên bản Java của tôi khi chạy lệnh java -version:

💻 java -version
java version "1.8.0_471"
Java(TM) SE Runtime Environment (build 1.8.0_471-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.471-b09, mixed mode)

Bước 2: Cài đặt MySQL

MySQL là nơi EzyPlatform lưu trữ dữ liệu. Bạn cần cài MySQL, sau đó tạo sẵn một database rỗng dành riêng cho EzyPlatform. Đầu tiên hãy nói AI hướng dẫn bạn cách cài đặt trước

📋 Prompt mẫu — Cài MySQL
Hãy kiểm tra máy tôi đã cài MySQL chưa. Nếu chưa, hướng dẫn tôi cài MySQL trên {Windows / macOS / Linux} và khởi động dịch vụ.

Bạn hãy làm theo hướng dẫn, lưu ý bạn cần nhớ mật khẩu root mà bạn điền khi cài đặt MySQL.

Sau đó bạn hãy gõ lệnh mysql -u root -p để truy cập vào giao diện dòng lệnh của MySQL, nếu terminal hiện lên Enter password: để yêu cầu nhập mật khẩu thì bạn đã cài đặt MySQL thành công, ngược lại bạn cần nói AI trợ giúp cài đặt tiếp. Bạn hãy nhập mật khẩu để truy cập. Sau đó bạn hãy nói AI gợi ý cách tạo cơ sở dữ liệu có tên là ezyplatform.

📋 Prompt mẫu — Tạo database ezyplatform
Sau đó hướng dẫn tôi tạo một database rỗng tên ezyplatform cùng một user có quyền truy cập database đó, và cho tôi biết cần ghi lại những thông tin gì (host, port, username, password) để dùng ở bước cấu hình sau.

Bạn hãy làm theo hướng dẫn, sau đó bạn có thể chạy lệnh show databases; ở giao diện dòng lệnh của MySQL, nếu hiện có ezyplatform trong danh sách database như sau là thành công:

💻 show databases;
+--------------------+
| Database           |
+--------------------+
| ezyplatform        |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.12 sec)

Sau đó bạn chạy lệnh exit; để thoát khỏi giao diện dòng lệnh của MySQL.

Bước 3: Cài đặt Maven

Maven là công cụ build cho các mô đun viết bằng Java — dùng để biên dịch và đóng gói mô đun thành file jar trước khi cài vào EzyPlatform.

📋 Prompt mẫu — Cài Maven
Hãy kiểm tra máy tôi đã cài Maven chưa (lệnh mvn -version). Nếu chưa có, hướng dẫn tôi cài Maven trên {Windows / macOS / Linux} và đảm bảo nó dùng đúng JDK 8 vừa cài ở Bước 1. Nếu cần bổ sung hay cập nhật biến môi trường hãy thực hiện, nếu không đủ quyền hãy hướng dẫn tôi thực hiện thủ công.
Sau khi cài xong, đưa tôi lệnh để xác nhận mvn -version chạy đúng.

Bạn hãy làm theo hướng dẫn sau đó chạy lệnh mvn -version. Nếu hiện kiểu thế này là thành công:

💻 mvn -version
Apache Maven 3.9.14 (996c630dbc656c76214ce58821dcc58be960875b)
Maven home: /Users/tvd12/Programs/apache-maven-3.9.14
Java version: 1.8.0_471, vendor: Oracle Corporation, runtime: /Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home/jre
Default locale: en_GB, platform encoding: UTF-8
OS name: "mac os x", version: "15.7.2", arch: "x86_64", family: "mac"

Trên Linux hoặc macOS, AI có thể sẽ tự bổ sung thêm biến môi trường mới vào file cấu hình shell của bạn — ví dụ khi chạy lệnh cat ~/.zshrc, tôi nhận được kết quả:

📄 ~/.zshrc
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export PATH=$PATH:$JAVA_HOME/bin
export MAVEN_HOME=/Users/tvd12/Programs/apache-maven-3.9.14
export PATH=$PATH:$MAVEN_HOME/bin

Bước 4: Tải và cấu hình EzyPlatform

Sau khi có đủ JDK, MySQL và Maven, đến lượt tải chính EzyPlatform về, giải nén, rồi khai báo biến môi trường EZYPLATFORM_HOME để chạy lệnh từ bất kỳ đâu.

Bạn có thể truy cập vào trang chủ ezyplatform.com rồi nhấn vào nút tải xuống EzyPlatform, hoặc truy cập trực tiếp đường dẫn https://ezyplatform.com/api/v1/platforms/latest/download. Sau đó giải nén vào thư mục làm việc của bạn. Lưu ý cần đặt vào một thư mục không có khoảng trắng và không dấu tiếng Việt để tránh những lỗi bất thường, ví dụ:

❌ Không nên
/thư mục/của bạn/ezyplatform
✅ Nên dùng
/thu-muc/cua-ban/ezyplatform
📋 Prompt mẫu — Tải và cấu hình EzyPlatform
Hướng dẫn tôi khai báo biến môi trường EZYPLATFORM_HOME trỏ đến thư mục /thu-muc/cua-ban/ezyplatform.
Sau đó mở file settings/setup.properties của ezyplatform giúp tôi điền thông tin kết nối tới database MySQL đã tạo ở Bước 2 (host, port, tên database, username, password). Nếu bạn không đủ quyền ghi tập tin, hãy hướng dẫn tôi điền thủ công

Ở đây /thu-muc/cua-ban/ chỉ là ví dụ tôi đưa ra, bạn cần điền chính xác thư mục của mình. Với tôi, khi chạy lệnh cat ~/.zshrc tôi nhận được kết quả:

📄 ~/.zshrc
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export PATH=$PATH:$JAVA_HOME/bin
export MAVEN_HOME=/Users/tvd12/Programs/apache-maven-3.9.14
export PATH=$PATH:$MAVEN_HOME/bin
export EZYPLATFORM_HOME=/Users/tvd12/Documents/tvd12/java/projects/ezyplatform/deploy

Bước 5: Chạy thử

Để đảm bảo mọi thứ đã được cài đặt xong, chúng ta sẽ khởi động EzyPlatform ở chế độ console trước.

Bạn hãy mở terminal và di chuyển đến thư mục EzyPlatform. Sau đó, ở Linux và macOS chạy lệnh bash cli.sh console admin, còn trên Windows chạy lệnh cli.bat console admin. Nếu bạn thấy log tại terminal hiển thị như dưới đây nghĩa là thành công.

Log terminal hiển thị EzyPlatform admin đã khởi động thành công ở chế độ console
Log terminal khi chạy cli.sh console admin thành công.

Sau đó bạn có thể truy cập vào đường dẫn http://localhost:9090. Trình duyệt sẽ tự chuyển hướng bạn sang đường dẫn cài đặt http://localhost:9090/setup-admin và bạn sẽ thấy giao diện:

Giao diện thiết lập tài khoản super admin ban đầu tại http://localhost:9090/setup-admin
Giao diện thiết lập tài khoản super admin ban đầu tại /setup-admin.

Bạn hãy điền đầy đủ thông tin và nhấn nút Submit, giao diện trang admin sẽ hiển thị ra.

Giao diện trang quản trị (Admin) đầu tiên sau khi tạo tài khoản super admin thành công
Giao diện trang Admin sau khi tạo tài khoản super admin thành công.

Bây giờ, nếu ở Linux hay macOS bạn hãy nhấn tổ hợp phím Ctrl + C để thoát chế độ console, rồi chạy lệnh bash cli.sh start admin để chạy ở chế độ nền (background).

Tiếp theo, bạn hãy cài đặt các mô đun cần thiết mà chúng ta đã cài cho máy chủ như ở Chương 3 đến Chương 13.

Xem hướng dẫn cài đặt chi tiết từng bước tại trang hướng dẫn chính thức của EzyPlatform.

Sau khi cài đặt xong các mô đun cần thiết, bạn hãy tắt EzyPlatform đang chạy đi — trên Linux, macOS dùng lệnh bash cli.sh stop, còn trên Windows nhấn tổ hợp phím Ctrl + C hoặc tắt terminal đi là được.

Cài đặt bộ công cụ hỗ trợ phát triển (EzyPlatform SDK)

EzyPlatform cài xong ở phần trên là nơi chạy website/ứng dụng của bạn. Còn EzyPlatform SDK là bộ công cụ dòng lệnh (ezy.sh) dành riêng cho việc phát triển mô đun — sinh khung project, build và đóng gói mô đun. Gồm 3 bước:

Bước 1: Tải và giải nén SDK

Bạn có thể truy cập vào trang chủ ezyplatform.com rồi nhấn vào nút tải xuống SDK, hoặc truy cập trực tiếp đường dẫn https://ezyplatform.com/api/v1/platform-sdks/latest/download. Sau đó giải nén vào một thư mục cố định, ví dụ /thu-muc/cua-ban/ezyplatform-sdk. Cũng như EzyPlatform, bạn nên để EzyPlatform SDK trong một thư mục có đường dẫn tiếng Anh và không có khoảng trắng.

Bước 2: Khai báo biến môi trường

Khai báo biến EZYPLATFORM_SDK trỏ đến thư mục vừa giải nén, rồi thêm $EZYPLATFORM_SDK/bin vào PATH để có thể gọi lệnh ezy.sh từ bất kỳ đâu.

📋 Prompt mẫu — Khai báo biến môi trường SDK
Hãy giúp tôi khai báo biến môi trường EZYPLATFORM_SDK trỏ đến thư mục /thu-muc/cua-ban/ezyplatform-sdk và thêm $EZYPLATFORM_SDK/bin vào biến PATH. Nếu bạn không đủ quyền hãy hướng dẫn tôi thực hiện thủ công.

Bạn hãy làm theo hướng dẫn. Ví dụ khi chạy lệnh cat ~/.zshrc, kết quả biến môi trường của tôi là:

📄 ~/.zshrc
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk-1.8.jdk/Contents/Home
export PATH=$PATH:$JAVA_HOME/bin
export EZYPLATFORM_HOME=/Users/tvd12/Documents/tvd12/java/projects/ezyplatform/deploy
export MAVEN_HOME=/Users/tvd12/Programs/apache-maven-3.9.14
export PATH=$PATH:$MAVEN_HOME/bin
export EZYPLATFORM_SDK=/Users/tvd12/Documents/tvd12/java/projects/ezyplatform/sdk
export PATH=$PATH:$EZYPLATFORM_SDK/bin

Bây giờ bạn hãy mở một terminal mới và chạy lệnh ezy.sh h. Nếu bạn thấy kết quả:

💻 ezy.sh h
usages:
	> help, h, -h, --help: to get help
  ....

Nghĩa là bạn đã cài đặt EzyPlatform SDK thành công.

Bước 3: Build các thư viện cần thiết

SDK cần một số thư viện được build sẵn bằng Maven từ kho mã nguồn ezyplatform-development trước khi dùng được. Bước này yêu cầu đã cài Maven ở phần trước.

Bạn hãy dùng git để clone mã nguồn của ezyplatform-development về một thư mục cố định:

💻 Clone ezyplatform-development
git clone git@github.com:youngmonkeys/ezyplatform-development.git

Sau đó bạn hãy chạy lệnh bash build.sh trên Linux hoặc macOS, và build.bat trên Windows. Nếu bạn thấy kết quả sau khi build như sau:

💻 bash build.sh
[INFO] Reactor Summary for ezyplatform-sdk 0.0.2:
[INFO]
[INFO] ezyplatform-sdk .................................... SUCCESS [  3.413 s]
[INFO] ezyplatform-common-sdk ............................. SUCCESS [ 48.505 s]
[INFO] ezyplatform-http-sdk ............................... SUCCESS [  8.533 s]
[INFO] ezyplatform-admin-sdk .............................. SUCCESS [  3.982 s]
[INFO] ezyplatform-socket-sdk ............................. SUCCESS [  4.892 s]
[INFO] ezyplatform-web-sdk ................................ SUCCESS [  3.962 s]
[INFO] ezyplatform-test-sdk ............................... SUCCESS [  2.088 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS

Nghĩa là thành công.

Sau khi hoàn tất cả 3 bước, bạn đã có đủ công cụ để bắt đầu nhờ AI sinh khung mô đun mới bằng ezy.sh. Xem chi tiết tại trang hướng dẫn cài đặt EzyPlatform SDK chính thức.

Cài đặt IntelliJ IDEA

Ngoài VS Code để trò chuyện với AI, khi phát triển mô đun bạn còn cần một IDE Java chuyên dụng để debug, xem cấu trúc project Maven và điều hướng mã nguồn Java thuận tiện hơn — IntelliJ IDEA là lựa chọn phổ biến nhất. Bản Community Edition miễn phí và mã nguồn mở là đủ dùng cho việc phát triển mô đun EzyPlatform.

Bạn có thể tải xuống bản Community Edition tại kho github.com/JetBrains/intellij-community/releases. Nếu bạn có thể chi trả bản quyền, bạn có thể tải về các phiên bản trả phí tại trang chủ của JetBrains.

Hướng dẫn khởi tạo dự án mô đun

Sau khi đã có đủ JDK, MySQL, Maven, EzyPlatform, EzyPlatform SDK và IntelliJ IDEA, bạn đã sẵn sàng để sinh khung (scaffold) cho mô đun đầu tiên bằng lệnh ezy.sh. Gồm 3 bước:

Bước 1: Sinh khung project bằng ezy.sh

Lệnh ezy.sh cp (create project) sinh sẵn cấu trúc project Maven cho mô đun, gồm tên project, nhóm (group), phiên bản (version), và danh sách loại mô đun cần có — tham số -i nhận đúng 5 giá trị (identifier) mà ezy.sh hiểu: admin-plugin (màn hình quản trị), web-plugin (hiển thị phía website), theme (giao diện), socket-pluginsocket-app (xử lý realtime qua socket) — hoặc all để gồm cả 5. Đây là các identifier cố định do ezy.sh quy định, phải gõ đúng chính tả (tiếng Anh, có dấu gạch ngang), không dịch hay đổi tên tuỳ ý. Ví dụ tạo một project tên sweet-bakery, nhóm org.youngmonkeys, phiên bản 1.0.0, gồm 3 mô đun admin-plugin, web-plugin và theme:

💻 Ví dụ lệnh tạo project
ezy.sh cp sweet-bakery -g org.youngmonkeys -v 1.0.0 -i admin-plugin,web-plugin,theme

Bước 2: Mở project và chạy thử bằng IntelliJ IDEA

Import project vừa sinh vào IntelliJ IDEA (đã cài ở phần trên), cấu hình JDK 8 làm Project SDK nếu IntelliJ chưa tự nhận diện đúng, chạy bash export.sh (hoặc export.bat trên Windows) để export các thành phần cần thiết, rồi tìm file StartupTest tương ứng trong thư mục src/test/ của từng mô đun (ví dụ SweetBakeryAdminPluginStartupTest cho mô đun admin-plugin của project sweet-bakery) để chạy thử ngay trong IDE.

📋 Prompt mẫu — Chạy thử mô đun trong IntelliJ IDEA
Tôi vừa mở project mô đun {tên-mô đun-của-bạn} bằng IntelliJ IDEA. Hãy hướng dẫn tôi:
1. Kiểm tra và cấu hình JDK 8 làm Project SDK nếu IntelliJ chưa tự nhận đúng.
2. Build thử dự án bằng maven trên IntelliJ.
3. Tìm đúng file StartupTest trong thư mục src/test/ của mô đun admin-plugin để tôi chạy.
4. Chạy bash export.sh (hoặc export.bat) để export mô đun ra ezyplatform.

Ví dụ dưới đây là dự án của tôi sau khi được import vào IntelliJ IDEA:

Project sweet-bakery sau khi import vào IntelliJ IDEA, hiển thị cấu trúc các mô đun ở khung Project
Project sweet-bakery sau khi import vào IntelliJ IDEA.

Tôi chọn menu File → Project Structure để kiểm tra phiên bản JDK:

Chọn menu File > Project Structure trong IntelliJ IDEA để kiểm tra cấu hình JDK
Menu File → Project Structure.

Nếu phiên bản JDK đang không phải là 1.8, tôi sẽ chọn lại đúng JDK 8 ở mục SDK:

Màn hình Project Structure hiển thị SDK đang cấu hình là JDK 1.8
Kiểm tra và chọn đúng JDK 1.8 ở mục SDK trong Project Structure.

Tiếp theo, tôi build thử dự án bằng Maven bằng cách click đúp vào mục install ở khung Maven nằm bên phải giao diện của IntelliJ:

Khung Maven trong IntelliJ IDEA với mục install trong Lifecycle được chọn để build thử dự án
Click đúp vào install trong khung Maven để build thử dự án.

Khi nhìn thấy kết quả như dưới đây, tôi biết là đã build thành công:

Log cửa sổ Run trong IntelliJ IDEA hiển thị BUILD SUCCESS sau khi build dự án bằng Maven
Log BUILD SUCCESS sau khi build xong bằng Maven.

Ngược lại, có thể đã có lỗi xảy ra — tôi có thể tham khảo mục "Hướng dẫn khắc phục lỗi" ở phần sau, hoặc cung cấp log cho AI để AI hướng dẫn khắc phục.

Sau đó, tôi tìm và chạy (Debug) tập tin SweetBakeryAdminPluginStartupTest:

Menu chuột phải trong IntelliJ IDEA chọn Debug SweetBakeryAdminPluginStartupTest.main() để chạy thử ở chế độ debug
Chạy tập tin StartupTest ở chế độ Debug.

Sau khi thấy log ở console của IntelliJ như dưới đây, nghĩa là mô đun đã khởi động thành công:

Console Debug trong IntelliJ IDEA hiển thị log ASCII art của EzyPlatform sau khi chạy StartupTest thành công
Log ở console Debug khi StartupTest chạy thành công.

Tôi có thể truy cập vào địa chỉ http://localhost:9090 và kết quả cũng tương tự như khi chạy EzyPlatform thông qua dòng lệnh.

Bước 3: Export thử mô đun

Khi mô đun đã chạy đúng như mong muốn, bạn có thể export thử mô đun để hiểu export thực sự là gì.

Nếu bạn đang dùng Windows, trước tiên hãy tắt tạm EzyPlatform đang chạy qua IntelliJ bằng cách nhấn vào nút dừng (Stop) ở khung Debug:

Nút Stop trong khung Debug của IntelliJ IDEA để tạm dừng EzyPlatform đang chạy qua StartupTest
Nhấn nút Stop trong khung Debug để tạm dừng EzyPlatform (bắt buộc trên Windows trước khi export).

Bây giờ, ngay trên giao diện dòng lệnh (Terminal) của IntelliJ, bạn chạy lệnh bash export.sh nếu trên Linux, macOS, hoặc export.bat nếu trên Windows:

Chạy lệnh bash export.sh trên Terminal của IntelliJ IDEA để export mô đun sweet-bakery
Chạy bash export.sh ngay trên Terminal của IntelliJ IDEA.

Sau khi export thành công, bạn mở thư mục target/project của dự án, bạn sẽ thấy một thư mục mang tên dự án và một tập tin zip, ví dụ của tôi là:

Thư mục target/project sau khi export, chứa thư mục sweet-bakery và tập tin sweet-bakery-1.0.0.zip
Thư mục target/project chứa thư mục dự án và tập tin zip sau khi export.

Thư mục mang tên dự án tuân theo đúng quy chuẩn đóng gói mà EzyPlatform quy định; tập tin zip chỉ là kết quả nén lại của thư mục đó, dùng để cài vào bất kỳ EzyPlatform nào khác hoặc đưa lên Marketplace.

Bạn cũng có thể mở thư mục EzyPlatform, di chuyển vào admin/plugins, và sẽ thấy mô đun của dự án đã được export ra đây:

Thư mục ezyplatform/admin/plugins/sweet-bakery chứa dependencies.xml, lib, menus.properties, module.properties, resources sau khi export
Mô đun sweet-bakery đã được export vào ezyplatform/admin/plugins.

Bây giờ, bạn build lại dự án bằng cách click đúp vào mục install ở khung Maven như đã làm ở Bước 2, rồi chạy lại (Debug) file StartupTest. Khi EzyPlatform khởi động xong, bạn hãy truy cập lại vào trang Admin, kéo xuống dưới và sẽ thấy một menu mới tương ứng với mô đun của mình, ở mục "Các mở rộng":

Menu Sweet Bakery xuất hiện ở mục Các mở rộng trong sidebar trang Admin sau khi export và chạy lại mô đun
Menu mô đun mới xuất hiện ở mục "Các mở rộng" trong sidebar Admin.

Như vậy, bản chất của export là đóng gói mô đun theo đúng chuẩn và xuất bản nó vào EzyPlatform trên máy cục bộ. Khi EzyPlatform khởi động lại, mô đun sẽ được quét và hiển thị lên.

Xem hướng dẫn đầy đủ tại trang hướng dẫn khởi tạo mô đun chính thức của EzyPlatform.

Hướng dẫn khắc phục lỗi khi import dự án vào IntelliJ (nếu có)

Một số máy, đặc biệt trên Windows, IntelliJ đôi khi không nhận diện được các biến môi trường như EZYPLATFORM_HOME hay EZYPLATFORM_SDK dù đã khai báo đúng ở cấp hệ điều hành, khiến project báo lỗi build ngay khi import. Nếu gặp tình huống này, hãy thử lần lượt 4 bước sau — dừng lại ngay khi bước nào đó đã khắc phục được lỗi, không cần làm hết cả 4.

Bước 1: Kiểm tra lại biến môi trường ở cấp hệ điều hành

Đảm bảo biến (ví dụ EZYPLATFORM_HOME) đã khai báo đúng, trỏ đến thư mục chứa cli.sh/cli.bat, sau đó khởi động lại IntelliJ hoàn toàn (không chỉ đóng project) để IDE đọc lại biến môi trường mới.

📋 Prompt mẫu — Kiểm tra biến môi trường
Project mô đun của tôi báo lỗi build khi import vào IntelliJ, nghi ngờ do không nhận được biến môi trường {EZYPLATFORM_HOME hoặc EZYPLATFORM_SDK}.
Hãy kiểm tra giúp tôi biến này đã khai báo đúng ở cấp hệ điều hành chưa, rồi hướng dẫn tôi khởi động lại IntelliJ đúng cách để nó nhận biến mới.

Bước 2: Khai báo Path Variables trong IntelliJ

Nếu vẫn lỗi, vào Settings → Appearance & Behavior → Path Variables, thêm thủ công biến (ví dụ EZYPLATFORM_HOME) trỏ đúng đường dẫn, rồi build lại project.

📋 Prompt mẫu — Khai báo Path Variables
Bước kiểm tra biến môi trường cấp hệ điều hành chưa khắc phục được lỗi build. Hãy hướng dẫn tôi vào Settings → Path Variables của IntelliJ để khai báo thủ công biến {EZYPLATFORM_HOME} trỏ đến {đường dẫn thư mục EzyPlatform của bạn}, rồi build lại project để kiểm tra.

Bước 3: Thêm VM option cho Maven

Nếu vẫn chưa hết lỗi, vào Settings → Build, Execution, Deployment → Build Tools → Maven, thêm VM option -Denv.EZYPLATFORM_HOME=/đường/dẫn/của/bạn ở cả mục ImportingRunner — riêng mục Runner cần thêm cả biến môi trường tương ứng.

📋 Prompt mẫu — Cấu hình Maven VM options
Hai bước trước vẫn chưa hết lỗi build. Hãy hướng dẫn tôi vào Settings → Build, Execution, Deployment → Build Tools → Maven của IntelliJ, thêm VM option -Denv.EZYPLATFORM_HOME=/đường/dẫn/của/bạn vào cả mục Importing và Runner, đồng thời thêm biến môi trường EZYPLATFORM_HOME ở mục Runner.

Bước 4: Cấu hình ở cấp Run Configuration

Nếu lỗi vẫn còn khi chạy thử (ví dụ chạy file StartupTest), thêm cùng VM option và biến môi trường vào chính Run Configuration của class khởi động đó.

📋 Prompt mẫu — Cấu hình Run Configuration
Tôi vẫn gặp lỗi khi chạy file StartupTest trong IntelliJ. Hãy hướng dẫn tôi mở Run Configuration của file này, thêm VM option -Denv.EZYPLATFORM_HOME=/đường/dẫn/của/bạn và biến môi trường EZYPLATFORM_HOME tương ứng, rồi chạy lại để kiểm tra.

Xem hướng dẫn đầy đủ tại trang khắc phục lỗi PATH variable trong IntelliJ chính thức.

Cấu trúc dự án mô đun

Sau khi ezy.sh cp sinh project (ví dụ tên sweet-bakery), mỗi loại mô đun bạn chọn ở Bước 1 trở thành một sub-module Maven riêng, đặt tên theo mẫu {project}-{loại-mô đun} — ví dụ sweet-bakery-admin-plugin. Hiểu rõ vai trò từng mô đun giúp bạn mô tả yêu cầu cho AI đúng chỗ hơn, thay vì để AI tự đoán nên đặt code ở đâu.

  • {project}-sdk — chứa các lớp dùng chung (model, service, config...) cho toàn bộ mô đun còn lại.
  • {project}-admin-plugin — chứa model, controller và file tĩnh cho màn hình quản trị (Admin).
  • {project}-web-plugin — chứa model, controller và file tĩnh hiển thị phía Website.
  • {project}-theme — mô đun giao diện (theme) cho phần Website.
  • {project}-socket-plugin{project}-socket-app — xử lý các tác vụ realtime qua socket.
Cấu trúc project sweet-bakery trong IntelliJ IDEA với các mô đun sweet-bakery-admin-plugin, sweet-bakery-sdk, sweet-bakery-theme, sweet-bakery-web-plugin
Project sweet-bakery sau khi sinh bằng ezy.sh cp, mở trong IntelliJ IDEA — mỗi mô đun nằm trong một thư mục Maven riêng.

Bên trong mỗi mô đun, cấu trúc thư mục theo chuẩn Maven:

  • src/main/java — mã nguồn Java: model, controller, service, class cấu hình...
  • src/main/resources/static — file tĩnh: html, css, javascript, media.
  • src/main/resources/templates — template Thymeleaf.
  • src/test/java — mã kiểm thử, gồm cả file StartupTest dùng để chạy thử mô đun ngay trong IDE (đã nhắc ở phần trước).

Ở gốc mỗi mô đun còn có pom.xml (cấu hình Maven), module.properties (định nghĩa tên, version, group của mô đun), menus.properties (định nghĩa menu Admin, chỉ có ở mô đun admin-plugin) và assembly.xml (cấu hình đóng gói). Ở gốc project còn có script export.sh/export.bat dùng để xuất bản mô đun vào EzyPlatform cục bộ.

Khi export, mỗi mô đun được sao chép vào đúng vị trí tương ứng trong EzyPlatform:

  • {project}-admin-pluginezyplatform/admin/plugins/{project}
  • {project}-web-pluginezyplatform/web/plugins/{project}
  • {project}-themeezyplatform/web/themes/{project}
  • {project}-socket-pluginezyplatform/socket/plugins/{project}
  • {project}-socket-appezyplatform/socket/apps/{project}
  • {project}-sdk — không có thư mục cài đặt riêng trong EzyPlatform; vì các mô đun trên đều khai báo nó như một dependency Maven, khi export nó tự được đóng gói kèm theo vào thư mục lib bên trong từng mô đun đã export ở trên.
📋 Prompt mẫu — Nhờ AI định vị đúng mô đun
Tôi đang phát triển mô đun {tên-mô đun-của-bạn} với các loại mô đun {admin-plugin,theme,web-plugin}.
Tôi muốn thêm tính năng: {mô tả tính năng}.
Hãy cho tôi biết phần này nên đặt code ở mô đun nào (sdk, admin-plugin, web-plugin, theme...), theo đúng cấu trúc chuẩn của một mô đun project EzyPlatform, trước khi bắt đầu viết code.

Xem chi tiết đầy đủ tại trang hướng dẫn cấu trúc mô đun project chính thức.

Cài đặt mô đun cho dự án tiệm bánh

Dự án tiệm bánh ngọt của chúng ta vẫn hoạt động ổn, nhưng hãy giả sử chúng ta muốn bán nó trên chợ cho ai cần, hoặc bổ sung thêm các tính năng cao cấp cho nó. Bạn hãy mở Terminal của IntelliJ và nhập các lệnh sau để liên kết các mô đun liên quan mà bạn đã cài vào dự án:

💻 Liên kết các mô đun cần dùng
ezy.sh link ezyarticle
ezy.sh link ezymail
ezy.sh link ezysupport
ezy.sh link ecommerce
ezy.sh link ezypayment
ezy.sh link accounting
ezy.sh link ezylogin
ezy.sh link ezydelivery

Tiếp theo, bạn hãy mở dự án mô đun sweet-bakery bằng VSCode rồi gõ prompt như sau:

📋 Prompt mẫu — Chuyển đổi dự án low-code sang mô đun
Đọc mã nguồn các trang và các mảnh trang của dự án tiệm bánh ngọt từ /Users/tvd12/Documents/workspace-html/bakery sau đó khởi tạo các view, các controller tương ứng, mục tiêu của việc này là chuyển đổi một dự án low code sang dự án plugin để tôi đưa lên chợ ezyplatform.com. Nếu cần nghiên cứu sâu về mã nguồn của ezyplatform và các module bạn có thể truy cập vào thư mục /Users/tvd12/Documents/tvd12/java/projects/ezyplatform/deploy, bạn có quyền giải nén các file jar ra thư mục tmp để đọc mã nguồn.

AI có thể mất tới 15 phút để phân tích yêu cầu và cài đặt. Sau khi AI cài đặt xong, bạn sẽ thấy một loạt tập tin mới được tạo ra:

Danh sách các tập tin view, controller mới được AI tạo ra trong mô đun sweet-bakery-theme sau khi chuyển đổi từ dự án low-code
Các tập tin mới được AI tạo ra sau khi chuyển đổi dự án low-code sang mô đun.

Tiếp theo, bạn hãy tìm đến tập tin SweetBakeryThemeStartupTest và khởi chạy. Sau đó truy cập vào địa chỉ http://localhost:8080 và xem kết quả — nó có thể bị lỗi hiển thị font như sau:

Giao diện website sweet-bakery bị lỗi hiển thị font, chữ tiếng Việt hiện thành ký tự lạ dạng Thá»±c ÄÆ¡n
Giao diện bị lỗi font khi chữ có dấu hiển thị sai thành ký tự lạ.

Nguyên nhân của lỗi này là do chúng ta chưa cấu hình File Encodings. Bạn hãy truy cập vào menu Settings của IntelliJ:

Menu Settings của IntelliJ IDEA
Mở menu Settings của IntelliJ IDEA.

Chọn mục Editor → File Encodings, tích vào ô Transparent native-to-ascii conversion rồi nhấn OK:

Màn hình File Encodings trong IntelliJ IDEA với tuỳ chọn Transparent native-to-ascii conversion được tích chọn
Tích chọn Transparent native-to-ascii conversion tại File Encodings.

Tiếp theo, bạn hãy mở một phiên chat mới vì phiên chat cũ đã quá nhiều code, AI làm việc không còn hiệu quả nữa. Bạn gõ prompt như sau:

📋 Prompt mẫu — Fix lỗi font
Đang bị lỗi font Thá»±c ÄÆ¡n hãy fix giúp tôi.

Trong khi AI thực hiện công việc, bạn có thể quay trở lại IntelliJ và chọn Edit Run Configurations:

Chọn Edit Run Configurations trong IntelliJ IDEA
Chọn Edit Run Configurations trong IntelliJ IDEA.

Sau đó bạn hãy chỉ định Working directory đến chính xác thư mục sweet-bakery-theme, để khi AI thay đổi các tập tin template hoặc tĩnh, chúng ta không cần phải chạy lại tập tin StartupTest:

Chỉ định Working directory là thư mục sweet-bakery-theme trong Run Configurations của IntelliJ IDEA
Chỉ định Working directory là thư mục sweet-bakery-theme.

Sau khi AI thực hiện xong, bạn sẽ thấy các tập tin messages.properties bị thay đổi — các tập tin này không được EzyPlatform tự động tải lại khi có thay đổi, nên chúng ta cần chạy lại SweetBakeryThemeStartupTest. Bạn hãy truy cập lại http://localhost:8080 và sẽ thấy giao diện hết lỗi font:

Giao diện website sweet-bakery hiển thị đúng font tiếng Việt sau khi fix lỗi encoding
Giao diện đã hiển thị đúng font sau khi fix lỗi.

Đến đây bạn hãy commit code để tránh AI làm hỏng thành quả ở những lần chat tiếp theo.

Nhưng lại có vấn đề khác: banner và các bánh nổi bật vẫn chưa hiện. Khi xem log, bạn sẽ thấy:

💻 Log lỗi
2026-08-04 17:38:37.801 [qtp1110827035-43] ERROR org.thymeleaf.TemplateEngine [THYMELEAF][qtp1110827035-43] Exception processing template "home": Exception evaluating OGNL expression: "ezyfunctions.call('get_product_pagination', '{shopId:1, currencyId:3, categoryName:'banh', limit:12}')" (template: "home" - line 32, col 31)
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating OGNL expression: "ezyfunctions.call('get_product_pagination', '{shopId:1, currencyId:3, categoryName:'banh', limit:12}')" (template: "home" - line 32, col 31)

ezyfunctions là một tính năng hữu ích khi chúng ta không thể can thiệp ở phía backend — nhưng giờ chúng ta đã có mô đun riêng, can thiệp backend là hoàn toàn có thể. Bạn hãy prompt như sau:

📋 Prompt mẫu — Thay ezyfunctions bằng set biến ở Controller
Thay việc sử dụng ezyfunctions bằng việc set biến trực tiếp vào view ở controller, shop mặc định, tiền tệ mặc định cũng cần lấy qua hàm thay vì hardcode.

Trong lúc AI thực thi, bạn có thể tranh thủ khởi tạo shop, danh mục banh và các sản phẩm bánh — tương tự như đã làm ở máy chủ — vì hiện tại chúng ta đang ở môi trường cục bộ để phát triển mô đun.

Sau khi AI thực thi xong, chúng ta cần chạy lại SweetBakeryThemeStartupTest. Quan sát log, bạn sẽ thấy lỗi:

💻 Log lỗi
fragment: "~{'fragments/header' :: scripts}": template or fragment could not be resolved (template: "page" - line 89, col 11)
org.thymeleaf.exceptions.TemplateInputException: Error resolving fragment: "~{'fragments/header' :: scripts}": template or fragment could not be resolved (template: "page" - line 89, col 11)

Bạn hãy dán lỗi này cho AI để AI fix giúp bạn. Sau khi AI sửa xong, bạn không cần khởi động lại SweetBakeryThemeStartupTest vì AI chỉ sửa template header.html — chỉ cần quay lại trình duyệt đang mở http://localhost:8080 và refresh trang. Console của IntelliJ sẽ không còn log lỗi nữa.

Tuy nhiên bạn vẫn thấy header bị hiển thị 2 lần. Bạn hãy mở một phiên chat mới và gõ prompt:

📋 Prompt mẫu — Fix header hiển thị 2 lần
Header đang bị hiển thị 2 lần hãy sửa lỗi.

Sau khi AI sửa xong, bạn quay trở lại trình duyệt và refresh lại trang lần nữa. Kết quả bạn sẽ thấy mọi thứ được hiển thị tốt, giống như trên máy chủ:

Giao diện website sweet-bakery hiển thị đầy đủ banner và các sản phẩm bánh nổi bật sau khi sửa các lỗi template và dữ liệu
Giao diện đã hiển thị đầy đủ và đúng, tương tự trên máy chủ.

Bây giờ bạn đã có một mô đun hoàn chỉnh, bạn có thể export lại để có được tập tin sweet-bakery-1.0.0.zip.

Sau đó bạn có thể truy cập vào trang quản trị của máy chủ, di chuyển đến menu Themes, rồi nhấn vào nút "Cập nhật thủ công" của một theme bất kỳ, hoặc chọn Thêm mới → Tải lên tập tin zip và chọn tập tin sweet-bakery-1.0.0.zip vừa export:

Hộp thoại Tải lên dự án trên trang quản trị Themes, chọn tập tin sweet-bakery-1.0.0.zip để tải lên
Tải lên tập tin sweet-bakery-1.0.0.zip vào trang quản trị Themes.

Sau khi tải lên thành công, bạn có thể kích hoạt theme Sweet Bakery — hãy chọn Kích hoạt & Khởi động lại để kích hoạt cả 3 thành phần theme, web-plugin, admin-plugin cùng lúc:

Hộp thoại Kích hoạt Sweet Bakery 1.0.0 với các tuỳ chọn theme, web-plugin, admin-plugin và nút Kích hoạt và Khởi động lại
Chọn Kích hoạt & Khởi động lại để kích hoạt theme Sweet Bakery.

Theme Sweet Bakery sẽ tự động thay thế cho theme Freestyle đang có sẵn:

Danh sách Themes trên trang quản trị hiển thị theme Sweet Bakery đã được kích hoạt, thay thế cho theme Freestyle
Theme Sweet Bakery đã được kích hoạt, thay thế cho theme Freestyle.

Bạn truy cập vào trang web cửa hàng bánh và sẽ thấy mọi thứ vẫn hiển thị bình thường, giống hệt lúc chạy trên môi trường cục bộ.

Bạn cũng có thể tạo dự án trên chợ và đăng bán. Lưu ý có thể tên dự án đã được người khác sở hữu, khi đó bạn cần đổi tên gói rồi export lại.

Trang Khởi tạo dự án trên ezyplatform.com với các trường Tên dự án, Tên gói, Mô tả ngắn để đăng bán mô đun trên Marketplace
Khởi tạo dự án mới trên Marketplace của ezyplatform.com để đăng bán mô đun.

Các cài đặt nâng cao

Vibe code ở dạng mô đun cho phép bạn cài đặt các tính năng phức tạp hơn nhiều so với việc chỉnh sửa trực tiếp trên Admin — vì lúc này bạn có toàn quyền can thiệp vào code, không còn bị giới hạn bởi những gì EzyPlatform đã dựng sẵn. Phần này giới thiệu những mảnh ghép nâng cao thường gặp khi phát triển một mô đun/theme hoàn chỉnh: cho phép người dùng cuối tự chỉnh sửa giao diện qua page fragment, dựng giao diện theme từ file HTML/CSS tĩnh, ghép dữ liệu động và đa ngôn ngữ, tùy chỉnh menu Admin, tạo bảng dữ liệu riêng, xử lý dữ liệu hàng loạt bằng batch, và giao tiếp giữa các mô đun qua sự kiện nội bộ. Mỗi mục đều kèm prompt mẫu để bạn nhờ AI cài đặt nhanh, đúng theo quy ước của EzyPlatform.

Sử dụng các phần trang (page fragment) để cài đặt theme

Mỗi khách hàng lại muốn một giao diện khác nhau cho website của mình — nếu mọi thay đổi nhỏ đều phải nhờ developer sửa code, chi phí và thời gian phát triển theme sẽ rất tốn kém. Page fragment giải quyết vấn đề này bằng cách "phân mảnh" giao diện thành từng phần (styles, scripts, header, footer, nội dung trang chủ...), để người dùng cuối tự chỉnh sửa ngay trong Admin mà không cần đụng vào code. Gồm 3 bước để khai báo:

Bước 1: Đăng ký danh sách page fragment

Trong mô đun SDK dùng chung của mô đun/theme, tạo một lớp cấu hình implement EzyBeanConfig để đăng ký tên các fragment, ví dụ nhóm common (styles, scripts, header, footer dùng chung mọi trang) hoặc home, blog_details (container HTML riêng cho từng loại trang).

📋 Prompt mẫu — Đăng ký page fragment
Trong mô đun {tên-sdk-mô đun} của theme, hãy tạo một lớp cấu hình implement EzyBeanConfig để đăng ký các page fragment sau bằng pageFragmentManager.registerFragmentNames:
- Nhóm "common": styles, scripts, header, footer (dùng chung mọi trang).
- Nhóm "home": container (HTML trang chủ).
Giải thích cho tôi ý nghĩa của từng fragment trước khi tạo.

Bước 2: Mở rộng cấu hình cho mô đun Web và Admin

Tại mô đun web-pluginadmin-plugin, tạo lớp kế thừa từ config gốc ở Bước 1, đánh dấu @EzyConfigurationAfter để đảm bảo chạy sau cấu hình chung.

📋 Prompt mẫu — Mở rộng cấu hình fragment
Hãy tạo giúp tôi lớp cấu hình kế thừa từ {tên-lớp-config-gốc-ở-bước-1} trong mô đun web-plugin và admin-plugin, đánh dấu @EzyConfigurationAfter để nó chạy sau cấu hình gốc.

Bước 3: Hiển thị page fragment trong template

Cập nhật ViewDecorator để nạp fragment vào biến của view (ví dụ commonFragments), rồi trong page.html, render có điều kiện: nếu fragment đã được người dùng chỉnh sửa qua Admin thì lấy nội dung đó, nếu chưa thì giữ nguyên mặc định.

📋 Prompt mẫu — Render page fragment trong template
Hãy giúp tôi:
1. Cập nhật ViewDecorator để nạp các page fragment nhóm "common" vào biến commonFragments của view.
2. Sửa page.html: nếu commonFragments.get('styles') khác null và nội dung khác giá trị mặc định "styles" thì render nội dung đó bằng ezy:utext, ngược lại giữ nguyên style mặc định của theme.
Áp dụng tương tự cho scripts, header, footer.

Sau khi hoàn tất, người dùng có thể tự chỉnh sửa các phần trang này tại {đường-dẫn-admin-của-bạn}/ezyarticle/pages/fragments mà không cần nhờ developer. Xem chi tiết và ví dụ đầy đủ tại bài viết hướng dẫn page fragment chính thức.

Tạo giao diện cho theme

Nếu bạn (hoặc AI) đã có sẵn một giao diện HTML/CSS tĩnh — tải từ một template có sẵn, xuất từ Figma, hay do AI tạo riêng — bước tiếp theo là biến nó thành theme chạy được trên EzyPlatform bằng Thymeleaf, engine template mà EzyPlatform sử dụng. Gồm 4 bước.

Bước 1: Đưa file tĩnh vào đúng thư mục

Copy toàn bộ css, js, ảnh (thường nằm trong thư mục assets/ của giao diện gốc) vào src/main/resources/static/ của mô đun theme, rồi sửa lại các đường dẫn tham chiếu trong HTML — ví dụ ./assets/css/style.css đổi thành /css/style.css — vì khi chạy, EzyPlatform tự ánh xạ thư mục static về gốc /.

📋 Prompt mẫu — Đưa giao diện tĩnh vào theme
Tôi có sẵn một giao diện HTML/CSS tĩnh tại thư mục {đường-dẫn-giao-diện-gốc}, gồm các file css/js/ảnh trong assets/.
Hãy giúp tôi copy toàn bộ các file tĩnh đó vào src/main/resources/static/ của mô đun theme {tên-mô đun-theme}, rồi sửa lại mọi đường dẫn tham chiếu trong HTML từ dạng ./assets/... sang /... cho đúng với cách EzyPlatform ánh xạ thư mục static.

Bước 2: Tách phần dùng chung thành fragment và layout

Header, footer thường lặp lại ở mọi trang nên tách thành fragment riêng (ví dụ fragments/header.html, fragments/footer.html) bằng thuộc tính th:fragment. Phần khung chung — đầu trang, cuối trang, và chỗ chèn nội dung riêng của từng trang — gom vào một file layout.html, dùng thư viện thymeleaf-layout-dialect với layout:fragment="content" đánh dấu vị trí nội dung sẽ được thay thế.

📋 Prompt mẫu — Tách fragment và layout
Từ file index.html tĩnh tôi vừa đưa vào theme, hãy giúp tôi:
1. Tách phần <header>...</header> thành fragments/header.html với th:fragment="header".
2. Tách phần <footer>...</footer> thành fragments/footer.html với th:fragment="footer".
3. Tạo layout.html dùng thymeleaf-layout-dialect, nhúng lại hai fragment trên bằng th:replace, và đánh dấu layout:fragment="content" ở chỗ nội dung chính sẽ được chèn vào.

Bước 3: Tạo template riêng cho từng trang

Mỗi trang cụ thể (trang chủ, trang chi tiết bài viết...) chỉ cần viết phần nội dung riêng (ví dụ phần <main>...</main> cũ) rồi khai báo layout:decorate để "mặc" lại layout.html, tránh phải lặp lại code header/footer ở mọi trang.

📋 Prompt mẫu — Tạo template trang chủ kế thừa layout
Hãy giúp tôi tạo home.html từ phần nội dung chính (thẻ main) trong index.html gốc, khai báo layout:decorate="~{layout}" để kế thừa layout.html vừa tạo ở Bước 2, và đặt nội dung vào đúng layout:fragment="content".

Bước 4: Chạy thử và kiểm tra giao diện

Chạy thử theme trong EzyPlatform (xem lại Bước 2 ở phần "Hướng dẫn khởi tạo dự án mô đun"), sau đó truy cập website để kiểm tra giao diện đã hiển thị đúng như bản gốc chưa — đặc biệt là css, js và ảnh có load đúng không.

Nếu giao diện gốc lấy từ một template miễn phí có sẵn, hãy giữ lại credit cho tác giả gốc (trong README hoặc footer theme) — đây vừa là phép lịch sự, vừa thường là điều kiện bắt buộc trong giấy phép sử dụng của template đó.

Xem hướng dẫn đầy đủ kèm ví dụ mã nguồn tại bài viết tạo giao diện cho theme blog đơn giản.

Ghép dữ liệu động cho theme

Giao diện dựng ở phần trước mới chỉ có dữ liệu giả (hardcode trong HTML). Bước tiếp theo là thay bằng dữ liệu thật lấy từ EzyPlatform — ví dụ danh sách bài viết blog đã xuất bản — kèm phân trang và định dạng ngày tháng dễ đọc. Gồm 4 bước.

Bước 1: Liên kết mô đun EzyArticle vào theme

Theme cần truy vấn dữ liệu bài viết từ mô đun EzyArticle, nên trước tiên phải liên kết (link) mô đun đó vào project bằng ezy.sh — lệnh này tự thêm dependency SDK cần thiết vào pom.xml và cập nhật @ComponentsScan để quét đúng package của EzyArticle.

📋 Prompt mẫu — Liên kết mô đun EzyArticle
Hãy giúp tôi chạy lệnh ezy.sh link ezyarticle trong project theme {tên-mô đun-theme} của tôi, rồi kiểm tra pom.xml và @ComponentsScan đã được cập nhật đúng để dùng được các service của EzyArticle chưa.

Bước 2: Tạo dữ liệu mẫu để kiểm thử

Trước khi đụng vào code, tạo sẵn vài bài viết mẫu qua trang Admin — tiêu đề, ảnh đại diện, nội dung, loại bài viết là "blog", trạng thái "đã xuất bản" — để có dữ liệu thật dùng kiểm tra kết quả ở các bước sau. Đây là thao tác tay trên giao diện Admin (EzyArticle), không cần AI viết code, nhưng nếu chưa quen bạn vẫn có thể nhờ AI hướng dẫn từng cú nhấp chuột.

📋 Prompt mẫu — Tạo bài viết mẫu để kiểm thử
Tôi vừa cài mô đun EzyArticle vào EzyPlatform. Hãy hướng dẫn tôi từng bước tạo 3-5 bài viết mẫu qua trang Admin, gồm tiêu đề, ảnh đại diện, nội dung, chọn loại bài viết là "blog" và trạng thái "đã xuất bản", để tôi có dữ liệu thật kiểm tra theme đang phát triển.

Bước 3: Lấy danh sách bài viết trong Controller

Sửa HomeController: tiêm (inject) WebPostControllerService, tạo bộ lọc DefaultPostFilter với postType = PostType.BLOGpostStatus = PostStatus.PUBLISHED, gọi getPostItemPagination() kèm ngôn ngữ, thứ tự sắp xếp và token phân trang, rồi đưa kết quả vào view qua biến pagination.

📋 Prompt mẫu — Lấy danh sách bài viết cho trang chủ
Hãy sửa HomeController của theme để lấy danh sách bài viết loại "blog" đã xuất bản, có phân trang, hiển thị ở trang chủ:
1. Tiêm WebPostControllerService vào controller.
2. Tạo DefaultPostFilter lọc postType = PostType.BLOG, postStatus = PostStatus.PUBLISHED.
3. Gọi getPostItemPagination() kèm ngôn ngữ hiện tại, thứ tự sắp xếp, nextPageToken/prevPageToken và limit (mặc định 12).
4. Đưa kết quả vào view qua biến "pagination".

Bước 4: Lặp và hiển thị danh sách trong template

Trong home.html, dùng th:each lặp qua pagination.items, mỗi phần tử render qua một fragment riêng (ví dụ fragments/blog-item) để tái sử dụng HTML của từng thẻ bài viết thay vì lặp code. Vì dữ liệu trả về là timestamp dạng Unix, thêm thư viện moment.js để chuyển thành ngày tháng dễ đọc ngay trong template.

📋 Prompt mẫu — Hiển thị danh sách bài viết
Trong home.html, hãy giúp tôi:
1. Dùng th:each lặp qua pagination.items, mỗi bài viết render qua fragment fragments/blog-item (truyền biến blog vào fragment).
2. Tạo fragment blog-item hiển thị ảnh đại diện, tiêu đề, ngày đăng của bài viết.
3. Thêm thư viện moment.js và dùng nó để chuyển timestamp Unix của bài viết thành định dạng ngày tháng dễ đọc.
4. Thêm nút chuyển trang trước/sau dựa trên nextPageToken và prevPageToken của pagination.

Xem hướng dẫn đầy đủ kèm ví dụ mã nguồn tại bài viết ghép dữ liệu động cho theme blog đơn giản.

Lập trình đa ngôn ngữ cho theme

Nếu website của bạn phục vụ nhiều thị trường, theme cần hỗ trợ đa ngôn ngữ (i18n) ngay từ đầu, thay vì hardcode text trực tiếp trong HTML. EzyPlatform dùng cơ chế thay thế theo key: mỗi đoạn text trong giao diện ứng với một key, giá trị thật được lấy từ file properties riêng cho từng ngôn ngữ. Gồm 4 bước.

Bước 1: Thay text cứng bằng key

Trong template, thay các đoạn text tĩnh bằng cú pháp Thymeleaf [[#{key}]] — ví dụ <a>Liên hệ</a> đổi thành <a>[[#{contact}]]</a>. Đặt tên key theo quy ước chữ thường, các từ cách nhau bằng dấu gạch dưới, ví dụ contact, load_more, topic_title.

📋 Prompt mẫu — Thay text cứng bằng key đa ngôn ngữ
Trong các template của theme {tên-mô đun-theme}, hãy giúp tôi thay toàn bộ text tĩnh (tiêu đề, nhãn nút, thông báo...) bằng cú pháp Thymeleaf [[#{key}]], đặt tên key theo quy ước chữ thường và gạch dưới.
Liệt kê cho tôi danh sách đầy đủ các key vừa tạo kèm text gốc tương ứng, để tôi dùng cho bước tạo file bản dịch tiếp theo.

Bước 2: Tạo file bản dịch cho từng ngôn ngữ

Trong src/main/resources/messages, tạo messages.properties (giá trị mặc định) và các file riêng theo ngôn ngữ như messages_vi.properties, messages_zh.properties, mỗi dòng theo dạng key=giá trị, ví dụ about_me=Về tôi.

📋 Prompt mẫu — Tạo file bản dịch
Dựa trên danh sách key ở bước trước, hãy tạo giúp tôi các file trong src/main/resources/messages:
- messages.properties: giá trị mặc định bằng tiếng {ngôn ngữ mặc định của bạn}.
- messages_vi.properties: bản dịch tiếng Việt.
- messages_zh.properties: bản dịch tiếng Trung.
Mỗi file theo định dạng key=giá trị.

Bước 3: Cấu hình encoding trong IntelliJ để tránh lỗi font

Vì tiếng Việt và nhiều ngôn ngữ khác dùng ký tự có dấu, cần bật tùy chọn Transparent native-to-ascii conversion tại Settings → Editor → File Encodings của IntelliJ, để tránh chữ có dấu bị lưu sai thành ký tự lỗi trong file .properties.

📋 Prompt mẫu — Cấu hình encoding cho file properties
Hãy hướng dẫn tôi bật "Transparent native-to-ascii conversion" trong Settings → Editor → File Encodings của IntelliJ, để các file messages_vi.properties, messages_zh.properties lưu đúng ký tự có dấu, không bị lỗi font.

Bước 4: Chạy thử và chuyển đổi ngôn ngữ

Khởi động lại project (chạy lại file StartupTest tương ứng), rồi truy cập website kèm tham số lang trên URL để kiểm tra từng ngôn ngữ, ví dụ http://localhost:8080/?lang=vi.

📋 Prompt mẫu — Chạy thử đa ngôn ngữ
Hãy giúp tôi khởi động lại theme {tên-mô đun-theme} (chạy lại StartupTest), rồi cho tôi biết cách truy cập trang chủ với các tham số ?lang=vi và ?lang=zh trên URL để kiểm tra bản dịch từng ngôn ngữ đã hiển thị đúng chưa.
Bài hướng dẫn gốc chỉ dừng ở việc chuyển ngôn ngữ qua tham số ?lang= trên URL, chưa có sẵn nút chọn ngôn ngữ trên giao diện. Nếu muốn người dùng tự đổi ngôn ngữ bằng một menu, bạn cần tự thiết kế thêm — có thể nhờ AI tạo một dropdown chuyển hướng sang URL kèm đúng tham số lang tương ứng.

Xem hướng dẫn đầy đủ tại bài viết lập trình đa ngôn ngữ với EzyPlatform.

Hướng dẫn cài đặt menu cho admin mô đun

Mặc định, menu của mô đun bạn tạo sẽ nằm trong nhóm "Các mở rộng" (extensions) ở khu vực quản trị — nhưng bạn có thể tùy chỉnh vị trí và icon để menu nổi bật hơn, phù hợp mức độ quan trọng của mô đun. Gồm 2 bước.

Bước 1: Hiểu 4 khu vực đặt menu

EzyPlatform chia menu Admin thành 4 khu vực, ứng với 4 tiền tố (prefix) cố định phải viết đúng chính tả trong menus.properties — dùng tiền tố khác, menu sẽ tự động rơi về nhóm mặc định extensions:

  • top — hiển thị ngay khu vực đầu của sidebar, không có tiêu đề nhóm, dành cho mô đun quan trọng cần nổi bật nhất (ví dụ Dashboard).
  • components — nhóm "Các thành phần", dành cho menu của các thành phần cốt lõi thuộc hệ thống.
  • administrator — nhóm "Quản trị viên", dành cho mô đun phục vụ công việc quản trị (quản lý người dùng, phân quyền...).
  • extensions — nhóm "Các mở rộng", vị trí mặc định của mọi mô đun mới tạo.

Bước 2: Khai báo và tùy chỉnh menu trong menus.properties

Menu được khai báo trong file menus.properties ở gốc mô đun admin-plugin (ngang hàng với pom.xml, không nằm trong src/main/resources), theo cú pháp {khu-vực}.{tên-mô đun}=đường-dẫn cho mục cha và {khu-vực}.{tên-mô đun}.{tên-mục-con}=đường-dẫn; icon cho mục con — icon dùng class Font Awesome hoặc Ionic, ví dụ:

📄 menus.properties (mặc định, nhóm extensions)
extensions.personal=/
extensions.personal.dashboard=/dashboard; fas fa-tachometer-alt

Muốn chuyển menu lên nhóm Top và đổi icon, chỉ cần đổi tiền tố extensions thành top:

📄 menus.properties (chuyển sang top, đổi icon)
top.personal=/; fas fa-blog
top.personal.dashboard=/dashboard; fas fa-tachometer-alt
📋 Prompt mẫu — Tùy chỉnh menu admin mô đun
Hãy mở file menus.properties ở gốc mô đun admin-plugin của tôi, cho tôi xem cấu hình menu hiện tại.
Sau đó chuyển menu từ nhóm extensions sang nhóm {top / components / administrator}, đổi icon thành {tên icon Font Awesome hoặc Ionic bạn muốn}, giữ nguyên các mục con và đường dẫn.
Cuối cùng hướng dẫn tôi export lại và chạy lại StartupTest để xem thay đổi có hiển thị đúng trên sidebar Admin không.
Hướng dẫn gốc chỉ dừng ở việc đổi vị trí và icon menu, chưa đề cập cách khai báo menu con nhiều cấp, nhãn đa ngôn ngữ hay phân quyền hiển thị theo role. Nếu mô đun cần những tính năng menu nâng cao hơn, hãy nhờ AI đọc thêm mã nguồn các mô đun có sẵn (ví dụ EzyArticle, EzySupport) để tham khảo cách họ khai báo, thay vì đoán cú pháp.

Xem hướng dẫn đầy đủ tại bài viết lập trình menu cho EzyPlatform admin mô đun.

Tạo bảng mới

Khi mô đun cần lưu trữ dữ liệu riêng ngoài các bảng có sẵn của EzyPlatform, bạn tự định nghĩa bảng mới ngay trong mô đun. EzyPlatform dùng JPA/Hibernate với các annotation quen thuộc (@Entity, @Table, @Id, @Column) để ánh xạ entity Java với bảng MySQL. Gồm 3 bước.

Bước 1: Viết script SQL tạo bảng

Đặt file .sql trong thư mục src/main/resources/scripts của mô đun admin-plugin — EzyPlatform tự quét và chạy một lần duy nhất khi khởi động. Luôn dùng CREATE TABLE IF NOT EXISTS để tránh lỗi khi chạy lại, và đặt tiền tố tên mô đun trước tên bảng để tránh trùng với bảng của mô đun khác.

📋 Prompt mẫu — Viết script tạo bảng
Mô đun {tên-mô đun-của-bạn} cần lưu {mô tả dữ liệu cần lưu, ví dụ: số lượng từ trong mỗi bài viết}.
Hãy giúp tôi viết file SQL trong src/main/resources/scripts của mô đun admin-plugin, dùng CREATE TABLE IF NOT EXISTS, đặt tên bảng có tiền tố {tên-mô đun}_, khai báo đúng các cột, khóa chính và index cần thiết cho dữ liệu trên.

Bước 2: Khai báo Entity ánh xạ với bảng

Tạo class Java tương ứng, đánh dấu @Entity, @Table(name = ...), khai báo các cột bằng @Column và khóa chính bằng @Id, khớp đúng với bảng vừa tạo ở Bước 1.

📋 Prompt mẫu — Tạo Entity cho bảng
Hãy tạo giúp tôi một class Entity Java ánh xạ với bảng vừa tạo ở Bước 1, dùng @Entity, @Table, @Id và @Column, đặt tên các trường tương ứng đúng với tên cột trong bảng.

Bước 3: Sinh Repository để CRUD dữ liệu

Thay vì viết tay, EzyPlatform cung cấp công cụ RepositoryClassesGenerator — chạy như một class Java bình thường trong IntelliJ — để tự sinh ra lớp repository tương ứng (ví dụ AdminPersonalPostWordCountRepository), có sẵn các phương thức CRUD như save(), findById(), delete().

📋 Prompt mẫu — Sinh Repository từ Entity
Hãy giúp tôi tạo và chạy class RepositoryClassesGenerator để sinh repository cho Entity vừa tạo ở Bước 2, rồi viết cho tôi một đoạn code ví dụ dùng repository đó để save, findById và delete một bản ghi.

Sau này nếu cần thay đổi cấu trúc bảng đã tồn tại, tạo thêm một file riêng có chữ "alter" trong tên (ví dụ alter_add_column.sql) — EzyPlatform sẽ chạy các file này và bỏ qua lỗi nếu thay đổi đã được áp dụng trước đó, tránh việc phải sửa lại file tạo bảng gốc. Xem hướng dẫn đầy đủ tại bài viết tạo bảng trong EzyPlatform mô đun.

Cài đặt batch (data appender)

Data Appender (Batch) là cơ chế xử lý dữ liệu hàng loạt chạy nền, phù hợp cho các nghiệp vụ tổng hợp dữ liệu nặng — ví dụ quét toàn bộ lịch sử bài viết để đếm số từ và lưu vào bảng thống kê riêng, thay vì tính toán ngay mỗi khi người dùng thao tác. Gồm 3 bước.

Bước 1: Chuẩn bị Repository đọc dữ liệu nguồn

Tạo repository đọc dữ liệu nguồn theo trang (page), ví dụ AdminPersonalPostHistoryRepository với phương thức findByIdGt(id) lấy các bản ghi có id lớn hơn id đã xử lý lần trước — đảm bảo duyệt tuần tự và không xử lý trùng.

📋 Prompt mẫu — Tạo Repository đọc dữ liệu nguồn
Hãy tạo giúp tôi repository {tên-repository-nguồn}, có phương thức findByIdGt(id) lấy danh sách bản ghi {tên-entity-nguồn} có id lớn hơn id truyền vào, sắp xếp tăng dần theo id, giới hạn số bản ghi mỗi lần lấy.

Bước 2: Tạo lớp Data Appender

Tạo class kế thừa AdminDataAppender<Nguồn, Đích, KiểuPageToken> (ví dụ AdminDataAppender<PostHistory, PersonalPostWordCount, Long>), đánh dấu @EzySingleton để EzyPlatform tự nhận diện và quản lý vòng đời, rồi implement các phương thức chính: getValueList (lấy danh sách bản ghi cần xử lý), toDataRecord (chuyển entity nguồn sang entity đích), addDataRecord (lưu vào bảng đích), extractNewLastPageToken (lấy id bản ghi cuối để dùng cho lần chạy tiếp theo), và defaultStarted (trả về true để chạy ngay khi EzyPlatform khởi động).

📋 Prompt mẫu — Tạo Data Appender
Hãy tạo giúp tôi class {TênMô đunPostWordCountDataAppender} kế thừa AdminDataAppender<PostHistory, {EntityĐích}, Long>, đánh dấu @EzySingleton, dùng repository {tên-repository-nguồn} ở Bước 1 và repository của {EntityĐích} ở phần Tạo bảng mới.
Implement getValueList, toDataRecord (đếm số từ trong nội dung bài viết), addDataRecord, extractNewLastPageToken (lấy id bản ghi cuối cùng) và defaultStarted trả về true.

Bước 3: Quản lý Data Appender qua Admin

Sau khi export và cài vào EzyPlatform, vào Cài đặt → Thông thường để thấy appender xuất hiện trong danh sách (ví dụ personal_post_word_count) với ba tùy chọn: Stop (dừng), Restart (chạy tiếp từ token hiện tại) và Reload (xóa token, quét lại toàn bộ từ đầu) — hữu ích khi cần chạy lại sau khi sửa logic tính toán.

Xem hướng dẫn đầy đủ tại bài viết tạo Batch Data Appender trong EzyPlatform mô đun.

Tạo và xử lý sự kiện nội bộ

Để mô đun dễ mở rộng, các phần bên trong nó không nên gọi trực tiếp lẫn nhau — thay vào đó, EzyPlatform cung cấp cơ chế sự kiện nội bộ (Internal Event): một nơi bắn sự kiện, nhiều nơi khác nhau có thể tự đăng ký lắng nghe và xử lý mà không cần biết đến nhau. Tiếp nối ví dụ Data Appender ở phần trên: thay vì tính luôn "thời gian đọc" ngay trong lúc đếm số từ, ta bắn một sự kiện sau khi đếm xong — một handler riêng sẽ lắng nghe và tự tính thời gian đọc. Gồm 3 bước.

Bước 1: Định nghĩa tên sự kiện

Khai báo một hằng số String đặt tên sự kiện, thường gom vào một class hằng số chung của mô đun (ví dụ PersonalConstants), đặt tiền tố tên mô đun để tránh trùng với sự kiện của mô đun khác — ví dụ INTERNAL_EVENT_NAME_POST_WORD_COUNT = "personal_post_word_count".

📋 Prompt mẫu — Định nghĩa tên sự kiện
Hãy thêm vào class {TênMô đun}Constants của tôi một hằng số String đặt tên sự kiện nội bộ cho việc {mô tả hành động cần thông báo, ví dụ: đã đếm xong số từ trong bài viết}, đặt tiền tố tên mô đun để tránh trùng với mô đun khác.

Bước 2: Bắn sự kiện tại nơi xảy ra hành động

Tại nơi cần thông báo (ví dụ ngay sau khi addDataRecord của Data Appender lưu xong bản ghi số từ), tiêm EventHandlerManager phù hợp (AdminEventHandlerManager cho phía admin, WebEventHandlerManager cho phía web) qua constructor hoặc @EzyAutoBind, rồi gọi handleEvent(tên-sự-kiện, dữ-liệu) kèm dữ liệu cần truyền, đóng gói bằng EzyMapBuilder.

📋 Prompt mẫu — Bắn sự kiện
Trong {tên-class-nơi-xảy-ra-hành-động}, hãy giúp tôi tiêm AdminEventHandlerManager, rồi ngay sau khi {mô tả hành động, ví dụ: lưu xong bản ghi số từ}, gọi eventHandlerManager.handleEvent với tên sự kiện đã định nghĩa ở Bước 1, dữ liệu đóng gói bằng EzyMapBuilder gồm các trường {liệt kê dữ liệu cần truyền, ví dụ: postId, wordCount}.

Bước 3: Đăng ký handler lắng nghe sự kiện

Tạo class implement EventHandler<D, R> (hoặc kế thừa AbstractEventHandler<D, R> nếu không cần trả kết quả), đánh dấu @EzySingleton để EzyPlatform tự nhận diện, override getEventName() trả về đúng tên sự kiện ở Bước 1 và processEventData()/doHandleEventData() để xử lý logic. Một sự kiện có thể có nhiều handler cùng lắng nghe, mỗi handler làm một việc độc lập, không ảnh hưởng lẫn nhau.

📋 Prompt mẫu — Tạo handler xử lý sự kiện
Hãy tạo giúp tôi class {TênMô đunTimeToReadEventHandler} kế thừa AbstractEventHandler<Map<String, Object>, Void>, đánh dấu @EzySingleton.
Override getEventName() trả về hằng số sự kiện đã tạo ở Bước 1.
Override processEventData() để {mô tả logic xử lý, ví dụ: tính thời gian đọc dựa trên wordCount nhận được và lưu vào bảng tương ứng}.
Sự kiện nội bộ chỉ xử lý được trong cùng một thành phần (admin, web hoặc socket) và trên cùng một máy chủ — không thể dùng để giao tiếp giữa các thành phần khác nhau hoặc giữa nhiều máy chủ. Nếu cần điều đó, bạn sẽ cần một cơ chế khác (ví dụ message queue), nằm ngoài phạm vi của Internal Event.

Xem hướng dẫn đầy đủ tại bài viết tạo và xử lý sự kiện nội bộ trong EzyPlatform mô đun.

📌 Tóm tắt chương

  • Mô đun là đơn vị mở rộng độc lập; Marketplace Item là mô đun đã đóng gói để chia sẻ hoặc bán; Theme định hình toàn bộ diện mạo website.
  • Môi trường phát triển cục bộ cần JDK 8, MySQL, Maven, EzyPlatform, EzyPlatform SDK và IntelliJ IDEA — mỗi bước đều có thể nhờ AI kiểm tra và cài đặt giúp.
  • Dùng ezy.sh để sinh khung project mới; mỗi loại mô đun (sdk, admin-plugin, web-plugin, theme, socket-plugin, socket-app) là một sub-module Maven riêng với vai trò rõ ràng.
  • Xây theme gồm: dựng giao diện tĩnh bằng Thymeleaf, ghép dữ liệu động, lập trình đa ngôn ngữ, và cho phép người dùng tự chỉnh sửa qua page fragment.
  • Xây mô đun gồm: cấu hình menu Admin, tạo bảng dữ liệu riêng, xử lý dữ liệu hàng loạt bằng Data Appender, và giao tiếp nội bộ giữa các thành phần bằng Internal Event.
  • Luôn kiểm thử kỹ với dữ liệu giả trước khi đưa mô đun vào vận hành thật.
  • Sau khi mô đun hoàn chỉnh, export lấy tập tin zip rồi tải lên trang quản trị Themes trên máy chủ để kích hoạt, hoặc khởi tạo dự án trên Marketplace của ezyplatform.com để đăng bán.
Chương trước: kết nối sản phẩm của bạn với các dịch vụ bên ngoài như Google, Meta, cổng thanh toán. ← Đọc Chương 13
Chương tiếp theo: đảm bảo sản phẩm của bạn chạy nhanh và an toàn trước người dùng thật. Đọc Chương 15 →