วันพฤหัสบดีที่ 30 กรกฎาคม พ.ศ. 2558

ตามรอย JasperReports 3.6 Development Cookbook พาทำ Dynamic Titles

>> รันด้วย Ant สู่ Servlet และขณะนี้เราจะกลับมายังพื้นฐานอีกครั้งด้วยหนังสือพาทำงานแบบเป็นชิ้น นามว่า JasperReports 3.6 Development Cookbook ซึ่งครั้งนี้ขอยกสักตัวอย่างหนึ่งที่อยู่ตอนต้นของหนังสือมาลองทำตามครับ

>> ฐานข้อมูลเราจะใช้โปรแกรม PostgreSQL (อ่านว่า โพสต์เกรสคิวเอล) สามารถดาวน์โหลดได้ฟรีที่
http://www.postgresql.org/download/
ผมเลือกเป็นเวอร์ชัน Windows แบบตัวช่วยติดตั้งให้เลย และติดตั้งตามค่า default ทุกประการ ยกเว้นเครื่องมือสุดท้ายของมัน (ติดตั้งโปรแกรมหลักเสร็จ มันจะถามให้ติดตั้งอะไรสักอย่าง จำชื่อไม่ได้ ซึ่งผมตอบปฏิเสธไป)

>> ตัวชิ้นงานที่หนังสือใช้อ้างอิง สามารถโหลดได้ที่นี่
http://www.packtpub.com/code_download/5244
เป็น .zip ไฟล์ชื่อ 0769_Code.zip เนื้อหาด้านในประกอบด้วยงานแต่ละชิ้นในแต่ละบท สำหรับบทที่ 1 นี้มี Task1 ถึง Task7 พร้อมกับวิธีติดตั้ง PostgreSQL, สร้างฐานข้อมูลและเพิ่มข้อมูลลงไปในตาราง

>> เมื่อติดตั้ง PostgreSQL ผมก็เปิดโปรแกรมควมคุมในระดับผู้ควบคุมขึ้นมา (pgAdmin3.exe) โดยมันถูกเก็บไว้ที่นี่
C:\Program Files\PostgreSQL\9.4\bin\pgAdmin3.exe

>> ภายใต้หน้าต่าง Object browser มองหา Server Groups/Servers/PostgreSQL 9.4 (localhost:5432)/Databases (ระหว่างขั้นตอนนี้มันจะถามหา password ก็ใส่ไปให้ตรงกับที่ได้ตั้งไว้ตอนติดตั้งโปรแกรมนะครับ) สร้างฐานข้อมูลใหม่ก่อน ด้วยการคลิกขวาที่ไอคอนชื่อ Databases ข้างต้น ตั้งชื่อว่า jasperdb1 ตามตำรา


>> ต่อมา (วิ่ง) ก็สร้างตารางก่อน โดยการมองหาสิ่งที่เรียกว่า PSQL Console สำหรับเวอร์ชัน 9.4 (ปี 2558 หรือ 2015) มันถูกซ่อนไว้ใกล้กับไอคอนรูปจิ๊กซอว์สีออกน้ำตาลอ่อนกับเขียวด้านล่างเมนูบาร์ (ดูรูปประกอบ) เปิดมันขึ้นมาจะเป็นหน้าต่างสีดำครับ

***หมายเหตุ หากไม่สามารถคลิกเปิด PSQL Console ได้ แสดงว่าเรายังไม่ได้เลือกฐานข้อมูล (ที่เพิ่งสร้าง) ให้ไปคลิกซ้ายที่ฐานข้อมูล jasperdb1 หนึ่งที เพื่อจะสร้างตารางในนี้

>> ตารางและข้อมูลจะถูกสร้างและเพิ่มตามลำดับด้วยคำสั่งภายในไฟล์ชื่อ copySampleDataIntoPGS.txt ซึ่งเนื้อหาที่เราต้องการคัดลอกก็คือ

CREATE TABLE "CustomerInvoices" (
"InvoiceID" integer NOT NULL,
"CustomerName" varchar(80) NOT NULL,
"ProductName" varchar(80) NOT NULL,
"InvoicePeriod" varchar(20) NOT NULL,
"InvoiceValue" real NOT NULL,
CONSTRAINT CustomerInvoices_pkey PRIMARY KEY ("InvoiceID")
);

INSERT INTO "CustomerInvoices" VALUES (1001, ’Packt Publishing’, ’Packing Material’, ’Mar09’, 5020.25);
INSERT INTO "CustomerInvoices" VALUES (1002, ’Packt Publishing’, ’Offset Paper’, ’Apr09’, 3000.50);
INSERT INTO "CustomerInvoices" VALUES (1003, ’Packt Publishing’, ’Offset Paper’, ’Mar09’, 4150.05);
INSERT INTO "CustomerInvoices" VALUES (1005, ’Packt Publishing’, ’Packing Material’, ’Mar09’, 2050.00);
INSERT INTO "CustomerInvoices" VALUES (1004, ’Packt Publishing’, ’Packing Material’, ’Mar09’, 2050.00);
INSERT INTO "CustomerInvoices" VALUES (1006, ’Bob’, ’JapserReports Cookbook’, ’Mar09’, 50.00);

ได้แก่การสร้างตารางชื่อ CustomerInvoices พร้อมกับข้อมูล 6 รายการ เป็นของพี่ชายที่ชื่อ Packt Publishing ทั้งสิ้น ให้เราคัดลอกทั้งหมดนี้แล้วนำไปวางลงใน PSQL Console (ถ้าวางไม่เป็น หลังจากคัดลอกแล้วให้คลิกขวาที่กรอบหน้าต่างด้านบน จะปรากฏเมนูลอยออกมา ให้เลือก Edit ต่อด้วย Paste) มันจะทำงานสร้างตารางและเพิ่มข้อมูลให้เลยทันที

รูปด้านล่างนี้แสดงให้เห็นว่ามีตารางและข้อมูลเกิดขึ้น มองดูที่ Schemas/Tables


>> ทีนี้มาทดสอบดูว่าเราจะสามารถ query ข้อมูลที่ว่าผ่านทาง iReport ได้อย่างไร ครับ ก่อนอื่นเตรียม report view หรือหน้าตาของรายงานเสียก่อน
- ให้เปิด iReport ขึ้นมา
- สร้างไฟล์ชื่อ myreport.jrxml ไว้ ณ
D:\Workspace\Report\jasperreports\myreports\report4
- จากนั้นลาก Text Field มาวางภายในพื้นที่ของ Title

- มองหาหน้าต่าง Report inspector (หาไม่เจอให้คลิกเลือกเปิดที่เมนู Window) มองหากลุ่ม Parameters หากสงสัยว่ามันคืออะไรให้ข้ามไปก่อนนะ
- คลิกขวาที่กลุ่ม Parameters แล้วเลือก Add Parameter เราจะได้ parameter1 มา (อยู่ท้ายๆ)

- เปลี่ยนชื่อ parameter1 เป็น CustomerName ได้โดยคลิกที่ parameter1 ก่อนแล้วมองหาหน้าต่าง Properties ตรงช่อง Name ก็ใส่ชื่อ CustomerName ลงไปไงล่ะ

- ทีนี้กลับไปคลิกขวาที่ Text Field ตัวก่อนหน้านี้เพื่อเปลี่ยนเงื่อนไขของมัน เลือก Edit expression จะปรากฏหน้าต่าง Expression editor จงลบ $F{field} ทิ้งไป แล้วมองหากลุ่ม Parameters ด้านล่างซ้ายของหน้าต่างเดียวกันนี้ เลือกเสร็จไปดูช่องตรงกลาง ใช้เม้าส์เลื่อนหาพารามิเตอร์ที่เราเพิ่งเปลี่ยนชื่อไป นั่นก็คือ CustomerName ดับเบิลคลิกมัน จะได้ $P{CustomerName} มาแปะไว้ตรงช่อง expression ของ Expression editor เสร็จกิจกดปุ่ม Apply ด้านล่าง


>> ติดต่อฐานข้อมูลเพื่อใช้ทดสอบ query ผ่านทางปุ่ม Report Datasources (ดูรูปประกอบ) แล้วกดปุ่ม New เพื่อสร้าง connection ใหม่ไปยัง jasperdb1

- หน้าต่าง Datasource เลือก Database JDBC connection กด Next

- หน้าต่าง Database JDBC connection ระบุรายละเอียดลงไปดังนี้
-- Name อะไรก็ได้ ผมใส่เป็น PostgreSQL
-- JDBC Driver เลือก PostgreSQL (org.postgresql.Driver)
-- Username โดย default คือ postgres
-- Password ใส่ไป
-- กดปุ่ม Test สักหนเพื่อทดสอบว่าติดต่อฐานข้อมูลได้หรือไม่ ซึ่งต้องได้เท่านั้น
-- กดปุ่ม Save


