หน้าเว็บ

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

project module with maven

        บางครั้งโปรเจ็คของเรามีขนาดค่อนข้างใหญ่  ซึ่งถ้าจะให้พัฒนาทั้งหมดรวมกันไว้ใน project เดี่ยว  มันก็ค่อนข้างจะ management ลำบาก   เช่น  โปรเจ็คของเราต้องมีรายงาน แน่นอนว่า เราต้องเขียน library เพื่อใช้สำหรับออกรายงานเป็นจำมาก   นอกจากนั้นเราต้องการให้เว็บของเรา  ทำการเข้ารหัส  หน้าเว็บ html(id) css(class) javascript   เราก็ต้องมาเขียน library สำหรับเข้ารหัสอีก   ต่อมาอยากได้ feature web real time แน่นอนว่า  เราก็ต้องเขียน labrary หรือหา library สำหรับ web realtime มาปรับแต่งให้เข้ากับเว็บของเรา  จากนั้นอยากให้เว็บของเราติดต่อกับ hardware ได้ด้วย(java ทำได้อยู่แล้ว)  เราก็ต้องมาเขียน library หรือไปหา library สำหรับ hardware นั้นๆ มาใช้   ต่อมาอยากให้เว็บของเรามี OCR มี lucene เราก็ต้องเพิ่มเข้าไปอีก  ต่อมาต้องการแชร์ข้อมูลบางอย่างข้ามโปรเจ็คกัน  ต่อมา บลาๆๆๆๆ

        ลองคิดเล่นๆดูครับว่า  ถ้ามันมี 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  ทุกคนน่ะครับ ^_____^

ไม่มีความคิดเห็น:

แสดงความคิดเห็น