แสดงบทความที่มีป้ายกำกับ maven แสดงบทความทั้งหมด
แสดงบทความที่มีป้ายกำกับ maven แสดงบทความทั้งหมด

วันพฤหัสบดี, สิงหาคม 06, 2558

แก้ปัญหา maven dependency: spring-boot 1.2.5 กับ JSTL และ Jasper Reports

แก้ปัญหา maven dependency: spring-boot 1.2.5 กับ jstl 1.2.1 และ jasperreports 6.1

เนื่องจากมีน้องเดินมาให้ช่วยดูให้หน่อยว่าทำไมเค้าใส่ dependency ใน pom ของเค้าแล้วมันมีปัญหา เค้าอยากจะใส่ jstl กับ jasper report เข้าไปใน spring-boot project ของเค้า

บางส่วนของ pom ที่เรียกใช้งาน spring-boot 1.2.5

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.2.5.RELEASE</version>
</parent>
...
<dependencies>
...
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>   
...
</dependencies>
  • dependency ตัวนี้ org.springframework.boot.spring-boot-starter-web จะดึงเอา tomcat embeded version 7 มาให้อยู่แล้ว

JSTL dependency

เริ่มโดยน้องเค้าใส่

<dependency>
    <groupId>javax.servlet.jsp</groupId>
    <artifactId>javax.servlet.jsp-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency> 
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId> 
</dependency>
  • JSP 2.3 มากับ Tomcat 8 แต่ spring-boot 1.2.5 ใช้ embedded tomcat 7 classes มันน่าจะไม่ compatible กันละ
  • JSTL จาก group id javax.servlet เป็น version 2.0 ซึ่งหากดูใน web site เค้าก็บอกว่ามันย้าย group id ใหม่แล้ว javax.servlet.jsp.jstl
  • JSTL 2.0 มัน depend กับ jsp-api 2.0 ซึ่งมันก็ขัดกับ jsp-api ที่ระบุเอาไว้ก่อนหน้าอีก

ทีนี้ผมเลยพยายามจะใส่ JSTL 1.2.1 ใหม่ล่าสุดลงไป

ลบ dependency สองตัวข้างบนออกซะ แล้วใส่แบบนี้ลงไปใน pom

<dependencies>
...
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>javax.servlet.jsp.jstl-api</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>
...
</dependencies>
  • ใส่ org.apache.tomcat.embed.tomcat-embed-jasper เข้ามาด้วยเพราะว่าตัวนี้จะดึงเอา jsp-api ที่เหมาะสมมาให้เราด้วย, ถ้าจะใช่ jstl ต้องมี jsp-api (javax.servlet.jsp) ตัว spring-boot-starter-web เราได้มาแต่ servlet-api (javax.servlet)

พอทดสอบ $ mvn spring-boot:run กลับรันหน้า jsp ของเราไม่ได้ ลองมาเปิด jar ที่อยู่ .m2 ดู ปรากฎว่า jar ที่ได้จาก artifactId jstl มันเป็น jar เน่า มี classes ใน package name ด้วย :( ทำไง ... google ต่อ

คนนี้เค้าบอกวิธีที่ใช้ได้เอาไว้ที่ SO นี้ ขอบคุณครับ ;)

<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>javax.servlet.jsp.jstl-api</artifactId>
    <version>1.2.1</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>javax.servlet.jsp.jstl</artifactId>
    <version>1.2.1</version>
    <exclusions>
        <!-- jstl-api was adding selvlet-api 2.5 and jsp-api -->
        <exclusion>
            <artifactId>jstl-api</artifactId>
            <groupId>javax.servlet.jsp.jstl</groupId>
        </exclusion>
    </exclusions>
</dependency>

ต้องไปเอา jstl library จาก groupId ของ glassfish แทน

ต่อมาอยากได้

JasperReport 6.1

จะเอา jasper report ใส่ใน project maven ใส่แบบนี้

<dependency>
    <groupId>net.sf.jasperreports</groupId>
    <artifactId>jasperreports</artifactId>
    <version>6.1.0</version>
</dependency>  

มีปัญหาว่าพอให้ maven update dependency มันหา olap4j library ไม่เจอ ใน ecilpse ฟ้องแบบนี้ Missing artifact org.olap4j:olap4j:jar:0.9.7.309-JS-3

ลองกดดูที่ maven central ตาม URL นี้ org.olap4j » olap4j ก็จะเจอ 404 file not found !! ห๊ะ

[404]

Not Found: /artifact/org.olap4j/olap4j/0.9.7.309-JS-3

งงอยู่ซักแพ๊บ google ต่อ มาเจอ คำตอบ ที่นี่เอง

ใน community ของ jaspersoft ว่าเราจะต้องเพิ่ม URL repository ตัวนี้เข้าไปใน maven's proxy ของเราด้วย http://jaspersoft.artifactoryonline.com/jaspersoft/third-party-ce-artifacts/