>> กดปุ่มเขียน query ของรายงาน (ดูรูปประกอบ) แล้วเขียน query ลงไปดังนี้
SELECT * FROM "public"."CustomerInvoices" WHERE "public"."CustomerInvoices"."CustomerName" = $P{CustomerName}

มันหมายถึงดึงทุกฟิวล์จากตาราง CustomerInvoices เมื่อชื่อของลูกค้าตรงกับพารามิเตอร์ที่เราจะระบุส่งให้ในอนาคตอันใกล้นี้ เสร็จแล้วกดปุ่ม OK


>> กดปุ่ม Preview ของ iReport มันจะถามหาค่าของพารามิเตอร์ชื่อ CustomerName ก็ให้ใส่ไปว่า Packt Publishing (ต้องตรงตามนี้นะไม่งั้นไม่ออก)

>> เย้! รายงานมาแล้ว

*** หมายเหตุ ผมไม่เข้าใจว่าทำไมตำราให้ทำยากขนาดนี้ เพราะหัวข้อคือ Dynamic Titles หรือก็คือหัวเรื่องสามารถเปลี่ยนแปลงได้ในระหว่างที่รายงานนี้กำลังถูกประมวลผล (ซึ่งจัดอยู่ในขั้นตอน fill ข้อมูล) อันที่จริงเราแค่แปะ Text Field ไว้อันหนึ่ง สร้างพารามิเตอร์มาผูกแล้ว preview เลยก็ได้ ใส่อะไรให้พารามิเตอร์มันก็ออกอันนั้นแหละ

>> อ่านไปไกลแล้ว แต่ทดลองทำไม่มากเท่า หัวข้อไหนน่าสนใจจะมาทดลองทำและเล่าสู่กันใหม่เป็นกรณีศึกษาและส่งเสริมการอ่านทั้งส่งเสริมการซื้อ Cookbook อ่านกันอีกด้วย (ที่จริงผมได้รับสืบทอดมาอีกที) คืนนี้ดึกมากแล้ว สวัสดีครับ

วันอาทิตย์ที่ 26 กรกฎาคม พ.ศ. 2558

ทบทวน Hibernate หลังจากทิ้งไปสองปีครึ่ง



ทบทวน Hibernate หลังจากทิ้งไปสองปีครึ่ง
part 1: กลับมาเถิดความทรงจำที่รัก

>> ฐานข้อมูลกับสารพัดทฤษฎีของมันเป็นเรื่องที่ผมรักน้อยที่สุดในประดาศาสตร์วิทยาการคอมฯ เพราะมันไม่ได้โค้ด? ไม่สิ บางคนบอกผมว่า มันก็ภาษา SQL นะพี่

>> ก่อนไปเกณฑ์ทหารสักหกเดือนได้ที่เคยเรียนเรื่องนี้ควบคู่กับการโค้ดจาวา โดยอาศัยเครื่องมือไลบรารี่ที่ชื่อ Hibernate คืนที่ผ่านมาผมพยายามทบทวนเพื่อนำมันกลับมาจากอดีต นั่นยิ่งกว่าคลาน...

>> ผมเริ่มด้วยการศึกษา SQLite ในแง่ของภาษา SQL พื้นฐาน พี่ที่ทำงานมาเจอเข้าก็ถามว่า อ่าวเอ็งจะเขียน Android เหรอ ผมตอบไม่ครับ ผมแค่ลืม นั่นแหละยิ่งกว่าคลาน...

>> ผมศึกษา Hibernate จากเว็บไซต์นี้
http://www.tutorialspoint.com/hibernate/index.htm

>> Hibernate ในที่นี้คือความคิดหลักการแก้ปัญหาด้วยวิธีการ Object-Relational mapping (ORM) จับจาวาคลาสเข้ากับตารางในฐานข้อมูล แปลงชนิดข้อมูลของภาษาจาวา (java data type) ไปสู่ชนิดข้อมูลของ SQL (sql data type) แล้วทำไมต้องใช้ Hibernate?

>> เพราะ Hibernate เป็นฟีเจอร์หนึ่งที่ออกแบบมาเพื่อช่วยให้เราใช้งานแบตเตอรี่ของโน้ตบุ๊คได้นานขึ้น? ไม่ใช่แล้ว ผิดเรื่อง

>> ร้อยเปอร์เซ็นต์สำหรับงานที่เกี่ยวข้องกับฐานข้อมูลที่ต้องใช้ภาษาจาวาจัดการก็จะมีการเขียน sql สั่งทำโน่นนี่นั่น เช่น ไหนเอารายชื่อสินค้ามาดูหน่อย ปรับปรุงราคาสินค้าหน่อยสิ เพิ่มสินค้าชิ้นนี้หรือยัง นั่นๆสินค้านี่หมดสต๊อกแล้วช่วยเอาออกจากรายการโปรโมชั่นที สารพัด ฯลฯ หรือเรียก sql ที่ถูกสร้างไว้แล้วในลักษณะโมดูลมาทำงานเป็นต้น โปรแกรมเมอร์ก็ต้องมานั่งเขียน sql หรือขอ sql จากทีมหรือผู้ที่มีหน้าที่เขียนให้โดยตรงมาใช้ โค้ดจาวาของโปรแกรมเมอร์ผู้น่าสงสารก็จะเต็มไปด้วยคำสั่ง sql มากมาย (ที่ถูกจัดระเบียบเป็นอย่างดี)

>> ฮั่นแน่ยังมีหลักการ CRUD ช่วยได้ เขียนแยก sql ออกเป็นส่วนๆ ได้แก่ create, read, update และ delete แล้วส่งออบเจ็กต์จาวาเข้าไป มันก็โอเครนะ แต่จะดีกว่าไหมในเมื่อเราก็เขียนภาษาจาวาอยู่แล้วและต่อจากนี้สามารถกำหนดให้ออบเจ็กต์เหล่านั้นทำงาน sql ได้เลยโดยปราศจากโค้ด sql อันน่าสะพรึงกลัว โฮ้อะไรกันนี่! สวดยอด! อีกขีดขั้นของ high-performance Object/Relational persistence ก็โม้ไปมันส์ๆ

>> ครับ ก็หาเครื่องมือ (tool) มาใช้ หนึ่งในความคิดพัฒนาระบบ object-oriented ให้เข้าใจ relational database ก็คือวิธีการ ORM และหนึ่งชื่อจาวาคลาสไลบรารี่ที่ implement (ทำให้เกิดขึ้นจริง หรือนำมาใช้) ก็คือ Hibernate

>> ตามไปโหลดประดา .jar ไฟล์ก่อนได้ที่
http://www.hibernate.org/downloads
ของผม ณ ขณะนี้คือ
hibernate-release-4.3.10.Final

>> เปิด Eclipse (ของผมคือรุ่น Luna) สร้างจาวาโปรเจ็กต์ชื่อ ProteinTracker บอกแล้วว่ารื้อฟื้นความจำ คือยังเก็บโปรเจ็กต์เก่าๆที่รุ่นพี่เคยสอนไว้อยู่ ก็เลยต้องโค้ดใหม่แบบลอกทั้งดุ้น
- สร้าง main class ชื่อ Program
- RDBMS ที่ใช้คือ MySQL เปิดด้วย MySQL Workbench
- ฐานข้อมูล (มันเรียกว่า schema) ตั้งชื่อว่า protein_tracker
- สร้างตารางชื่อ users ประกอบไปด้วย id, name, total และ goal
- กลับมาสร้าง POJO หรือก็คือจาวาคลาสธรรมดาชื่อ User ให้ประกอบไปด้วย id, name, total และ goal
- สร้าง xml configuration file ในฝั่ง Hibernate ชื่อ hibernate.cfg.xml ใช้ควบคุมทั้งโปรเจ็กต์
- ต่อด้วย User.hbm.xml ให้ config จาวาคลาสเข้ากับตารางในฐานข้อมูลข้างต้น ในที่นี้ก็คือคลาส User กับตาราง users
- ลงทะเบียนให้ hibernate.cfg.xml รู้จัก User.hbm.xml
- สร้างออบเจ็กต์จากคลาส User ระบุชื่อเป็น I am Phai Panda แล้วสั่งให้บันทึกลงฐานข้อมูลก่อนจะ close session
- รัน
- ไปดูที่ฐานข้อมูล เย้ ข้อมูลมาแล้ว เย้ๆ

>> กระบวนการพื้นฐานที่สุดที่ทำให้เห็นภาพว่า Hibernate ด้วยจาวาโค้ดหน้าตาเป็นอย่างไรก็มีขั้นตอนดังที่ได้เล่าไปครับ part ต่อๆไปค่อยมาลงรายละเอียดกันว่าแต่ละส่วนคืออะไร ทำงานอย่างไร (ถ้าผมแปลภาษาอังกฤษถูกนะ ฮ่า)

