[maven] scopes & management & profile & test coverage

[maven] scopes & amp; management & amp; profile & amp; test coverage

Here are some other features and test coverage (mainly jacoco)

scopes

Maven’s scope is mainly used to limit and manage the transitivity of dependencies. Simply put, each scope has its corresponding characteristics and will determine whether the dependent package will be used during packaging and runtime.

The main difference discussed here is compile classpath and runtime classpath. The former is the environment that exists at compile time, and the latter is the environment that exists at runtime.

There are 6 scopes in total

  • compile (default)

    This is the default scope. Dependencies under this scope will be packaged into the final code of the code. It also means that the dependency will be saved to the compile classpath and runtime classpath. A rough understanding is that the packaged jar/war file will Code containing runtime classpath

  • provided

    This scope means that during deployment, the JDK or container will provide the dependency at runtime, so this dependency can be found in the compile classpath, but not in the runtime classpath.

    An example is the servlet API of tomcat, which is definitely needed when compiling, but when deploying, a servlet will be started in the environment, so the runtime classpath does not need to be included.

  • runtime

    This scope means that the dependency is not required at compile time, but is required at runtime, such as JDBC driver

  • test

    As the name suggests, it only needs to be used for compilation and testing, and will not be packaged into the final code.

  • system

    This is rarely used, because once it is used, it means that systemPath needs to be used, and it will become very dependent on the system, which seems to reduce its portability.

  • import

    A relatively special scope, used in special dependencies such as BOM, is mainly used to manage other dependency versions.

At present, the scope pulled from the central repo is relatively accurate. For example, the scope related to junit is test, but this can also be modified as needed.

Project Management

This is divided into three parts:

  • Dependency management
  • Plug-in management
  • Version management

The main application scenarios are version control of dependencies/plug-ins. In the case of an overloaded version, the value at the lower level (closer to the pom of the execution project) will replace the value set at the upper level.

Dependency management

This is mainly achieved by implementing dependencyManagement in the parent element, so that there is no need to re-declare the version in the child element, which facilitates unified management.

Define the junit version in the parent element:

<?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.goldenaarcher.product</groupId>
<artifactId>productparent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>

<name>productparent</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

<modules>
<module>productservices</module>
<module>productweb</module>
</modules>
</project>

At this time, if the version is redeclared in the sub-project, eclipse will report an error like this:

The pom in the sub-project needs to define the dependencies as needed, but the version declaration can be skipped to facilitate unified management.

Plug-in management

Plugin management has a similar pluginManagement, but it needs to be placed under build:

 <build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>17</release>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

In the same way, the same plug-in needs to be declared in sub-projects, but there is no need to implement version and conviguration

Version management

In addition to writing the version directly into version, if some dependencies (such as spring family bucket) need to use the same version, instead of repeating cv, you can also declare version variables in properties to facilitate management:

 <properties>
<java.version>17</java.version>
<junit.version>5.10.0</junit.version>
</properties>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>${java.version}</release>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>

profiles

Profile is some configuration content that can be used to override the default value.

In maven, you can also use different project families to load different configuration files to facilitate management.

Create new project

Select quickstart to create a new demo project

Create configuration file

The profile here is at the same level as main, just create 3 new cases:

?tree src
src
├── main
│ ├── java
│ │ └── com
│ │ └── goldenaarcher
│ │ └── maven
│ │ └── profiledemo
│ │ └── App.java
│ └── profiles
│ ├── dev
│ │ └── application.properties
│ ├── prod
│ │ └── application.properties
│ └── test
│ └── application.properties
└── test
    └── java
        └── com
            └── goldenaarcher
                └── maven
                    └── profiledemo
                        └──AppTest.java

The content inside is also very simple:

? cat src/main/profiles/dev/application.properties
db.url=devurl
db.userName=dev
db.password=dev%

In fact, profiles can also be placed in other places. I remember that one project was placed in resources. This depends on the project habits.

Configuration profile

Profile can be placed directly under xml:

 <profiles>
