Thursday, March 19, 2009

excluding transitive dependency in maven

ใครที่เคยใช้ maven คงจะรู้ดีกว่า มันช่วยลดอาการปวดหัวในการจัดการกับ jar file ได้ระดับหนึ่ง เพราะมันช่วยเราจัดการพวก transitive dependency ให้เราได้ (แต่ไปปวดหัวเรื่อง setup มันแทน)

แต่การที่มัน solve transitive dependency ให้ก็นำมาซึ่งปัญหาอันใหม่ นั่นก็คือ version conflict, สมมติว่า project เรามี dependency ถึง library Foo กับ library Bar. ทั้ง Foo และ Bar บังเอิญมี dependency ซึ่ง Library Z เหมือนๆกัน แต่ดันเป็นคนละ version. เมื่อเรา build project, เราก็จะมี library Z เข้ามาใน class path เราทั้งสอง version, ทำให้เกิด error พวก missing method หรือ missing class ได้
(Note: ที่ผมเจอ ผมเจอปัญหานี้ตอน mvn eclipse:eclipse, แต่จากการทดสอบด้วยคำสั่ง mvn dependency:resolve ปรากฎว่า มันได้ผลลัพท์ไม่เหมือนกัน เจ้า dependency:resolve ดูเหมือนจะจัดการได้ถูกต้อง)

วิธีแก้ไขก็คือ การระบุ exclusion ลงใน pom.xml ของ maven
จากของเดิม
<dependency>
<groupId>my.pphetra</groupId>
<artifactId>foo</artifactId>
<version>1.0</version>
</dependency>

<dependency>
<groupId>my.pphetra</groupId>
<artifactId>bar</artifactId>
<version>1.0</version>
</dependency>

ไปเป็น
<dependency>
<groupId>my.pphetra</groupId>
<artifactId>foo</artifactId>
<version>1.0</version>
<exclusions>
<exclusion>
<groupId>test</groupId>
<artifactId>Z</artifactId>
</exclusion>
</exclusions>
</dependency>

<dependency>
<groupId>my.pphetra</groupId>
<artifactId>bar</artifactId>
<version>1.0</version>
</dependency>


ทางแก้ดูแล้วง่ายดาย แต่จริงๆแล้ว มันไปยุ่งตอนที่หาว่า library ตัวไหนที่เราควรจะไปใส่ excludes ให้มัน
วิธีการก็คือ ตอนที่สั่ง mvn command (กรณีของผมก็คือ eclipse:eclipse) ให้ใส่ -X ลงไปด้วย
จากนั้นก็นั่งไล่หาว่า เจ้าตัวไหนคือตัวปัญหา (คำเตือน วิธีนี้มีผลข้างเคียงก็คือ ทำให้เกิดอาการง่วงนอน)

Related link from Roti