>> ขอบคุณ Wiki สำหรับนิยาม CRUD
https://en.wikipedia.org/wiki/Create,_read,_update_and_delete

ชวนคุยจาวา part 14-2 : มาสร้าง DocumentLocker กันเถอะ

Java OOP Example
: DocumentLocker part 2/2

>> ต่อจาก part แรกที่ว่า หากจะให้เอกสารของเราสามารถใส่รหัสป้องกันเข้าไปด้วย ด้วยจาวาคลาสเท่าที่มีจะทำได้อย่างไร หนึ่งในหลายวิธีการที่ทำให้บรรลุเป้าหมายและเป็นที่ยอมรับ นั่นก็คือการใช้ decorator pattern ครับ

>> decorator pattern ว่าด้วยการเพิ่มสิ่งใหม่ลงไปยังสิ่งเดิมที่มีอยู่ โดยไม่กระทบโครงสร้างเดิมของสิ่งเดิมนั้น ในที่นี้คือ ผมมีเอกสาร (document) และผมจะกำหนดรหัส (password) ให้กับมันสำหรับใครก็ตามที่ต้องการอ่านหรือเขียนเอกสารเจ้ากรรม นั่นแสดงว่าผมต้องการ input สองอย่าง
1) document object
2) password string
ดังนี้ครับ

public AbstractSecurityDocument(Document document, String password)

ข้างต้นนี้คือ constructor ของคลาส AbstractSecurityDocument ซึ่งเป็น abstract จัดเตรียมไว้ให้สืบทอด และมันยังคงต้อง read และ write ได้อย่างเดิม จึง implement เจ้า interface ที่ชื่อ Document ให้เป็นกติกาบังคับ สุดท้ายก็เพิ่มบริการสำหรับตรวจสอบรหัสว่าถูกต้องหรือไม่ (check password) ดังนี้ครับ

public abstract class AbstractSecurityDocument implements Document {
private final Document document;
private final String password;
protected final Messager messager;

public AbstractSecurityDocument(Document document, String password) {
this.document = document;
this.password = password;
messager = new Messager();
}

@Override
public String read() {
return document.read();
}

@Override
public void write(String content) {
document.write(content);
}

public boolean checkPassword(String yourPassword) {
return password.equals(yourPassword);
}
}

>> ไม่รอช้า สร้างอีกคลาสชื่อ SecurityDocument มาขยาย (สืบทอด) มันซะเลย โดยใช้บริหารตรวจสอบรหัสผ่านที่ได้เอ่ยไป เป็นเครื่องมือตรวจสอบว่า ผู้ที่ต้องกรอ่านหรือเขียนเอกสารเจ้ากรรมได้ใส่รหัสเข้ามาถูกต้องหรือไม่ ผ่านบริการที่ชื่อ enterPassword ครับ

public class SecurityDocument extends AbstractSecurityDocument {
private String yourPassword;

public SecurityDocument(Document document, String password) {
super(document, password);
}

@Override
public String read() {
if(checkPassword(yourPassword)) {
return super.read();
} else {
messager.showException("You don't have permission to read this document");
return "";
}
}

@Override
public void write(String content) {
if(checkPassword(yourPassword)) {
super.write(content);
} else {
messager.showException("You don't have permission to write this document");
}
}

public void enterPassword(String yourPassword) {
this.yourPassword = yourPassword;
}
}

>> และแล้วก็ทดสอบ โดยขอเอกสารมาจากโรงงาน จากนั้นใส่รหัสล็อคไว้ก่อนด้วย SecurityDocument ตามนี้

public class Program {
public static void main(String[] args) {
DocumentFactory factory = new DocumentFactory();

Document readOnlyDocument = factory.get(DocumentSpec.READ_ONLY, "AAA");
Document readWriteDocument = factory.get(DocumentSpec.READ_WRITE, "BBB");

SecurityDocument securityReadOnlyDocument = new SecurityDocument(readOnlyDocument, "1234");
SecurityDocument securityReadWriteDocument = new SecurityDocument(readWriteDocument, "1234");

securityReadOnlyDocument.enterPassword("4321");
securityReadOnlyDocument.write("XXX");
System.out.println(securityReadOnlyDocument.read());
System.out.println("--------------------");

securityReadWriteDocument.enterPassword("1234");
securityReadWriteDocument.write("YYY");
System.out.println(securityReadWriteDocument.read());
}
}

เอกสาร AAA ที่อ่านได้อย่างเดียวใส่รหัสไว้เช่นเดียวกับเอกสาร BBB ที่ทั้งอ่านและเขียนได้ แต่เอกสาร AAA เมื่อพยายามจะอ่านและเขียน XXX ลงไปโดยทดสอบใส่รหัสผิดปรากฏว่าไม่สามารถอ่านหรือเขียนได้เลย (ปกติมันก็เขียนไม่ได้อยู่แล้ว ตอนนี้อ่านไม่ได้ด้วยเพราะรหัสไม่ถูก) ต่างจากเอกสาร BBB เมื่อพยายามจะอ่านและเขียน YYY ลงไปโดยได้ใส่หรัสถูกต้อง ปรากฏว่าสามารถเขียนและอ่านออกมาได้ครับผม เชิญชมผลลัพธ์

Exception: You don't have permission to write this document
Exception: You don't have permission to read this document

--------------------
YYY

>> นี่แหละจึงเรียกว่าเรื่องนี้ว่า DocumentLocker สำหรับคืนนี้ฝันดีครับ

ชวนคุยจาวา part 14-1 : มาสร้าง DocumentLocker กันเถอะ

Java OOP Example
: DocumentLocker part 1/2

>> ได้หยิบยืมหนังสือของรุ่นน้องมาอ่าน เป็นหนังสือเก่าแล้ว หลายคนชอบ หลายคนว่าซับซ้อน หลายคนไม่เห็นคุณค่าดราม่าไปต่างๆนานา แต่สำหรับผมที่ต้องการตัวอย่าง ขึ้นชื่อว่าเป็นตัวอย่างไม่ว่าจะดีหรือแย่ ก็ดีกว่าไม่มีเลย สำคัญคือมันแจ๋วมากครับ

>> DocumentLocker ว่าด้วยเรื่องเอกสาร (document) ที่แบ่งออกเป็นสองประเภท
1) อ่านได้อย่างเดียว (read only)
2) กับอ่านและเขียนได้ (read write)
แน่ล่ะว่าเราต้องกำหนดกติกาของเอกสารขึ้นมาก่อน กติกาที่ว่านี้ก็คือ interface ครับ ให้ชื่อว่า Document เห็นไหม คิดถึงการออกแบบ พาไปหา interface ก่อนเลย

public interface Document {
String read();
void write(String content);
}

เจ้านี่ทำได้สองอย่าง อ่าน (read) กับเขียน (write) ตามแนวคิดแป๊ะซะ

>> ในระบบต้องมีเรื่องการแจ้งเตือนหรือแจ้งความผิดพลาดด้วย เผื่อว่าผู้ใช้ (user) บางคนเลือกเอกสารที่อ่านได้อย่างเดียวแล้วพยายามจะเขียนอะไรลงไป? (เขาทำแบบนั้นไปทำไมหว่า?) งั้นสร้างคลาสข้อความออกมารองรับสิ่งนี้ก็แล้วกัน

public class Messager {
public void showException(String exception) {
System.out.println("Exception: " + exception);
}

public void showNotification(String notification) {
System.out.println(notification);
}
}

คลาสนี้ทำอะไร คลาสนี้นำเสนอข้อความสองประเภท
1) exception หรือความผิดพลาด (บอกเลยว่าความผิดพลาดคนละเรื่องกับ error นะครับ เรารู้ว่าผิดพลาดยังแก้ไขได้ แต่ถ้า error นี่เงิบนะครับบอกตง)
2) notification หรือแจ้งให้ทราบ อย่างนั้นอย่างนี้ อะไรงี้

>> อยากให้เอกสารของเราแจ้งเตือนหรือแจ้งความผิดพลาดนานาประการ ก็สร้างของกลางๆเอาไว้สืบทอดต่อไป เพื่ออะไร? เพื่อเตรียมทรัพยากรให้ผู้สืบทอดหรือคลาสที่จะมาขยายสามารถนำไปใช้ได้เลยไงล่ะ

public abstract class AbstractDocument implements Document {
protected String content;
protected final Messager messager;

public AbstractDocument(String content) {
this.content = content;
messager = new Messager();
}
}

จะเห็นว่าคลาสนี้บรรจุคลาส Message พร้อมกับต้องการให้คลาสสืบทอดใส่เนื้อหา (content) เอกสารเข้ามา

>> เอกสารที่สามารถอ่านได้อย่างเดียว ตั้งชื่อว่า ReadOnlyDocument สืบทอดจากคลาส AbstractDocument ข้างต้นจ้า