<profile>
<id>dev</id>
<properties>
<build.profile.id>dev</build.profile.id>
</properties>
<build>
<resources>
<resource>
<directory>src/main/profiles/dev</directory>
</resource>
</resources>
</build>
</profile>

<profile>
<id>prod</id>
<properties>
<build.profile.id>prod</build.profile.id>
</properties>
<build>
<resources>
<resource>
<directory>src/main/profiles/prod</directory>
</resource>
</resources>
</build>
</profile>

<profile>
<id>test</id>
<properties>
<build.profile.id>test</build.profile.id>
</properties>
<build>
<resources>
<resource>
<directory>src/main/profiles/test</directory>
</resource>
</resources>
</build>
</profile>
</profiles>

If there is only one profile, there is no need to set the ID. If there is more than one profile, an error will be reported if not set.

profile use case

Command line execution profile

The syntax is: mvn -P

like:

? mvn install -Pdev
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------< com.goldenaarcher.maven:profiledemo >-----------------
[INFO] Building profiledemo 0.0.1-SNAPSHOT
[INFO]--------------------------------[ jar ]--------------------- --------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ profiledemo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ profiledemo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/usr/study/maven/profiledemo/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ profiledemo ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory /Users/usr/study/maven/profiledemo/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ profiledemo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/usr/study/maven/profiledemo/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ profiledemo ---
[INFO]
[INFO] -------------------------------------------------- --------
[INFO] T E S T S
[INFO] -------------------------------------------------- --------
[INFO] Running com.goldenaarcher.maven.profiledemo.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 s - in com.goldenaarcher.maven.profiledemo.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ profiledemo ---
[INFO] Building jar: /Users/usr/study/maven/profiledemo/target/profiledemo-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ profiledemo ---
[INFO] Installing /Users/usr/study/maven/profiledemo/target/profiledemo-0.0.1-SNAPSHOT.jar to /Users/usr/.m2/repository/com/goldenaarcher/maven/profiledemo/0.0.1-SNAPSHOT /profiledemo-0.0.1-SNAPSHOT.jar
[INFO] Installing /Users/usr/study/maven/profiledemo/pom.xml to /Users/usr/.m2/repository/com/goldenaarcher/maven/profiledemo/0.0.1-SNAPSHOT/profiledemo-0.0.1-SNAPSHOT .pom
[INFO] -------------------------------------------------- --------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------- --------------------------
[INFO] Total time: 2.714 s
[INFO] Finished at: 2023-09-14T22:44:31-04:00
[INFO] -------------------------------------------------- --------------------------

If you unzip the packaged jar file, you can see the application.properties content inside as follows:

? cat target/profiledemo-0.0.1-SNAPSHOT/application.properties
db.url=devurl
db.userName=dev
db.password=dev%
Settings in eclipse

Just modify this in project properties:

jacoco code coverage

sonarqube execution failed

jacoco

Modify pom:

 <build>
<plugins>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.7</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
    </build>

If this plugin is placed under pluginManagement, an error will be reported, but if you pull it out and put it directly under build, the reason is unknown. The solution found on Stack Overflow: maven jacoco: not generating code coverage report

Simply go through the xml configuration. Goal is mentioned in [maven] maven brief introduction and using maven to manage a single project, but execution is not.

The goal is provided by the plugin, and it is only responsible for calling it here.

Execution is used to configure which phase the goal should be executed in. There are two executions here. The first goal is the prepare-agent provided by jacoco. Ignoring the other means that it will be executed from the beginning.

The second execution specifies the phase of generating the report. The phase of generating the test report should be testing, so the report goal is executed in the testing phase.

operation result:

# You need to use verify here but not test. Test will skip report.
? mvn clean verify
[INFO] Scanning for projects...
[INFO]
[INFO]-------------< com.goldenaarcher.product:productservices>--------------
[INFO] Building productservices 1.0
[INFO]--------------------------------[ jar ]--------------------- --------------------------
[INFO]
[INFO] --- maven-clean-plugin:3.1.0:clean (default-clean) @ productservices ---
[INFO] Deleting /Users/usr/study/maven/parent/productservices/target
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.7:prepare-agent (default) @ productservices ---
[INFO] argLine set to -javaagent:/Users/usr/.m2/repository/org/jacoco/org.jacoco.agent/0.8.7/org.jacoco.agent-0.8.7-runtime.jar=destfile=/ Users/usr/study/maven/parent/productservices/target/jacoco.exec
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ productservices ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/usr/study/maven/parent/productservices/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ productservices ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 5 source files to /Users/usr/study/maven/parent/productservices/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ productservices ---
[WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory /Users/usr/study/maven/parent/productservices/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ productservices ---
[INFO] Changes detected - recompiling the module!
[WARNING] File encoding has not been set, using platform encoding UTF-8, i.e. build is platform dependent!
[INFO] Compiling 1 source file to /Users/usr/study/maven/parent/productservices/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ productservices ---
[INFO]
[INFO] -------------------------------------------------- --------
[INFO] T E S T S
[INFO] -------------------------------------------------- --------
[INFO] Running com.goldenaarcher.product.dao.ProductDAOImplTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.07 s - in com.goldenaarcher.product.dao.ProductDAOImplTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- jacoco-maven-plugin:0.8.7:report (report) @ productservices ---
[INFO] Loading execution data file /Users/usr/study/maven/parent/productservices/target/jacoco.exec
[INFO] Analyzed bundle 'productservices' with 3 classes
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ productservices ---
[INFO] Building jar: /Users/usr/study/maven/parent/productservices/target/productservices-1.0.jar
[INFO] -------------------------------------------------- --------------------------
[INFO] BUILD SUCCESS
[INFO] -------------------------------------------------- --------------------------
[INFO] Total time: 4.440 s
[INFO] Finished at: 2023-09-15T00:01:59-04:00
[INFO] -------------------------------------------------- --------------------------

You can see that when running to the test, jacoco’s goal is executed: jacoco-maven-plugin:0.8.7:report (report) @ productservices, and the final directory and results of the report are generated:

? tree target/site
target/site
└── jacoco
    ├── com.goldenaarcher.product.bo
    │ ├── ProductBOImpl.html
    │ ├── ProductBOImpl.java.html
    │ ├── index.html
    │ └── index.source.html
    ├── com.goldenaarcher.product.dao
    │ ├── ProductDAOImpl.html
    │ ├── ProductDAOImpl.java.html
    │ ├── index.html
    │ └── index.source.html
    ├── com.goldenaarcher.product.dto
    │ ├── Product.html
    │ ├── Product.java.html
    │ ├── index.html
    │ └── index.source.html
    ├── index.html
    ├── jacoco-resources
    │ ├── branchfc.gif
    │ ├── branchnc.gif
    │ ├── branchpc.gif
    │ ├── bundle.gif
    │ ├── class.gif
    │ ├── down.gif
    │ ├── greenbar.gif
    │ ├── group.gif
    │ ├── method.gif
    │ ├── package.gif
    │ ├── prettify.css
    │ ├── prettify.js
    │ ├── redbar.gif
    │ ├── report.css
    │ ├── report.gif
    │ ├── session.gif
    │ ├── sort.gif
    │ ├── sort.js
    │ ├── source.gif
    │ └── up.gif
    ├── jacoco-sessions.html
    ├── jacoco.csv
    └──jacoco.xml

6 directories, 36 files

sonarqube

Sonarqube is also a very useful code testing tool, but it needs to modify the local proxy and start a local server to perform the remaining operations. Unfortunately, the proxy of the working machine cannot be changed, so here…

The way it runs is quite simple. Sonarqube provides the sh/bat file. You can start the server by running it directly. After logging in, a string of login numbers is generated on the dashboard. When maven is running, add the login number and sonarqube can analyze it. It is not Too many tools to modify maven configuration