I've been using Gradle for a long time, but I have to use Maven for work, so I'm studying.
Java build tool. OSS. It seems to have been created as an alternative to Apache Ant.
The reading is "Maven" or "Maven" (I am a Maven school).
It's been around for a long time [^ 1], but it's still under development, and I get the impression that there are many projects that use Maven. As of 2020, Maven or Gradle is often the choice for Java build tools (I think).
[^ 1]: Maven 1.0 in 2004, Maven 2.0 in 2005, Maven 3.0 in 2010 (Maven – Maven Releases History)
The major version as of 2020 is 3. Maven 1 and 2 are not compatible, but 2 and 3 are still compatible.
>mvn --version
Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
Maven home: ...\bin\..
Java version: 11.0.6, vendor: AdoptOpenJDK, runtime: ...
Default locale: ja_JP, platform encoding: MS932
OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"
-Download the archive (ʻapache-maven-X.X.X-bin.zip`) from Official Site --Unzip at a suitable place
State after defrosting
`-apache-maven-X.X.X/
|-bin/
|-boot/
|-conf/
|-lib/
|-LICENSE
|-NOTICE
`-README.txt
in the above example) is described as
% MAVEN_HOME%` thereafter.--Pass the path to % MAVEN_HOME% \ bin
--Installation is completed when the version information is displayed by executing the following command.
Confirmation of installation
>mvn --version
Apache Maven X.X.X (...)
...
Common settings across projects can be described in one of the following files:
%MAVEN_HOME%\conf\settings.xml
%USERPROFILE%\.m2\settings.xml
[^2][^ 2]: % USERPROFILE%
is a Windows environment variable that points to the user's home (for Linux, it means $ HOME
).
The contents set in the former file are common to all projects across users. The contents set in the latter file are common across projects within the user.
The former file is in the downloaded zip, but all settings are empty and explained in the comments. The latter file does not exist at first, so it is better to copy the former file.
settings.xml
<settings ...>
...
<proxies>
<proxy>
<id>optional</id>
<active>true</active>
<protocol>http</protocol>
<username>proxyuser</username>
<password>proxypass</password>
<host>proxy.host.net</host>
<port>80</port>
<nonProxyHosts>local.net|some.host.com</nonProxyHosts>
</proxy>
</proxies>
...
</settings>
Rewrite the required settings and write them in one of the above settings.xml
.
Hello World
--Open the command line in an appropriate folder and execute the following command.
> mvn archetype:generate
--For the first time, the following list will be displayed after various downloads and other processes have been performed.
...
Choose archetype:
1: internal -> org.appfuse.archetypes:appfuse-basic-jsf (AppFuse archetype for creating a web application with Hibernate, Spring and JSF)
2: internal -> org.appfuse.archetypes:appfuse-basic-spring (AppFuse archetype for creating a web application with Hibernate, Spring and Spring MVC)
3: internal -> org.appfuse.archetypes:appfuse-basic-struts (AppFuse archetype for creating a web application with Hibernate, Spring and Struts 2)
...
16: internal -> org.apache.maven.archetypes:maven-archetype-quickstart ()
...
57: internal -> org.fusesource.scalate.tooling:scalate-archetype-empty (Generates a Scalate empty web application)
58: internal -> org.fusesource.scalate.tooling:scalate-archetype-guice (Generates a Scalate Jog web application)
Choose a number or apply filter (format: [groupId:]artifactId, case sensitive contains): 16:
--"Choose archetype is displayed and you are prompted to enter the archetype number to use. --For now, try selecting the default 16 (ʻorg.apache.maven.archetypes: maven-archetype-quickstart
) (just press Enter to select the default number)
Define value for property 'groupId': : 【com.example】
Define value for property 'artifactId': : 【hello-world】
Define value for property 'version': 1.0-SNAPSHOT: :【】
Define value for property 'package': com.example: :【】
Confirm properties configuration:
groupId: com.example
artifactId: hello-world
version: 1.0-SNAPSHOT
package: com.example
Y: : 【y】
--You will be prompted to enter the basic information of the project to be created, so enter it appropriately.
--In the above example, the part surrounded by []
is the content entered with the keyboard (the empty []
is the part entered without entering anything).
――The meaning of each is a great explanation
--You will be asked if you want to create with the information you entered last, so if there is no problem, enter y
and Enter
--Successful if BUILD SUCCESS
is displayed
--A folder with the same name as the name specified by ʻartifactIdis created in the current folder. --If you created it in the above example, a folder called
hello-worldis created. --The contents of the
hello-world` folder are as follows
hello-The contents of the world folder
hello-world/
|-pom.xml
`-src/
|-main/java/
| `-com/example/
| `-App.java
`-test/java/
`-com/example/
`-AppTest.java
pom.xml
<?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.example</groupId>
<artifactId>hello-world</artifactId>
<version>1.0-SNAPSHOT</version>
<name>hello-world</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
...
</plugins>
</pluginManagement>
</build>
</project>
App.java
package com.example;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
System.out.println( "Hello World!" );
}
}
--A simple Hello World program project has been generated
--Execute the following command to compile the source code
compile
> mvn compile
--Also, various download processes run for the first time (it should be faster because there will be no downloads after the second time)
--Successful when "BUILD SUCCESS" is displayed --The compilation result of ʻApp.java
is output underhello-world / target / classes /
.
--Execute with the following command
hello-Run world
> java -cp target\classes com.example.App
Hello World!
--The first mvn archetype: generate
implements a mechanism called ** archetype ** that automatically generates a project from a template.
--Here, the simplest maven-archetype-quickstart
is selected to automatically generate the project.
POM Maven – Introduction to the POM
Maven settings are described in an XML file called pom.xml. POM is an abbreviation for Project Object Model.
Maven manages build targets in units called ** projects **. The POM is a file that describes various settings for the project.
Super POM POMs have a parent-child relationship, and there is a ** Super POM ** as the highest parent of all POMs. For example, the latest Super POM can be found on the next page.
Maven Model Builder – Super POM
If there is no setting in the POM of the project, the setting of the parent POM is basically inherited. In other words, the Super POM is a POM that describes the default settings that apply to all projects.
If you create a POM with the minimum configuration, the contents of pom.xml will be as follows.
Minimum configuration pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</project>
--Write the <project>
tag at the top
--At least the following four tags must be described in it.
- <modelVersion>
- <groupId>
- <artifactId>
- <version>
--<modelVersion>
specifies the version of POM
――This basically doesn't change, so I think you should specify this value for the time being.
--<groupId>
, <artifactId>
, <version>
define the information to uniquely identify the project.
--The fully qualified name of the project will be <groupId>: <artifactId>: <version>
--In other words, in the case of the above settings, ʻexample: hello: 1.0.0is the fully qualified name of this project. -
--For
groupId, specify a name that can identify the organization to which the project belongs or the superior project. --For example, many plugins provided by Maven have a
groupId of ʻorg.apache.maven.plugins
.
--.
May or may not be attached (junit
etc. is not attached)
--The value of groupId
does not have to match the Java package structure of the project, but it is safer to match it for less confusion.
- <artifactId>
--Specify a name that identifies the project
--For example, the compiler plugin provided by Maven is maven-compiler-plugin
, which is ʻartifactId. -
--
version specifies the version of the project --
groupId and ʻartifactId
will uniquely identify the project, and version
will identify the version.
--Settings not described in this pom.xml are basically inherited from Super POM Ru [^ 3]
--In other words, <url> https://repo.maven.apache.org/maven2 </ url>
is adopted for the setting of <repository>
that is not described.
――However, there are some settings that are not described in Super POM but are adopted by default (such as <packaging>
).
――The story is awesome
[^ 3]: I think "<modelVersion>
is also in Super POM", but unfortunately this is not inherited (it will cause an error if deleted)
--There is no fixed numbering rule for the version number of the artifact (probably)
--However, the version with -SNAPSHOT
at the end has a special meaning.
--A version with the -SNAPSHOT
prefix indicates that it is a version under development.
--The version under development indicates that the contents of the artifact (jar) may be updated.
――On the other hand, the version without SNAPSHOT basically represents the release version, and the contents are not updated (promise).
――It's just a promise, so it's not tied up by the mechanism
--With the repository (Nexus) function described later, it is possible to control the release version so that it cannot be updated and SNAPSHOT can be updated.
In pom.xml, variables can be referenced to avoid the problem of duplicating the same value in multiple places.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>project.groupId = ${project.groupId}</echo>
<echo>project.artifactId = ${project.artifactId}</echo>
<echo>project.version = ${project.version}</echo>
<echo>project.build.directory = ${project.build.directory}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
――Somehow, a lot of them suddenly appeared, but the important points here are as follows.
Extract only important parts
<echo>project.groupId = ${project.groupId}</echo>
<echo>project.artifactId = ${project.artifactId}</echo>
<echo>project.version = ${project.version}</echo>
<echo>project.build.directory = ${project.build.directory}</echo>
--Echoing the values of some variables --The ones that are written around this are adding plugins to enable echo. --When you do this, you get:
Execution result
> mvn antrun:run
...
[echo] project.groupId = example
[echo] project.artifactId = hello
[echo] project.version = 1.0.0
[echo] project.build.directory = F:\tmp\maven\hello\target
...
--You can see that the part described by $ {variable reference expression}
is replaced with the evaluation result of the expression and output.
--All the variables referenced in this example are called ** Project Model Variables **.
--In short, it refers to the value of the tag under <project>
in pom.xml.
--project.version
refers to the value of<project> <version>
--project.build.directory
is not in this pom.xml but Super POM Declared in
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>project.class = ${project.class}</echo>
<echo>project.getClass() = ${project.getClass()}</echo>
<echo>plugins[0].artifactId = ${project.build.plugins[0].artifactId}</echo>
<echo>plugins[1].artifactId = ${project.build.plugins[1].artifactId}</echo>
<echo>plugins[2].artifactId = ${project.build.plugins[2].artifactId}</echo>
</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jdeps-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn antrun:run
...
[echo] project.class = class org.apache.maven.model.Model
[echo] project.getClass() = ${project.getClass()}
[echo] plugins[0].artifactId = maven-antrun-plugin
[echo] plugins[1].artifactId = maven-jdeps-plugin
[echo] plugins[2].artifactId = ${project.build.plugins[2].artifactId}
--The expression written in $ {...}
basically allows you to refer to the property of the object separated by dots (.
).
--If you refer to a property named foo
, the methodgetFoo ()
(or ʻisFoo ()) is executed behind the scenes. --In other words, if you have Getter, you can refer to it by the corresponding property name (you can also refer to
class) --However, you can only refer to properties, you cannot execute methods directly. --If the property is an array or
List, you can use square brackets (
[] ) to refer to the index. --If the expression cannot be evaluated successfully, it will be treated as just a string --The substance of the
projectvariable is [org.apache.maven.model.Model](https://maven.apache.org/ref/current/maven-model/apidocs/org/apache/maven/model/Model" It is an instance of a class called .html) --This
Model` instance is [ReflectionValueExtractor](https://github.com/apache/maven-shared-utils/blob/master/src/main/java/org/apache/maven/shared/utils/introspection/ReflectionValueExtractor" The expression is being evaluated by being passed to .java # L163)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>${project.build.pluginsAsMap(org.apache.maven.plugins:maven-antrun-plugin).id}</echo>
<echo>${project.build.pluginsAsMap(org.apache.maven.plugins:maven-jdeps-plugin).id}</echo>
</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jdeps-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn antrun:run
...
[echo] org.apache.maven.plugins:maven-antrun-plugin:1.8
[echo] org.apache.maven.plugins:maven-jdeps-plugin:3.1.2
--If the property is Map
, you can refer to the key specification in the form offooMap (<key>)
.
--<key>
does not need to be enclosed in double quotation marks ("
), and is used as it is as the key of String
.
--The property pluginsAsMap
is a class called PluginContainer Refers to the method defined in
--This Map
has [Plugin # getKey ()](https://maven.apache.org/ref/3.6.3/maven-model/apidocs/org/apache/maven/model/Plugin.html" as the key. As a result of # getKey-), the Plugin
instance corresponding to the value is set.
--Plugin # getKey ()
returns the value of the plugin's groupId
and ʻartifactId connected by a colon (
: ). --The [Build](https://maven.apache.org/ref/3.6.3/maven-model/apidocs/org/apache/maven/model/Build.html) class that can be referenced in
project.buildis It inherits from this
PluginContainer --As you can see, some classes provide properties that convert
List to
Mapformat. --Specifically, the following class provides
~ AsMap`
- PluginContainer#getPluginsAsMap()
- Plugin#getExecutionsAsMap()
- Reporting#getReportPluginsAsMap()
- ReportPlugin#getReportSetsAsMap()
The overall picture of each class and property that can be referenced from Model
is summarized in the class diagram.
- Red line inherits </ font> - A single reference with a blue line </ font> - Green line is the reference in List </ font>
--There are some variables that are not included in the project model but are specially defined and can be referenced.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
...
<target>
<echo>project.basedir = ${project.basedir}</echo>
<echo>project.baseUri = ${project.baseUri}</echo>
<echo>maven.build.timestamp = ${maven.build.timestamp}</echo>
</target>
...
</build>
</project>
Execution result
[echo] project.basedir = F:\tmp\maven\hello
[echo] project.baseUri = file:///F:/tmp/maven/hello/
[echo] maven.build.timestamp = 2020-03-04T13:45:10Z
--The following three are variables that are implicitly defined as ** Special Variables **.
- project.basedir
--Folder of the project itself
- project.baseUri
--project.basedir
as a URI
- maven.build.timestamp
--Runtime Timestamp (UTC)
--By declaring the property maven.build.timestamp.format
, you can specify the format of maven.build.timestamp
arbitrarily.
--The format format follows SimpleDateFormat.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<properties>
<maven.build.timestamp.format>yyyy/MM/dd HH:mm:ss</maven.build.timestamp.format>
</properties>
<build>
...
<echo>maven.build.timestamp = ${maven.build.timestamp}</echo>
...
</build>
</project>
Execution result
[echo] maven.build.timestamp = 2020/03/04 13:49:49+00:00
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<properties>
<foo>FOO!!</foo>
<fizz.buzz>FIZZ.BUZZ!?</fizz.buzz>
<hoge-fuga>HOGE-FUGA??</hoge-fuga>
</properties>
<build>
...
<echo>foo = ${foo}</echo>
<echo>fizz.buzz = ${fizz.buzz}</echo>
<echo>hoge-fuga = ${hoge-fuga}</echo>
<echo>FOO = ${FOO}</echo>
...
</build>
</project>
Execution result
[echo] foo = FOO!!
[echo] fizz.buzz = FIZZ.BUZZ!?
[echo] hoge-fuga = HOGE-FUGA??
[echo] FOO = ${FOO}
--You can declare your own variables in the <properties>
tag
--You can include -
and .
in the name
--Case sensitive
xml.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
...
<echo>hoge = ${env.hoge}</echo>
<echo>Hoge = ${env.Hoge}</echo>
<echo>HOGE = ${env.HOGE}</echo>
...
</build>
</project>
Execution result(When running on Windows)
> set Hoge=Hello
> mvn antrun:run
...
[echo] hoge = ${env.hoge}
[echo] Hoge = ${env.Hoge}
[echo] HOGE = Hello
...
Execution result(When running on Linux)
$ export Hoge=Hello
$ mvn antrun:run
...
[echo] hoge = ${env.hoge}
[echo] Hoge = Hello
[echo] HOGE = ${env.HOGE}
-- $ {env. Environment variable name}
can be used to refer to the value of the OS environment variable.
--When running on Windows, the variable name of ʻenvis ** normalized with all uppercase letters ** --That is, even if the name of the environment variable declared on Windows is
Path, it must be capitalized as
$ {env.PATH} `when referenced on pom.xml.
――It's just a story on Windows, and when running on Linux, specify it with the same name that is case-sensitive.
――Well, I think that it is common to declare environment variables in all capital letters, so if you write pom.xml in all capital letters, you will not have an accident.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<properties>
<foo.bar>foo-bar</foo.bar>
<fizz.buzz>fizz-buzz</fizz.buzz>
</properties>
<build>
...
<echo>java.version = ${java.version}</echo>
<echo>java.vm.vendor = ${java.vm.vendor}</echo>
<echo>foo.bar = ${foo.bar}</echo>
<echo>fizz.buzz = ${fizz.buzz}</echo>
...
</build>
</project>
Execution result
> mvn antrun:run -Dfoo.bar=FOO-BAR
...
[echo] java.version = 11.0.6
[echo] java.vm.vendor = AdoptOpenJDK
[echo] foo.bar = FOO-BAR
[echo] fizz.buzz = fizz-buzz
--Java system properties (values that can be obtained with System.getProperties ()
) can be referenced as they are with $ {system property name}
.
--If a property with the same name is declared in <properties>
, the value specified in the system property takes precedence.
--One of the important components of Maven is ** Repository ** --In Maven, the artifacts of the created project are saved and managed in the repository. --The actual artifact is usually a jar file created by building the project.
--There are two types of repositories
--Local repository
--Remote repository
--There is a remote repository used by default called Central Repository (https://repo.maven.apache.org/maven2).
-If you open the link above with a browser, you can see that various subdirectories exist.
--If you follow the directory properly, you will finally reach the directory where the jar file is located.
--For example, in this, ver 5.2.4.RELEASE of Spring Framework core is placed. Become a directory
--As you can see, the central repository contains various OSS artifacts from around the world.
--The central repository is managed by a company called Sonatype.
--Anyone can publish their OSS in the central repository by applying (free of charge)
--However, the application is in English
--The unit of application is for each groupId
--If you search for "Maven Central Repository Publishing Procedure", you will find various commentary articles.
--Since it is difficult to search the central repository opened directly in the browser, usually use a search site such as Maven Repository: Search / Browse / Explore.
--Alternatively, refer to the information written on the official page of the library you want to use.
--One of Maven's powerful features is dependency resolution. --In pom.xml, the artifacts used by the project can be defined as dependencies as follows:
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
</project>
--<dependency>
under <dependencies>
points to an artifact
--If you declare it like this, Maven will automatically download the artifacts declared with <dependencies>
from the remote repository when you build the project and add them to your classpath.
――In other words, you can save the trouble of dropping the library by hand.
--In addition, the artifacts stored in the repository also contain their own pom.xml.
--If there are more <dependencies>
in the pom.xml of the artifact specified in the project, Maven will automatically download those dependent artifacts as well.
――In other words, it is a mechanism that resolves all dependencies to the Imozuru formula.
--Maven makes managing dependent libraries much easier thanks to this mechanism.
--Maven's predecessor, Apache Ant, was very painful because it had to manage dependencies manually.
--This mechanism is also used in Gradle, a latecomer to Maven.
--Artif and meta information (such as pom.xml) downloaded from remote repositories are cached locally on the machine running Maven
--This cache destination is called ** local repository **
――If you access the remote repository every time you build, it will take a long time and you will not be able to build in an environment where the network is not available.
--Therefore, Maven is supposed to search the local repository first.
--If the desired artifact does not exist in the local repository, it will go to the remote repository for searching.
--If you find an artifact in the remote repository, download it and save it in your local repository
--This allows you to build a project without network access, as you only need to refer to the local repository from the second time onwards.
--The local repository location defaults to % USERPROFILE% \ .m2 \ repository
--For Linux OS, $ HOME / .m2 / repository
--Artifs cached in the local repository will remain if nothing is done
--Unless there is a reason such as running out of disk space, there is no need to erase it.
--You can build your own remote repository using an OSS application called Nexus Repository OSS. --Nexus is developed by Sonatype, which manages the central repository. --There is a paid version and a free OSS version --For example, if you have an artifact that you want to share only within your company, you can easily use it as a private repository by building a Nexus server within your intranet. --The remote repository to use can be specified in pom.xml as follows: --Host name and port number need to be adjusted according to the actual environment
Pom when a remote repository is specified.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<repositories>
<repository>
<id>my-private-repository</id>
<name>My Private Repository</name>
<url>http://private.repository.host/repository</url>
<layout>default</layout>
</repository>
</repositories>
</project>
--In addition, Nexus also acts as a proxy for other remote repositories. ――For example, suppose you have the following configuration --Build the Nexus repository as a proxy for the central repository --Set Nexus repository as remote repository in pom.xml --If the project has dependent artifacts, Maven will first search the local repository --If it is not in the local repository, then search for the Nexus repository you specified as the remote repository. --Nexus searches the central repository if it is not in the Nexus repository either --And it returns the artifacts downloaded from the central repository to Maven --At this time, the Nexus repository internally caches the artifacts downloaded from the central repository. --If a search request for the same artifact comes in, it will return the cached artifact. ――This will allow you to reduce network traffic, or even if the Internet is not connected due to some kind of failure, you can resolve the dependency by connecting to the Nexus repository in the intranet.
** Proxy image **
In Maven, all processing is done by ** Plugin **.
For example, the process for compiling Java source code is provided by maven-compiler-plugin.
The basic plugins provided by the Maven project itself can be found in the list at Maven – Available Plugins.
--Individual tasks (processes) defined in the plugin are called ** Goal **. --Refer to the documentation of each plugin to find out what goals the plugin you want to use has. --Goals defined in maven-jdeps-plugin - jdkinternals - test-jdkinternals --Goals defined in maven-jar-plugin - jar - test-jar
There are two main ways to execute the goals of a plugin.
The method of linking to the second phase is set aside, and the method of directly specifying 1 is confirmed first.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</project>
Run the jdeps plugin
> mvn org.apache.maven.plugins:maven-jdeps-plugin:3.1.2:jdkinternals
...
classes -> java.base
example -> java.io java.base
example -> java.lang java.base
...
--I'm passing some lengthy arguments to the mvn command
--This specifies the fully qualified name and goal name of the previous maven-jdeps-plugin.
--In the format, it looks like <fully qualified name>: <goal name>
--<fully qualified name>
is here ʻorg.apache.maven.plugins: maven-jdeps-plugin: 3.1.2, --
becomes
jdkinternals`
--If you specify a fully qualified name, the plugin jar file is fetched from the repository based on that information and the goal is executed.
――Since it is difficult to enter the fully qualified name every time, you can also omit the following description.
If omitted
> mvn jdeps:jdkinternals
...
classes -> java.base
example -> java.io java.base
example -> java.lang java.base
...
--This is how to specify the format <prefix>: <goal name>
--Whether it is a fully qualified name specification or a prefix specification is distinguished by the number of colons (:
) [^ 4]
--If there are three :
, specify with the fully qualified name groupId: artifactId: version: goal
.
--If there are two :
, specify groupId: artifactId: goal
without the version number.
--If there is only one :
, specify it with the prefix prefix: goal
.
--If prefix is specified, the fully qualified name will be resolved as follows.
--First, let groupdId
be one of the following:
- org.apache.maven.plugin
- org.codehaus.mojo
--Next, look at the metadata (maven-metadata.xml
) for each groupId
-maven-metadata.xml in org.apache.maven.plugin
-org.codehaus.mojo maven-metadata.xml
--If you look at the contents of maven-metadata.xml
, you can see that the correspondence of prefix is listed for each ʻartifactId`.
xml:org.apache.maven.plugin maven-metadata-xml
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<plugins>
<plugin>
<name>Apache Maven ACR Plugin</name>
<prefix>acr</prefix>
<artifactId>maven-acr-plugin</artifactId>
</plugin>
...
<plugin>
<name>Apache Maven JDeps Plugin</name>
<prefix>jdeps</prefix>
<artifactId>maven-jdeps-plugin</artifactId>
</plugin>
...
</plugins>
</metadata>
--Find a prefix in this maven-metadata.xml
that matches the prefix specified on the command line, and set that<artifactId>
to ʻartifactId. --The prefix specified on the command line is
jdeps, so
maven-jdeps-plugin becomes ʻartifactId
--Next, check the metadata (maven-metadata.xml
) for each ʻartifactId`
-maven-metadata.xml of maven-jdeps-plugin
maven-jdeps-plugin maven-metadata.xml
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jdeps-plugin</artifactId>
<versioning>
<latest>3.1.2</latest>
<release>3.1.2</release>
<versions>
<version>3.0.0</version>
<version>3.1.0</version>
<version>3.1.1</version>
<version>3.1.2</version>
</versions>
<lastUpdated>20190619052916</lastUpdated>
</versioning>
</metadata>
--Set the value set in the release version (<release>
) to version
--If there is no release version, set the latest version (<latest>
) [^ 5] to version
--The groupId
, ʻartifactId,
versiondetermined above are fully qualified names. -
groupId:
org.apache.maven.plugin -
artifactId:
maven-jdeps-plugin -
version:
3.1.2`
[^ 4]: Strictly speaking, even if you specify something like compiler :::: compile
, it will be judged as a prefix specification, but for the sake of clarity, the number of colons is used here (for details, [MojoDescriptorCreator implementation] See](https://github.com/apache/maven/blob/maven-3.6.3/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java#L141) )
[^ 5]: <release>
is the latest version in the release version, while <latest>
refers to the latest version, including snapshots.
-In the method of ↑, the version of the plug-in is decided based on the metadata.
--Maybe you will use the latest version when a new version comes out, but if you can not fix the movement, the build may become unstable
--Therefore, normally, the version of the plug-in used for each project is fixed.
--In the case of ↑, prefix can be specified only when groupId
is either ʻorg.apache.maven.plugin or ʻorg.codehaus.mojo
[^ 6]
--If you want to use plugins of groupId
other than these by specifying prefix, you need to explicitly set the plugin.
[^ 6]: Strictly speaking, you can add the groupId
to be searched by<pluginGroups>
in settings.xml
(Reference: Introduction to Plugin Prefix Resolution guides / introduction / introduction-to-plugin-prefix-mapping.html # Configuring_Maven_to_Search_for_Plugins))
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.8</version>
</plugin>
</plugins>
</build>
</project>
--Individual plugins are set with the <plugin>
tag
--<plugin>
is listed under <build> <plugins>
--Specify the fully qualified name of the plugin with <groupId>
, <artifactId>
, <version>
--Here, Asciidoctor Maven Plugin is set.
--This setting locks the version of ʻasciidoctor-mavne-pluginto
1.5.8`.
asciidoctor-maven-Running plugin
> mvn asciidoctor:process-asciidoc
...
[INFO] BUILD SUCCESS
...
-When the plugin is specified by <plugin>
as in ↑, the method of resolving the fully qualified name from the prefix specification changes a little.
--First, Maven checks the plugin.xml
of each plugin that is explicitly set in pom.xml.
--Usually plugin.xml
is stored under META-INF / maven
in the plugin jar
--For example, the plugin.xml
of ʻasciidoctor-mavne-plugin` looks like this:
asciidoctor-maven-plugin plugin.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by maven-plugin-tools 3.5 on 2019-03-30 -->
<plugin>
<name>Asciidoctor Maven Plugin and Doxia Parser</name>
<description>Asciidoctor Maven Plugin and Doxia Parser (for Maven Site integration)</description>
<groupId>org.asciidoctor</groupId>
<artifactId>asciidoctor-maven-plugin</artifactId>
<version>1.5.8</version>
<goalPrefix>asciidoctor</goalPrefix>
<isolatedRealm>false</isolatedRealm>
<inheritedByDefault>true</inheritedByDefault>
...
--The important thing here is the value set in <goalPrefix>
--The plugins groupId
and ʻartifactIdwhose value is equal to the prefix specified on the command line are adopted. --Finally,
version is determined as follows --If specified in pom.xml, that version will be adopted --If not specified, it is determined from the metadata (
maven-metadata.xml) for each ʻartifactId
(same method as when no plugin is specified).
--In the explanation so far, you can see that ʻartifactIdand prefix are essentially unrelated. --The prefix is determined by
in
maven-metadata.xml or
in
plugin.xml. --However, the plugins that actually exist have the following relationship between ʻartifactId
and prefix.
--For official plugins provided by the Maven project
--If ʻartifactId is
maven-XXX-plugin,
XXX is the prefix --For other plugins --If ʻartifactId
is XXX-maven-plugin
, XXX
is the prefix
――These are the results of such a naming rule being recommended, and it does not mean that you cannot make a plugin without this name.
--If you want to make it, you can also make a plugin with ʻartifactIdthat is completely different from this naming rule. -** However, the name
maven-XXX-plugin is meant to indicate that it is an official Maven plugin, so be careful as non-official use of this name will result in trademark infringement ** - [Important Notice: Plugin Naming Convention and Apache Maven Trademark](https://maven.apache.org/guides/plugin/guide-java-plugin-development.html#Important_Notice:_Plugin_Naming_Convention_and_Apache_Maven_Trademark) --Unusual naming is not beneficial because it only confuses users, so if you make your own plugin, it is safe to use ʻartifactId
as XXX-maven-plugin
unless you have a specific reason.
――So, ʻartifactId and prefix are not essentially related, but it is safe to think that they are related in practice (I think). --So, if ʻartifactId
is foo-maven-plugin
, you can think of prefix as foo
(I think)
--Conversely, if the prefix is foo
, you can think of ʻartifactId as
foo-maven-plugin` (if it's not a plugin provided by the Maven project).
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>Hello World!!</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn antrun:run
...
main:
[echo] Hello World!!
...
--Plugin settings (** parameters **) can be described with the <configuration>
tag under <plugin>
--The tags that can be specified under <configuration>
are different for each plugin goal.
--Here we are using a plugin called maven-antrun-plugin
--This plugin has the goal of run
--You can see that the parameter that can be specified by <configuration>
is listed on the description page of the run
goal.
--For plugins with multiple goals, the parameters specified in <configuration>
will be applied to all goals.
--You can check what kind of goals the plugin has and what parameters can be specified by looking at the explanation page of each plugin. --However, if you have trouble opening each page, you can check it with maven-help-plugin.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</configuration>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn help:describe
...
Name: Apache Maven AntRun Plugin
Description: Runs Ant scripts embedded in the POM
Group Id: org.apache.maven.plugins
Artifact Id: maven-antrun-plugin
Version: 1.8
Goal Prefix: antrun
This plugin has 2 goals:
antrun:help
Description: Display help information on maven-antrun-plugin.
Call mvn antrun:help -Ddetail=true -Dgoal=<goal-name> to display parameter
details.
antrun:run
Description: Maven AntRun Mojo.
This plugin provides the capability of calling Ant tasks from a POM by
running the nested Ant tasks inside the <tasks/> parameter. It is
encouraged to move the actual tasks to a separate build.xml file and call
that file with an <ant/> task.
For more information, run 'mvn help:describe [...] -Ddetail'
...
-By executing the goal describe, you can describe the plugin specified by <configuration>
. Can be confirmed
--<groupId>
and <artifactId>
allow plugins to be identified as maven-antrun-plugin
-- describe
As you can see from the goal description page, you can use <goal>
to narrow down the goal and <detail>
to output details (parameters that can be specified for each goal).
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<goal>run</goal>
<detail>true</detail>
</configuration>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn help:describe
...
antrun:run
Description: Maven AntRun Mojo.
...
Implementation: org.apache.maven.plugin.antrun.AntRunMojo
Language: java
Available parameters:
...
target
The XML for the Ant target. You can add anything you can add between
<target> and </target> in a build.xml.
...
...
-Although the example of ↑ is omitted, all parameters are output with explanations.
--The parameters specified in <configuration>
of help: describe
can also be specified from the system properties.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn help:describe -Dplugin=antrun
...
Name: Apache Maven AntRun Plugin
Description: Runs Ant scripts embedded in the POM
Group Id: org.apache.maven.plugins
Artifact Id: maven-antrun-plugin
Version: 1.8
Goal Prefix: antrun
This plugin has 2 goals:
antrun:help
Description: Display help information on maven-antrun-plugin.
...
antrun:run
Description: Maven AntRun Mojo.
...
For more information, run 'mvn help:describe [...] -Ddetail'
...
---Dplugin = antrun
is specified as a system property when executing Maven
--Refer to Documentation for the description of the plugin
parameter.
--As you can see, some goal parameters can be passed as system properties.
--Not all parameters can be specified in system properties
--Whether a parameter can be specified in a system property can be checked by checking whether the parameter's document contains ** User property **.
--For example, the plugin parameter documentation says ʻUser Property: plugin. Can be confirmed --This means that you can specify a value with a property named
plugin. --Parameter names and property names do not always match ** --
pluginjust happens to match, like [antrun skip](https://maven.apache.org/plugins/maven-antrun-plugin/run-mojo.html#skip) Some are not --Here, ** properties ** means that you can specify not only system properties but also
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<properties>
<plugin>jdeps</plugin>
</properties>
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-help-plugin</artifactId>
<version>3.2.0</version>
</plugin>
</plugins>
</build>
</project>
--In <properties>
, jdeps
is set in plugin
.
Execution result (when plugin is not specified in the system property)
> mvn help:describe
...
Name: Apache Maven JDeps Plugin
Description: The JDeps Plugin uses the jdeps tool to analyze classes for
internal API calls.
Group Id: org.apache.maven.plugins
Artifact Id: maven-jdeps-plugin
Version: 3.1.2
Goal Prefix: jdeps
...
Execution result (when plugin is specified in the system property)
> mvn help:describe -Dplugin=antrun
...
Name: Apache Maven AntRun Plugin
Description: Runs Ant scripts embedded in the POM
Group Id: org.apache.maven.plugins
Artifact Id: maven-antrun-plugin
Version: 1.8
Goal Prefix: antrun
...
--If no system properties are specified, the value specified by <properties>
(jdeps
) is adopted.
--If you specify a system property, that value (ʻantrun`) is adopted.
――Even if you say "build" in a nutshell, its contents include various processes. --For example, to build a simple Java program, the following processing can be considered.
--Maven has the following three life cycles as standard
- default
- clean
- site
--default
life cycle defines the life cycle from building and deploying a project
--The default
life cycle consists of the following phases:
1. validate
2. initialize
3. generate-sources
4. process-sources
5. generate-resources
6. process-resources
7. compile
8. process-classes
9. generate-test-sources
10. process-test-sources
11. generate-test-resources
12. process-test-resources
13. test-compile
14. process-test-classes
15. test
16. prepare-package
17. package
18. pre-integration-test
19. integration-test
20. post-integration-test
21. verify
22. install
23. deploy
--clean
life cycle defines a life cycle to delete project artifacts
--clean
The life cycle consists of the following phases
1. pre-clean
2. clean
3. post-clean
--site
life cycle defines the life cycle of project website generation
--The site
life cycle consists of the following phases:
1. pre-site
2. site
3. post-site
4. site-deploy
――The goal of the plug-in to be executed in that phase is linked to each phase of the life cycle.
--For example, in the clean
life cycle and the site
life cycle, the goals are linked as follows:
** clean plugin **
Phase | Plugin | goal |
---|---|---|
pre-clean |
- | - |
clean |
maven-clean-plugin |
clean |
post-clean |
- | - |
** site plugin **
Phase | Plugin | goal |
---|---|---|
pre-site |
- | - |
site |
maven-site-plugin |
site |
post-site |
- | - |
site-deploy |
maven-site-plugin |
deploy |
--That is, running the clean
phase will run the clean
goal of the maven-clean-plugin
.
--In the case of the default
life cycle, the link between the phase and the goal is not fixed.
--The goals executed in the default
life cycle depend on the ** packaging ** of the project
packaging
-Packaging is a setting value that determines how to package the project, and one of the following values can be specified.
- pom
- jar
- ejb
- maven-plugin
- war
- ear
- rar
--This packaging is specified on pom.xml as follows
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<packaging>jar</packaging>
...
</project>
--Here, jar
is specified as packaging.
--The <packaging>
tag can be omitted in pom.xml.
--If omitted, the default is jar
--default
The goals associated with the life cycle phases differ depending on the packaging as follows:
--As an example, the goals associated with pom
and jar
are as follows:
--Since there are many phases, the phases that are not associated with anything are excluded (validate
etc.)
--For packaging other than these, refer to Maven Core – Plugin Bindings for Default Lifecycle Reference etc.
pom
Phase | Plugin | goal |
---|---|---|
install |
maven-install-plugin |
install |
deploy |
maven-deploy-plugin |
deploy |
jar
Phase | Plugin | goal |
---|---|---|
process-resources |
maven-resources-plugin |
resources |
compile |
maven-compiler-plugin |
compile |
process-test-resources |
maven-resources-plugin |
testResources |
test-compile |
maven-compiler-plugin |
testCompile |
test |
maven-surefire-plugin |
test |
package |
maven-jar-plugin |
jar |
install |
maven-install-plugin |
install |
deploy |
maven-deploy-plugin |
deploy |
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</project>
Run the test phase
> mvn test
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello ---
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello ---
...
--Phase can be executed by specifying it as an argument of mvn command.
--Here, I'm trying to run the test
phase in a project whose packaging is jar
.
--packaing defaults to jar
because the description of<packaing>
is omitted.
--If you specify a phase and execute it, all the phases before that phase will also be executed in order.
--For example, the test
phase is preceded by phases such as validate
, process-resources
, and test-compile
.
--In the above example, you can see that maven-resources-plugin: resources
, maven-compiler-plugin: compile
, ... are executed.
--When a phase is executed, all goals associated with that phase are executed.
--maven-resources-plugin: resources
The goal is in the resources
phase,
maven-compiler-plugin: compile
The goal is tied to the compile
phase
> mvn clean compiler:compile
--Multiple phases and goals can be specified in the mvn command and executed.
--In this case, the execution order is clean
→ compiler: compile
.
--In other words, it is executed in the order specified by the argument.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<target>
<echo>Hello Antrun!!</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn compile
...
[INFO] --- maven-antrun-plugin:1.8:run (default) @ hello ---
[INFO] Executing tasks
main:
[echo] Hello Antrun!!
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
--Any goal can be linked to any phase
--Phase and goal are linked with <execution>
in the plugin settings.
--Specify the phase with <phase>
and specify the goal to be linked with <goals> <goal>
--Here, the run
goal of maven-antrun-plugin
is associated with the validate
phase.
--As you can see from the structure <goals> <goal>
, it is possible to link multiple goals of the same plugin to one phase.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jdeps-plugin</artifactId>
<version>3.2.6</version>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>jdkinternals</goal>
<goal>test-jdkinternals</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn verify
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello ---
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello ---
...
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello ---
...
[INFO] --- maven-jdeps-plugin:3.1.2:jdkinternals (default) @ hello ---
...
[INFO] --- maven-jdeps-plugin:3.1.2:test-jdkinternals (default) @ hello ---
--Linking jdkinternals
and test-jdkinternals
of maven-jdeps-plugin
to the verify
phase
--If multiple goals are linked to one phase, those goals will be executed in the order declared on pom.xml [^ 7]
--In other words, in the case of ↑ setting, it is executed in the order of jdkinternals
→ test-jdkinternals
.
--You can change the execution order by changing the order of the <goal>
tags.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>foo</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>bar</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<target>
<echo>Hello Antrun!!</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn compile
...
[INFO] --- maven-antrun-plugin:1.8:run (foo) @ hello ---
...
[echo] Hello Antrun!!
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-antrun-plugin:1.8:run (bar) @ hello ---
...
[echo] Hello Antrun!!
...
--If you write multiple <execution>
tags, you will be able to link goals to multiple phases.
--If you specify more than one <execution>
, you must also specify the <id>
tag.
--Set <id>
to a unique value that can identify the <execution>
--This value is output to the console at runtime ( (foo)
part of maven-antrun-plugin: 1.8: run (foo)
)
--This is information to identify which <execution>
was executed, so it is useful for debugging when the build does not go well.
――Therefore, it is better to give a descriptive name that is easy to identify.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>foo</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo>VALIDATE!!</echo>
</target>
</configuration>
</execution>
<execution>
<id>bar</id>
<phase>compile</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo>COMPILE!!</echo>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn compile
...
[INFO] --- maven-antrun-plugin:1.8:run (foo) @ hello ---
...
[echo] VALIDATE!!
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-antrun-plugin:1.8:run (bar) @ hello ---
...
[echo] COMPILE!!
...
--The <configuration>
that describes the goal setting can also be specified for each <execution>
.
――This makes it possible to divide the settings for each specific phase.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<target>
<echo>Hello @ default-cli</echo>
</target>
</configuration>
</execution>
<execution>
<id>validate-phase</id>
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo>Hello @ validate-phase</echo>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn antrun:run
...
[echo] Hello @ default-cli
...
> mvn validate
...
[echo] Hello @ validate-phase
...
--If you execute the goal directly, ʻid defaults to
default-cli --Therefore, if you set
--Since 3.3.1 of Maven, it is possible to execute the goal by specifying <id>
of <execution>
.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<target>
<echo>Hello default-cli!!</echo>
</target>
</configuration>
</execution>
<execution>
<id>foo</id>
<configuration>
<target>
<echo>Hello Foo!!</echo>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
--The two <id>
, default-cli
and foo
, define <execution>
.
Execution result
> mvn antrun:run
...
[echo] Hello default-cli!!
> mvn antrun:run@foo
...
[echo] Hello Foo!!
--ʻAntrun: If you run only with run,
default-cliwill be run better -By following the goal specification with
@ , such as ʻantrun: run @ foo
, the <execution>
of the specified <id>
is executed.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.1</version>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn verify
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello ---
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello ---
...
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello ---
...
[INFO] --- maven-checkstyle-plugin:3.1.1:check (default) @ hello ---
--Adding maven-checkstyle-plugin to run the verify
phase
--In pom.xml, only <goal> check </ goal>
is specified in <execution>
, not <phase>
.
--However, if you look at the execution result, you can see that the check
goal is executed in the verify
phase.
--Goals can define the phases associated with them by default.
--If you look at the check goal description page, you can see that the default phase is verify
. Recognize
--If the phase is not specified in <execution>
, it will be executed in the phase associated with this default.
--If a goal has no phases associated with it, that goal can only be activated by specifying it directly on the command line.
--Plugins can be used to some extent without being explicitly set with <plugin>
-Some basic plugins (such as maven-compiler-plugin
) are automatically applied depending on the packaging settings
--If a prefix is specified, groupId
, ʻartifactId,
versionwill be automatically resolved. --If it works without any settings, I feel like you don't have to write
. --However, the method of executing without setting
――You can have a parent-child relationship in the project
Folder structure
|-pom.xml
`-child/
`-pom.xml
--Put the parent project pom.xml in the top folder and the child project pom.xml under the child
folder
/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>artifactId = ${project.artifactId}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--In the parent project's pom.xml, you must specify pom
for<packaging>
/child/pom.xml
<?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>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child</artifactId>
</project>
--In the child project pomx.ml, use <parent>
to specify the parent
--<parent>
specifies groupId
, ʻartifactId,
versionto identify the parent POM --In a parent-child relationship project, the child POM inherits the parent POM --For this reason, settings not described in the child pom.xml will be inherited from the settings in the parent pom.xml. --Since the parent settings are inherited for
and
, the description is unnecessary in the child pom.xml. --However,
Execution result (top folder)
> mvn antrun:run
...
[echo] artifactId = parent
Execution result (child folder)
> mvn antrun:run
...
[echo] artifactId = child
--Since the setting of <plugins>
is also inherited, the ʻantrun` plugin set in the parent project can be used in the child project as well.
--Parent pom.xml set with <parent>
is searched in the following order:
<relativePath>
is specified, refer to pom.xml in that location<relativePath>
is not specified, refer to pom.xml of ** one level up **--However, in the case of a folder structure like ↓, it is necessary to specify the path with <relativePath>
.
Folder structure
|-parent/
| `-pom.xml
`-child/
`-pom.xml
--parent
and child
are side by side, and pom.xml of the parent project does not exist one above the child project.
--If you run Maven in a child project in this state, you will get the following error:
Execution result (child project)
> mvn antrun:run
...
[FATAL] Non-resolvable parent POM for example:child:1.0.0: Failure to find example:parent:pom:1.0.0 in https://repo.maven.apache.org/maven2 was cached in the local repository, resolution will not be reattempted until the update interval of central has elapsed or updates are forced and 'parent.relativePath' points at wrong local POM @ line 6, column 11
@
...
--To solve this, you need to register the parent project jar in the repository or specify the location of the parent project with <relativePath>
as shown below.
/child/pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<relativePath>../parent/pom.xml</relativePath>
</parent>
<artifactId>child</artifactId>
</project>
Execution result (child project)
> mvn antrun:run
...
[echo] artifactId = child
--The parent project was found and worked
--If the POM has a parent-child relationship, the parent POM will be merged into the child POM. --Let's see how the merge is done
Parent pom.xml
<?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>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<properties>
<hoge>PARENT</hoge>
<fuga>PARENT</fuga>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>parent/dir</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>hoge = ${hoge}</echo>
<echo>fuga = ${fuga}</echo>
<echo>piyo = ${piyo}</echo>
<echo>dependencies[0].artifactId = ${project.dependencies[0].artifactId}</echo>
<echo>dependencies[1].artifactId = ${project.dependencies[1].artifactId}</echo>
<echo>resources[0].directory = ${project.build.resources[0].directory}</echo>
<echo>resources[1].directory = ${project.build.resources[1].directory}</echo>
<echo>plugins[0] = ${project.build.plugins[0].id}</echo>
<echo>plugins[1] = ${project.build.plugins[1].id}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--For verification, some settings are described so that the settings can be displayed by the ʻantrun` plugin.
Child pom.xml
<?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>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child</artifactId>
<properties>
<fuga>CHILD</fuga>
<piyo>CHILD</piyo>
</properties>
<dependencies>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.14</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>child/dir</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jdeps-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>
</project>
--It inherits the parent POM and describes so that some settings overlap.
Execution result (parent project)
> mvn antrun:run
...
[echo] hoge = PARENT
[echo] fuga = PARENT
[echo] piyo = ${piyo}
[echo] dependencies[0].artifactId = commons-lang3
[echo] dependencies[1].artifactId = ${project.dependencies[1].artifactId}
[echo] resources[0].directory = parent/dir
[echo] resources[1].directory = ${project.build.resources[1].directory}
[echo] plugins[0] = org.apache.maven.plugins:maven-antrun-plugin:1.8
[echo] plugins[1] = ${project.build.plugins[1].id}
--First, try to output each setting value in the parent project --Of course, only the value set in the parent POM is output, and the value that is not set is output as it is without the expression being evaluated.
Execution result (child project)
> mvn antrun:run
...
[echo] hoge = PARENT
[echo] fuga = CHILD
[echo] piyo = CHILD
[echo] dependencies[0].artifactId = commons-codec
[echo] dependencies[1].artifactId = commons-lang3
[echo] resources[0].directory = child/dir
[echo] resources[1].directory = ${project.build.resources[1].directory}
[echo] plugins[0] = org.apache.maven.plugins:maven-antrun-plugin:1.8
[echo] plugins[1] = org.apache.maven.plugins:maven-jdeps-plugin:3.1.2
--As a result of outputting in the child project, the setting of the child POM is adopted for the overlapping part (<properties> <fuga>
etc.) in the single value setting.
--On the other hand, the overlapping part (<dependencies>
, <plugins>
, etc.) in the setting of multiple values is based on the parent POM and the element of the child POM is added.
--Basically, single-valued items are overwritten and multi-valued items (such as <plugins>
) are added with elements.
--However, there are some exceptions, for example, <build> <resources>
is a multi-valued item but is overwritten.
-Official documentation states that <resources>
is also subject to merging, but in reality Overwritten
--In terms of implementation, [ModelMerger](https://github.com/apache/maven/blob/maven-3.6.3/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger It seems that POM is being merged in a class called .java)
--[MergeBuildBase_Resources ()] of this class (https://github.com/apache/maven/blob/maven-3.6.3/maven-model/src/main/java/org/apache/maven/model/merge/ ModelMerger.java # L2195) merges <resources>
--In this implementation, <resource>
is supposed to be merged in addition
--But it's actually a subclass of this ModelMerger
[MavenModelMerger](https://github.com/apache/maven/blob/maven-3.6.3/maven-model-builder/src/main/java/ org / apache / maven / model / merge / MavenModelMerger.java) seems to be merging
--MavenModelMerger
is [mergeBuildBase_Resources ()](https://github.com/apache/maven/blob/maven-3.6.3/maven-model-builder/src/main/java/org/apache/maven/model Overriding /merge/MavenModelMerger.java#L381) to merge the contents of the parent POM only if the <resources>
of the target
(child POM) is empty
--In other words, if <resources>
exists in the child POM, the merge will not be performed and only the contents of the child POM will be adopted (resulting in an overwrite operation).
--Other than <resources>
, do you have to take a look at this implementation of MavenModelMerger
?
--POMs have a parent-child relationship, and if you have multiple POMs as parents, you cannot tell the final state just by looking at the terminal POMs.
—— Especially when the build doesn't work, you often want to make sure the POMs are merged as expected.
--In such a case, you can use the effective-pom goal of maven-help-plugin
.
effective-run the pom goal
> mvn help:effective-pom
...
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<groupId>example</groupId>
<artifactId>child</artifactId>
<version>1.0.0</version>
(Omitted because it is long)
...
--ʻEffective-pom` Goal prints the final POM with the information of all parent POMs including Super POM merged. ――By looking at this, you can see what the settings of the project are actually.
--Description of plugin settings <configurations>
The following does not have a fixed schema definition because the settings are different for each plugin.
--Therefore, the merging of <configurations>
is done uniformly according to certain rules.
--For example, if <execution>
, the definition is fixed so that it can be identified by <id>
, so you can merge the same <id>
.
――However, the tags under <configurations>
cannot be identified in that way, so it feels like merging tags in the same position.
-(I haven't confirmed the exact specifications and implementation, so I feel like that)
――Let's see how it is merged with an actual example
Parent POM
...
<configuration>
<persons>
<person>
<name>Taro</name>
<age>18</age>
</person>
<person>
<name>Hanako</name>
<sex>female</sex>
</person>
</persons>
</configuration>
...
Child POM
...
<configuration>
<persons>
<person>
<sex>male</sex>
</person>
<cat>nya-</cat>
<person>
<name>Ayako</name>
<age>15</age>
</person>
<person>
<name>Rin</name>
<age>12</age>
<sex>female</sex>
</person>
</persons>
</configuration>
...
In this state, use help: effective-pom
to check the merge result.
effective-pom
...
<configuration>
<persons>
<person>
<sex>male</sex>
<name>Taro</name>
<age>18</age>
</person>
<cat>nya-</cat>
<person>
<name>Ayako</name>
<age>15</age>
<sex>female</sex>
</person>
<person>
<name>Rin</name>
<age>12</age>
<sex>female</sex>
</person>
</persons>
</configuration>
...
――It's difficult to explain in words, but you can see that it has been merged in a nice way. ――Probably, if there is a tag with the same name in the same position, it seems that the contents are being merged recursively.
――I feel that even the default behavior will merge reasonably well. --But if that's a problem, you can change the default merge behavior.
Parent POM
...
<configuration>
<persons>
<person>
<name>Taro</name>
<age>18</age>
</person>
<person>
<name>Hanako</name>
<sex>female</sex>
</person>
</persons>
</configuration>
...
--Parent POM has not changed
Child POM
...
<configuration>
<persons>
<person combine.self="override">
<sex>male</sex>
</person>
<cat>nya-</cat>
<person combine.children="append">
<name>Ayako</name>
<age>15</age>
</person>
<person>
<name>Rin</name>
<age>12</age>
<sex>female</sex>
</person>
</persons>
</configuration>
...
--Adding the attributes combile.self =" override "
and combine.children =" append "
effective-pom
...
<configuration>
<persons>
<person combine.self="override">
<sex>male</sex>
</person>
<cat>nya-</cat>
<person combine.children="append">
<name>Hanako</name>
<sex>female</sex>
<name>Ayako</name>
<age>15</age>
</person>
<person>
<name>Rin</name>
<age>12</age>
<sex>female</sex>
</person>
</persons>
</configuration>
...
--You can see that the merged method has changed only for the element to which the combine. *
Attribute has been added.
--If you specify combine.self =" override "
, the elements of the parent POM are completely discarded and only the elements of the child POM are used.
--If combine.children =" append "
is specified, the child POM element is simply added to the end of the parent POM element.
--By using these two attributes in the child POM, you will be able to adjust the merging method to some extent.
--However, these attributes are effective only for the element that describes this attribute.
--Does not propagate to nested elements
--If you want to change the behavior of nested elements, you need to specify the combine. *
Attribute in the same way for nested elements.
--Parent project settings are always inherited by child projects --It is convenient if the settings are common to all child projects, but if the settings are required only for some child projects, extra inheritance will occur. --Therefore, there is a method to put only the definition in the parent project and explicitly apply it in the child project that wants to use the definition.
Parent pom.xml
<?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>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>validate</phase>
<goals><goal>run</goal></goals>
<configuration>
<target>
<echo>Hello ${project.artifactId}</echo>
</target>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
--Use <pluginManagement>
to put together plugin definitions in the parent project
--Under this, you can write <plugins>
just like a normal plugin definition.
--However, what is described here only defines the settings and is not applied to the project.
Child 1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child1</artifactId>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
--To actually apply to a project, describe <groupId>
, <artifactId>
in the plugin definition of the project you want to apply.
--If the version is omitted, the one described in <pluginManagement>
will be used.
--It is also possible to add individual settings in the child project
Child 2 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child2</artifactId>
</project>
――This is not applying any plugin in particular
Execution result (child 1)
> mvn validate
...
[INFO] ---------------------------< example:child1 >---------------------------
[INFO] Building child1 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-antrun-plugin:1.8:run (default) @ child1 ---
[INFO] Executing tasks
main:
[echo] Hello child1
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
--The plugin is applied with the settings defined in the parent POM
Execution result (child 2)
> mvn validate
...
[INFO] ---------------------------< example:child2 >---------------------------
[INFO] Building child2 1.0.0
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
--No plugins applied
Parent pom.xml
<?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>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
</dependencies>
</project>
--Use <dependencyManagement>
to group dependency definitions into a parent
--Under this, you can write the same as normal <dependencies>
--Similar to <pluginManagement>
, the definition here is only a declaration, and it is applied to the project individually.
Child 1 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child1</artifactId>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
</dependencies>
</project>
--Apply in child project by writing <groupId>
and <artifactId>
in the dependency.
--If <version>
is omitted, the one specified by <dependencyManagement>
will be used.
--It is also possible to overwrite <version>
independently in the child project.
Child 2 pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child2</artifactId>
</project>
--This does not define any dependencies in particular
Execution result (effective of child 1-pom)
> mvn help:effective-pom
...
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
<scope>compile</scope>
</dependency>
</dependencies>
...
--commons-io
is applied in the version set in the parent POM
Execution result (effective of child 2)-pom)
> mvn help:effective-pom
...
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
<scope>compile</scope>
</dependency>
</dependencies>
...
--commons-io
dependencies not applied
--The parent-child relationship was a form in which the child referred to the parent. ――On the other hand, in project aggregation, the parent refers to the child. --When you aggregate projects, you can specify goals and phases in the parent project and execute them.
Folder structure
|-pom.xml
`-sub/
`-pom.xml
--Project whose top folder is the aggregation source
--There is a project to be aggregated under the child
folder
Aggregation source pom.xml
<?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>example</groupId>
<artifactId>root</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>sub</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>Hello ${project.artifactId}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--To aggregate projects, use <modules>
in the project from which they are aggregated.
--Under <modules>
, list the projects to be aggregated with <module>
--The <packaging>
of the project to be aggregated must be pom
.
Pom to be aggregated.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>sub</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>Hello ${project.artifactId}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--Write pom.xml to be aggregated normally
--Since this POM does not inherit the project of the aggregation source, the description of <groupId>
etc. is individual.
Execution result (executed in the aggregation source project)
> mvn antrun:run
...
main:
[echo] Hello sub
...
main:
[echo] Hello root
...
--When the goal of the plug-in is executed in the project to be aggregated, the same goal is executed in the project to be aggregated. --In this way, when projects are aggregated, the commands executed in the aggregation source project will also be executed in the aggregation destination project. ――It is convenient to have this mechanism when you want to build all projects at once.
--The mechanism of aggregation and parent-child relationship can be combined (or rather, usually used in combination).
Folder structure
|-pom.xml
`-child/
`-pom.xml
Parent pom.xml
<?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>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<modules>
<module>child</module>
</modules>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>Hello ${project.artifactId}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--There is no particular change in the composition of the parent POM
Child pom.xml
<?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>
<parent>
<groupId>example</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>child</artifactId>
</project>
--Declare the parent project with <parent>
--This allows the plugin settings to inherit the parent settings, eliminating the need for writing.
Execution result (executed in the parent project)
> mvn antrun:run
...
main:
[echo] Hello parent
...
main:
[echo] Hello child
...
--Parent-child relationship and aggregation can be applied at the same time
-Understand how a project with packaging jar
is built.
--Packaging defaults to jar
when creating a project that builds Java normally
--Therefore, the goals executed in the default
life cycle are:
1. resources:resources
2. compiler:compile
3. resources:testResources
4. compiler:testCompile
5. surefire:test
6. jar:jar
7. install:install
8. deploy:deploy
――Look at what each goal is doing one by one
--The first thing that runs is the [resources goal] of maven-resources-plugin
(https://maven.apache.org/plugins/maven-resources-plugin/resources-mojo.html)
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</project>
--Verify with minimum configuration pom.xml
Folder structure
|-pom.xml
`-src/main/
|-java/
| `example/
| `-App.java
`-resources/
|-hoge.txt
`-foo/
`-bar.txt
--Files and folders are arranged appropriately under src / main / resources
Command execution
> mvn resources:resources
...
[INFO] --- maven-resources-plugin:2.6:resources (default-cli) @ hello ---
...
[INFO] BUILD SUCCESS
--resources: resources
Execute goals directly
Folder structure after execution
|-pom.xml
|-src/main/
| |-java/
| | `example/
| | `-App.java
| `-resources/
| |-hoge.txt
| `-foo/
| `-bar.txt
`-target/classes/
|-hoge.txt
`-foo/
`-bar.txt
--The following contents of src / main / resources
are copied under the target / classes
folder.
--maven-resources-plugin
provides the process of copying the project resource folder to the output folder
--The resource folder and output folder are as follows by default.
--Resource folder: src / main / resources
--Output folder: target / classes
--The resource folder is the folder set in $ {project.build.resources}
--This value is set to $ {project.basedir} /src/main/resources
in Super POM
--The output destination folder is the location specified by the ʻoutputDirectory parameter of the
resourcesgoal. --This parameter defaults to
$ {project.build.outputDirectory} --And this value is set to
$ {project.build.directory} / classesby default by Super POM --In addition,
$ {project.basedir} / target is set in
$ {project.build.directory} `
--So, for example, you can customize the behavior by writing pom.xml as follows.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<build>
<resources>
<resource>
<directory>src/main/hoge</directory>
</resource>
</resources>
</build>
</project>
--Changing the resource folder to src / main / hoge
Folder structure
|-pom.xml
`-src/main/
|-hoge/
| |-fizz.txt
| `-hoge/
| `-fuga.txt
|
`-resources/
|-buzz.txt
`-foo/
`-bar.txt
--There are two options, src / main / resources
and src / main / hoge
.
Execute resources goal
> mvn resources:resources
...
Execution result
|-pom.xml
|-src/main/
| |-hoge/
| | |-fizz.txt
| | `-hoge/
| | `-fuga.txt
| |
| `-resources/
| |-buzz.txt
| `-foo/
| `-bar.txt
|
`-target/classes/
|-fizz.txt
`-hoge/
`-fuga.txt
--src / main / hoge
It has changed so that only the following is copied
--In summary, the resources: resources
goal works by default as follows:
--Copy the files and folders under $ {project.basedir} /src/main/resources
under $ {project.basedir} / target / classes
--Resource folders can be set with <project> <build> <resources>
--The output destination folder can be set with <project> <build> <outputDirectory>
--The next goal to be executed is compile of maven-compiler-plugin. /plugins/maven-compiler-plugin/compile-mojo.html) Goal
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</project>
--Verify with the minimum configuration POM
Folder structure
|-pom.xml
`-src/main/java
`-example/
`-Hello.java
--Simple configuration with only Hello.java
Run compile goal
> mvn compiler:compile
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-cli) @ hello ---
...
[INFO] -------------------------------------------------------------
[ERROR] COMPILATION ERROR :
[INFO] -------------------------------------------------------------
[ERROR]Source option 5 is not currently supported. Please use 6 or later.
[ERROR]Target option 1.5 is not currently supported. 1.Please use 6 or later.
--Failed due to an error
--Compile option [-source](https://docs.oracle.com/javase/jp/11/tools/javac.html#GUID-AEEC9F07-CB49-4E96-8BC7-BCC2C7F725C9__GUID-B4EE2436-E146- 428D-A3CB-E0DAE27BA5B7) and [-target](https://docs.oracle.com/javase/jp/11/tools/javac.html#GUID-AEEC9F07-CB49-4E96-8BC7-BCC2C7F725C9__GUID-89CBDEA1-9FF4- The error content is that the version specified in 4EA0-AB7D-B418FA2C3DE9) is too old with 5
, 1.5
.
--In JDK 11, the versions below 5 for -source
and -target
are [cannot be specified](https://docs.oracle.com/javase/jp/11/migrate/index.html# JSMIG-GUID-77874D97-46F3-4DB5-85E4-2ACB5F8D760B)
--If packaging is jar
, the default version of maven-compiler-plugin
is [3.1](https://maven.apache.org/ref/3.6.3/maven- core / default-bindings.html # Plugin_bindings_for_jar_packaging)
--In 3.1 of maven-compiler-plugin
, the version specification of -source
and -target
is [1.5] by default (https://github.com/apache/maven-compiler- plugin / blob / maven-compiler-plugin-3.1 /src/main/java/org/apache/maven/plugin/compiler/AbstractCompilerMojo.java#L120)
--By the way, in 3.8.1 of the latest maven-compiler-plugin
at the time of confirmation, [1.6](https://github.com/apache/maven-compiler-plugin/blob/maven-compiler-plugin-3.8. 1 / src / main / java / org / apache / maven / plugin / compiler / AbstractCompilerMojo.java # L100) is the default
--So, to get rid of this error, you need to increase the version of maven-compiler-plugin
or increase the specification of source
and target
.
--It is safe to specify both to confirm the operation.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
--To specify source
with maven-compiler-plugin
, use source parameter Set
--Although it can be specified with <configuration>
, it can also be specified with the maven.compiler.source
property.
――Here, the setting using the property is used (Is this more common?)
--The same is true for target
, which can be set with the maven.compiler.target
property.
Execution result
> mvn compiler:compile
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-cli) @ hello ---
...
[WARNING] File encoding has not been set, using platform encoding MS932, i.e. build is platform dependent!
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
...
--I was able to compile, but I got some warning
--The warning is that the encoding of the source file depends on the environment defaults.
--Specify the encoding of the source file in encoding parameter
--As mentioned in the description, by default it uses $ {project.build.sourceEncoding}
--However, this value is not set in Super POM, so it results in an environment default (such as MS932 for Windows).
--So, let's set the encoding as well
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
--From the description $ {project.build.sourceEncoding}
, you can imagine that you should describe the element <sourceEncoding>
under <project> <build>
, but in reality, you declare the property ( Who knows </ del>)
――By the way, it is possible to set it with the property ʻencoding, but if you look it up on the net, the method of
project.build.sourceEncoding will be caught. ――If it is ʻencoding
, it may be applied to encodings other than Java source, or is there such a thing? (suitable)
Execution result
> mvn compiler:compile
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-cli) @ hello ---
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
--Successfully compiled without warning
Output result
|-pom.xml
|-src/main/java/
| :
`-target/
|-classes/
: `-example/
`-Hello.class
--The compilation result is output under target / classes
--The output destination setting is not described in the compile goal document.
--This is the implementation class for the compile
goal [outputDirectory](https://github.com/apache/maven-compiler-plugin/blob/maven-compiler-plugin-3.8.1/src/main/java /org/apache/maven/plugin/compiler/CompilerMojo.java#L76) Declared in the field
--The default value is $ {project.build.outputDirectory}
--Since readonly = true
is set, this field cannot be set directly from the outside.
--The source folder defaults to src / main / java
--Also, there is no description in the document
--In terms of implementation, [compileSourceRoots](https://github.com/apache/maven-compiler-plugin/blob/maven-compiler-plugin-3.8.1/src/main/java/org/apache/maven/plugin /compiler/CompilerMojo.java#L70) declared in the field
--Looking at defaultValue
, you can see that$ {project.compileSourceRoots}
is set.
--But when I try to reference this property called project.compileSourceRoots
on pom.xml, I can't see the value.
--compileSourceRoots
is [MavenProject](https://github.com/apache/maven/blob/maven-3.6.3/maven-core/src/main/java/org/apache/maven/project/MavenProject.java # L131) Declared as a field in the class
--This field is DefaultProjectBuilder The value is set by # L691)
--From this implementation, you can see that project.build.sourceDirectory
is set to compileSourceRoots
.
--And $ {project.basedir} /src/main/java
is set in project.build.sourceDirectory
by Super POM.
――If you look at this mechanism, you can expect that you cannot set multiple source folders.
--If you want to set multiple source folders, you need to install a plugin called build-helper-maven-plugin.
--In summary, compiler: compile
does the following:
--Compile Java source code under $ {project.basedir} /src/main/java
and output to $ {project.basedir} / target / classes
--javac's -source
, -target
options can be specified with the maven.compiler.source
, maven.compiler.target
properties
--Encoding can be specified with the project.build.sourceEncoding
property
--The source folder can be specified with <project> <build> <sourceDirectory>
--If you want to specify multiple folders, you need build-helper-maven-plugin
--The output destination folder is <project> <build> <outputDirectory>
--The next thing to run is resources: testResources, which collects resources for testing.
Compile the source code for testing compiler: testCompile
--The basic operation of each is the same as resources: resources
, compiler: compile
, so only roughly
Folder structure
|-pom.xml
`-src/test/
|-java/
| `-example/
| `-HelloTest.java
|
`-resources/
|-foo/
| `-bar.txt
`-fizz.txt
--The test source code under src / test / java
,
Place test resource files under src / test / resources
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
--pom.xml is the same as for compiler: compile
Run
> mvn resources:testResources compiler:testCompile
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-cli) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-cli) @ hello ---
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
Execution result
|-pom.xml
|-src/test/
| :
`-target/
`-test-classes/
|-fizz.txt
|-foo/
| `-bar.txt
`-example/
`-HelloTest.class
--Results are output under target / test-classes
――When organized, the operation is as follows.
--The testResources
goal is to copy the files and folders under $ {project.basedir} /src/test/resources
to $ {project.basedir} / target / test-classes
.
--Resource folders can be specified with <project> <build> <testResources>
--The testCompile
goal compiles the Java source files under $ {project.basedir} /src/test/java
and outputs them to $ {project.basedir} / target / test-classes
.
--The source folder can be specified with <project> <build> <testSourceDirectory>
--Next, in order to execute the compiled test code, [test goal](https: //) of maven-surefire-plugin maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html) is executed.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
</plugin>
</plugins>
</build>
</project>
--The following modifications have been made to make JUnit5 work.
--Add junit-jupiter
to dependencies
--Specify 2.22.2 for the version of maven-surefire-plugin
--2.22.0 or higher must be specified to use JUnit5
Folder structure
|-pom.xml
`-src/
|-main/java/
| `-example/
| `-Hello.java
`-test/java/
`-example/
`-HelloTest.java
--Place the test target class (Hello.java
) and the test class (HelloTest.java
)
Run
> mvn test
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ hello ---
...
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ hello ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running example.HelloTest
...
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.027 s - in example.HelloTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
> dir /b target\surefire-reports
example.HelloTest.txt
TEST-example.HelloTest.xml
--The surefire: test
goal is tied to the test
phase, so it is executed with the test
phase specified.
--It is possible to run surefire: test
alone, but in that case the source must be compiled separately.
--The test class to be executed is specified in includes parameter, and the following classes are executed by default. Is targeted
- **/Test*.java
- **/*Test.java
- **/*Tests.java
- **/*TestCase.java
--Test results are printed in text and xml format under target / surefire-reports
--This is specified in the surefire: test
goal's reportsDirectory parameter (https://maven.apache.org/surefire/maven-surefire-plugin/test-mojo.html#reportsDirectory) (default is $ {project.build.directory} / surefire-reports
)
--After the test
phase, the package
phase is executed, which jars the compilation result of the project.
--That is, the test
phase must complete successfully in order to generate the jar.
--If the test fails in the test
phase, the package
phase will not run
--It should be that the code that has not passed the test is not usable even if it is packed in a jar, but unfortunately there are projects where the test code is not maintained and the test does not pass.
--In such cases, it is common (and should not be) to skip execution of the test
phase and execute the package
phase.
Execution result
> mvn -DskipTests package
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ hello ---
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ hello ---
[INFO] Tests are skipped.
...
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello ---
...
--surefire: test
The goal has a parameter called skipTests.
--If this is set, test execution will be skipped.
--To summarize, the test
phase does the following:
--Test code is executed by maven-surefire-plugin
--In order to use JUnit 5, the version of maven-surefire-plugin
must be 2.22.0 or higher.
--The test class to be executed is specified in includes parameter.
--Test results are printed under target / surefire-reports
(reportsDirectory parameter" )
--Test execution can be skipped by setting the skipTests parameter
--However, the use of this should be kept to the minimum necessary
--The test is not maintained and you need a jar now (the correct response is to fix it so that the test passes)
--The test passes, but it takes a long time to execute, so it cannot be executed every time.
- etc
--The process of solidifying the compilation result into a jar is the jar goal of maven-jar-plugin. .org / plugins / maven-jar-plugin / jar-mojo.html)
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
--The minimum settings required for compilation
Folder structure
|-pom.xml
`-src/
|-test/
| :
`-main/
|-java/
| `-example/
| `-Hello.java
`-resources/
`-hoge.txt
Run package phase
> mvn package
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ hello ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ hello ---
...
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ hello ---
...
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ hello ---
...
[INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ hello ---
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
--The jar: jar
goal is tied to the package
phase, so you are running the package
phase.
Execution result
|-pom.xml
|-src/
| :
`-target/
|-hello-1.0.0.jar
:
--hello-1.0.0.jar
is output directly under the target
folder.
--The output destination of the jar file is set by the outputDirectory parameter of the jar goal.
--The default for this parameter is $ {project.build.directory}
($ {project.basedir} / target
)
--Also, the name of the jar file is finalName in the implementation of the jar goal. /org/apache/maven/plugins/jar/AbstractJarMojo.java#L80) declared in the field
--This field is readonly = true
, so it cannot be changed directly from the outside.
--The value of this field is set to $ {project.build.finalName}
--This value is set by Super POM to $ {project.artifactId}-$ {project.version}
by default.
--Therefore, if you want to rename the jar, you can set <project> <build> <finalName>
--When you unzip this jar, the contents are as follows
text:hello-1.0.0.Contents of jar
|-hoge.txt
|-example/
| `-Hello.class
`-META-INF/
|-MANIFEST.MF
`-maven/example/hello/
|-pom.properties
`-pom.xml
--hoge.txt
and Hello.class
are packed with the output under target / classes
by resources: resources
and compiler: compile
, respectively.
--Which folder contents are packed in a jar is set by the classesDirectory parameter of the jar goal. Have been
--The default for this parameter is $ {project.build.outputDirectory}
($ {project.basedir} / target / classes
)
--Pom.xml is output under META-INF
, but the content is the same as pom.xml of this project.
--MANIFEST.MF
and pom.properties
have the following contents, respectively.
MANIFEST.MF
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven 3.6.3
Built-By: xxxxx
Build-Jdk: 11.0.6
pom.properties
#Generated by Maven
#Sun Mar 29 21:59:48 JST 2020
groupId=example
artifactId=hello
version=1.0.0
--These are set in the archive parameter of the jar goal. --Details of ʻarchive` settings can be found in Apache Maven Archiver – Reference. --These files are generated with the settings enabled by default
--In summary, the jar
goal works like this:
${project.artifactId}-${project.version}
--Specify with <project> <build> <finalName>
to change
--Output location${project.basedir}/target
--Specify with <project> <build> <directory>
to change
--Packing target${project.basedir}/target/classes
--If you want to change it, specify it with the <project> <build> <outputDirectory>
or the classesDirectory
parameter of the jar
goal.
--In addition, the ʻarchiveparameter can be used to set the information added under
MANIFEST.MF and
META-INF`.--ʻInstall` install goal of maven-install-plugin associated with the phase. apache.org/plugins/maven-install-plugin/install-mojo.html) provides the ability to install project artifacts in a local repository
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
...
</project>
Run install
> mvn install
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
--ʻInstall: install The goal is tied to the ʻinstall
phase, so you are running the ʻinstallphase (confusing) --When execution is complete, check inside the local repository --The default location of the local repository is
% USERPROFILE% \ .m2 \ repository on Windows (
$ HOME / .m2 / repositoryon Linux OS) --If you have specified a different location in
settings.xml`, that
Local repository
Local repository/
|-example/
: `-hello/
|-1.0.0/
: |-hello-1.0.0.jar
:
--The jar file is stored in the local repository
--The jar file to be registered is probably the jar file generated in the package
phase
--ʻInstall: installThe goal docs said
project's main artifact, but I couldn't find a clear description of what would be
project's main artifact. --In terms of implementation, [getArtifact () of MavenProject](https://github.com/apache/maven/blob/maven-3.6.3/maven-core/src/main/java/org/apache/maven/project [GetFile () of Artifact](https://github.com/apache/maven/blob/maven-3.6.3/maven-artifact/src/main/java/org/) which can be obtained by /MavenProject.java#L215) I could read up to the point where the file that can be obtained by apache / maven / artifact / Artifact.java # L85) seems to be installed, but I could not find the place where this
File` object is set.
--Artifs installed in the local repository will be visible in another local project
pom.xml
<?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>example</groupId>
<artifactId>foo</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
--Declaring dependencies on hello-1.0.0.jar
with<dependencies>
Foo.java
package example;
public class Foo {
public static void main(String... args) {
new Hello().hello();
}
}
--I'm writing an implementation that uses the Hello
class
Compile the project
> mvn compile
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ foo ---
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ foo ---
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
--Compiled successfully (Hello
class has been resolved)
--In summary, the ʻinstallgoal works like this: --Probably install the artifacts generated in the
package` phase (such as jar files) in your local repository
--Installed artifacts will be visible as dependencies from other local projects
--The last execution is the deploy
phase
--In the deploy
phase, the deploy goal of maven-deploy-plugin plugins / maven-deploy-plugin / deploy-mojo.html) is executed
--deploy
goal is to deploy the project artifacts to a remote repository
―― I feel that there are few opportunities to actually use it even though it is troublesome to build the environment. </ Del> Verification is omitted.
See how your project builds if you set -packaging to war
--However, the plugins executed in the default
phase are almost the same as in the case of jar
.
--The difference from jar
is that the goal executed in the package
phase is war war goal
Folder structure
|-pom.xml
`-src/main/
|-java/
| `-example/webapp/
| `-HelloServlet.java
`-webapp/
`-WEB-INF/
`-hello.jsp
--Create a folder called src / main / webapp
and under that a folder such as WEB-INF
to include in war
pom.xml
<?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>example</groupId>
<artifactId>webapp</artifactId>
<version>1.0.0</version>
<packaging>war</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.3</version>
</plugin>
</plugins>
</build>
</project>
--war
is specified for<packaging>
--The following two are specified as dependencies
- Servlet API
- Apache Commons Lang3
Build
> mvn package
...
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ webapp ---
...
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ webapp ---
...
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ webapp ---
...
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ webapp ---
...
[INFO] --- maven-surefire-plugin:2.12.4:test (default-test) @ webapp ---
...
[INFO] --- maven-war-plugin:3.2.3:war (default-war) @ webapp ---
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
--As in the case of jar
, the goal of the plugin is executed in each phase, and finally war: war
is executed.
Output result
|-pom.xml
|-src/
| :
`-target/
`-webapp-1.0.0.war
--The war file is generated directly under target
--The output location is specified in the war
goal's outputDirectory parameter and defaults to$ It is {project.build.directory}
--The name of the war file is [warName](https://github.com/apache/maven-war-plugin/blob/maven-war-plugin-3.2.3/src/main/java/org/apache/ It is specified by a read-only parameter called maven / plugins / war / WarMojo.java # L71) and defaults to $ {project.build.finalName}
.
--The contents of webapp-1.0.0.war
are as follows
text:webapp-1.0.0.The contents of the war
webapp-1.0.0.war/
|-WEB-INF/
| |-hello.jsp
| |-classes/
| | `-example/webapp/
| | `-HelloServlet.class
| `-lib/
| `-commons-lang3-3.10.jar
`-META-INF/
|-MANIFEST.MF
`-maven/example/webapp/
|-pom.properties
`-pom.xml
--You can see that the compilation result of src / main / java
and the contents under src / main / webapp
are contained in the war file.
--Place files other than class files and library jars that you put in war under the src / main / webapp
folder.
--This is specified in the war
goal's warSourceDirectory parameter and defaults to $ { basedir} / src / main / webapp
--In addition, the Apache Commons Lang3 jar specified as a dependency is also stored under WEB-INF / lib
.
--The Servlet API jar is not stored
--This is because the scope of the dependency on the Servlet API was specified in provided
.
--Detailed explanation of scope will be described later.
--In summary, if packaging is war
, the project will be built as follows:
--Basically built like jar
--However, the point that the war: war
goal is executed only in the package
phase is different from the case of jar
.
--In the war: war
goal, the compilation result of the project is output in a war file.
--In addition to the class files, resources, and dependent libraries, the files placed under src / main / webapp
are also stored in the war.
Hello.java
package example;
import java.util.Arrays;
public class Hello {
public static void main(String... args) {
System.out.println("Hello World! args=" + Arrays.toString(args));
}
}
--Hello World, implementation that outputs command line arguments
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>example.Hello</mainClass>
<arguments>
<argument>one</argument>
<argument>two</argument>
<argument>three</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
-A plugin called exec-maven-plugin has been added.
Run
> mvn compile exec:java
...
[INFO] --- exec-maven-plugin:1.6.0:java (default-cli) @ hello ---
Hello World! args=[one, two, three]
...
--Hello.java
was executed
--If you use the [java goal] of ʻexec-maven-plugin (https://www.mojohaus.org/exec-maven-plugin/java-mojo.html), you can put the build result of the project in the classpath. Can execute Java programs --ʻExec-maven-plugin
also has an exec goal that allows you to execute arbitrary commands. Omitted here
--mainClass You can execute Java program by specifying Main class with parameter.
-arguments You can pass command line arguments with parameters
--You can also pass arguments with the parameter commandlineArgs
, but this is for use when executing from the command line described below (probably).
--For the first example, it is necessary to describe all the execution configurations in pom.xml in advance. --In some cases, you may want to execute it while changing various arguments on the command line. --In that case, it is easier to specify the goal parameters via the system properties.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<mainClass>example.Hello</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
--Since it is troublesome to specify the Main class from the command line, I think that only this can be described in pom.xml in advance.
Execution result
> mvn compile exec:java -Dexec.args="ONE TWO THREE"
...
Hello World! args=[ONE, TWO, THREE]
-commandlineArgs You can use the parameter to specify the argument as a space-separated string. --When specifying in system properties, specify in ʻexec.args`
--You can set a dependency called ** Scope **.
--Scope represents the range in which the dependency is used.
--For example, the dependency specified in the compile
scope indicates that it will always be used from the time the source code is compiled to the time the application is executed.
--Also, the dependency with the test
scope indicates that it should be used only when compiling the test code (src / test / java
) and executing the test.
--There are 6 types of scopes as follows.
- compile
- provided
- runtime
- test
- system
- import
pom.xml
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
--If no scope is specified, the compile
scope is adopted by default (it can be specified).
--The compile
scope indicates that you always need that dependency from compilation to execution.
pom.xml
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
--The provided
scope indicates that the dependency is provided by the execution environment.
--Use when the following conditions are met
--Required for compilation and testing
--However, the execution environment provides the jar at runtime, so the application does not need to keep it separately.
--The most common example is the Servlet API.
--The Servlet API uses the one provided by the application server that deploys the war, so the application does not need to have a separate dependency at run time.
--For the same reason, specify other APIs (EJB, JAX-RS, etc ...) provided by Java EE (Jakarta EE) with provided
.
--When a war is generated with maven-war-plugin
, the dependencies specified in provided
are not placed under WEB-INF / lib
.
pom.xml
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>42.2.12</version>
<scope>runtime</scope>
</dependency>
--The runtime
scope is the opposite of provided
and is used with dependencies that are not needed at compile time but are needed at run time.
--A typical example is the JDBC driver.
--When writing a program using the JDBC driver, the implementation provides java.sql.Connection provided by the standard API. You only have to rely on classes such as sql / java / sql / Connection.html)
--Basically, it does not directly depend on the concrete classes provided by each database product.
――But, of course, you need an entity at runtime
--So, this applies to the case where it is not needed at compile time but needed at runtime.
pom.xml
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.6.1</version>
<scope>test</scope>
</dependency>
--test
scope is used for dependencies that are used only when compiling and running the test source.
--Cannot be used when compiling or running the main source code
--Use with dependencies that are only needed for testing, such as JUnit
pom.xml
<dependency>
<groupId>javax.sql</groupId>
<artifactId>jdbc-stdext</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${java.home}/lib/rt.jar</systemPath>
</dependency>
--The system
scope indicates that the dependency is provided by the system (JRE or JDK of the execution environment).
--This scope seems to be prepared for the purpose of using extension libraries that are not in the repository and are stored internally by the JRE and JDK.
--If you specify the system
scope, you must specify the path of the target jar file with<systemPath>
.
--You can also have a library in your project that doesn't exist in the repository and use it to reference it.
――Originally, it is a straightforward approach to prepare a private repository and manage it there.
--For the time being, the use of this scope is deprecated.
- System Dependencies
Folder structure
|-foo/
| `-pom.xml
`-bar/
`-pom.xml
--There are two projects, foo and bar
pom.xml(foo)
<?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>example</groupId>
<artifactId>foo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
--The foo project sets packaging to pom
and declares only<dependencyManagement>
--The following two are declared as dependent targets.
- org.apache.commons:commons-lang3:3.10
- org.apache.commons:commons-text:1.8
pom.xml(bar)
<?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>example</groupId>
<artifactId>bar</artifactId>
<version>1.0.0</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>example</groupId>
<artifactId>foo</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
--In the bar project, in <dependencyManagement>
, the foo project mentioned earlier is specified in the ʻimport scope. --ʻImport
Scope can only be specified in <dependencyManagement>
--ʻImportIf you specify the scope, you must also specify the
. --In addition, the following two are declared as other dependent targets. -
org.apache.commons:commons-lang3:3.9 -
org.apache.commons:commons-csv:1.8 --In this state, check ʻeffective-pom
of the bar project.
effective-Confirmation of pom(bar)
> cd bar
> mvn help:effective-pom
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-text</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
</dependencyManagement>
artifactId | foo | bar | effective-pom |
---|---|---|---|
commons-lang3 |
3.10 |
3.9 |
3.9 |
commons-csv |
- | 1.8 |
1.8 |
commons-text |
1.8 |
- | 1.8 |
--The declaration of dependency on the foo project has disappeared, and instead the dependencies declared in <dependencyManagement>
of the foo project have been added.
--However, if the artifacts are duplicated, the version of the bar project is adopted (commons-lang3
).
--As you can see, ʻimport has a special scope to import (import)
BOM
--There is a method called ** BOM (bill of materials) ** that uses the ʻimport scope as a version control method for dependencies in multiple projects. --In BOM, first prepare a BOM project with pom.xml --
is declared in the pom.xml of the BOM project, which defines the dependencies used in each project. --For each project, load this BOM project with ʻimport
scope
--Dependency versions are declared in the BOM project, so each project only needs to declare groupId
, ʻartifactId in
--In order to give a bird's-eye view of the range of each scope, I made a table of the relationship between scopes and goals (excluded because ʻimport` is special).
-- ○
indicates that the goal refers to and uses the dependency of the corresponding scope.
--For war: war
, it means whether it will be packed in the generated war file.
--Other than that, it means whether or not it is set in the classpath.
--You can check the dependency of the project by displaying it in a tree structure graph.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
</dependencies>
</project>
--Declaring Spring Framework web and jdbc as dependencies
――However, the library that the project depends on is not limited to this, and in fact it also depends on the library that spring-web
and spring-jdbc
depend on.
--You can't tell just by looking at pom.xml how many libraries your project ultimately depends on.
-tree goal of maven-dependency-plugin If you execute plugin / tree-mojo.html), you can see all the dependencies including this transitional dependency in the tree structure graph.
Execution result
> mvn dependency:tree
...
[INFO] +- org.springframework:spring-web:jar:5.2.5.RELEASE:compile
[INFO] | +- org.springframework:spring-beans:jar:5.2.5.RELEASE:compile
[INFO] | \- org.springframework:spring-core:jar:5.2.5.RELEASE:compile
[INFO] | \- org.springframework:spring-jcl:jar:5.2.5.RELEASE:compile
[INFO] \- org.springframework:spring-jdbc:jar:5.2.5.RELEASE:compile
[INFO] \- org.springframework:spring-tx:jar:5.2.5.RELEASE:compile
...
--You can see that spring-web
further depends on spring-beans
, spring-core
, and spring-core
depends on spring-jcl
.
--And you can see that spring-jdbc
depends on spring-tx
--By the way, spring-jdbc
also depends on spring-beans
and spring-core
, but the display is omitted because it overlaps with the spring-web
side.
--By default, the dependencies of all scopes are output, but you can also narrow down by scope parameter. it can
--In rare cases, you want to get all the actual jar files that your project depends on.
--This can be achieved with the copy-dependencies goal of maven-dependency-plugin
.
-Try running with the same settings as pom.xml in ↑
Execution result
> mvn dependency:copy-dependencies
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...
> dir /b target\dependency
spring-beans-5.2.5.RELEASE.jar
spring-core-5.2.5.RELEASE.jar
spring-jcl-5.2.5.RELEASE.jar
spring-jdbc-5.2.5.RELEASE.jar
spring-tx-5.2.5.RELEASE.jar
spring-web-5.2.5.RELEASE.jar
--All dependent jars are output under the target / dependency
folder
--By default, jars of all scopes are targeted, but narrow down by includeScope parameter etc. be able to
--Basically, it is good to build the project so that the same result is output with the same settings in every environment. ――The build succeeds in one environment, but an error occurs in another environment, which is troublesome. ――However, it seems that it is rare that environment-dependent build settings are required during actual development (although I don't know). --If you want to switch the contents of pom.xml depending on the build environment (enable a specific plugin or change the setting value), you can use a mechanism called ** Profile **.
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<profiles>
<profile>
<id>foo</id>
<properties>
<message>foo profile!!</message>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.10</version>
</dependency>
</dependencies>
<build>
<directory>${project.basedir}/build</directory>
</build>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>message = ${message}</echo>
<echo>project.build.directory = ${project.build.directory}</echo>
<echo>dependency[0] = ${project.dependencies[0].artifactId}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--<profiles> <profile>
declares a profile called foo
--In the foo
profile, properties, dependencies, and project.build.directory
settings are set.
--I use maven-antrun-plugin
to display those values
Execution result
> mvn antrun:run
...
[echo] message = ${message}
[echo] project.build.directory = F:\tmp\maven\hello\target
[echo] dependency[0] = ${project.dependencies[0].artifactId}
...
> mvn -P foo antrun:run
...
[echo] message = foo profile!!
[echo] project.build.directory = F:\tmp\maven\hello\build
[echo] dependency[0] = commons-lang3
--When executed normally, the contents set in the foo
profile are not reflected.
--On the other hand, if you specify -P foo
and execute it, you can see that the contents set in the foo
profile are reflected.
--In this way, using a profile allows you to define settings that apply only when you use that profile.
--Profile definition is described by <profile>
--<id>
to set a name to uniquely identify the profile
--Other than that, you can basically describe the elements that can be described in pom.xml (<dependencies>
, <build>
, etc.) as they are.
--To specify the profile, specify -P
followed by<id>
of the profile on the command line.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>foo</id>
<properties>
<foo>FOO</foo>
<message>foo profile!!</message>
</properties>
</profile>
<profile>
<id>bar</id>
<properties>
<bar>BAR</bar>
<message>bar profile!!</message>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<configuration>
<target>
<echo>foo = ${foo}</echo>
<echo>bar = ${bar}</echo>
<echo>message = ${message}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--Declaring two profiles, foo
and bar
--message
is declared in both profiles to be duplicated
Execution result
> mvn -P bar,foo antrun:run
...
[echo] foo = FOO
[echo] bar = BAR
[echo] message = bar profile!!
--When specifying multiple profiles, list ʻid`s separated by commas. --Duplicate elements seem to be adopted later on pom.xml (it does not seem to be in the order specified in the profile)
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>foo</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<message>foo profile!!</message>
</properties>
</profile>
<profile>
<id>bar</id>
<properties>
<message>bar profile!!</message>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
...
<configuration>
<target>
<echo>message = ${message}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--The foo
profile is set to<activeByDefault> true </ activeByDefault>
Execution result
> mvn antrun:run
...
[echo] message = foo profile!!
...
> mvn -P bar antrun:run
...
[echo] message = bar profile!!
--The foo
property is enabled by default
--If you set <activation> <activeByDefault>
to true
, the profile will be enabled by default.
--If a different profile is specified with -P
, the profile with<activeByDefault>
is true
will be invalid.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>foo</id>
<activation>
<property>
<name>foo</name>
</property>
</activation>
<properties>
<message>foo profile!!</message>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
...
<configuration>
<target>
<echo>message = ${message}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--Declaring <property>
in <activation>
Execution result
> mvn antrun:run
...
[echo] message = ${message}
...
> mvn -Dfoo antrun:run
...
[echo] message = foo profile!!
--The profile is not specified by -P
, but the foo
profile is enabled by declaring the system property with -Dfoo
.
--In <activation>
, you can define the conditions to enable the profile.
--<property>
can be specified on the condition that a system property is declared or a specific value is set.
--Here, only <name> foo </ name>
is set, so if the system property foo
is set, the profile will be valid regardless of the value.
--If the value is also a condition, declare <value>
as follows:
When the value of the system property is also included in the condition
<property>
<name>foo</name>
<value>enable</value>
</property>
Execution result
> mvn -Dfoo antrun:run
...
[echo] message = ${message}
...
> mvn mvn -Dfoo=enable antrun:run
...
[echo] message = foo profile!!
--The foo
profile is enabled only when the value of the system property foo
is ʻenable`.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>jdk11</id>
<activation>
<jdk>11</jdk>
</activation>
<properties>
<message>jdk11 profile!!</message>
</properties>
</profile>
<profile>
<id>jdk14</id>
<activation>
<jdk>14</jdk>
</activation>
<properties>
<message>jdk14 profile!!</message>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
...
<configuration>
<target>
<echo>message = ${message}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--You are using the <jdk>
element in <activation>
Execution result
> java --version
openjdk 11.0.6 2020-01-14
...
> mvn antrun:run
...
[echo] message = jdk11 profile!!
...
> java --version
openjdk 14 2020-03-17
...
> mvn antrun:run
...
[echo] message = jdk14 profile!!
--The profile has been switched according to the version of the JDK at runtime.
--You can use <jdk>
to make the Java version at runtime a condition for profile application.
--The condition described in <jdk>
is prefix-matched and compared with the Java version.
--If you specify 11
, it also matches 11.0.6
because it is a prefix match.
--Furthermore, you can write a range specification such as (, 11]
(in this case, it matches 11 or lower versions).
--Refer to Apache Maven Enforcer Built-In Rules – Version Range Specification for how to write the range specification.
--For the Java version to be compared, the value obtained by the system property java.version
is used.
--Implementation is probably [this](https://github.com/apache/maven/blob/maven-3.6.3/maven-model-builder/src/main/java/org/apache/maven/model/profile/ activation / JdkVersionProfileActivator.java # L66)
--You can negate the condition by prefixing it with !
, Like <jdk>! 11 </ jdk>
.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>Windows</id>
<activation>
<os>
<name>Windows 10</name>
</os>
</activation>
<properties>
<message>Windows profile!!</message>
</properties>
</profile>
<profile>
<id>Linux</id>
<activation>
<os>
<name>Linux</name>
</os>
</activation>
<properties>
<message>Linux profile!!</message>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
...
<configuration>
<target>
<echo>message = ${message}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--<activation>
is set to <os>
Execution result(Windows)
> mvn antrun:run
...
[echo] message = Windows profile!!
Execution result(Linux)
> mvn antrun:run
...
[echo] message = Linux profile!!
--The applied profile is switched depending on the OS at runtime.
--<os>
allows the OS to be used as a condition for profile application at run time
--<name>
is conditional on the name of the OS
--The OS name uses the value that can be obtained from the system property ʻos.name. --It seems that there is no distinction between uppercase and lowercase letters. --In addition to the name, you can specify the following conditions -
--OS type --See [Apache Maven Enforcer Built-In Rules – Require OS Version](https://maven.apache.org/enforcer/enforcer-rules/requireOS.html) for a list of possible values. --By the way, for Linux, specify ʻunix
.
- <arch>
--CPU architecture
--Specify x86
or ʻamd64 -
Execution result
> mvn enforcer:display-info
...
[INFO] Maven Version: 3.6.3
[INFO] JDK Version: 11.0.6 normalized as: 11.0.6
[INFO] OS Info: Arch: amd64 Family: windows Name: windows 10 Version: 10.0
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>Exists</id>
<activation>
<file>
<exists>${basedir}/pom.xml</exists>
</file>
</activation>
<properties>
<message>Exists profile!!</message>
</properties>
</profile>
</profiles>
<build>
<plugins>
<plugin>
...
<configuration>
<target>
<echo>message = ${message}</echo>
</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
--<activation>
specifies <file>
Execution result
> mvn antrun:run
...
[echo] message = Exists profile!!
--You can use <file>
to use the presence or absence of a file as a condition for applying a profile.
--<exists>
is set on condition that the file exists
--Use <missing>
if the condition is that the file does not exist
--In the file path specification, the embedded parameter is $ {basedir}
or system property / request property? There is a limitation that it can only be used
--If you write $ {project.basedir} /pom.xml
, it will not be judged well.
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<profiles>
<profile>
<id>foo</id>
<properties>
<message>foo profile!!</message>
</properties>
</profile>
<profile>
<id>bar</id>
<properties>
<message>bar profile!!</message>
</properties>
</profile>
</profiles>
...
</project>
--foo
, bar
, two profiles are defined
Execution result
> mvn help:all-profiles
...
[INFO] Listing Profiles for Project: example:hello:jar:1.0.0
Profile Id: bar (Active: false , Source: pom)
Profile Id: foo (Active: false , Source: pom)
-all-profiles in maven-help-plugin You can check the available profiles by running -plugin / all-profiles-mojo.html)
Execution result
> mvn -P foo help:active-profiles antrun:run
...
Active Profiles for Project 'example:hello:jar:1.0.0':
The following profiles are active:
- foo (source: example:hello:1.0.0)
...
[echo] message = foo profile!!
--Use active-profiles to see which profiles are active at runtime it can --Maybe it's useful for debugging
--Profiles allow you to create different build results for each profile
――For this reason, if the profiles are too diverse, different developers may get different build results.
--There was a rule like "For development use, you have to enable the develop
profile "and forgot to specify it.
--Changes in build results can cause confusion
--As you can imagine from the fact that conditions such as <os>
can be set, I think the original purpose of the profile is to absorb the differences in the build environment.
――Therefore, I think it is better to avoid using it for other purposes as much as possible (personal opinion).
--For example, the profile may not be used in the method of switching the configuration file used for development, verification environment, and production environment.
--I feel that it is best practice to use environment variables as a way to switch app settings for each environment these days.
--Reference: III. Settings | The Twelve-Factor App (Japanese translation)
--You can make your own plugin
--If the plugins at ʻorg.apache.maven.pluginsor
com.codehaus.mojo` do not meet your goals, you will have to create your own plugins.
Hello World
pom.xml
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
<packaging>maven-plugin</packaging>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>3.6.3</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.6.0</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<version>3.6.0</version>
</plugin>
</plugins>
</build>
</project>
--Set packaging to maven-plugin
--Set the following two as dependencies
- org.apache.maven:maven-plugin-api
- org.apache.maven.plugin-tools:maven-plugin-annotations
--This is specified in the provided
scope
--Setting maven-plugin-plugin
--When you try to compile with Java 11, it seems that you will get an error unless you update the version of this plugin?
HelloMojo.java
package example;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
@Mojo(name="hello")
public class HelloMojo extends AbstractMojo {
public void execute() throws MojoExecutionException {
getLog().info("Hello Custom Plugin!");
}
}
--ʻAbstractMojoCreate a class by inheriting the class --This
HelloPluginclass corresponds to one goal --Implement the processing of the plugin in the ʻexecute ()
method
--The goal meta information is set with the @Mojo
annotation.
--name
becomes the name of the goal
Build
> mvn install
...
――Run the ʻinstall` phase to install the created plugin in your local repository --Try using the installed plugin in another project
pom.xml(Other projects)
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
<build>
<plugins>
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
</plugins>
</build>
</project>
--You have set hello-maven-plugin
to<plugin>
Execution result
> mvn hello:hello
...
[INFO] Hello Custom Plugin!
--I was able to execute my own plug-in
pom.xml
...
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
...
--It is customary to set ʻartifactId of your own plug-in to
XXX-maven-plugin. --If you set ʻartifactId
to this pattern, the meta definition will be automatically created with the XXX
part as the prefix of the plugin.
--Trial, check inside the created jar file
Contents of jar
hello-1.0.0.jar/
|-example/
`-META-INF/
|-MANIFEST.MF
`-maven/
|-example/
`-plugin.xml
--Looking at the contents of this plugin.xml
, it looks like this:
plugin.xml
...
<plugin>
<name>hello-maven-plugin</name>
<description></description>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
<goalPrefix>hello</goalPrefix>
<isolatedRealm>false</isolatedRealm>
<inheritedByDefault>true</inheritedByDefault>
...
--<goalPrefix>
is now hello
--This allows this plugin to be prefixed with hello: <goal>
.
--If you have ʻartifactId called
foo-maven-plugin, the prefix is
foo`.
Mojo --The class that implements the goal of Maven plugin is called ** Mojo (Maven Old Java Object) **. --When reading Maven documentation, the term Mojo appears here and there. ――In that case, you can think of it as a class that implements goals.
HelloMojo.java
package example;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@Mojo(name="hello")
public class HelloMojo extends AbstractMojo {
@Parameter
private String message;
public void execute() throws MojoExecutionException {
getLog().info("message = " + message);
}
}
--Adding a message
field to Mojo and annotating it with @Parameter
--Getter and Setter are not defined
pom.xml(Another project)
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<message>Hello World!!</message>
</configuration>
</plugin>
</plugins>
</build>
</project>
--<configuration>
declares the same element as the Mojo field name
Execution result
> mvn hello:hello
...
[INFO] message = Hello World!!
--The message
field declared in Mojo can now be specified as a parameter.
--By the way, in this state, you cannot specify the value in the system property.
HelloMojo.java
package example;
...
@Mojo(name="hello")
public class HelloMojo extends AbstractMojo {
@Parameter(property="hello.message")
private String message;
public void execute() throws MojoExecutionException {
getLog().info("message = " + message);
}
}
--Set property
of @Parameter
to the name specified in the system properties.
pom.xml (separate project)
...
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
...
--Do not specify <configuration>
(if it is set, this will take precedence)
Execution result
> mvn hello:hello -Dhello.message="HELLO WORLD!!"
...
[INFO] message = HELLO WORLD!!
--You can now set the value via system properties
HelloMojo.java
package example;
...
@Mojo(name="hello")
public class HelloMojo extends AbstractMojo {
@Parameter(property="hello.message", defaultValue="Hello Custom Plugin!!")
private String message;
public void execute() throws MojoExecutionException {
getLog().info("message = " + message);
}
}
--You can declare the default value for that parameter with the @Parameter
annotation defaultValue
.
pom.xml(Another project)
...
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
...
--<configuration>
is unconfigured
Execution result
> mvn hello:hello
...
[INFO] message = Hello Custom Plugin!!
...
> mvn hello:hello -Dhello.message=OVERRIDE!!
...
[INFO] message = OVERRIDE!!
--If nothing is set, you can see that the value set in defaultValue
is adopted.
HelloMojo.java
package example;
...
@Mojo(name="hello")
public class HelloMojo extends AbstractMojo {
@Parameter(defaultValue="${hello.mojo.message}")
private String message;
public void execute() throws MojoExecutionException {
getLog().info("message = " + message);
}
}
--For the value of defaultValue
, you can write an expression like$ {...}
--Refer to PluginParameterExpressionEvaluator Javadoc for the values that can be referenced in the expression.
--You can also refer to system properties and project properties (<properties>
)
pom.xml(Another project)
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<properties>
<hello.mojo.message>Project Property</hello.mojo.message>
</properties>
<build>
<plugins>
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
</plugin>
</plugins>
</build>
</project>
--Declaring a value in <properties>
with the same key that was declared in the expression defaultValue
Execution result
> mvn hello:hello
...
[INFO] message = Project Property
...
> mvn hello:hello -Dhello.mojo.message="System Property"
...
[INFO] message = System Property
--The value declared in <properties>
is set in the messge
parameter
--Can also be overridden with system properties
--Parameter types can be declared with various types, not just String
HelloMojo.java
package example;
import java.io.File;
import java.net.URL;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
@Mojo(name="hello")
public class HelloMojo extends AbstractMojo {
@Parameter
private int intValue;
@Parameter
private long longValue;
@Parameter
private boolean booleanValue;
@Parameter
private double doubleValue;
@Parameter
private Date dateValue;
@Parameter
private File fileValue;
@Parameter
private URL urlValue;
@Parameter
private HelloEnum enumValue;
@Parameter
private List<String> listValues;
@Parameter
private Map<String, String> mapValue;
public void execute() throws MojoExecutionException {
Log log = getLog();
log.info("intValue=" + intValue);
log.info("longValue=" + longValue);
log.info("booleanValue=" + booleanValue);
log.info("doubleValue=" + doubleValue);
log.info("dateValue=" + dateValue);
log.info("fileValue=" + fileValue);
log.info("urlValue=" + urlValue);
log.info("enumValue=" + enumValue);
log.info("listValues=" + listValues);
log.info("mapValue=" + mapValue);
}
public enum HelloEnum {
HELLO,
WORLD;
}
}
--Parameters are defined with various types
pom.xml(Another project)
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
<configuration>
<intValue>123</intValue>
<longValue>1234567890</longValue>
<booleanValue>true</booleanValue>
<doubleValue>1234.5678</doubleValue>
<dateValue>2019-10-20 12:13:14</dateValue>
<fileValue>foo/bar</fileValue>
<urlValue>https://www.google.co.jp/</urlValue>
<enumValue>HELLO</enumValue>
<listValues>
<aaa>fizz</aaa>
<bbb>buzz</bbb>
</listValues>
<mapValue>
<foo>FOO</foo>
<bar>BAR</bar>
</mapValue>
</configuration>
</plugin>
</plugins>
</build>
</project>
Execution result
> mvn hello:hello
...
[INFO] intValue=123
[INFO] longValue=1234567890
[INFO] booleanValue=true
[INFO] doubleValue=1234.5678
[INFO] dateValue=Sun Oct 20 12:13:14 JST 2019
[INFO] fileValue=F:\tmp\maven\hello\foo\bar
[INFO] urlValue=https://www.google.co.jp/
[INFO] enumValue=HELLO
[INFO] listValues=[fizz, buzz]
[INFO] mapValue={bar=BAR, foo=FOO}
...
--Primitive types such as ʻint,
long,
float,
double,
boolean can be used normally --Wrapper class is also possible --
java.util.Date is specified in one of the following formats --
yyyy-MM-dd HH: mm: ss.S a (Example:
2005-10-06 2:22: 55.1 PM) --
yyyy-MM-dd HH: mm: ssa (Example:
2005-10-06 2:22:55 PM) ――However, even if they do not match exactly, they can be analyzed flexibly (AM and PM can be omitted, but the time cannot be omitted). --
java.io.File treats the value as a path --
java.net.URLtreats the value as a URL --In case of enum type, it can be set by specifying the same value as the listed constant. --In the case of
List, if you enumerate the elements with arbitrary names while writing the same element as the parameter name, it seems that it will be processed as an element of
List. --Usually, it's easier to write like
--In the case of
Map, the name of the nested element is the key and the value of the element is the value. --Although verification is omitted,
java.util.Properties` can be used in the same way.
HelloMojo.java
package example;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
@Mojo(name="hello", defaultPhase=LifecyclePhase.VALIDATE)
public class HelloMojo extends AbstractMojo {
public void execute() throws MojoExecutionException {
getLog().info("Hello Mojo!!");
}
}
--You can specify the default phase with defaultPhase
of @ Mojo
--Use the LifecyclePhase
enumeration to specify the phase
--Here, it is linked to the validate
phase.
pom.xml(Another project)
...
<plugin>
<groupId>example</groupId>
<artifactId>hello-maven-plugin</artifactId>
<version>1.0.0</version>
<executions>
<execution>
<goals>
<goal>hello</goal>
</goals>
</execution>
</executions>
</plugin>
...
--hello
Only the goal is declared, and the phases are not linked.
Execution result(Another project)
> mvn validate
...
[INFO] Hello Mojo!!
--The hello
goal is being executed in the execution of the validate
phase.
Folder structure
|-pom.xml
`-target/
pom.xml
<?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>example</groupId>
<artifactId>hello</artifactId>
<version>1.0.0</version>
</project>
Execution result
> mvn clean
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ hello ---
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Folder structure (after execution)
`-pom.xml
-clean goal of maven-clean-plugin You can remove all project products by running plugin / clean-mojo.html)
--The clean
phase is specified here.
--The clean
goal is associated with the clean
phase by default (confusing)
--By default, the following folders are targeted for deletion
- ${project.build.directory}
- ${project.build.outputDirectory}
- ${project.build.testOutputDirectory}
- ${project.reporting.outputDirectory}
--$ {project.basedir} / target
will be deleted unless you have changed the path of the above folder.
Folder structure
|-pom.xml
|-target/
`-foo/
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project ...>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<filesets>
<fileset>
<directory>${project.basedir}/foo</directory>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
</project>
--Adding <filesets>
and adding the foo
folder to be deleted
Execution result
> mvn clean
...
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ hello ---
[INFO] Deleting ...\foo (includes = [], excludes = [])
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
Folder structure (after execution)
`-pom.xml
--Not only target
but foo
has been deleted
--filesets parameter allows you to add folders and files to be deleted
--<filesets>
specifies a collection of Fileset To do
--It seems that you can narrow down the files not only with <directory>
but also with <includes>
and <excludes>
(I haven't tried it).
It's too difficult to understand where and what information is, so I'll sort it out </ del>
Recommended Posts