public class ReadOnlyDocument extends AbstractDocument {

public ReadOnlyDocument(String content) {
super(content);
}

@Override
public String read() {
return content;
}

@Override
public void write(String content) {
messager.showException("This is read-only ducument, you cannot write to it.");
}
}

เมื่อพยายามจะเขียนเนื้อหาเข้าไปใหม่ ซึ่งตัวเอกสารไม่อนุญาต ก็จะได้ exception กลับไปว่า เอกสารนี้ไม่สามารถเขียนเนื้อหาเข้าไปนะจ๊ะ

>> เอกสารที่สามารถอ่านและเขียนได้ในหนึ่งเดียว ตั้งชื่อว่า ReadWriteDocument สืบทอดจากคลาส AbstractDocument เช่นกัน

public class ReadWriteDocument extends AbstractDocument {

public ReadWriteDocument(String content) {
super(content);
}

@Override
public String read() {
return content;
}

@Override
public void write(String content) {
this.content = content;
}
}

>> ดูเหมือนว่าทุกอย่างพร้อมทดสอบกันแล้ว แต่...เรามาสร้างตัวช่วยสร้างเอกสารกันดีกว่า เพื่อความสะดวกสะบาย เอาเป็นโรงงานผลิตเอกสาร ที่เพียงเราต้องการเอกสารประเภทไหน ก็แค่ระบุลงไปพร้อมกับเนื้อหาของเอกสารนั้น ใช่ครับผม กรณีนี้เข้าข่ายของ factory pattern

public class DocumentFactory {
public Document get(DocumentSpec documentSpec, String content) {
Document document = null;
switch (documentSpec) {
case READ_ONLY:
document = new ReadOnlyDocument(content);
break;
case READ_WRITE:
document = new ReadWriteDocument(content);
}

return document;
}
}

ส่วนค่าคงที่ที่ใช้ก็คือ enum ดังนี้จ๊ะ

public enum DocumentSpec {
READ_ONLY, READ_WRITE
}

>> สุดท้ายเราจึงสร้างคลาสทดสอบ โดยขอเอกสารจาก factory แล้วพยายามเขียนเนื้อหาลงไป ตามด้านล่างเลยฮับ

public class Program {
public static void main(String[] args) {
DocumentFactory factory = new DocumentFactory();

Document readOnlyDocument = factory.get(DocumentSpec.READ_ONLY, "AAA");
Document readWriteDocument = factory.get(DocumentSpec.READ_WRITE, "BBB");

readOnlyDocument.write("CCC");
System.out.println(readOnlyDocument.read());
System.out.println("--------------------");

readWriteDocument.write("CCC");
System.out.println(readWriteDocument.read());
System.out.println("--------------------");
}
}

>> ผลลัพธ์คือเอกสารที่อ่านได้อย่างเดียวมีเนื้อหาเป็น AAA แสดง exception ออกมา ส่วนเอกสารที่อ่านและเขียนได้มีเนื้อหาเป็น BBB เนื้อหาจะถูกเปลี่ยนเป็น CCC ครับ ตามนี้

Exception: This is read-only ducument, you cannot write to it.
AAA
--------------------
CCC
--------------------

>> part ต่อไปของเรื่องเดียวกันนี้จะเพิ่มความสามารถให้เอกสารทั้งสองประเภทสามารถเข้ารหัสได้ คือมีรหัสผ่าน ถ้าต้องการจะใช้ไม่ว่าจะอ่านหรือเขียนก็ต้องใส่รหัสให้ถูกต้องก่อน ถือว่าเป็นหัวใจของเรื่องนี้ คืนนี้สวัสดีครับ

วันเสาร์ที่ 25 กรกฎาคม พ.ศ. 2558

JasperReport and iReport part 4-3



สวัสดีชาวโลก กับ PDF Online ด้วย Servlet (จบภาค)

>> ตามคำมั่นที่ให้ไว้ว่าจะมาจัดการเรื่องภาษาไทยให้ เมื่อ report จาก part ก่อนไม่แสดงภาษาไทย (ภาษาอื่นๆก็เช่นกัน เช่น ญี่ปุ่น จีน ฯลฯ) สิ่งนี้คือคุณสมบัติ fontName ครับ ในโปรแกรม iRepot เพื่อนๆจะเห็นว่ามันสามารถ review เห็นภาษาไทยปกติทุกอย่างเมื่อกำหนด fontName ทว่าไฉนแปลงเป็น PDF แล้วกลับกลายเป็นไม่รู้จัก

>> เมื่อกำหนด fontName และเลือกภาษาไทยจากในเครื่อง (ผมหมายถึงเครื่องคอมฯของเพื่อนๆ ซึ่งมีฟอนต์เก็บไว้ ณ C:\Windows\Fonts) ภาษาไทยที่เลือกนี้ไม่ได้ติดไปด้วยนะครับ เพื่อนๆจะต้องแพ็กภาษาไทยหรือฟอนต์ใดๆที่ต้องการนี้เป็น .jar แล้ว build มันเข้ากับตัวโปรเจ็กต์เสียก่อน (ผมคิดว่าคงมีวิธีอื่นๆอีก แต่ตอนนี้ทราบแต่วิธีนี้เท่านั้น ขออภัยด้วยจริงๆ)

>> ฟอนต์ราชการไทย จำไม่ผิดน่าจะเป็น TH Sarabun PSK ขนาดปกติคือ 16 หรือ TH Niramit AS หากสนใจแนะนำดาวน์โหลดได้ที่
http://www.f0nt.com/release/13-free-fonts-from-sipa/

>> ข้อสำคัญฟอนต์พวกนี้ต้องเป็นไฟล์ที่มีนามสกุล .ttf นะครับ ผมเลือกตัวนี้มาทดสอบล่ะกัน Lomoor-Renew.ttf
http://www.f0nt.com/release/lomoor/

>> เปิด iReport ตัวเก่งขึ้นมาแล้วมองหาเมนู Tools เลือก Option ที่กลุ่มชื่อ iReport แท็บ Fonts เพื่อนๆจะมองเห็นปุ่ม Install Font กดเลยครับ ไปนำเข้า Lomoor กัน

>> เมื่อเข้าสู่หน้าต่าง Font Installation หลังจากเลือกฟอนต์มา มันจะให้เลือกไปที่ฟอนต์แบบหน้า (Bold), แบบเอียง (Italic) และทั้งหนาทั้งเอียง (แหม ถ้าเป็นแว่นสายตาคงอาการหนักเอาเรื่อง Bold Italic) ไม่มีไม่เป็นไร (Lomoor มีแบบเดียวคือแบบธรรมดา) เหล่านี้เรียกว่า Family คือเป็นครอบครัวของฟอนต์ ให้เพื่อนๆมองไปยังพื้นที่ด้านล่างของหน้าต่างนี้ มันเขียนว่า
PDF details
These settings are used when a report is exported in PDF
หมายถึงเราต้องจัดการเข้ารหัสอะไรสักอย่างกับฟอนต์ ให้ลองเลือก PDF Encoding เป็น
Identity-H (Unicode with horizontal writing)
อย่าลืมเลือกตัวเลือก Embed this font in the PDF document ด้วยล่ะครับ


>> ตอบ Next ไปยาวๆ ทีนี้กลับมาหน้ารายงานของเรา ปรับฟอนต์เป็น Lomoor ได้แล้ว (มันอยู่ด้านบน) ทดสอบ review เป็นที่น่าพอใจ แต่ยังนะ เราต้องทำอีกอย่างหนึ่งคือแพ็กมันเป็น .jar ส่งให้โปรเจ็กต์ของเราด้วย (แล้วแต่ JasperReports Library จะจัดการ)

>> ณ iReport ตัวเก่งกลับไปที่เมนูของมัน Tools > Option > กลุ่ม iReport > แท็บ Fonts
- ณ Fonts เลือก Lomoor แล้วกดปุ่ม Export as extension
- ตรงไปยัง D:\Workspace\Report\jasperreports\myreports\Report3\lib
- บันทึก .jar นี้ด้วยชื่อ TH-Lomoor.jar (ชื่ออะไรก็ได้ แต่อย่าลืมเติมสกุลล่ะ .jar)

>> ที่โปรเจ็กต์เพิ่ม .jar นี้เช่นเดียวกับเหล่า .jar ก่อนหน้านี้

- คลิกขวาที่รูปโลกสีฟ้า เลือก Properties
- มองหา Libraries ทางซ้าย
- แท็บ Compile กดปุ่ม Add JAR/Folder หามันจากที่ได้บันทึกไว้ดังข้างต้น กด OK

***โปรดอย่าลืม review หรือ compile รายงานที่ได้เปลี่ยนฟอนต์ไปล่ะ สักครั้งหนึ่งเพื่อให้ไฟล์ .jasper มัน update

>> จัดการ
- Clean & Build
- Deploy
- Run

