Maven Java Example Application
In this application, we will create a simple adder that computes the sum of two integers. During this process, we will:
- Generate a Maven project using the Maven command-line tool
- Configure the
pom.xml
file - Create main and test source code files
- Execute a Maven build
- Execute the resulting JAR file
Generating a Project
The first step to create our application is to generate the basic project structure. While we could do this manually, Maven includes a goal that will generate a quickstart project for us.
To generate this project, we execute the following command:
mvn archetype:generate \
-DgroupId=com.dzone.albanoj2.maven.java \
-DartifactId=adder \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
Maven will then generate the following project structure for us:
adder/
|- src/
| |- main
| | +- java/
| | +- com/dzone/albanoj2/maven/java
| | +- App.java
| +- test
| +- java/
| +- com/dzone/albanoj2/maven/java
| +- AppTest.java
+- pom.xml
Configuring the POM
Although the pom.xml
file has been generated for us, it contains boilerplate configuration that is unnecessary for our purposes. Instead, we will replace the entire contents of the pom.xml
file with the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.dzone.albanoj2.maven.java</groupId>
<artifactId>addr</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<junit.version>5.6.2</junit.version>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.dzone.albanoj2.maven.java.Application</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
Starting from the top, we have our standard model version and GAV. After the GAV, we have our properties. These properties are key-value pairs, where the element name is the key, and the element value is the value. For example, the entry <maven.compiler.target>11</maven.compiler.target> creates a property where maven.compiler.target
is the key and 11
is the value.
从顶部开始,我们有标准模型版本和GAV。GAV之后,我们拥有属性。这些属性是键-值对,其中元素名称是键,元素值是值。例如,条目<maven.compiler.target> 11 </maven.compiler.target>创建一个属性,其中maven.compiler.target是键,而11是值
Generally, properties can be any arbitrarily-named entry — so long as the key is a valid XML element name— and can be used elsewhere in the POM using the ${<key>}
syntax. For example, we declare a property <junit.version> 5.6.2</junit.version> and use it in the
通常,属性可以是任意命名的条目(只要键是有效的XML元素名称),并且可以使用$ {
Other properties, such as maven.compiler.source
, have special meaning. We have four of these special-case properties in our POM:
其它属性,例如maven.compiler.source,具有特殊含义。POM中有以下四个特殊情况属性:
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
The first two define the encoding type of our source code and reporting output, respectively. If we omit these encoding types, Maven will warn us during compilation that our build is platform-dependent:
前两个分别定义了源代码和报告输出的编码类型。如果省略这些编码类型,则Maven将在编译期间警告我们,我们的构建依赖于平台:
[WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent!
[WARNING] File encoding has not been set, using platform encoding Cp1252, i.e. build is platform dependent!
The last two properties configure the JDK version of our source code and the expected target JDK version, respectively. These keys are known by the Java compiler plugin for Maven and will, in turn, set the source and target JDK versions of the compiler.
最后两个属性分别配置我们的源代码的JDK版本和预期的目标JDK版本。这些密钥是Maven的Java编译器插件已知的,它们将依次设置编译器的源JDK版本和目标JDK版本
Next, we declare our JUnit dependency (under the dependencies
element), which allows us to execute our automated tests. Note that the scope is test
, which ensures that this dependency is not compiled or resolved in our executable application — only during the test phase.
接下来,我们声明JUnit依赖项(在依赖项下),这使我们能够执行自动化测试。请注意,作用域是test,这可以确保仅在测试阶段就不会在我们的可执行应用程序中编译或解析此依赖项
Lastly, we add the build
element to override the default build configuration. In this case, we override the configuration for the maven-jar-plugin
plugin to set the fully-qualified name of the main class that will be executed when we run our generated JAR file. While this is a concise override, there is an array of other options that can be overridden if needed. For more information, see the official Maven JAR Plugin documentation.
最后,我们添加构建元素以覆盖默认的构建配置。在这种情况下,我们将覆盖maven-jar-plugin插件的配置,以设置运行生成的JAR文件时将执行的主类的全限定名称
Creating the Main & Test Source Code
With our project structure and POM established, we can now add the source code to our project. The first step is to delete the App.java
and AppTest.java
files in src/main/java/com/dzone/albanoj2/maven/java
and src/test/java/com/dzone/albanoj2/maven/java
, respectively. We will then create a new file called Adder.java
in src/main/java/com/dzone/albanoj2/maven/java
:
Adder.java
package com.dzone.albanoj2.maven.java;
public class Adder {
public int add(int a, int b) {
return a + b;
}
}
Next, we create an Application
class in the same directory that includes a basic main
method:
Application.java
package com.dzone.albanoj2.maven.java;
public class Application {
public static void main(String[] args) {
Adder adder = new Adder();
System.out.println("2 + 2 = " + adder.add(2, 2));
}
}
Lastly, we will create a new file called AdderTest.java
in src/test/java/com/dzone/albanoj2/maven/java
that will act as our unit test for our Adder
class:
AdderTest.java
package com.dzone.albanoj2.maven.java;
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import com.dzone.albanoj2.maven.java.Adder;
public class AdderTest {
private Adder adder;
@BeforeEach
public void setUp() {
adder = new Adder();
}
@Test
public void whenAddTwoZeros_ThenSumIsZero() {
assertEquals(0, adder.add(0, 0));
}
@Test
public void whenAddFirstZeroSecondNegative_ThenSumIsEqualToSecond() {
assertEquals(-1, adder.add(0, -1));
}
@Test
public void whenAddFirstNegativeSecondZero_ThenSumIsEqualToFirst() {
assertEquals(-1, adder.add(-1, 0));
}
@Test
public void whenTwoNegatives_ThenSumIsCorrect() {
assertEquals(-3, adder.add(-1, -2));
}
@Test
public void whenAddFirstZeroSecondPositive_ThenSumIsEqualToSecond() {
assertEquals(1, adder.add(0, 1));
}
@Test
public void whenAddFirstPositiveSecondZero_ThenSumIsEqualToFirst() {
assertEquals(1, adder.add(1, 0));
}
@Test
public void whenTwoPositives_ThenSumIsCorrect() {
assertEquals(3, adder.add(1, 2));
}
@Test
public void whenAddFirstPositiveSecondNegative_ThenSumIsCorrect() {
assertEquals(0, adder.add(1, -1));
}
@Test
public void whenAddFirstNegativeSecondPositive_ThenSumIsCorrect() {
assertEquals(0, adder.add(-1, 1));
}
}
This results in the following directory structure:
adder/
|- src/
| |- main
| | +- java/
| | +- com/dzone/albanoj2/maven/java
| | |- Adder.java
| | +- Application.java
| +- test
| +- java/
| +- com/dzone/albanoj2/maven/java
| +- AdderTest.java
+- pom.xml
Executing the Build
We now have all of the components necessary to execute our Maven build. Our goal for this build will be to generate a JAR file that we can execute from the command-line. Therefore, we will use the Maven package
goal to generate our JAR.
现在,具有执行Maven构建所需的所有组件。此构建的目标是生成可以从命令行执行的JAR文件。因此,我们将使用Maven package目标来生成JAR。
Before starting the build, we must change the directory to our project root (the adder/
directory). Once inside the project root, we then execute the following command:
开始构建之前,我们必须将目录更改为项目根目录(adder/)。进入项目根目录后,我们将执行以下命令:
mvn package
Finding & Running Packaged JAR
Once the build completes, we can find the packaged JAR — adder-1.0.0.jar
— in the target/
directory. To execute this JAR, we change directory to target/
and execute the following command:
java -jar target\addr-1.0-SNAPSHOT.jar
This execution results in the following output:
2 + 2 = 4