เมื่อไปเพิ่ม URL ข้างต้นใน Artifactory virtual repository แล้วก็ update dependency ใหม่อีกครั้ง ที่นี้ก็ทำงานต่อได้แล้ว

เผอิญว่าที่ทำงาน ผมตั้ง Artifactory server เป็น maven proxy เอาไว้ ก็เลยเจอปัญหานี้ หาก maven ได้วิ่งออก internet ตรงๆ ก็คงไม่เป็นไร

วันจันทร์, กรกฎาคม 20, 2558

แก้ปัญหา ส่ง parameter ภาษาไทยด้วย RESTful GET กับ tomcat-maven-plugin

ปัญหามันเกิดจากค่า default uriEncoding ของ tomcat จะเป็น ISO-8859-1 (ตัวอักษรอังกฤษเท่านั้น) ถึงเราจะใช้ servlet filter เช่น org.springframework.web.filter.CharacterEncodingFilter กำหนดไว้ที่ web.xml แล้วก็ตาม เราจะต้องกำหนด uriEncoding ของ tomcat connector เป็น UTF-8 ด้วย

วิธีแก้ไข คือบอก tomcat ให้ใช้ uriEncoding เป็น UTF-8 ด้วย property นี้ maven.tomcat.uriEncoding

ซึ่งทำได้หลายวิธีดังนี้

วิธีที่ 1. ใส่ property เวลา execute mvn tomcat:run

 $ mvn tomcat:run -Dmaven.tomcat.uriEncoding=UTF-8  

วิธีที่ 1 มันเปลืองพลังงานการพิมพ์ นำมาสู่วิธีที่ 2

วิธีที่ 2. ใส่ไว้ที่ pom.xml ในส่วนที่เราประกาศใช้งาน tomcat-maven-plugin

<project>
  ...
  <build>
    ...
    <plugins>
      ...
    <plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
  <uriEncoding>UTF-8</uriEncoding>
</configuration>
   </plugin>
    ...
    </plugins>
    ...
  </build>
  ...
</project>

ข้อสังเกต หากทำแล้วก็ยังใช้งานไม่ได้อีก ให้สังเกตดูที่ console เวลา log มันวิ่งไป ว่า maven มันใช้งาน tomcat-maven-plugin ตัวไหนกันแน่

[INFO] <<< tomcat-maven-plugin:1.1:run (default-cli) @

ซึ่งหากเป็นแบบนี้ คือมันดันไปเอา tomcat plugin version 1.1 มาใช้ แทนที่จะเอา version 2.2 ตามที่เรา config เอาไว้ใน pom ข้างต้นแล้วล่ะก็ มันก็เท่ากับว่าเรา config ผิดตัวน่ะสิ่ -_-” แสดงว่ามันมี dependencies บางตัวที่ไปดึงเอา tomcat คนละตัวมา

ถ้าไม่อยากแก้ไข pom เรายังมีไม้สุดท้าย วิธีที่ 3

วิธีที่ 3. กำหนด properties เป็น global ไปเลย

<project>
  …
<properties>
…
<maven.tomcat.uriEncoding>UTF-8</maven.tomcat.uriEncoding>
…
</properties>
  ...
</project>

หากสังเกตดูจะพบว่าการที่เรากำหนด configuration ต่างๆใน properties tag เนี่ย จะเหมือนกับที่เราใส่ตอนที่ execute ใน command line แล้วใส่ -D เลย

ฉะนั้นหากจะต้องมาพิมพ์ใส่ -D หลายๆตัวใน command line มันก็ดูเยอะ เลอะเทอะ ย้ายเอามาใส่ใน properties tag นี้ ได้นะเออ

Happy Coding ^ ^

วันศุกร์, มกราคม 23, 2558

SOLVED: แก้ไข exception ComponentLookupException เวลา execute MojoTest

    ทำ maven plugin ขึ้นมาเพื่อให้ทีมฯใช้งาน เราก็จะเขียน test plugin ของเราด้วย

  link นี้ข้อมูลเก่า ไม่เห็นใครใน github เขียนแบบที่แนะนำเอาไว้เลย...ข้ามไป
https://cwiki.apache.org/confluence/display/MAVENOLD/Maven+Plugin+Harness

  link ที่ได้มาจากหน้าแรกของการ googling คือ Cookbook: How To Use Maven Plugin Testing Harness? ข้อมูลยังใหม่อยู่ จะเห็นว่าอัพเดตเมื่อปี 2014 นี่เอง ผมก็ทำตามที่เค้าแนะนำ คือ

1. ให้ใช้ plugin ตัวนี้ maven-plugin-testing-harness
<project>
  ...
  <dependencies>
    <dependency>
      <groupId>org.apache.maven.plugin-testing</groupId>
      <artifactId>maven-plugin-testing-harness</artifactId>
      <scope>test</scope>
    </dependency>
    ...
  </dependencies>
  ...
