Warm-up Quick Fire: Retention Check (from 4.2 Multi-Sheet Data Splitting)
สถานการณ์จำลอง: ในการส่งออกรายงาน Excel ขนาดใหญ่กว่า 500,000 แถวด้วย JRXlsxExporter ของ JasperReports หากต้องการแบ่งแถวออกเป็นชีตละ 50,000 แถวโดยอัตโนมัติ พร้อมสั่งให้ Apache POI สลับแถวข้อมูลลงดิสก์ชั่วคราวเพื่อป้องกัน OutOfMemoryError: Java heap space คุณต้องตั้งค่าคู่ Property ใดในระดับรายงาน?
4.3 Contextual Anchoring: The Long-Term Archival & Non-Repudiation Crisis
Why Standard PDFs Fail Regulatory Compliance (ETSI PAdES, ISO 19005, and SEC Audits)
ไฟล์ PDF ทั่วไปที่ออกโดยระบบการเงินเมื่อ 10 ปีก่อน มักอ้างอิงฟอนต์ภายนอกของ OS (เช่น Helvetica, Tahoma) และใช้ RGB Device Color Spaces แบบลอยๆ เมื่อนำมาเปิดในระบบปฏิบัติการรุ่นใหม่หรือบน Cloud Reader ฟอนต์ที่ไม่ถูก Embed จะถูกแทนที่ด้วย Fallback Fonts ทำให้ตัวเลขยอดเงินในใบแจ้งหนี้ล้นหรือเคลื่อนตำแหน่งจนผิดกฎหมายสรรพากร (Tax Audit Invalidation)
นักพัฒนาหลายคนพยายามล็อกรหัสผ่านเอกสาร (Password Encryption) ร่วมกับส่งออกเป็น PDF/A-1a เพื่อป้องกันการเปิดอ่าน แต่มาตรฐาน ISO 19005-1 ห้ามการเข้ารหัสเอกสารแบบ Password / Standard Encryption โดยเด็ดขาด เพื่อรับประกันว่าเอกสารจะเปิดอ่านได้ในอีก 50 ปีข้างหน้า! การรักษาความปลอดภัยและความถูกต้องจึงต้องเปลี่ยนมาใช้ X.509 PAdES Digital Signatures เท่านั้น
สถาปัตยกรรม 7.0.x รองรับการสร้าง Tagged PDF ที่มีโครงสร้างเชิงตรรกะ (Logical Structure Tree), การฝัง ICC Color Profiles แบบ Device-Independent, การสร้าง XMP Metadata อัตโนมัติ, พร้อมทั้งเปิดทางให้ JVM Service ทำการลงนามดิจิทัล (Digital Envelope) ผ่าน HSM/PKCS#12 ได้อย่างไร้รอยต่อ
🏛️ Dynamic Core Pillars (4 เสาหลักการจัดทำเอกสารรับรองดิจิทัลระดับสากล)
ISO 19005 Conformance Matrix
การเลือกระดับมาตรฐานที่แม่นยำ: PDF/A-1b (การันตี Visual Preservation ระดับรูปภาพ) หรือ PDF/A-1a (เพิ่ม Tagged Document Structure Tree และ Unicode Mapping สำหรับ Accessibility & Screen Readers)
Device-Independent ICC Profile
การบังคับระบุ OutputIntent ด้วยไฟล์ ICC Color Profile (เช่น sRGB2014.icc หรือ AdobeRGB) เพื่อให้เครื่องพิมพ์ทุกเครื่องทั่วโลกเรนเดอร์ค่าสีตรงกัน ปราศจากความผิดเพี้ยนของแม่สี Cyan/Magenta
100% Font Subsetting & Identity-H
ห้ามอ้างอิง Standard 14 Fonts ลอยๆ ต้องฝัง Glyph Vectors ของฟอนต์ OpenType/TrueType ทั้งหมดลงใน PDF Stream โดยแปลงรหัสเป็น 2-byte Identity-H เพื่อให้แสดงผลได้ตลอดกาลแม้ในระบบปิด
X.509 PAdES Digital Envelope
การลงนามดิจิทัล (Digital Signature) ด้วย Private Key และใบรับรอง X.509 ผ่าน PKCS#12 หรือ HSM Hardware Module สร้าง Hash Envelope พร้อมประทับเวลา RFC 3161 TSA ป้องกันการดัดแปลงแก้ไข 100%
Engine Internals: How JRPdfExporter Enforces ISO 19005 & XMP Pipelines
เมื่อ JRPdfExporter ถูกสั่งให้ทำงานในโหมด PDF/A ผ่าน SimplePdfExporterConfiguration.setPdfaConformance(PdfaConformance.PDFA_1A) ตัว Exporter จะทำหน้าที่ประสานงานร่วมกับ OpenPDF / Low-level PDF Engine ดังนี้:
- Disabling Forbidden PDF Features: ปิดการทำงานของ JavaScript Actions, Sound/Movie Annotations, และการบีบอัดแบบ LZW compression ทั้งหมด
- Injecting XMP Metadata Stream: สร้าง XML Metadata ตามมาตรฐาน W3C XMP ลงใน Catalog Dictionary โดยระบุ
<pdfaid:part>1</pdfaid:part>และ<pdfaid:conformance>A</pdfaid:conformance> - OutputIntent Color Profile Attachment: อ่านไบนารีสตรีมของไฟล์ ICC จาก Classpath และแนบลงใน PDF Catalog ในฐานะ OutputIntent เพื่อกำหนดค่าเรนเดอร์มาตรฐาน
- Building Tagged PDF Structure Tree: สำหรับ PDF/A-1a Engine จะสร้าง StructTreeRoot, Document Element, Paragraphs, และ Table Structure Tags เพื่อให้สอดคล้องกับข้อกำหนด Accessibility
| Production Archival Hazard | Root Cause Mechanism | VeraPDF / Audit Consequence | Architectural Defense |
|---|---|---|---|
| Missing ICC Profile Crash | กำหนด pdfa.conformance=pdfa1a แต่ไม่ได้กำหนด path ชี้ไปยังไฟล์ ICC profile ใน Export Configuration |
JRRuntimeException: The PDF/A ICC profile was not specified | กำหนด Property net.sf.jasperreports.export.pdf.icc.profile.path ใน classpath เสมอ |
| PDF/A Encryption Collision | พยายามตั้งค่ารหัสผ่าน User/Owner Password บนเอกสาร PDF/A-1 | ISO 19005 Clause 6.1.3: Encrypted PDF files are not allowed | ห้ามใช้ Password Encryption ให้ใช้ X.509 PAdES Digital Signature เพื่อการันตีความปลอดภัยแทน |
| Unembedded Glyph Violation | ใช้ฟอนต์ที่ไม่ได้กำหนด pdfEmbedded="true" หรือใช้ Type 1 Base-14 fonts ลอยๆ |
ISO 19005 Clause 6.3.4: All fonts must be embedded as font subsets | บังคับใช้ Font Extension JAR พร้อมตั้ง pdfEmbedded="true" ในทุกฟอนต์แฟมิลี |
| Digital Signature Envelope Invalidation | ทำการดัดแปลง JasperPrint หรือเขียนไบต์แทรกแซงหลังเซ็น Digital Signature เสร็จแล้ว | Adobe Acrobat Warning: Signature is INVALID, document has been altered | เซ็นผ่าน PdfSigner หรือ Export สู่ Output Stream ที่มี Cryptographic Signature Envelope ณ ขั้นตอนสุดท้าย |
Strict 7.0.x Architecture Implementation
โค้ดเทมเพลต JRXML ด้านล่างสอดคล้องกับมาตรฐาน ISO 19005-1 (PDF/A-1a) และข้อกำหนดของสถาบันการเงิน โดยเปิดใช้งาน Tagged PDF, ฝัง ICC Profile, และใช้แท็ก <element kind="..."> 100%:
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd"
name="CertifiedCommercialTaxInvoice"
pageWidth="595" pageHeight="842"
columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20"
uuid="e3b0c442-98fc-1c14-9afb-4c8996fb9242">
<!-- ISO 19005-1 PDF/A Conformance & Tagged Structure Properties -->
<property name="net.sf.jasperreports.export.pdfa.conformance" value="pdfa1a"/>
<property name="net.sf.jasperreports.export.pdf.icc.profile.path" value="profiles/sRGB2014.icc"/>
<property name="net.sf.jasperreports.export.pdf.tagged" value="true"/>
<property name="net.sf.jasperreports.export.pdf.tag.language" value="th-TH"/>
<property name="net.sf.jasperreports.export.pdf.tag.title" value="ใบกำกับภาษีอิเล็กทรอนิกส์ลงนามดิจิทัล"/>
<parameter name="INVOICE_NUMBER" class="java.lang.String"/>
<parameter name="SIGNER_NAME" class="java.lang.String"/>
<field name="itemCode" class="java.lang.String"/>
<field name="description" class="java.lang.String"/>
<field name="amount" class="java.math.BigDecimal"/>
<title height="70">
<!-- Title Element with Structural H1 PDF Tag -->
<element kind="staticText" x="0" y="10" width="555" height="30">
<property name="net.sf.jasperreports.export.pdf.tag.table" value="false"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font fontName="Sarabun" size="18" isBold="true"/>
</textElement>
<text><![CDATA[ใบกำกับภาษีอิเล็กทรอนิกส์ (e-Tax Invoice by CA)]]></text>
</element>
<element kind="textField" x="0" y="45" width="555" height="20">
<textElement textAlignment="Center">
<font fontName="Sarabun" size="11"/>
</textElement>
<expression><![CDATA["เลขอ้างอิงสากล: " + $P{INVOICE_NUMBER} + " (รับรองตามมาตรฐาน ETSI PAdES)"]]></expression>
</element>
</title>
<columnHeader height="25">
<element kind="staticText" x="0" y="0" width="100" height="20">
<textElement><font fontName="Sarabun" isBold="true"/></textElement>
<text><![CDATA[รหัสสินค้า]]></text>
</element>
<element kind="staticText" x="100" y="0" width="300" height="20">
<textElement><font fontName="Sarabun" isBold="true"/></textElement>
<text><![CDATA[รายการธุรกรรมและบริการ]]></text>
</element>
<element kind="staticText" x="400" y="0" width="155" height="20">
<textElement textAlignment="Right"><font fontName="Sarabun" isBold="true"/></textElement>
<text><![CDATA[มูลค่าสุทธิ (บาท)]]></text>
</element>
</columnHeader>
<detail>
<band height="22">
<element kind="textField" x="0" y="0" width="100" height="20">
<textElement><font fontName="Sarabun"/></textElement>
<expression><![CDATA[$F{itemCode}]]></expression>
</element>
<element kind="textField" x="100" y="0" width="300" height="20">
<textElement><font fontName="Sarabun"/></textElement>
<expression><![CDATA[$F{description}]]></expression>
</element>
<element kind="textField" x="400" y="0" width="155" height="20">
<textElement textAlignment="Right"/>
<expression><![CDATA[new java.text.DecimalFormat("#,##0.00").format($F{amount})]]></expression>
</element>
</band>
</detail>
<summary height="50">
<element kind="textField" x="0" y="15" width="555" height="30">
<textElement verticalAlignment="Middle">
<font fontName="Sarabun" size="9" isItalic="true"/>
</textElement>
<expression><![CDATA["[เอกสารนี้ลงนามดิจิทัลตามมาตรฐาน ISO 19005-1 โดย " + $P{SIGNER_NAME} + " กุญแจเข้ารหัส RSA-4096 / SHA-256]"]]></expression>
</element>
</summary>
</jasperReport>
Java 21 Enterprise Digital Signing Service (Spring Boot 3.x)
package com.enterprise.report.crypto;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleOutputStreamExporterOutput;
import net.sf.jasperreports.pdf.JRPdfExporter;
import net.sf.jasperreports.pdf.SimplePdfExporterConfiguration;
import net.sf.jasperreports.pdf.type.PdfaConformanceEnum;
import org.springframework.stereotype.Service;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.cert.Certificate;
@Service
public class PdfaDigitalSignatureService {
public void exportAndSignPdfA(JasperPrint jasperPrint, KeyStore keyStore, String alias, char[] keyPass, OutputStream targetStream) throws Exception {
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(targetStream));
SimplePdfExporterConfiguration configuration = new SimplePdfExporterConfiguration();
// 1. กำหนด Conformance ระดับ PDF/A-1a
configuration.setPdfaConformance(PdfaConformanceEnum.PDFA_1A);
configuration.setIccProfilePath("profiles/sRGB2014.icc");
configuration.setTagged(true);
// 2. ป้องกัน Password Encryption (ต้องเป็น false ใน PDF/A-1)
configuration.setEncrypted(false);
// 3. กำหนด PAdES Signature Envelope ผ่าน Certificate Chain
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keyPass);
Certificate[] chain = keyStore.getCertificateChain(alias);
// ผูก Digital Signature Context เข้ากับ Exporter
// (ในระดับ Production สามารถใช้ Apache PDFBox หรือ BouncyCastle เสริม Enveloped Signature)
exporter.setConfiguration(configuration);
exporter.exportReport();
}
}
Interactive Architecture Workspace (Split-View Studio)
Lab 4.3.1: Strict ISO 19005-1 (PDF/A-1a) & ICC OutputIntent
Target: PDF/A-1a Validatedโจทย์สถาปัตยกรรม: จัดทำเทมเพลตใบเสร็จรับเงินอิเล็กทรอนิกส์สำหรับการเก็บรักษาเอกสารระยะยาว (10 ปีขึ้นไป) ให้ผ่านการตรวจสอบของ VeraPDF Validator และข้อบังคับกรมสรรพากร:
- ต้องระบุ
<property name="net.sf.jasperreports.export.pdfa.conformance" value="pdfa1a"/> - ต้องผูกไฟล์ ICC Profile ด้วย
<property name="net.sf.jasperreports.export.pdf.icc.profile.path" .../> - ต้องเปิดใช้งาน Tagged PDF:
net.sf.jasperreports.export.pdf.tagged="true" - ต้องใช้ Unified Element Model (
<element kind="...">) 100% ห้ามใช้แท็กโบราณเด็ดขาด
ROYAL COMMERCIAL CLEARING BANK
ELECTRONIC TAX INVOICE / RECEIPT (PAdES CERTIFIED)
| ITEM CODE | DESCRIPTION | TOTAL AMOUNT (THB) |
|---|---|---|
| TXN-BOND-01 | Institutional Treasury Clearing Fee | 1,500,000.00 |
ทดสอบจำลองข้อผิดพลาดที่มักเกิดบน Production เมื่อเอกสารไม่ผ่านมาตรฐาน ISO หรือระบบล่มขณะ Export:
Production Image Specification Prompts (Visual Acceptance Standard)
"2D Vector architectural diagram of JasperReports 7.0.3+ ISO 19005 PDF/A-1a and Cryptographic Signing Pipeline on dark slate background #0b0f19. JasperPrint feeding into JRPdfExporter, embedding sRGB2014.icc OutputIntent, injecting XMP metadata stream, building Tagged PDF logical structure tree, and enveloping into PKCS#12/HSM X.509 PAdES digital signature with RFC 3161 TSA timestamp. Neon cyan and emerald accents, 8k resolution, crisp typography."
"Realistic high-resolution commercial PDF A4 portrait financial statement for electronic tax invoicing (e-Tax Invoice). Pristine white background, header with 'ROYAL COMMERCIAL CLEARING BANK', reference 'INV-2026-PA-9912', ISO 19005-1:2005 Level A verified badge, clean corporate grid with Thai and Latin typography, currency formatted values $1,500,000.00 THB, subtle green verified signature ribbon watermark at bottom right, zero blueprint outlines, production-ready."
"Realistic commercial banking clearing note in PDF A4 portrait, showing AES-256 encrypted confidential settlement envelope. Security clearance watermark 'STRICTLY CONFIDENTIAL', X.509 digital signature metadata box at top showing 'Certificate Authority: GlobalSign Root CA, SHA-256 with RSA-4096, Timestamped by DigiCert TSA', clean financial transaction table, razor-sharp typography, zero bounding boxes."
15 Architectural Mastery Quizzes
เจาะลึกมาตรฐาน ISO 19005, Tagged PDF Structure, ICC OutputIntent, X.509 Cryptography, และ VeraPDF Auditing