>> เย้มาแล้ว! คืนนี้ฝันดีครับ

JasperReport and iReport part 4-2



สวัสดีชาวโลก กับ PDF Online ด้วย Servlet
>> มาแตะขอบฟ้ากันเถอะ ด้วยการทดลองเพิ่มโค้ดที่จะไปเรียก report ให้ปรากฏ ตรงไปที่ servlet ของเรา ที่ชื่อ ReportServlet นั่นไง

>> มันมีรายละเอียดอย่างไร ตอนนี้ยังไม่ต้องสนใจ ลบไส้ของคลาส servlet นี้ออกให้หมดเลย ดูรูปถ้าไม่เข้าใจที่ผมสื่อ จากนั้นตรงไปที่เว็บนี้ครับ
http://www.ensode.net/jasperreports_pdf_send_to_browser.html

>> ลอกโค้ดเขามาแปะได้เลย เอาตรงนี้เป็นต้นไป
protected void doGet... จนถึง } ของมัน
เพื่อนทำได้นะ เราไว้ใจเธอ รายละเอียดเป็นอย่างไรไว้ผมจะอธิบายให้ภายหลังนะครับ

>> เห็นหลอดไฟสีเหลืองกับ error สีแดงเต็มไปหมดเลยสินะ อย่ากังวลไป ค่อยๆคลิกซ้ายที่หลอดไฟ แล้วทยอยดับไฟทีละดวง กิกิ ให้มัน import คลาสต่างๆแก่เรา ดูรูปประกอบนะ เยี่ยมมาก เราจะเหลือหลอดไฟแถม error อยู่นิดหน่อย (เฉพาะที่เส้นใต้สีแดง) ต้องแก้ด้วย JasperReports Library ครับผม แน่นอนว่าเรามีมันเก็บไว้ตั้งแต่ part ก่อนๆ

>> แต่ก่อนอื่นเราควรมี folder สำหรับเก็บ library พวกนี้เป็นการส่วนตัว จงตรงไปที่
D:\Workspace\Report\jasperreports\myreports\Report3

>> สร้าง folder ชื่อ lib ตรงนี้เลย จึงได้เส้นทางเข้าถึงเป็น
D:\Workspace\Report\jasperreports\myreports\Report3\lib

>> ทีนี้ทำตามผมบอกนะ ตรงไปที่
D:\Workspace\Report\jasperreports\dist
ขโมย jasperreports-6.1.0.jar มาใส่ lib ของเรา (คัดลอกไปนะ)

>> อีกที่หนึ่ง
D:\Workspace\Report\jasperreports\lib
คว้า .jar ตามนี้ไปใส่ lib ของเรา (คัดลอกไปนะ)
- commons-codec-1.5.jar
- commons-logging-1.1.1.jar
- commons-collections-3.2.1.jar
- commons-digester-2.1.jar
สุดท้าย
- iText-2.1.7.js2.jar

>> หุหุ หวังว่าจะไม่มีใครที่ใช้จาร์เวอร์ชันต่างจากผมมากนัก อาจรันและเงิบได้ รวมแล้ว 6 จาร์จัดไปสดๆ

>> กลับไป NetBeans นำ .jar ทั้งสิ้นใน lib ของเราเข้าโปรเจ็กต์ก่อน คลิกขวาที่ลูกโลกสีฟ้า เลือก Properties จะปรากฏหน้าต่าง Project Properties มองหาต่ออีกจากทางซ้ายหมวด Categories คลิกซ้ายที่ Libraries มองหาปุ่ม add JAR/Folder กดปุ่มนี้แล้วไปกวาดจาร์ไฟล์ของเราใน lib มาใส่ให้หมด

>> จัดการกับหลอดไฟและ error ที่เหลือซึ่งไม่ยากเย็นเลย เกลี้ยง นั่นแหละครับ ทำได้ดีมาก ดูรูปประกอบ

>> จากบรรทัดที่เขียนว่า
.getRealPath("/reports/Simple_Report.jasper");
ให้เราตามเขาไปก่อน โดยการตรงไปที่นี่ของโปรเจ็กต์เราครับ
D:\Workspace\Report\jasperreports\myreports\Report3\web

>> สร้าง folder ชื่อ reports ต่อจากนั้นเปิด iReport ขึ้นมาสร้างไฟล์ .jrxml ชื่อตามที่เขาว่า Simple_Report หรือจะไปคัดลอกเอาตัวที่แล้วของ part 2 ก็ได้ จากนั้นจึงเปลี่ยนชื่อมันเป็น Simple_Report โดยวางมันไว้ที่นี่
D:\Workspace\Report\jasperreports\myreports\Report3\web\reports

>> ไม่ว่าอย่างไรถือว่าเพื่อนๆเปิด iReport และให้ iReport เปิด Simple_Report.jrxml ไว้แล้วนะครับ ที่อยู่ไฟล์ตามนี้
D:\Workspace\Report\jasperreports\myreports\Report3\web\reports\Simple_Report.jrxml

>> ผมใช้ Static Text เขียนอีกข้อความลงไป รวมเป็น
- สวัสดีชาวโลก
กับ Hello World

>> ยังอยู่กับ iReport ตรวจสอบ report ตัวนี้ก่อนให้มัน focus ไปที่ภาษาจาวา ไม่ใช่ภาษา Groovy โดยคลิกขวาที่ไอคอนทางมุมบนซ้ายของหน้าต่าง Report Inspector ซึ่งไอคอนนี้มีชื่อเดิมว่า myreport นั่นเพราะผมใช้วิธีไปคัดลอกมาจาก part 2 เมื่อคลิกขวาแล้วให้เลือก Properties ครับ หรือจะมองหาหน้าต่าง Properties ทางด้านมุมขวาล่างก็ได้

>> เลื่อนลงไปจนกว่าจะเจอ Language เปลี่ยน Groovy เป็น Java นะ


>> เอาล่ะ อย่างที่เพื่อนๆทราบ .jrxml คือ XML แต่เราต้องการ .jasper ซึ่งหมายถึงตัว report ที่พร้อมจะเติม (fill) ข้อมูลลงไป ให้เพื่อนๆมองหาปุ่มที่ชื่อ Preview ครับ (มันอยู่ใกล้ๆกับปุ่ม Designer และ XML ณ ด้านบนรายงานของเรา ดูที่รูป) เจอแล้วกด Preview ไปหนหนึ่ง เจ้า iReport ก็จะสร้าง .jasper ให้จากการคอมไพล์ .jrxml โดยอัตโนมัติไงล่ะ ไม่เชื่อกลับไปดูที่
D:\Workspace\Report\jasperreports\myreports\Report3\web\reports
จะพบกับ Simple_Report.jasper

>> Simple_Report.jasper ตรงกับ real path ที่เรากำลังจะเซตให้ออบเจ็กต์ File รอช้าอยู่ใยล่ะ รัน servlet ตัวนี้กันอีกหน ตามขั้นตอนที่เคยบอกไป
- Clean and Build
- Deploy
- Run

>> ว้าวมันมาแล้ว! PDF ออนไลน์ กรรม ผมเปิดด้วย IE มันให้ผมดาวน์โหลดเพราะมันไม่มีตัวอ่าน pdf ในตัวเอง ผมจึงเปลี่ยนไปใช้ Chrome ผลจึงเป็นอย่างในภาพครับ ส่วนภาษาไทยยังไม่ขึ้นเป็นเรื่องปกติ ซึ่งไว้ผมจะจัดการให้ใน part 4-3 ล่ะกัน คืนนี้ดึกแล้ว ฝันดีครับ

JasperReport and iReport part 4-1



สวัสดีชาวโลก กับ PDF Online ด้วย Servlet

>> รักหนอรักทำไมเจ็บปวดอย่างนี้ คนหนอคนเหตุใดทำร้ายหัวใจกัน ชีวิตคือการเรียนรู้และรู้จักตัวเอง เจ็บปวดใช่ไหม ยืนขึ้นแล้วบอกกับตัวเราเองว่า ฉันจะต้องผ่านมันไปให้ได้!

>> คุยไว้ part ก่อนจะออก PDF ด้วย NetBeans โดยเทคโนยี HTML & Servlet ก็มาลองกันสักตั้งเป็นไร มี NetBeans แล้วใช่ไหมครับ ในช่อง categories เลือก Java Web แล้วช่องทางขวา Project เราก็เลือก Web Application นะคนดี ตั้งชื่อโปรเจ็กต์ของเราว่า Report3 และกำหนด Project Location ไปที่
D:\Workspace\Report\jasperreports\myreports

>> คืออย่างที่บอก เราจะรวมๆโปรเจ็กต์รายงานนี้ไว้ด้วยกัน ตั้งเป็น report3, report4, report5 ไปเรื่อยๆจนกว่าจะเบื่อ อ้อ อย่าเพิ่งกดปุ่ม Finish ล่ะ ในหน้าต่าง New Web Application นี้ ส่วนของ Server and Setting ผมเลือกเป็น
server: GlassFish Server 4.0
Java EE Version: Java EE 7 Web
สุดท้ายของหน้านี้คือ context Path: /Report3

