Level 1: Core Fundamentals

Sub-topic 1.1: JasperReports Lifecycle & Internal Mechanics

Architectural Specification & In-Depth Guide (JasperReports 7.0.3+, Java 17/21, Jakarta EE 10)

1 & 2. Modular Architecture & Core Lifecycle (4 Stages)

JasperReports 7.0.x ได้รื้อถอนสถาปัตยกรรม Monolithic JAR เดิมทั้งหมด เพื่อตอบสนองต่อข้อกำหนด Java 17/21 LTS และมาตรฐาน Jakarta EE โดยแตกโมดูลแยกเป็นอิสระ (Decoupled Engine):

Modern Architecture and Lifecycle Summary
รูปที่ 1: เปรียบเทียบ Monolithic 6.x สู่ Modular Decoupled 7.0.x และผัง Lifecycle ภาพรวม

การเปลี่ยนแปลงเชิงโครงสร้าง (7.0.x vs 6.x):

  • Legacy 6.x (Fat Monolith): ผูกมัด Core Engine, iText 2.1.7 (ติด Security CVE และ LGPL), และ javax.servlet เมื่อรันบน Spring Boot 3+ จะเกิด Classpath Conflict และ Metaspace Pollution ทันที
  • Modern 7.0.x (Decoupled Modules): แยกเป็น jasperreports-core, jasperreports-pdf (OpenPDF/PDFBox สะอาดปราศจากข้อจำกัด License), jasperreports-excel (Decoupled POI), และ jasperreports-jakarta สำหรับ Web Integration
JasperReports 4 Stages Lifecycle
รูปที่ 2: วงจรชีวิต 4 สเตจ Design, Compile, Fill, Export และการจัดสรร Memory บน JVM

ผัง 4 สเตจหลัก (Core Lifecycle Flow):

  1. Design Stage (.jrxml): เอกสารนิยามโครงสร้างและนิพจน์ (Expressions) ในรูป XML Schema 7.0.x
  2. Compile Stage (JasperCompileManager): แปลง XML Template และ Expressions ภาษา Java ให้อยู่ในรูป Executable Bytecode (JasperReport / .jasper)
  3. Fill Stage (JasperFillManager): ฉีดข้อมูลจริงจาก Data Source และ Parameters เข้าไปใน Template เพื่อคำนวณและวาด Layout ทีละหน้า ได้ผลลัพธ์เป็น JasperPrint
  4. Export Stage (JRAbstractExporter): สังเคราะห์ Abstract Page Model ให้ออกมาเป็น Byte Stream ของไฟล์มาตรฐานจริง เช่น PDF หรือ Excel

3. The Compile Stage & JVM Metaspace Hazard

เมื่อมีการสั่งคอมไพล์ผ่าน JasperCompileManager.compileReport(...) Engine จะมีกระบวนการทำงานระดับ Low-level ดังนี้:

Compile Stage and Metaspace Leak Mechanics
รูปที่ 3: กลไก Dynamic Class Generation และการรั่วไหลของ Metaspace Memory

กลไกการทำงานภายใน (Execution Steps):

  1. XML Digestion: JRXmlDigester อ่านและสกัด Java Expressions ทั้งหมด
  2. Dynamic Source Synthesis: สร้างซอร์สโค้ดภาษา Java ขึ้นมา 1 คลาสสดๆ ในหน่วยความจำ (เช่น invoice_1715000000_12345.java) บรรจุ Logic การคำนวณลงใน Method evaluate()
  3. In-Memory Compilation: เรียกใช้ Eclipse JDT Core หรือ JDK Compiler คอมไพล์ String ซอร์สโค้ดนั้นให้เป็น Bytecode (.class)
  4. Dynamic ClassLoading: Engine สร้าง Custom ClassLoader ตัวใหม่เพื่อโหลด Bytecode ก้อนนั้นเข้าไปยัง JVM Metaspace
  5. JasperReport Output: มัดรวม Template Layout เข้ากับ Compiled Class กลายเป็นอ็อบเจกต์ JasperReport ที่พร้อมนำไป Fill
จุดตายบน Production (The Metaspace Fatal Trap):
หากเรียก compileReport() ใน Controller ทุกคำขอ เมื่อมีโหลดสูง JVM จะต้องรัน Java Compiler ตลอดเวลาทำให้ CPU พุ่ง 100% และ Custom ClassLoader จะโหลดคลาสใหม่เข้า Metaspace อย่างต่อเนื่องจน Garbage Collector กวาดทิ้งไม่ทัน ส่งผลให้ระบบล่มด้วย OutOfMemoryError: Metaspace
Enterprise Best Practice:
AOT Pre-compilation: คอมไพล์ .jrxml เป็น .jasper ตั้งแต่ขั้นตอน CI/CD Build แล้วโหลดผ่าน JRLoader.loadObject()
Singleton Cache: หากจำเป็นต้องใช้ JRXML ให้คอมไพล์เพียงครั้งเดียวตอน Startup แล้วเก็บเป็น Singleton Spring Bean

