วันพุธที่ 5 สิงหาคม พ.ศ. 2558

JasperReport and iReport part 6

JavaBeans Set Datasource

>> ตามตำราที่ได้แนะนำไป ผมก็ทยอยทำตามตัวอย่างและประยุกต์ใช้หลังจากที่อ่านไป ก็ได้สร้าง folder งานชื่อ report8 ซึ่ง part ก่อนยังเป็น report4 อยู่เลย เห็นว่าเรื่องนี้น่าสนใจมากจึงนำมาเสนอก่อนครับ

>> ในงานของ JasperReports เราสามารถเตรียม Datasource ได้อย่างหลากหลาย ไม่ว่าจะเป็น JDBC Connection หรือ Hibernate Connection ที่ส่งมาทางโค้ดจาวา, XML Datasource, CSV Datasource, JRDataSourceProvider, MS Excel Datasource, JSON Datasource และอื่นๆอีกมากมายรวมถึงเรื่องนี้ JavaBeans ที่ถูกกำหนดให้เป็น Datasource อีกประเภทหนึ่งด้วย

>> ก็ตามประสาผู้เริ่มต้น อะไรคือ จาวาบีน (JavaBean) มันก็คือจาวาคลาสธรรมดาที่มีนิยามอยู่ไม่กี่ข้อ ได้แก่
1) จาวาคลาสนั้นต้องมี public default constructor หรือ public constructor ที่ไม่มี arguments (บางคนเรียกมันว่า parameter) ตัวอย่าง

public class Product { } //มันจะสร้าง default constructor ให้เอง

หรือ

public class Product {
public Product() { } //แบบนี้เราตั้งใจเขียน constructor เปล่าๆเอง
}

หรือ

public class Product {
public Product(String name) { } //เมื่อเขียน constructor แบบนี้
public Product() { } //ดังนั้นจะต้องเขียน constructor เปล่าให้มันด้วย
}

2) จาวาคลาสนั้นต้องใช้ accessible ได้แก่ get, set สำหรับเข้าถึงคุณลักษณะ (attributes) ของมัน หรือใช้ is หากคุณลักษณะนั้นมีชนิดเป็น boolean ตัวอย่าง

public class Product {
private String name;
public Product(String name) { this.name = name; }
public Product() { }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}

3) จาวาคลาสนั้นควรมีความสามารถ (ไม่บังคับหรอกนะ) serializable ได้ เมื่อต้องถูกจัดเก็บหรือเคลื่อนย้ายโดยการทำงานของ virtual machine ที่เป็นอิสระจาก platform ใดๆเช่น การส่งจาวาบีนข้ามเครือข่ายที่ต่างระบบปฏิบัติการ ตัวอย่างโค้ด

public class Product implements java.io.Serializable {
private String name;
public Product(String name) { this.name = name; }
public Product() { }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
}

>> อ่านเพิ่มเติมเกี่ยวกับ JavaBean conventions
https://en.wikipedia.org/wiki/JavaBeans

>> เมื่อเรามีจาวาบีน ก็ต้องมีตัวสร้างหรือเตรียมจาวาบีนให้ แน่นอนว่าเราจะสร้างจาวาคลาสมาจัดการความจำเป็นนี้ จาวาบีนทั้งหลายที่เป็นข้อมูลของเราซึ่งจะถูกส่งให้กับ JasperReports จะต้องถูกเก็บหรือส่งมาเก็บไว้ในคลาสดังกล่าวนี้ก่อน โดยมีข้อกำหนดว่ามันต้องประกาศ public static เมธอดที่สามารถคืนค่าเป็น Java Collection เท่านั้น คลาสเตรียมจาวาบีนนี้เราให้นิยามว่าเป็น โรงงาน (Factory) สมมติให้ชื่อว่า ProductFactory ดังนี้

public class ProductFactory {
public static List getProducts() {
Product p1 = new Product("product 1");
Product p2 = new Product("product 2");
List products = new ArrayList();
products.add(p1);
products.add(p2);
return products;
} //end static method
} //end class

>> เป็นความคิดที่ไม่ซับซ้อนเลยใช่ไหมล่ะ เรียบง่ายเสียด้วยซ้ำ สมมติให้จาวาบีนและคลาสโรงงานข้างต้นต่างก็อยู่ใน package ชื่อ com.sample เราจะได้เห็นภาพการเรียกใช้ package ใน iReport ด้วย เอาล่ะ ตอนนี้เรามีทรัพยากรตามนี้นะครับ (ดูรูปประกอบนะ)
- ณ D:\Workspace\Report\jasperreports\myreports\report8
มี myreport.jrxml
- ณ D:\Workspace\Report\jasperreports\myreports\report8\com\sample
มี Product.java และ ProductFactory.java


>> เปิด Command Prompt ขึ้นมา แล้วยิงไปที่
D:\Workspace\Report\jasperreports\myreports\report8\com\sample
ทำให้ .java เหล่านี้เป็น .class ก่อนด้วยคำสั่ง javac *.java เราจะได้
- Product.class
- ProductFactory.class