>> หากกด Next ไปอีกก็จะเจอส่วน Frameworks ตรงนี้ไม่ต้องเลือกอะไรนะครับ กด Finish เสร็จการสร้างโปรเจ็กต์ไปได้เลย

>> ลองรันโปรเจ็กต์ก่อนเป็นไง คลิกขวาที่รูปลูกโลกสีฟ้า เลือก Run ดูสิว่าหน้าเว็บขึ้นหรือเปล่า มันต้องเขียนว่า TODO write content

>> หน้านี้เกิดขึ้นได้อย่างไร? ใจเย็นๆนะถ้าเราเป็นมือใหม่ ของอาจดูเยอะแยะ (ก็เยอะจริงๆแหละ เข้าใจ) ตามๆไปก่อนนะครับคนดี หาไฟล์ที่ชื่อ index.html ซึ่งอยู่ภายใต้ folder ชื่อ Web Pages โดยปกติสร้างโปรเจ็กต์ครั้งแรกมันก็เปิดขึ้นมาให้เลย

>> เขียน HTML เป็นใช่ไหม เขียน form ใส่ให้ผมหน่อย ขอปุ่มชนิด submit ให้ผมแค่ปุ่มเดียวเท่านั้น ดังในรูปนะถ้าไม่แน่ใจ ปุ่มนี้เมื่อกดแล้วมันจะไปเรียก servlet ให้เรา โดยฝาก action ไว้กับ form ดังนี้ครับ
action="ReportServlet"

>> มองไปที่ Web Pages อีกครั้งนะครับ จะเห็นว่ามีอีก folder ชื่อ WEB-INF ถูกสร้างไว้คอยท่าแล้ว เราต้องสร้างหัวใจให้โปรเจ็กต์นี้ก่อน ด้วย web.xml เพื่อบอกเล่าเรื่องราวว่าโปรเจ็กต์ของเรามี servlet เก็บไว้ที่ไหนอย่างไรล่ะ

>> คลิกขวาสร้างไฟล์ web.xml ภายใต้ folder ชื่อ WEB-INF หากไม่เจอให้เลือก New > Other... จะปรากฏหน้าต่าง New File มองหาช่อง Filter แล้วพิมพ์ลงไปว่า xml เราก็จะเห็นช่อง Categories ผุดออกมา เลือก Web แล้วเลือก File Type เป็น Standard Deployment... มันจะให้ชื่อมาเลยว่า web.xml คลิก Next และ Finish นะคนดี

>> มองหา Source Packages ที่ภายใต้มันจะเขียนว่า default packages คลิกขวา New > Servlet... โดยพิมพ์เข้าไปเลยตามนี้เลยในช่อง Class Name ว่า
com.sample.ReportServlet
จากนั้นกด Next จะพบกับหน้าต่าง Configure Servlet Deployment ให้คลิกเลือก Add information to deployment descriptor ด้วยนะ มันจะได้ร่างส่วนติดต่อ servlet ให้ ไม่อย่างนั้นเราคงต้องไปเขียนกันเอง รายละเอียดอื่นในหน้านี้ของผมได้แก่
Class Name: com.sample.ReportServlet
Servlet Name: ReportServlet
URL Pattern(s): /ReportServlet
เหมือนกันใช่ไหมล่ะ โอเคเยี่ยมมาก กดปุ่ม Finish เลยครับ

>> อยากรู้ว่ามันเขียนอะไรให้ในไฟล์ web.xml ก็ไปเปิดดูสิ มีอยู่สองส่วนที่สำคัญ ได้แก่
1) servlet
2) servlet-mapping
- สองส่วนข้างต้นต้องรู้จักกัน มันจึงใช้ชื่อ servlet-name เดียวกันถูกไหมล่ะ
ReportServlet
- servlet-class บอกว่าคลาส servlet อยู่ ณ แห่งใด
com.sample.ReportServlet
- url-pattern นั่นบอกว่าจะเรียกคลาส servlet ที่ชื่อ ReportServlet ดังกล่าวได้อย่างไร ก็ตาม action ที่เรากำหนดไว้ครับ
/ReportServlet
(ใส่ / นั่นหมายถึงจาก root ของโปรเจ็กต์เรา หรือก็คือ Report3/ReportServlet)

>> ทดลองก่อนว่าเรียก servlet ตัวนี้ผ่านไหม คลิกขวาที่ลูกโลกสีฟ้า ทำตามขั้นตอนนี้ ให้แน่ใจว่าโปรเจ็กต์ของเราบนเซิร์ฟเวอร์ได้รับการเปลี่ยนแปลงที่เกิดขึ้น
- Clean and Build (เกี่ยวกับ .jar และ .war)
- Deploy (start server ถ้ามันยังไม่ตื่น วาง .war ลงไป)
- Run (เรียกหน้าแรกให้ปรากฏตามที่กำหนดใน web.xml)

>> ตัดจบก่อนดีกว่า ขอแยกเป็น part 4-1, 4-2 และ 4-3 ยาวเกินไปขั้นตอนก็เยอะ เอาเป็นว่า ณ part นี้เราเรียก servlet ด้วยการกดปุ่มได้แล้ว ยืนยันตามรูปครับ

JasperReport and iReport part 3



สวัสดีชาวโลก กับ iReport

>> ต่อจากหนก่อน Hello World ขั้นตอนก็เยอะแยะมากมาย เพื่อนๆคนไหนผ่านมาได้แสดงว่ามาถูกทางแล้ว (หรือผมพามั่ว) ขออย่าได้ละความพยายาม และเอาใจช่วยซึ่งกันและกันด้วยนะครับ part นี้ผมจะพาไป สวัสดีชาวโลก แบบว่าให้เจ้า report มันแสดงภาษาไทยออกมาควบคู่กับการทดลองใช้ iReport สร้างไฟล์สกุล .jasper ให้ในอนาคต (part หน้า)

>> อย่างที่เราทราบกันอยู่แล้วว่า ภาษาพื้นฐานที่สุดที่ต้องเจอเมื่อเล่นกับ JasperReports ก็คือ XML ใครเขียนเพียว XML ได้ก็จะได้เปรียบพวกที่ใช้เครื่องมืออย่าง iReport เพราะมีอิสระในการขยับโน่นนี่นั่นมากกว่าการใช้เม้าส์ค่อยๆบรรจงจัดระยะห่าง หรือใช้แป้นพิมพ์เคาะทีละหนึ่งสองสาม ซึ่งงานจริงๆนั้นค่อยข้างลำบาก แต่ iReport ก็มีประโยชน์มากกว่าจะไม่ใช้เลย เพราะใช้ง่าย ให้ XML ที่เป็นผลลัพธ์ได้ไวกว่าจะมานั่งพิมพ์เองทั้งหมด อย่างไรก็อยากให้ใช้ควบคู่กันไปครับ

>> โหลด iReport มาก่อนนะ จากที่นี่
http://community.jaspersoft.com/project/ireport-designer/releases
ของผมเลือกเป็น .zip ขณะนี้คือ iReport-5.6.0.zip
ครับ ระเบิดมันออกมา วางไว้ไหนก็แล้วแต่ แต่อย่าลืม set JAVA_HOME ล่ะ เดี๋ยวเปิดไม่ขึ้นนะ ตามข้ออ้างอิงนี้ครับ
http://community.jaspersoft.com/wiki/environment-variable-configuration-issue-when-installing-jaspersoft-etl

>> เปิด iReport แล้วเริ่มสร้างหน้ารายงานเปล่าๆกันเลย Blank A4 คือชนิดที่ผมเลือก อ้อ เกือบลืมไป จากโครงสร้าง part ที่ผ่านมาขอให้เพื่อนๆสร้าง folder ชื่อ report2 ซึ่งในเครื่องผมมันจะวางอยู่ตรงนี้ครับ
D:\Workspace\Report\jasperreports\myreports\report2
รบกวนคัดลอกไฟล์ build.xml กับ baseBuild.xml ใส่ลงไปด้วย

>> บันทึกหน้าเปล่าของเราชื่อว่า myreport.jrxml (สกุลมันใส่ให้เอง ไม่ต้องพิมพ์ไปก็ได้) เห็นไหม ตอนนี้โครงสร้างของเราเหมือนคราวก่อน ไหนลองรันหน้าขาวๆนี้ขึ้นมาหน่อยสิ ด้วย command prompt คำสั่งเดิมทุกอย่าง

>> เอาล่ะอยู่กับ iReport นะ มองหาสิ่งที่เขียนว่า Static Text ทางด้านขวามือภายใต้หน้าต่างที่ชื่อว่า Palette ครับ ถ้ามันไม่มี ตรวจดูหน่อยว่าได้เปิดไว้หรือไม่ ไปที่เมนู Window เลือก Palette