4 & 5. Fill Stage Mechanics & Exporter Serialization

Fill Stage Mechanics and JRVerticalFiller Loop
รูปที่ 4: กลไกการวนลูปของ JRVerticalFiller และความเสี่ยง Heap Exhaustion

Internal Filler Pipeline (JRVerticalFiller):

  • Record Iteration: วน Loop ดึงข้อมูลแถวถัดไปด้วย datasource.next()
  • Expression Evaluation: ส่งข้อมูลเข้าไปประเมินผลใน Dynamic Bytecode เพื่อดึงค่า $F{}, $P{} และสะสมตัวแปร $V{}
  • Band Height & Overflow Check: เช็คความสูง Detail Band หากเกินพื้นที่หน้ากระดาษ จะ Trigger New Page (JRPrintPage) ทันที
  • Element Materialization: คำนวณพิกัดสัมบูรณ์ ($X, Y$) และขนาด ($W, H$) แล้ว Instantiate Concrete Objects (JRPrintText, JRPrintLine) ยัดลงใน Page Model
Heap Bloat Risk:
JasperPrint เป็น In-Memory Visual Tree ขนาดมหึมา หากมีหลายพันหน้า Element Nodes นับล้านชิ้นจะอยู่บน Heap พร้อมกันจนเกิด OutOfMemoryError: Java heap space
Exporter Serialization Architecture
รูปที่ 5: การ Serialize ข้อมูลจาก JasperPrint ไปยัง PDF Canvas และ Excel Matrix

Abstract Model Serialization:

  • JRPdfExporter (Vector-based): อ่าน Element Nodes แล้วนำพิกัด Points ($1/72$ นิ้ว) ไปวาดลง Canvas เวกเตอร์ของ PDF และฝัง Font Extensions ลงในไบนารีสตรีม
  • JRXlsxExporter (Grid-based): สลายระบบพิกัดสัมบูรณ์ แล้วแปลง Elements ลง Matrix ตาราง (Row, Column) หากวางเหลื่อมกันจะเกิดปัญหา Cell Merging ทันที

6 & 7. Production Implementation & Architecture Matrix

// Production-Grade Implementation (Spring Boot 3.x / Java 21)
@Configuration
public class JasperReportConfig {
    @Bean
    public JasperReport invoiceReport() throws JRException, IOException {
        // แนะนำที่สุด: โหลด .jasper ที่ Pre-compile แล้วจาก CI/CD
        try (InputStream is = new ClassPathResource("reports/invoice.jasper").getInputStream()) {
            return (JasperReport) JRLoader.loadObject(is);
        }
    }
}

@Service
public class InvoiceReportingService {
    private final JasperReport invoiceReport;
    public InvoiceReportingService(JasperReport invoiceReport) { this.invoiceReport = invoiceReport; }

    public void streamInvoicePdf(InvoiceData data, OutputStream outputStream) throws JRException {
        Map<String, Object> parameters = new HashMap<>();
        parameters.put("REPORT_LOCALE", Locale.of("th", "TH"));
        JRDataSource dataSource = new JRBeanCollectionDataSource(data.getItems());

        // Fill Stage: สร้าง JasperPrint แยก Context ต่อ Request Thread
        JasperPrint jasperPrint = JasperFillManager.fillReport(invoiceReport, parameters, dataSource);

        // Export Stage: สตรีมตรงสู่ OutputStream โดยไม่เก็บ Buffer ก้อนใหญ่ใน Heap
        JRPdfExporter exporter = new JRPdfExporter();
        exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
        exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream));
        exporter.exportReport();
    }
}
Stage Engine API Input Object Output Artifact JVM Threat Architectural Mitigation
Compile JasperCompileManager .jrxml (XML Template) JasperReport / .jasper CPU 100%, Metaspace OOM Pre-compile via CI/CD, Singleton Cache
Fill JasperFillManager JasperReport + Data JasperPrint (Page Tree) Heap OOM (Bloat) Virtualizers (Disk Paging), Thread Isolation
Export JRAbstractExporter JasperPrint PDF / XLSX Binary Stream Memory Buffer Spikes Direct OutputStream Streaming

Interactive Checkpoint Quiz (20 ข้อ ครอบคลุมเนื้อหา 1.1 ทั้งหมด)

คลิกเลือกคำตอบในแต่ละข้อ ระบบจะตรวจ สอบสิทธิ์ อัปเดตคะแนนทันที และกางเฉลยเชิงลึก:

⚡ Real-time Score Tracker (Level 1.1)
คะแนน: 0 / 20 (ตอบแล้ว: 0 / 20)