***สำคัญมาก! iReport เวอร์ชัน 5.6 ที่ผมใช้นี้ ทำงานไม่ได้กับจาวาเวอร์ชัน 1.8 จึงถอยไปใช้จาวาเวอร์ชัน 1.7 ทว่าเมื่อผมสั่งสร้างจาร์บนสภาพแวดล้อมจาวาเวอร์ชัน 1.7 มันกลับใช้เป็น datasource ไม่ได้ (มีปัญหาความไม่เข้ากันสืบเนื่องมาจากตัวโหลดคลาส) จึงต้องถอยไปสร้างจาร์บนจาวาเวอร์ชัน 1.6 แทน (JDK 1.8 ซึ่งมี major version 52 และ JDK 1.7 ซึ่งมี major version 51 ไม่สามารถใช้ได้กับ iReport version 5.6 ต่างจาก JDK 1.6 ซึ่งมี major version 50 สามารถใช้เตรียม .jar กระทั่งถึง fill data ลง report ดังนั้นผมจะบอกว่าขณะนี้ผมใช้ JRE และ JDK เวอร์ชัน 1.6 นะครับ)

>> ยังใช้ Command Prompt เดิม ถอยมาที่
D:\Workspace\Report\jasperreports\myreports\report8
สร้าง .jar จากประดา .class ของเราโดยอ้างถึง package ด้วย ผมตั้งชื่อจาร์ตัวอย่างนี้ว่า ProductBeanDataSource.jar ร่ายคำสั่งสร้างจาร์ขั้นพื้นฐานคือ
jar cf (ดูลำดับวิธีการได้ในรูป) ตามด้วยชื่อพร้อมสกุลของจาร์ ตามด้วยประดา .class เจ้ากรรม โดยอาศัยการเคาะหนึ่งทีเป็นการคั่นคำสั่ง

และถ้าอยากจะดูว่าจาร์ที่ได้ไส้ข้างในเป็นอย่างไรก็
jar tf ตามด้วยชื่อจาร์นั้น
อย่าลืมนะครับว่าจาวาสำคัญชื่อไฟล์กับ public class ที่ถูกเขียนอยู่ภายใน ดังนั้นพิมพ์ใหญ่พิมพ์เล็กอย่าได้ตกหล่นเทียว


>> เรื่องนี้คือ JavaBean กับ Datasource เราจึงใช้การเชื่อมต่อแบบ JavaBeans set datasource ซึ่งต้องใช้ไฟล์จาร์เป็นวัตถุดิบ และเราก็ได้เตรียมเสร็จแล้ว

>> ณ iReport เพิ่ม ProductBeanDataSource.jar เข้ามาเลยสิครับ ตรงไปที่ Tools > Options > แท็บ Classpath กดปุ่ม Add JAR ตามรูป



>> ได้แล้วก็ตรงไปที่ไอคอน datasource เปิดหน้าต่าง Connections/Datasource กดปุ่ม New


>> เลือก JavaBeans set datasource กดปุ่ม Next


>> ตั้งชื่อ datasource ผมตั้งว่า TestProductBeanDataSource
- ระบุ factory คลาสไปที่ com.sample.ProductFactory ที่เราได้สร้างไว้
- ระบุ public static method ชื่อ getProducts
- ทดสอบการเชื่อมต่อ กดปุ่ม Test (ขอย้ำว่าขณะนี้ทำงานบนสภาพแวดล้อม JRE 1.6)


>> กดปุ่มไอคอน Query เลือกแท็บที่ชื่อ JavaBean Datasource ในช่อง Class name บอกมันให้หาบีนที่ชื่อ com.sample.Product กดปุ่ม Read attributes เราจะพบกับ attribute ที่เราได้สร้างไว้ นั่นคือ name (สร้างไว้เยอะก็เห็นเยอะ) ตอนนี้อยากทำงานกับ attribute ตัวไหนก็คลิกแล้วกดปุ่ม Add selected field(s) ด้านล่าง มันจะไปสร้าง field ชื่อเดียวกันนี้ให้ครับ อย่าลืมปิดท้ายด้วยการกดปุ่ม OK


>> ลาก Text Field ตัวหนึ่งเพื่อทดสอบผลลัพธ์ มาวาง ณ ส่วนใดๆของรายงาน ผมเลือกส่วน Detail 1 คลิกขวาที่มันเพื่อเลือก Edit expression


>> อะไรก็ตามที่ถูกเขียนไว้ใน Expression editor ให้ลบออก แล้วมองหา name ของเราได้จากหมวด Fields เจอแล้วดับเบิลคลิกที่ name สองครั้ง มันจะถูกเขียนใน Expression editor เป็น $F{name} กดปุ่ม Apply


>> สุดท้ายแล้วไป Preview กันเลย เย้ มาแล้วๆ คืนนี้ดึกแล้ว ฝันดีครับเพื่อนๆ

1 ความคิดเห็น:

  1. เป็น report writer ที่ชอบมากตัวหนึ่งเลย เพราะสามารถคำนวณข้อมูลขึ้นมา แล้วยิงเข้า report writer โดยไม่ต้องดึงข้อมูลมากจาก java bean, database หรือ csv file

    ตอบลบ