>> ลาก Static Text มาวางใน report ของเราส่วนที่เขียนว่า Title จากนั้นดับเบิลคลิกเขียนข้อความใจฝันลงไป สวัสดีชาวโลก จากนั้นบันทึก

>> ปิดอันเก่า (ถ้ายังไม่ได้ปิด) แล้วรันคำสั่ง ant เฉยๆอีกครั้งใน command prompt ฮั่นแน่ สวัสดีชาวโลก! มาแว้วๆ

>> รวบรัดไว้เจอกัน part 4 เปิด NetBeans ขึ้นมาลุย ดึงเจ้า report สวัสดีชาวโลกนี้เป็นไฟล์ PDF แสดงบน Browser ด้วย HTML & Servlet เป็นไง ไม่ต้องกังวลหากไม่รู้จักสองเทคโนโลยีนี้ เดี๋ยวผมพาลุยอย่างเคย รักษาตัวเอง คืนนี้ฝันดีครับ

JasperReport and iReport part 2



Hello World

>> โหลๆยังอยู่ด้วยกันหรือเปล่า แล้วโหลด jasperreports-6.1.0-project.zip (เวอร์ชันในขณะนี้) กันมาหรือยังล่ะ หาอะไรนะ! เยี่ยมเลย โหลดมาแล้วก็มาลุยกันต่อเลยครับ

>> ผมระเบิด .zip ออกมา วางไว้ตรงนี้ในเครื่องครับ
D:\Workspace\Report\jasperreports
คือเปลี่ยนชื่อ folder มันให้สั้นๆหน่อย เอาแค่ jasperreports พอ เพื่อนๆจะวางไว้ที่ไหนก็แล้วแต่ แต่อย่าลืม set PATH ให้ระบบปฏิบัติการล่ะ ไม่งั้นเครื่องเราก็จะหาไลบรารีนี้ไม่เจอ จากข้างต้นดังนั้น PATH ของผมจึงเป็น
D:\Workspace\Report\jasperreports\dist
และ
D:\Workspace\Report\jasperreports\lib
(คั้นมันแต่ละ PATH ด้วยเครื่องหมาย ; นะอย่าลืม อันท้ายสุดไม่ต้อง)

>> path ทั้งสองข้างต้นสำคัญอย่างไร? สำคัญอย่างนี้ครับ
...\dist นั่นสำหรับ jasperreports-x.x.x.jar เพื่อกระบวนการสร้าง report ตลอดจนคอมไพล์ภาษาอื่นที่ใช้กับ report ได้ เช่น Groovy
...\lib นี้สำหรับสั่งให้ build report และใช้ปลุก report ของเราหลังจากนี้ให้มีชีวิต

>> เราจะคอมไพล์ (compile) ประมวลผล (execute) ด้วยหน้าดำนะครับ (command prompt) ผ่านอีกเทคโนโลยีหนึ่ง นั่นก็คือ Ant โอ๊ะมด!

>> เริ่มด้วยสร้างไฟล์ baseBuild.xml ทำไง กิกิ ไปลอกมาเลยครับ ไม่ต้องเขียนเอง ที่นี่ (มันใช้ทำอะไรเดี๋ยวบอกคร่าวๆให้)
http://www.tutorialspoint.com/jasper_reports/jasper_environment_setup.htm
เลื่อนลงมากลางๆหน่อย copy แล้วเอาไปวางในโปรแกรมเขียน text แล้วตั้งชื่อว่า baseBuild.xml ซึ่งเจ้านี่ยังทำงานอะไรไม่ได้นะครับ เป็นเพียงตัวกำหนดว่าไลบรารีอยู่ไหน, จาวาคลาสของเราที่ใช้เริ่มต้นชื่ออะไร, สั่งคอมไฟล์จาวา, สั่ง run จาวาคลาสดังกล่าว, สั่งยิง (ไม่ช่ายแระ สั่ง clean) .jasper และ .jrprint ทุกครั้งไป ประมาณนั้นครับ เพียงแต่ผมขอให้แก้ไขสักสองจุด ดังในรูปนะ
- จุดแรก เปลี่ยนชื่อไฟล์ .jrxml ที่จะสร้างในอนาคตอันใกล้นี้ให้สั้นหน่อย เป็น myreport ก็แล้วกัน
- จุดที่สอง เพิ่ม ../ เข้าไปอีกชั้น เพราะว่าโปรเจ็กต์ของเราแบ่งชั้นย่อยลงมาอีกหนึ่งชั้น เดี๋ยวมันจะหาไลบรารีไม่เจอ

>> เมื่อมี baseBuild.xml แล้ว ซึ่งผมสร้างมันไว้ที่ที่ระเบิด .zip ไว้ก็คือ
D:\Workspace\Report\jasperreports\myreports\report1
เพราะผมตั้งใจว่าจะสร้างตามตัวอย่าง แล้วเอามาเล่าให้เพื่อนๆฟังทีละตัวอย่างกันเลย ก็จะเป็น report1, report2, ... ว่ากันไปจนกว่าจะเบื่อ

>> ทีนี้ก็มาสร้างสิ่งที่เจ้า Ant เข้าใจกันเสียก่อน นั่นก็คือไฟล์แรกที่ Ant จะไปทำงาน มันต้องชื่อ build.xml เหมือนเคย เปิดไปที่นี่ (copy มันซะ หึหึหึ)
http://www.tutorialspoint.com/jasper_reports/jasper_report_designs.htm
(ในหน้านี้มี XML อยู่สองไฟล์ คัดลอกอันล่างมา)

>> เมื่อมี build.xml ซึ่งมันจะไปเรียก baseBuild.xml ให้ทำงานอีกต่อหนึ่ง โอเค สร้างมันวันที่เดียวกัน
D:\Workspace\Report\jasperreports\myreports\report1

>> ตื่นเต้นหรือยัง! ใกล้ความจริงแล้วครับ อย่างที่บอกไปว่า เริ่มต้นต้องเริ่มจาก .jrxml หรือก็คือ report template สร้างมันขึ้นมาเลย (ด้วย iReport ก็ได้) หรือใช้ที่ผมเขียน จากลิงค์นี้ครับ
http://www.mediafire.com/view/6c84cdpxg448ga3/myreport.jrxml
ตั้งชื่อว่า myreport.jrxml นะโอเค (กับคนที่สร้างเอง) ให้มันอยู่ที่เดียวกับ XML ไฟล์ทั้งสองข้างต้น
D:\Workspace\Report\jasperreports\myreports\report1

>> เมื่อมี myreport.jrxml ก็เหลือเพียงปลุกผีให้ตื่น หมายถึงใช้ Ant รันไฟล์ build.xml น่ะครับ แฮะๆ ก็อย่าลืมโหลด Ant และ set ANT_HOME กับ PATH ให้เครื่องเราตามหามันเจอด้วยล่ะ โหลด Ant ได้ ณ
http://ant.apache.org/bindownload.cgi
เลือกที่เป็น .zip นะ ของผมขณะนี้คือ
apache-ant-1.9.6-bin.zip
ระเบิดมันไว้ไหนก็แล้วแต่ เซต ANT_HOME ด้วย ของผมคือ
D:\Workspace\Ant\apache-ant-1.9.6
ส่วน PATH คือ
%ANT_HOME%\bin

>> เอาล่ะสั่ง Ant ทำงาน build.xml ได้แล้ว เปิด command prompt พิมพ์ป๊อกๆแป๊กๆ ดังในรูป พั๊วะ! report ของเราก็ผุดขึ้นมาแล้ว เย้ๆ

>> ซึ่ง Ant ไปสั่งให้โปรแกรม JasperDesignViewer เอา myreport ของเรามาโชว์นั่นเอง เยอะแล้ว ฝันดีครับเพื่อนๆ

JasperReport and iReport part 1

>> ประเดิมประสบการณ์เขียนรายงาน (report) ด้วยจาวาไลบรารีแบบเป็นเรื่องเป็นราวกันเสียทีหลังจากกรุย UI กันเสียนาน อยากให้เวิร์กฐานข้อมูลใช่ไหม ได้เลย อยากให้หัดเขียนจาวาหลังบ้านใช่ไหม ได้เลย อย่างนั้นมาหัด JasperReport กับ iReport กันก่อน คล่องแล้วก็ไป query ข้อมูลมาใส่ ต่อมันด้วย servlet อีกทีเป็นไง น้อยไปใช่ไหม พ่วง web service ให้อีก (โม้) หลับเพลินเลย กิกิ

