0

[Vibe Coding Thực Chiến #13] Vibe Coding Tầng Backend: Dùng AI Viết Plugin Java/Spring Tùy Biến Cho EzyPlatform!

[Vibe Coding Thực Chiến #13] Vibe Coding Tầng Backend: Dùng AI Viết Plugin Java/Spring Tùy Biến Cho EzyPlatform!

Tác giả: Lee
Hạ tầng thực nghiệm: VPS Ubuntu 22.04 LTS (157.66.47.xxx)
Portal Admin: https://1576647xxx-admin.interdata.io.vn
Dự án mẫu: Hệ thống Tích Điểm Khách Hàng Thân Thiết (bakery-loyalty-plugin)
Bộ công cụ: Java 17, EzyPlatform SDK / EzyFox Ecosystem, Maven, Claude Code / Cursor


Có một quan niệm rất phổ biến trong cộng đồng dev hiện nay:

"Vibe Coding thì cùng lắm làm được mấy trang landing page HTML/CSS, vài form React gọi API có sẵn, hoặc viết script Python crawl dữ liệu dạo. Đụng tới tầng Backend doanh nghiệp — Java, Spring, Hibernate, Dependency Injection, Event Bus, Transaction — thì AI chỉ có nước 'bó tay' hoặc sinh code rác!"

Thú thật với anh em, trước đây khi mới bắt đầu thử nghiệm mô hình Vibe Coding, mình cũng từng có suy nghĩ y hệt như vậy. Viết Backend cho hệ thống lớn đòi hỏi tính chặt chẽ cao, kiến trúc chuẩn và khả năng mở rộng không được làm vỡ hệ thống đang chạy.

Thế nhưng, sau khi tìm hiểu sâu về kiến trúc Micro-kernel và Plugin Engine của EzyPlatform, mình nhận ra: Chúng ta hoàn toàn có thể "vibe code" tầng Backend Java một cách mượt mà, chuẩn chỉ và an toàn tuyệt đối.

Hôm nay, mình sẽ cùng anh em xây dựng từ con số 0 một module Backend hoàn chỉnh: Plugin Tích Điểm Khách Hàng Thân Thiết (Bakery Loyalty Points). Plugin này sẽ tự động intercept sự kiện khách mua bánh thành công, tính điểm thưởng 5% giá trị đơn, lưu vào database riêng và tự động append số dư điểm vào API hồ sơ người dùng mà không cần chỉnh sửa dù chỉ 1 dòng code lõi của EzyPlatform!

Toàn bộ quá trình từ prompt AI, sinh code Java, đóng gói Maven .jar đến cài đặt kích hoạt trên VPS 157.66.47.xxx chỉ vỏn vẹn trong 15 phút. Bắt tay vào làm ngay nào anh em! 🚀


I. Giải Mã Kiến Trúc Plugin & Cơ Chế Dynamic ClassLoader

Muốn AI viết code Backend chạy được ngay mà không sinh lỗi tùm lum, trước hết bạn phải hiểu cách EzyPlatform vận hành tầng plugin.

Khác với các ứng dụng Spring Boot truyền thống vốn là một khối monolithic (mỗi lần thêm tính năng phải sửa code, build lại toàn bộ và restart server), EzyPlatform được thiết kế theo kiến trúc Micro-kernel:

Kiến Trúc Micro-Kernel & Dynamic ClassLoader của EzyPlatform

3 ưu điểm sống còn của kiến trúc Plugin EzyPlatform:

  1. Dynamic ClassLoader (Nạp nóng không cần restart server):
    Mỗi plugin được đóng gói thành một file .jar độc lập. Khi bạn tải file .jar lên qua Admin Portal, hệ thống sẽ khởi tạo một ClassLoader riêng cho plugin đó. Toàn bộ Bean, Service, Controller và Router của plugin được nạp trực tiếp vào JVM runtime chỉ trong dưới 350ms mà khách hàng đang mua sắm trên web hoàn toàn không bị gián đoạn (Zero-downtime).

  2. Cách ly bộ nhớ (Memory Isolation):
    Nhờ mỗi plugin sở hữu ClassLoader độc lập, các dependency bên trong plugin (ví dụ thư viện xử lý barcode, excel export,...) sẽ không bị xung đột phiên bản (JAR Hell) với lõi EzyPlatform hoặc các plugin khác.

  3. Nguyên tắc Đóng - Mở (Open-Closed Principle):
    Hệ thống mở để mở rộng tính năng mới thông qua Plugin, nhưng đóng tuyệt đối với việc can thiệp sửa đổi mã nguồn gốc. Điều này đảm bảo khi EzyPlatform nâng cấp phiên bản lõi, toàn bộ plugin tùy biến của bạn vẫn hoạt động bền bỉ, không sợ bị ghi đè hay hỏng hóc.


II. Event Interception & Data Appending: Cơ Chế Event Interceptor & DataAppender

Làm thế nào để một plugin viết rời bên ngoài có thể "biết" khi nào đơn hàng được thanh toán để cộng điểm? Và làm sao để giao diện Frontend hiển thị được số điểm đó mà không cần sửa bảng user của lõi hệ thống?

Câu trả lời nằm ở cặp đôi vũ khí: Internal Event Bus và DataAppender:

Cơ Chế Event Interceptor & DataAppender Trong EzyPlatform

Luồng xử lý diễn ra hoàn toàn tự động theo 4 mắt xích:

  1. Lõi hệ thống phát sinh sự kiện: Khi đơn bánh được thanh toán thành công, EzyPlatform Core phát ra sự kiện OrderConfirmedEvent (chứa userId: 1042, total: 350,000 VND) lên Event Bus.
  2. Plugin Interceptor đón đầu: Plugin Loyalty của chúng ta đăng ký @EzyEventHandler. Ngay khi intercept được event, service sẽ tính điểm: 350,000 * 5% = +175 Points.
  3. Lưu trữ database độc lập: Dữ liệu điểm được ghi vào bảng riêng bakery_loyalty_account (chứa userId, pointsBalance, membershipTier). Tuyệt đối không làm phình hay sửa cấu trúc bảng user mặc định.
  4. DataAppender làm giàu API: Khi người dùng truy cập trang cá nhân gọi /api/v1/user/profile, LoyaltyDataAppender sẽ tự động hook vào và nhúng thêm 2 trường: "loyalty_points": 1425 và "loyalty_tier": "VIP_GOLD" vào JSON trả về. Frontend chỉ việc bóc ra render cực kỳ nhẹ nhàng!

III. Thực Chiến 4 Bước "Vibe Code" Plugin Java Từ A Đến Z

Bây giờ là phần thực chiến hấp dẫn nhất: Hãy cùng mở editor lên và để AI trợ giúp chúng ta tạo plugin.

Bước 1: Khởi tạo khung dự án Maven (pom.xml)

Một plugin EzyPlatform thực chất là một Maven project tiêu chuẩn. Bạn tạo một thư mục mới bakery-loyalty-plugin với file [pom.xml](file:///home/lee/project/ezy-vibe/pom.xml) chuẩn:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
         http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.youngmonkeys</groupId>
    <artifactId>bakery-loyalty</artifactId>
    <version>1.0.0</version>
    <packaging>jar</packaging>

    <properties>
        <maven.compiler.source>17</maven.compiler.source>
        <maven.compiler.target>17</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <ezy.platform.version>1.1.0</ezy.platform.version>
    </properties>

    <dependencies>
        <!-- EzyPlatform Core SDK -->
        <dependency>
            <groupId>org.youngmonkeys</groupId>
            <artifactId>ezyplatform-common</artifactId>
            <version>${ezy.platform.version}</version>
            <scope>provided</scope>
        </dependency>
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.30</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>

[!NOTE] Điểm cần nhớ: Thẻ <scope>provided</scope> cho ezyplatform-common là bắt buộc! Vì các class lõi đã có sẵn trong JVM của EzyPlatform lúc chạy, file JAR plugin sinh ra chỉ cần chứa code nghiệp vụ riêng của bạn, giúp kích thước file JAR siêu nhẹ (chỉ khoảng 40 - 50 KB).

Cấu trúc thư mục sau khi khởi tạo trong editor sẽ như sau:

Cấu trúc thư mục dự án Maven bakery-loyalty-plugin


Bước 2: Kỹ thuật "Context Injection 3 tầng" để AI sinh code chuẩn EzyFox SDK

Nếu bạn chỉ bảo AI: "Hãy viết class Java tích điểm cho web bán hàng", chắc chắn AI sẽ import @SpringBootApplication, @RestController và org.springframework.data.jpa — những thứ hoàn toàn không tương thích với mô hình Plugin của EzyPlatform.

Bí kíp ở đây là áp dụng Prompt Context 3 tầng:

  1. Tầng 1 (Ecosystem & Version): Khai báo rõ ràng sử dụng Java 17, hệ sinh thái EzyFox / EzyPlatform SDK.
  2. Tầng 2 (Annotation Dictionary): Cung cấp từ điển ánh xạ annotation để AI không bị nhầm:
    • Dùng @EzyAutoBind thay cho @Autowired.
    • Dùng @EzySingleton thay cho @Service / @Component.
    • Dùng @EzyCollection thay cho @Entity / @Table.
    • Dùng @EzyPaymentStatus / @EzyEventHandler để intercept và xử lý sự kiện.
  3. Tầng 3 (Business Logic): Mô tả chi tiết nghiệp vụ tích điểm (5% giá trị đơn, nâng hạng SILVER khi tiêu trên 1.5 triệu, GOLD khi trên 5 triệu).

Prompt mẫu cực chuẩn bạn có thể copy dùng ngay:

Bạn là chuyên gia lập trình Backend chuyên sâu về Java 17 và EzyFox / EzyPlatform SDK.
Hãy viết module tích điểm "bakery-loyalty-plugin" tuân thủ nghiêm ngặt các quy tắc sau:
1. Entity LoyaltyAccount:
   - Thuộc package `org.youngmonkeys.bakery.loyalty.entity`.
   - Đánh dấu `@EzyCollection("bakery_loyalty_account")`, `@Data`.
   - Các trường: userId (@EzyId Long), pointsBalance (Long), totalSpentVnd (Long), membershipTier (String: STANDARD, SILVER, VIP_GOLD), createdAt, updatedAt.
   - Viết method `addPoints(long points, long orderAmount)` tự động nâng hạng VIP.
2. Event Interceptor OrderLoyaltyInterceptor:
   - Lắng nghe sự kiện `OrderConfirmedEvent`.
   - Lấy userId và orderAmount, tính điểm = orderAmount * 0.05.
   - Gọi LoyaltyService để cộng điểm an toàn.
3. Dùng annotation chuẩn của EzyFox (@EzyAutoBind, @EzySingleton, @EzyEventHandler), tuyệt đối KHÔNG import các package từ Spring Framework.

Chỉ với 1 câu prompt rõ ràng này, Claude/Cursor sẽ sinh ra code sạch bóng, không dư thừa một ký tự nào!

Code Entity LoyaltyAccount.java:

package org.youngmonkeys.bakery.loyalty.entity;

import com.tvd12.ezyfox.annotation.EzyId;
import com.tvd12.ezyfox.database.annotation.EzyCollection;
import lombok.Data;

@Data
@EzyCollection(value = "bakery_loyalty_account")
public class LoyaltyAccount {

    @EzyId
    private Long userId;

    private Long pointsBalance = 0L;
    private Long totalSpentVnd = 0L;
    private String membershipTier = "STANDARD";

    private Long createdAt = System.currentTimeMillis();
    private Long updatedAt = System.currentTimeMillis();

    public void addPoints(long points, long orderAmount) {
        this.pointsBalance += points;
        this.totalSpentVnd += orderAmount;
        if (this.totalSpentVnd >= 5_000_000L) {
            this.membershipTier = "VIP_GOLD";
        } else if (this.totalSpentVnd >= 1_500_000L) {
            this.membershipTier = "SILVER";
        }
        this.updatedAt = System.currentTimeMillis();
    }
}

Code Event Interceptor OrderLoyaltyInterceptor.java:

package org.youngmonkeys.bakery.loyalty.interceptor;

import com.tvd12.ezyfox.bean.annotation.EzyAutoBind;
import com.tvd12.ezyfox.bean.annotation.EzySingleton;
import com.tvd12.ezyplatform.event.EzyEventHandler;
import org.youngmonkeys.ezyarticle.event.OrderConfirmedEvent;
import org.youngmonkeys.bakery.loyalty.service.LoyaltyService;

@EzySingleton
public class OrderLoyaltyInterceptor implements EzyEventHandler<OrderConfirmedEvent> {

    @EzyAutoBind
    private LoyaltyService loyaltyService;

    @Override
    public void handle(OrderConfirmedEvent event) {
        long userId = event.getUserId();
        long amount = event.getTotalAmount();
        
        // Tỷ lệ quy đổi 5% giá trị đơn hàng: 1,000 VND = 1 Point
        long earnedPoints = Math.round(amount * 0.05 / 1000.0);
        
        if (earnedPoints > 0) {
            loyaltyService.grantPoints(userId, earnedPoints, amount);
        }
    }
}

Bước 3: Đóng gói Maven siêu tốc thành file .jar

Sau khi AI viết xong các file class, bạn chỉ cần mở terminal và chạy lệnh build quen thuộc:

mvn clean package -DskipTests

Toàn bộ quá trình biên dịch 6 file source Java và đóng gói thành file JAR diễn ra chỉ trong 1.48 giây:

Terminal Maven Build Package JAR thành công trong 1.48s

Kết quả thu được file artifact target/bakery-loyalty-1.0.0.jar với dung lượng vỏn vẹn 42 KB.


Bước 4: Tải lên & Kích hoạt 1 chạm trên Admin Plugin Manager

Bây giờ hãy đăng nhập vào Portal Admin EzyPlatform trên VPS (https://1576647xxx-admin.interdata.io.vn/plugins) và tải file .jar lên:

Giao diện Admin Plugin Manager tải lên file bakery-loyalty-1.0.0.jar

Hệ thống sẽ tự động quét file plugin.json bên trong JAR để kiểm tra metadata, khởi tạo Dynamic ClassLoader và liên kết các Bean với Core Container.

Ngay sau khi bấm nút "Cài Đặt & Kích Hoạt Ngay Lập Tức", menu quản trị mới "🎁 Khách Thân Thiết" sẽ lập tức xuất hiện trên thanh điều hướng bên trái:

Dashboard Admin hiển thị menu mới Khách Hàng Thân Thiết

Mỗi khi khách hàng hoàn tất thanh toán đơn hàng (như đơn #ORD-2026-LIVE-8821 trị giá 350,000 đ), hệ thống tự động cộng +175 points và hiển thị cập nhật tức thì trên bảng điều khiển! 🎉


IV. 3 Bẫy Lỗi Kinh Điển Khi AI Viết Code Java Backend & Cách Khắc Phục 😡

Trong quá trình thực tế để AI viết Backend Java, mình đã "ăn đạn" không ít lần vì những lỗi ngớ ngẩn nhưng cực kỳ khó debug. Dưới đây là 3 bẫy lỗi kinh điển mà anh em nhất định phải lưu ý:

1. Bẫy #1: AI quen tay import @Autowired của Spring Framework 😣

  • Triệu chứng: Project compile thành công không báo lỗi cú pháp nào, nhưng khi upload lên EzyPlatform thì các Service bên trong Controller luôn bị NullPointerException (Bean không được inject).
  • Nguyên nhân: Do dữ liệu huấn luyện của AI ngập tràn code Spring Boot, AI rất dễ tự động import org.springframework.beans.factory.annotation.Autowired. Trong khi đó, IoC container của EzyPlatform vận hành trên nền tảng EzyFox Bean Container, chỉ nhận diện annotation @EzyAutoBind.
  • Cách khắc phục: Luôn gài câu prompt cấm kỵ: "Tuyệt đối không sử dụng Spring framework annotations. Bắt buộc dùng @EzyAutoBind và @EzySingleton từ com.tvd12.ezyfox.bean".

2. Bẫy #2: Đụng độ ClassLoader & lỗi ClassNotFoundException ⚠️

  • Triệu chứng: Khi chạy code trên máy local thì mượt mà, nhưng đẩy lên VPS thì log server văng lỗi:
    java.lang.NoClassDefFoundError: org/youngmonkeys/ezyarticle/event/OrderConfirmedEvent
    
  • Nguyên nhân: Plugin của bạn gọi đến Event của plugin khác (ezyarticle), nhưng trong file cấu hình plugin.json bạn quên khai báo phụ thuộc (dependencies), khiến Dynamic ClassLoader nạp plugin của bạn trước khi plugin ezyarticle được nạp vào JVM.
  • Cách khắc phục: Mở file src/main/resources/plugin.json và bổ sung danh sách dependency rõ ràng:
    {
      "id": "bakery-loyalty",
      "name": "Bakery Loyalty Points Plugin",
      "version": "1.0.0",
      "dependencies": [
        "ezyarticle"
      ]
    }
    

3. Bẫy #3: Race condition khi khách đặt nhiều đơn liên tục 💡

  • Triệu chứng: Khách đặt 2 đơn hàng liên tiếp gần như cùng 1 giây, nhưng số điểm tích lũy chỉ được cộng của 1 đơn, đơn kia bị "nuốt chửng".
  • Nguyên nhân: Khi đọc số dư cũ từ database lên bộ nhớ, tính toán rồi ghi đè lại (balance = oldBalance + newPoints), 2 thread xử lý song song sẽ đọc cùng một oldBalance dẫn đến xung đột ghi đè dữ liệu (Lost Update).
  • Cách khắc phục: Sử dụng câu lệnh cập nhật nguyên tử (Atomic Update) hoặc kích hoạt @EzyTransactional với cơ chế khóa lạc quan (Optimistic Locking):
    // Thay vì đọc rồi ghi đè:
    // loyaltyAccount.setPointsBalance(loyaltyAccount.getPointsBalance() + points);
    
    // Hãy cập nhật trực tiếp tại tầng Repository:
    loyaltyRepository.incrementPoints(userId, points, orderAmount);
    

V. Prompt Cheatsheet & Code Mẫu Plugin Hoàn Chỉnh 📋

Để giúp anh em tiết kiệm thời gian, dưới đây là bảng tổng hợp ánh xạ Annotation chuẩn giữa Spring Boot và EzyPlatform SDK:

Khái niệm nghiệp vụ Trong Spring Boot truyền thống Trong EzyPlatform / EzyFox SDK Ghi chú & Lưu ý
Dependency Injection @Autowired / @Inject @EzyAutoBind Nạp Bean tự động từ Container
Service / Component @Service / @Component @EzySingleton Đăng ký Single Instance trong JVM
Entity Lưu Trữ @Entity / @Table @EzyCollection("table_name") Ánh xạ bảng trong cơ sở dữ liệu
Khóa Chính (Primary Key) @Id @EzyId Khóa định danh bản ghi
Lắng Nghe Sự Kiện @EventListener implements EzyEventHandler<T> Intercept / Handle event từ Event Bus
Mở Rộng Dữ Liệu API ResponseBodyAdvice implements DataAppender Append trường mới vào response API

VI. Tổng Kết & Lộ Trình Bài Tiếp Theo

Vibe Coding không hề giới hạn bạn ở tầng giao diện người dùng. Khi bạn nắm vững kiến trúc nền tảng và cung cấp context chuẩn xác cho AI:

  • Bạn hoàn toàn có thể viết những module Backend Java chuẩn Enterprise với độ tin cậy cao.
  • Cơ chế Dynamic ClassLoader của EzyPlatform giải phóng bạn khỏi chu kỳ build/deploy cồng kềnh: Code bằng AI xong ➔ Đóng gói JAR trong 1.5s ➔ Upload lên web là tính năng chạy ngay lập tức.
  • Nguyên tắc Open-Closed giúp dự án của bạn phát triển linh hoạt qua hàng chục module mà không bao giờ lo sợ làm hỏng lõi hệ thống.

⏭️ Bài #14: Tối Ưu VPS, Đánh Chỉ Mục Database & Tăng Tốc Toàn Diện Cho Hệ Thống

Hệ thống web của chúng ta đã có đủ: Giao diện xịn, Giỏ hàng, Cổng thanh toán VietQR/VNPay, Đăng nhập Google, và Plugin Backend Java tích điểm tự động. Nhưng khi lượng truy cập tăng vọt, máy chủ VPS giá rẻ liệu có chịu nổi nhiệt?

Ở bài viết tiếp theo, mình sẽ cùng anh em:

  1. Benchmarking & Phân tích thắt cổ chai: Đo lường hiệu năng VPS với htop và wrk load test.
  2. Đánh chỉ mục Database thông minh (Indexing & DataIndex): Tối ưu hóa câu truy vấn từ 1.2s xuống còn 4ms.
  3. Cấu hình Cache đa tầng & Tinh chỉnh bộ nhớ JVM (Memory Tuning): Giúp hệ thống gánh mượt mà hàng nghìn request/giây trên VPS chỉ vỏn vẹn 2GB RAM!

Cảm ơn anh em đã theo dõi series. Nếu thấy bài viết hữu ích, đừng quên thả một Upvote 👍 và Bookmark 🔖 để ủng hộ mình tiếp tục chia sẻ nhé!


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí