➜ Old React website
Chung Cheuk Hang MichaelJava Web Developer
用 Vite 建立 React 網站JMeter performance testing

寫一個 Maven Java shared library

Table of contents

1 何謂 Maven shared libraries

顧名思義,Maven shared libraries 就係可以畀唔同 Maven projects 共用既 Maven libraries。一般黎講,shared libraries 都會提供一啲有特定用途既 public API classes。

1.1 3rd party Maven library 例子

  • Apache Commons Lang
  • Apache Commons IO
  • Google Guava

2 Best practices

  • 所有 public 既 Java classes 都要寫 Javadoc,因為用家可能會睇。
  • 所有 public 既 Java methods 都要寫 Javadoc,因為用家可能會睇。
  • 應該提供埋包含 Java source code 既 JAR 檔。
  • 應該提供埋包含 Javadoc HTML 既 JAR 檔。
  • 應該要寫 unit tests,最好有 full code coverage,覆蓋到所有或者大部分 branches(conditions),亦要出到 report,喺 CI/CD pipeline 平台(例如 Jenkins、GitHub Actions)上面睇到。

3 動手寫

Project structure:
  • src
    • /main/java
      • /code
        • MickMathUtils.java
    • /test/java
      • /code
        • MickMathUtilsTest.java
  • pom.xml

3.1 Maven POM

如果需要將 artifact 上載到某個 remote Maven repository,可以參考呢篇:自建 Nexus Maven repo
1<?xml version="1.0" encoding="UTF-8"?> 2<project xmlns="http://maven.apache.org/POM/4.0.0" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> 5 <modelVersion>4.0.0</modelVersion> 6 7 <groupId>com.michael</groupId> 8 <artifactId>mick-math-lib</artifactId> 9 <version>1.0.0</version> 10 <packaging>jar</packaging> 11 12 <name>mick-math-lib</name> 13 <description>This is Michael's shared library for Math calculations.</description> 14 15 <properties> 16 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 17 <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> 18 <java.version>17</java.version> 19 <javac.source>17</javac.source> 20 <javac.target>17</javac.target> 21 <maven.compiler.target>17</maven.compiler.target> 22 <maven.compiler.source>17</maven.compiler.source> 23 </properties> 24 25 <dependencies> 26 <dependency> 27 <groupId>junit</groupId> 28 <artifactId>junit</artifactId> 29 <version>4.13.2</version> 30 <scope>test</scope> 31 </dependency> 32 </dependencies> 33 34 <build> 35 <plugins> 36 <plugin> 37 <groupId>org.apache.maven.plugins</groupId> 38 <artifactId>maven-source-plugin</artifactId> 39 <version>3.3.1</version> 40 <executions> 41 <execution> 42 <id>attach-sources</id> 43 <phase>package</phase> 44 <goals> 45 <goal>jar-no-fork</goal> 46 </goals> 47 </execution> 48 </executions> 49 </plugin> 50 51 <plugin> 52 <groupId>org.apache.maven.plugins</groupId> 53 <artifactId>maven-javadoc-plugin</artifactId> 54 <version>3.6.3</version> 55 <executions> 56 <execution> 57 <id>attach-javadoc</id> 58 <phase>package</phase> 59 <goals> 60 <goal>jar</goal> 61 </goals> 62 </execution> 63 </executions> 64 </plugin> 65 66 <plugin> 67 <groupId>org.jacoco</groupId> 68 <artifactId>jacoco-maven-plugin</artifactId> 69 <version>0.8.12</version> 70 <executions> 71 <execution> 72 <goals> 73 <goal>prepare-agent</goal> 74 </goals> 75 </execution> 76 <execution> 77 <id>jacoco-coverage</id> 78 <phase>test</phase> 79 <goals> 80 <goal>report</goal> 81 </goals> 82 </execution> 83 </executions> 84 </plugin> 85 </plugins> 86 </build> 87</project>

3.2 寫 Java code

喺寫 code 既同時,都要寫埋 Javadoc(/** */ 裡面既野)。
MickMathUtils.java
1package code; 2 3/** 4 * A very simple math utility class. 5 * 6 * @author Michael 7 */ 8public class MickMathUtils { 9 10 /** 11 * Adds the two given values and returns the sum. 12 * 13 * @param a the fist addend (a.k.a. augend) 14 * @param b the second addend 15 * @return the sum 16 */ 17 public int add(int a, int b) { 18 return a + b; 19 } 20 21 /** 22 * Divides a value by another and returns the quotient. 23 * 24 * @param a the dividend 25 * @param b the divisor 26 * @return the quotient 27 * @throws IllegalArgumentException if the divisor is zero 28 */ 29 public int divide(int a, int b) throws IllegalArgumentException { 30 31 if (b == 0) { 32 throw new IllegalArgumentException("Divisor cannot be zero!"); 33 } 34 35 return a / b; 36 } 37}

4 Unit testing

我地會寫足以達到 100% code coverage 既 unit tests。要達到 100% code coverage,必須覆蓋到所有 if-else logical conditions。

4.1 寫 JUnit test class

MickMathUtilsTest.java
1package code; 2 3import org.junit.Assert; 4import org.junit.Test; 5 6public class MickMathUtilsTest { 7 8 @Test 9 public void test_add() { 10 final int sum = new MickMathUtils().add(2, 5); 11 Assert.assertEquals("Incorrect sum", 7, sum); 12 } 13 14 @Test 15 public void test_divide() { 16 final int product = new MickMathUtils().divide(10, 2); 17 Assert.assertEquals("Incorrect quotient", 5, product); 18 } 19 20 @Test 21 public void test_divide_byZero() { 22 try { 23 new MickMathUtils().divide(10, 0); 24 Assert.fail(); 25 } catch (IllegalArgumentException e) { 26 // expected 27 } 28 } 29}

4.2 Eclipse IDE JUnit code coverage

開發既時候,我地可以利用 Eclipse IDE,喺執行 JUnit unit testing 既時候睇到 unit test 既 code coverage:

5 本地安裝/上載 remote repo

執行 command 安裝到本地 Maven repo:
mvn clean test install
或者上載埋去 remote repo:
mvn clean test install deploy

5.1 Jacoco coverage report

執行完 mvn test 就會生成到 Jacoco coverage HTML report。
我地可以打開 target/site/jacoco/index.html

6 喺另一個項目使用 shared library

我地會寫一個 Spring Boot web application 項目去用我地寫左既 Maven shared library。

6.1 Maven dependencies

1<parent> 2 <groupId>org.springframework.boot</groupId> 3 <artifactId>spring-boot-starter-parent</artifactId> 4 <version>3.2.5</version> 5</parent> 6 7<dependencies> 8 <dependency> 9 <groupId>org.springframework.boot</groupId> 10 <artifactId>spring-boot-starter-web</artifactId> 11 </dependency> 12 13 <dependency> 14 <groupId>com.michael</groupId> 15 <artifactId>mick-math-lib</artifactId> 16 <version>1.0.0</version> 17 </dependency> 18</dependencies>

6.2 寫 Java code

MyController.java
1@RestController 2public class MyController { 3 4 @GetMapping("/add") 5 public int add(@RequestParam("a") int a, @RequestParam("b") int b) { 6 return new MickMathUtils().add(a, b); 7 } 8 9 @GetMapping("/divide") 10 public int divide(@RequestParam("a") int a, @RequestParam("b") int b) { 11 return new MickMathUtils().divide(a, b); 12 } 13}

6.2.1 檢視 shared library Java source code

Ctrl + click 落 MickMathUtils 既話,Eclipse IDE 會帶我地去 MickMathUtils.class,而因為有 mick-math-lib-1.0.0-sources.jar,就可以顯示到原本既 Java source code,唔需要用到 decompiler。

6.2.2 檢視 shared library Javadoc

因為有 mick-math-lib-1.0.0-javadoc.jar,我地可以叫 Eclipse IDE 喺瀏覽器開個 Javadoc 網頁出黎。
Package Explorer > 個 Spring Boot web app project > Maven Dependencies > mick-math-lib-1.0.0.jar > rick-click > Maven > Open Javadoc。

7 參考資料