0

Apache Derby Bài 44: Đóng gói và phân phối ứng dụng Desktop kèm Apache Derby Embedded (Standalone App)

1. Kiến trúc Standalone: Trở lại với Embedded Mode

Xuyên suốt các bài trước, chúng ta đã tối ưu hóa Derby cho môi trường mạng (Network Server) phục vụ ứng dụng Backend phân tán. Tuy nhiên, một thế mạnh tuyệt đối khác của Apache Derby là khả năng nhúng sâu vào các ứng dụng Desktop (JavaFX, Swing) hoặc các công cụ dòng lệnh (CLI Tools) để chạy trực tiếp trên máy tính người dùng mà không cần cài đặt bất kỳ máy chủ CSDL nào.

Trong kiến trúc này (Standalone App), ứng dụng Java và hệ quản trị CSDL cùng chia sẻ một tiến trình JVM (Embedded Mode). Người dùng cuối chỉ cần nhấp đúp vào file chạy là ứng dụng hoạt động ngay lập tức với dữ liệu lưu cục bộ.

2. Quản lý không gian lưu trữ (Relative Path & User Home)

Khi đóng gói ứng dụng đem sang máy khách, bạn không thể sử dụng các đường dẫn tuyệt đối tĩnh như C:/data/db vì hệ điều hành của khách hàng có thể là macOS, Linux, hoặc ổ C bị khóa quyền ghi.

Có hai cách chuyên nghiệp để định tuyến thư mục lưu CSDL:

Cách 1: Lưu trong thư mục làm việc hiện tại (Relative Path)

CSDL sẽ được tạo ra ngay cạnh file .jar chạy ứng dụng.

Java

// URL không có dấu gạch chéo đầu tiên đại diện cho đường dẫn tương đối
String url = "jdbc:derby:app_database;create=true";

Cách 2: Lưu vào thư mục người dùng hệ điều hành (Khuyên dùng)

Để tránh lỗi quyền ghi (Write Permission) khi ứng dụng được đặt trong C:\Program Files, hãy lưu dữ liệu vào thư mục User Home của hệ điều hành.

Java

// Lấy đường dẫn thư mục gốc của User (VD: C:\Users\Hieu)
String userHome = System.getProperty("user.home");
String dbPath = userHome + "/.my_desktop_app/local_db";

String url = "jdbc:derby:" + dbPath + ";create=true";

3. Tắt cơ sở dữ liệu an toàn (Graceful Shutdown)

Trong Embedded Mode, khi ứng dụng hoạt động, Derby tạo ra một tệp khóa db.lck. Nếu người dùng nhấn nút "X" để đóng cửa sổ ứng dụng mà mã Java tắt đột ngột, tệp khóa này không được xóa đi, dễ dẫn đến nguy cơ hỏng dữ liệu hoặc báo lỗi Database locked ở lần mở tiếp theo.

Bạn bắt buộc phải lập trình để gửi tín hiệu tắt tới Derby Engine (sử dụng thuộc tính shutdown=true) trước khi JVM kết thúc.

Java

package com.hieu.derby.desktop;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class DesktopAppManager {

    private static final String DB_URL = "jdbc:derby:local_db;create=true";
    private static final String SHUTDOWN_URL = "jdbc:derby:;shutdown=true"; // Tắt toàn bộ Derby Engine

    public static void startApp() {
        // Đăng ký một luồng sẽ chạy tự động khi JVM chuẩn bị tắt (Ví dụ: user bấm Alt+F4)
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            System.out.println("Đang tắt ứng dụng, dọn dẹp cơ sở dữ liệu...");
            try {
                DriverManager.getConnection(SHUTDOWN_URL);
            } catch (SQLException e) {
                // Mã lỗi 08006 xác nhận Derby đã tắt thành công
                if ("08006".equals(e.getSQLState())) {
                    System.out.println("Derby Engine đã tắt an toàn.");
                } else {
                    e.printStackTrace();
                }
            }
        }));

        // Logic kết nối bình thường
        try (Connection conn = DriverManager.getConnection(DB_URL)) {
            System.out.println("Ứng dụng Desktop đã khởi động, kết nối CSDL thành công!");
            // Mở giao diện JavaFX / Swing tại đây...
            
            // Giả lập ứng dụng đang chạy
            Thread.sleep(5000); 
            
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        startApp();
    }
}

4. Đóng gói thành Fat JAR (Uber-JAR)

Để người dùng có thể chạy ứng dụng bằng một cú đúp chuột (Double-click), bạn cần gói toàn bộ mã nguồn của mình cộng với thư viện lõi derby.jar vào chung một file duy nhất gọi là "Fat JAR".

Sử dụng plugin maven-shade-plugin hoặc maven-assembly-plugin trong tệp pom.xml:

XML

<dependencies>
    <!-- BẮT BUỘC dùng thư viện lõi derby, KHÔNG dùng derbyclient -->
    <dependency>
        <groupId>org.apache.derby</groupId>
        <artifactId>derby</artifactId>
        <version>10.17.1.0</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>3.6.0</version>
            <configuration>
                <archive>
                    <manifest>
                        <!-- Trỏ đến Class chứa hàm main() của ứng dụng -->
                        <mainClass>com.hieu.derby.desktop.DesktopAppManager</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Mở Terminal và chạy lệnh mvn clean package. Maven sẽ sinh ra một tệp ví dụ như my-desktop-app-1.0-jar-with-dependencies.jar.

5. Phân phối và khởi chạy ở máy khách

Bây giờ, bạn chỉ cần gửi đúng một file .jar duy nhất cho khách hàng. Mọi thứ từ logic xử lý đến hệ quản trị cơ sở dữ liệu đều đã được nén gọn bên trong.

Cách khởi chạy:

  1. Khách hàng nhấp đúp vào file .jar (yêu cầu máy tính có cài sẵn JRE/JDK).

  2. Hoặc tạo một file khởi chạy nhanh start.bat (trên Windows) với nội dung:

    DOS

    @echo off
    java -jar my-desktop-app-1.0-jar-with-dependencies.jar
    pause
    
    

Nâng cao: Từ Java 14 trở đi, bạn có thể dùng công cụ jpackage để bọc file Fat JAR này cùng với một máy ảo Java thu nhỏ thành một file cài đặt .exe (Windows), .dmg (macOS), hoặc .deb (Linux). Khách hàng cài đặt và chạy ứng dụng như một phần mềm Native bình thường mà không hề biết bên trong nó đang chạy Apache Derby.

Hệ thống của chúng ta đã được định hình từ môi trường Server tải cao cho đến ứng dụng Desktop nhỏ gọn. Trong quá trình vận hành dài hạn, việc đọc hiểu các cảnh báo của hệ thống là kỹ năng bắt buộc để bảo trì. Bài tiếp theo sẽ đi sâu vào kỹ thuật gỡ lỗi: Apache Derby Bài 45: Phân tích nhật ký hệ thống (derby.log) và khắc phục sự cố.


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í