ลองคิดเล่นๆดูครับว่า ถ้ามันมี feature เพิ่มขึ้นไปเรื่อยๆ แล้วเราจะจัดการ project ของเรายังไง มันจะไม่เล๊ะเป็นโจ๊กเลยหรอครับ เพราะทุกอย่างมันรวมกันไปหมด ถึงแม้จะมีการจัดแบ่ง code เป็น package ย่อย แต่ขนาดของโปรเจ็ค มันก็ดูใหญ่เกินไป จะเทสทีก็ลำบาก กว่าจะ build ผ่าน นั่งรอจนเหนื่อยเลยครับ ทั้งๆที่ แก้ code ไปแค่ไม่กี่บรรทัด เรามาหาทางแก้กันดีกว่าครับ โดยการแบ่ง project นั้นๆ ออกเป็น module ย่อย
มาเริ่มกันดีกว่าครับ เดี๋ยวผมจะสร้างตามที่ผมได้ยกตัวอย่างไปครับ
สมมติมีโครงสร้างประมาณนี้
test-project (parent project) - report - obfuscator - realtime - hardware - ocr - lucene - test-api - mainสร้าง parent project หรือ test-project
-- ที่ Netbeans IDE
-- New Project เลือก Categories เป็น Maven และ Projects เป็น POM Project จากนั้นคลิก Next >
สร้าง children project เก็บไว้ใน parent project
-- สร้าง project obfuscator
-- ที่ Netbeans IDE
-- New Project เลือก Categories เป็น Maven และ Projects เป็น Java Application จากนั้นคลิก Next >
:: ตรง Project Location ให้จัดเก็บ project นี้ไว้ใน parent project หรือ test project
ชื่อ package จะเหมือนหรือไม่เหมือน parent อันนี้ แล้วแต่น่ะครับ
เราก็จะได้ obfuscator ที่เป็นส่วนหนึ่งของ test ครับ
file pom.xml ของ parent project หรือ test project มีการเพิ่ม module ชื่อ obfuscator ซึ่งตัวนี้เป็น relative path ครับ ซึ่งมันอยู่ในระดับเดียวกันกับ pom.xml ของ test project
และ pom.xml ของ obfuscator สังเกตว่าจะมี <parent></parent> ถูก define ไว้ ซึ่งมี artifactId เป็น test
ลองสร้าง children project ตัวอื่นๆ ดู
เมื่อสร้างไปเรื่อยๆ ก็จะเป็นแบบนี้ครับ
ลองไปดูที่ pom.xml ของ parent project หรือ test project อีกครั้ง จะเห็นว่ามี module อื่นๆ ถูกเพิ่มเข้ามา
และใน pom.xml ของแต่ะละ project ก็จะมี <parent></parent> ถูก define ขึ้นมา เหมือน obfuscator
เรียกใช้
ต่อมา อยากให้ main project เรียกใช้ project อื่นๆ (main project คือ project จริงๆ ของเรา)
ที่ pom.xml ของ main ให้ add dependencies ดังต่อไปนี้
<dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-web-api</artifactId> <version>6.0</version> <scope>provided</scope> </dependency> <dependency> <artifactId>obfuscator</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> </dependency> <dependency> <artifactId>report</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> </dependency> <dependency> <artifactId>realtime</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> <type>war</type> </dependency> <dependency> <artifactId>hardware</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> </dependency> <dependency> <artifactId>ocr</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> </dependency> <dependency> <artifactId>lucene</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> </dependency> <dependency> <artifactId>api</artifactId> <groupId>${project.groupId}</groupId> <version>${project.version}</version> </dependency> </dependencies>ข้อสังเกต มี project realtime ที่มี <type>war</type> เนื่องจาก realtime เป็น web application เมื่อ build เสร็จจะได้เป็น war ส่วน project อื่นๆ เป็น java application เมื่อ build เสร็จจะได้ jar file ซึ่งเป็น <type>jar</type> โดย default อยู่แล้ว ถ้าเราไม่ใส่
<artifactId>api</artifactId> คือ identifier ของ project นั้นๆ ส่วน <groupId>${project.groupId}</groupId> กับ <version>${project.version}</version> คือ group กับ version ของ project ที่เราเรียกใช้ แต่พอดีว่า เราพัฒนาไปพร้อมกัน ก็เลยใช้ group กับ version เดียวกันกับ main ทั้ง 3 อย่างนี้ให้ไปดูที่ pom.xml ของ project นั้นๆ ครับ
ตัวอย่างเช่น report project
จากนั้นลอง build ที่ parent project หรือ test project ดูครับ chrildren project จะถูก build ตามไปด้วย ส่วนลำดับการ build นั้น เราจะไม่มีทางทราบว่าอันไหนจะถูก build ก่อนหลัง แต่ขึ้นอยู่กับว่า อันไหนไป denpend กับตัวไหนครับ ซึงจากภาพ main จะถูก build หลังสุดเสมอ เนื่องจาก main เรียกใช้ตัวอื่นๆ
แค่นี้เราก็สามารถเรียกใช้งาน project อื่นๆ ได้แล้วครับ เดี๋ยวเราลองมาใช้งานจริงๆกันดูสักหน่อยครับ
ที่ report-project ผมสร้าง class ReportUtils สำหรับ ออกรายงานขึ้นมา
ที่ api project ผมสร้าง model price เพื่อที่จะแชร์ไปยัง project อื่นๆ
จากนั้นให้ build parent (ในกรณีที่ต้องการ build children ทั้งหมด) แล้วลองมาเขียน code ทดสอบที่ main project กันดูครับ
CallOtherTest.java
package com.blogspot.na5cent.test.main; import com.blogspot.na5cent.test.api.model.Price; //***** import com.blogspot.na5cent.test.report.ReportUtils; //***** import java.io.IOException; import java.io.InputStream; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; /** * * @author redcrow */ public class CallOtherTest { private static final Logger LOG = Logger.getLogger(CallOtherTest.class.getName()); public static void main(String[] args) { Price price = new Price(); //**** price.setDateIn(new Date()); price.setDateOut(new Date()); price.setDiag(10000D); price.setTotal(10000D); InputStream jasperInputStream = null; try { jasperInputStream = CallOtherTest.class.getResourceAsStream("/report/priceReport.jasper"); ReportUtils.downloadPdf(new Object[]{price}, jasperInputStream); //**** } catch (IOException ex) { LOG.log(Level.WARNING, null, ex); }finally{ if(jasperInputStream != null){ try { jasperInputStream.close(); } catch (IOException ex) { LOG.log(Level.WARNING, null, ex); } } } } }เราสามารถเรียกใช้งาน project อื่นๆ ได้ เนื่องจากเราได้ add dependencies ของ project อื่นๆ ไว้ใน pom.xml ของ main เรียบร้อยแล้ว
สบายแมวเลยทีนี้ management ง่ายขึ้นเยอะ อ้อ เวลาจะเอาไป deploy ก็เอาแต่ main ไปครับ เพราะ project อื่นๆ จะถูก build รวมไปใน main เลย เพราะ main project เราเรียกใช้ project อื่นๆ แล้วครับ
หวังว่าบทความนี้คงเป็นประโยชน์สำหรับ java developer ทุกคนน่ะครับ ^_____^
ไม่มีความคิดเห็น:
แสดงความคิดเห็น