</project>

2.  เขียน test class ขึ้นมา ซึ่งเราต้อง extends AbstractMojoTestCase และใน class ต้อง override setUp() ด้วย, มี method สำหรับ test class ของเรา ในเอกสารมันก็บอกแค่นี้

public class MyMojoTest
    extends AbstractMojoTestCase
{
...
protected void setUp()
        throws Exception
    {
        // required
        super.setUp();

        ...
    }
...
public void testSomething()
        throws Exception
    {
...
}
...
}

3. สร้าง pom สำหรับ test, แก้ไข pom ของ plugin project

4. ทดลองสั่ง

$mvn clean test

มึน!ครับ ได้ Exception แบบนี้
...
org.codehaus.plexus.component.repository.exception.ComponentLookupException: java.util.NoSuchElementException
      role: org.apache.maven.repository.RepositorySystem
  roleHint:
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:257)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:245)
at org.codehaus.plexus.DefaultPlexusContainer.lookup(DefaultPlexusContainer.java:239)
at org.codehaus.plexus.PlexusTestCase.lookup(PlexusTestCase.java:206)
at org.apache.maven.plugin.testing.AbstractMojoTestCase.setUp(AbstractMojoTestCase.java:126)
... 

คือตามที่ทำตัวหน้า แค่เรียกตัว method setup ก็พังแล้ว -_-" 

    นั่งงมอยู่นานครับ ทำไมๆๆ ไม่อยากให้เสียเวลาเหมือนกับผม จึงมาเขียนเอาไว้ครับ เราจะต้องเพิ่ม dependency อีกหนึ่งตัวสำหรับการ test นี้ maven-compat;ที่ทำตัวหนาไว้
...
<dependency>
    <groupId>org.apache.maven.plugin-testing</groupId>
   <artifactId>maven-plugin-testing-harness</artifactId>
   <version>3.1.0</version>
   <scope>test</scope>
 </dependency>
<dependency>
    <groupId>org.apache.maven</groupId>
    <artifactId>maven-compat</artifactId>
    <version>3.1.1</version>
</dependency>
...

   ส่วน dependecy junit ผมเลือกใช้ version 4.10 มันมี warning บอกให้ใช้ version ที่ใหม่กว่านี้ ก็เลยเปลี่ยนซะ

เพิ่ม depency maven-compat แล้ว ก็ไปต่อได้แล้วครับ มันจะวิ่งเข้า test method เราแล้ว 



วันพฤหัสบดี, มกราคม 22, 2558

ใส่ build time ใน MANIFEST.MF ให้ jar file ที่ build ด้วย maven 3

    ทำ library package เป็น jar file ออกมาแล้วอยากให้มี build time อยู่ใน jar file ด้วย ข้อมูลแบบนี้เค้าจะใส่ไว้ใน MANIFEST ไฟล์กัน ไฟล์มันจะชื่อ MANIFEST.MF

ถ้าลองแกะออกมาดูจาก jar file จะเห็นcontent ประมาณนี้ 

Manifest-Version: 1.0
Built-By: siritas_s
Build-Jdk: 1.7.0_25
Created-By: Apache Maven 3.1.0
Archiver-Version: Plexus Archiver

    ค้นๆ ไปเจอ Cookbook: How To Add Build Time To A JAR Manifest? นี้ นั่งทดลองอยู่ตั้งนานทำไมมันไม่ได้ซักที(วะ) ผมสรุปเองว่ามันเป็นวิธีที่เก่าแล้ว สมัย maven 2 ล่ะมั้ง แถมต้องใส่โน่นนี่ยึบยั่บใน pom

   วิธีสำหรับ maven 3.x สั้นกระชับ ตามนี้เลย

ถ้าใน build ยังไม่มี plugin id maven-jar-plugin ตัวนี้ก็ใส่เข้าไปใต้ <build>

<build>
...
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
    <archive>
        <manifestEntries>
            <Build-Time>${maven.build.timestamp}</Build-Time>
        </manifestEntries>
    </archive>
    </configuration>
    </plugin>
...
</build>

เพิ่ม config ใน pom แล้ว สั่ง mvn clean package ใหม่  ลองแกะออกมาดูจาก jar file จะเห็นcontent ประมาณนี้

Manifest-Version: 1.0
Build-Time: 20150122-1421
Built-By: siritas_s
Build-Jdk: 1.7.0_25
Created-By: Apache Maven 3.1.0
Archiver-Version: Plexus Archiver

ถ้าอยากเปลี่ยน date format ของ build time ก็เพิ่ม property ตามนี้เข้าไปใต้ <project>
<project>
...
<properties>
    <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>

</properties>
...
</project>

Happy แล้ว กลับไปทำงานต่อละ