>> บอกก่อนผมเป็นประเภทเกลียดการทำรายงานมาก ตั้งแต่สมัยเรียนมอปลาย ติดศูนย์บ่อย (เกี่ยวไรกับ Jasper) ยังจำได้ว่าต้องมานั่งลอกรายงานส่งจารย์มือแทบหงิกยันฟ้าสว่าง เฮ้อ~ ว่าไปก็คิดถึงนายนะอ้วน เล่นอยู่ด้วยกันแท้ๆจู่ๆก็แต่งงาน ไวไปไหน!

>> ผมเริ่มอ่านจากที่นี่ครับสำหรับ JasperReport ทำตามไม่ได้ให้เตะ กิกิ
http://www.tutorialspoint.com/jasper_reports/
ภาพกว้างหรือความคิดก็คือ
- เราต้องมี jasper report library
- กำหนด path ให้เครื่องของเรารู้จัก jasper report library นั่น
- เขาแนะให้เราใช้ ant เป็นตัวสั่ง build จาวาไฟล์ตลอดจนกระบวนการสร้าง report
- แน่นอนว่าเราต้องกำหนด path ของจาวา JDK ให้เรียบร้อยด้วย

>> ทางเดินของ report (JasperReports - Life Cycle)
1) เขียน report ด้วยโครงสร้างภาษา XML หากว่ามันเขียนยากนัก ผิดบ่อย จัด layout ไม่ได้ แง้ๆ แบบนี้ให้ใช้ iReport ช่วย (เขาประดิษฐ์มันขึ้นมาก็เพื่อการนี้แหละสหาย) สมมติว่าเขียนได้แล้ว ตั้งชื่อเป็น report.jrxml โดยเราจะเรียกเธอว่า report template

2) report.jrxml ยังใช้ในงานของจาวาไม่ได้ ต้อง compile ให้เป็น .jasper ก่อน ฮั่นแน่รู้เลยใช่ไหม งานของ jasper report library ที่โหลดมานั่นแหละ ก็จะได้เป็น report.jasper หรือเรียกเธอว่า jasper file

3) report.jasper ก็คือรายงานของเราที่พร้อมเติม (fill) ข้อมูลลงไปด้วยจาวาโค้ด โดยประเภทของข้อมูลที่จะนำมาเติมมาจากสองทาง ได้แก่ datasource กับ parameter คืออะไรค่อยว่ากันทีหลังเน๊อะ และเมื่อมันถูกเติมข้อมูลลงไปสำเร็จแล้ว ตอนนี้ .jarper จะกลายเป็น .jrprint หรือก็คือ report.jrprint และเราเรียกเธอว่า jasper print file

4) report.jrprint คือ (ไฟล์) รายงานที่เกือบจะสำเร็จเป็นรูปร่างให้ตาเห็น (มีข้อมูลพร้อม) กิกิ มันพร้อมแล้วที่จะถูก export เป็นรูปแบบต่างๆเท่าที่ library รองรับ ไม่ว่าจะเป็น
- report.pdf
- report.html
- report.csv
- report.xml
และอื่นๆ

สรุปเส้นทางกว่าจะไปถึงขอบฟ้าดังนี้
report.jrxml
report.jasper
report.jrprint
และ export เป็น .pdf, .html, .csv, .xml ฯลฯ

>> ค่อยเรียนรู้กันไปนะครับ เร็วรีบก็มึนเปล่าๆ ยิ่งเราเป็นมือใหม่ด้วย ควรทำตามตำราไปก่อนเป็นดี และ part ต่อไปมาดูกันสิว่าผมจะ Hello World ได้อย่างไร

>> ส่วนเล่มที่ผมกำลังอ่านอยู่มีชื่อว่า JasperReports 3.6 Development Cookbook ผมล่ะชอบมาก หลับสบาย คืนนี้ฝันดีครับ

Apache POI



ครั้งแรกกับ Apache POI และเที่ยงคืนตรง

>> ถามมาจากพี่ซีเนียร์ที่ทำงานครับ ว่าอยากทำความเข้าใจ จาวา ที่สร้าง รายงาน ออกมาได้ พี่ท่านแนะนำตัวนี้มา มันคืออะไรพี่? คำถามแรกแบบไม่ต้องคิดและหวังคำตอบ ณ ตรงนั้น แต่ก็เฉลี่ยวใจ ทำไมไม่เอาชื่อนี้ที่พี่เขาให้มาไปลองเล่นเองว่ะ โอเคไม่น่าเล่นยาก มันต้องเป็นของดีแน่

>> หลังจากนั้นจึงสัญญากับตัวเองว่าอย่างไรคืนนี้จะต้องเริ่มให้ได้ ถ้ามีเวลากินข้าวพ่วงดูหนังอย่าง 'Focus เกมกล เสน่ห์คนเหนือเมฆ' จนจบได้ สัญญาก็ต้องทำให้ได้ด้วย ธรรมดาของคนอยู่ลำพัง ก็มาเล่าให้ฟังตามเคยครับ

>> Apache POI หรือก็คือ Apache Poor Obfuscation Implementation ห๊ะ? มันคืออะไรน่ะ เป็นไลบรารี่สำหรับอ่านและเขียนชุดโปรแกรมไมโครซอฟออฟฟิศด้วยภาษาจาวา! ไอ้ย่ะ ได้แก่ MS Word, MS PowerPoint และ MS Excel เป็นต้น

>> คะคือพี่ครับ ผมนึกถึง iReport มากกว่านะครับ (คิดเองในใจ) แต่ไหนถอยมาไกลถึงเพียงนี้ 'ก็ iReport มันสวมอยู่บนตัวนี้แหละ' หือ? คำตอบนี้ไม่ยากไปเหรอครับพี่ ภาษาอังกฤษด้วยนะที่ผมต้องอ่านและแปลให้ตัวเองรับรู้ โอเคเริ่มท่อง A, B, C, ... กันเลยก็แล้วกัน

>> สั้นๆง่ายๆไวๆไร้ลีลา (ยังไง?) ประสามือใหม่ใจสั่น ผิดถูกค่อยว่ากันทีหลังนะครับ เริ่มต้นจากติดตั้ง JDK ลงเครื่องก่อนเลย ของผมนี่เลย
C:\Program Files\Java\jdk1.8.0_31

>> ต่อไปตามไปโหลดไลบรารี่ (อย่างที่บอกว่ามันเป็นไลบรารี่) ณ
http://poi.apache.org/download.html
มองหา
poi-bin-XXX.zip (ตอนนี้คือเวอร์ชัน poi-bin-3.12-20150511.zip)

>> ผมเลือก tutorial ที่สอนสร้างไฟล์ Excel (ผมชอบโปรแกรมตารางคำนวณนี้มากที่สุดในประดาชุด MS Office) เอาเป็นว่าเราจะมาลอง Hello Excel! กันแบบสดๆ จัดกันแบบ real time กันเลยคืนนี้

>> ฟังเรื่อง core classes กันก่อน ทิดดีๆ (ทฤษฎี) อย่าเพิ่งเบื่อ ผมก็ใหม่เหมือนกัน มีสองคลาสควรรู้จักครับ
1) คลาส HSSFWorkbook สำหรับอ่านและเขียน excel มีสกุลเป็น .xls หรือก็คือ excel เวอร์ชัน 2007 ลงไป (ราวเวอร์ชัน 97-2003)
2) คลาส XSSFWorkbook สำหรับอ่านและเขียน excel มีสกุลเป็น .xls หรือ .xlsx หรือก็คือ excel เวอร์ชัน 2007 ขึ้นไป

>> ใช้ Eclipse IDE เขียน ส่วน jar ไฟล์ที่ได้เซตให้เรียบร้อย ทำไม่เป็นตามลิงค์นี้ มีหลายวิธีให้เลือกครับ
http://www.wikihow.com/Add-JARs-to-Project-Build-Paths-in-Eclipse-(Java)

>> เป็นว่าผมใช้คลาส XSSFWorkbook
- สร้างออบเจ็กต์ workbook เปล่าๆแล้วให้ออบเจ็กต์นี้สร้าง spreadsheet ของมันเอง
- ออบเจ็กต์ spreadsheet ที่ได้ ให้มันสร้าง row ของมันเอง
- ออบเจ็กต์ row ที่ได้ ให้มันสร้าง cell ของมันเอง
- ในที่นี้จองแค่ 1 row 1 cell เพื่อเขียนคำว่า Hello Excel! ลงไป
- สั่งมันเขียนไฟล์ ปิดไฟล์ที่เขียน (D:\MyExcel.xlsx)
- เปิดมันด้วย MS Excel ครับ

>> ทั้งหมดนี้ผมอ่านจาก
http://www.tutorialspoint.com/apache_poi/apache_poi_java_excel.htm

>> ขอบคุณสำหรับความหมายของ POI
https://en.wikipedia.org/wiki/List_of_Apache_Software_Foundation_projects

>> คืนนี้คงต้องนอนกันก่อน ไว้เจอกันใหม่ สวัสดีครับ