I'm creating a common library that will be used accross several Spring application. I've extracted the common classes I want to share between these application into a new Spring application named "Common". I've used mvn install on this application to put it in my local maven repository. On my main project, I've added the maven dependency, with the same version, in the pom.xml.
Now, if I try to launch mvn compile on my main project, I got this error :
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project recruitment: Compilation failure: Compilation failure:
[ERROR] /D:/[...]/application/src/main/java/com/example/application/service/Service.java:[8,37] package com.example.common.exception does not exist
Indicating that my common library is not present and thus my application cannot find package coming from it.
If I try to launch my Spring application from the main (using Spring Boot), it launchs perfectly and behaves like before.
I'm using IntelliJ on Windows, maven is bundled with IntelliJ with the default installation. If I check in my local maven repository I can find the common library jar. IntelliJ does not show any error on my imports, it recognizes my library.
There seem to be some conflict between IntelliJ, which read the pom.xml to find libraries imported for my application, and maven that use the same pom.xml to compile my code.
I used mvn compile -X to have more information and the funny part is that maven is using the common library jar from the local repository :
[INFO] Changes detected - recompiling the module!
[DEBUG] Classpath:
[DEBUG] D:\[...]\application\target\classes
[DEBUG] C:\[...]\.m2\repository\com\example\common\0.0.1\common-0.0.1.jar
Do you have any idea why I can't compile my project with maven while
I can launch it as a Spring application ?
Here is my dependency in my pom.xml :
<dependency>
<groupId>com.example</groupId>
<artifactId>common</artifactId>
<version>0.0.1</version>
<scope>compile</scope>
</dependency>
And the common library definition :
<groupId>com.example</groupId>
<artifactId>common</artifactId>
<version>0.0.1</version>
<name>common</name>
<description>Common project with generic technical modules</description>
Okay, that's embarassing... I just found the solution ! It has been two days looking for a solution to this tricky situation and I just found what was missing, or rather what was too much.
This bad boy :
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
The Spring boot maven plugin is what makes my Spring boot application launchable from maven, and it seems that it affects the way the common jar library is made, or the way it is imported.
I don't really understand why exactly it affects my import, but I deleted the plugin above in my common library pom.xml, I reinstalled in my local repository and I launch mvn install again on my main application... And it now works !
I think that launching via Spring boot used a little bit of Spring boot magic to make it works that the maven way lacks.
If someone understands it better and can explain it, that would be great and the accepted answer I think.
The reason for that is that application classes are packaged in BOOT-INF/classes so that the dependent module cannot load a repackaged jar’s classes
Proper config will look like:
<project>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.3.1.RELEASE</version>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Taken from
https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/html/#repackage-examples
Related
I have a Maven Spring Boot Micro Services Java project arranged into a parent module and 6 sub-modules. In the parent pom.xml, I have included the Maven Spring Boot Plugin in the build/plugins section: -
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.5.RELEASE</version>
</plugin>
5 of my 6 sub-modules are Micro Services, and the above plugin ensures that these are built into executable Spring Boot jars, including all dependencies, when I run mvn clean install
However, the other sub-module is just a standard Java utility project and does not have a Spring Boot context. When I try to build, I see the following error: -
Execution repackage of goal org.springframework.boot:spring-boot-maven-plugin:2.1.5.RELEASE:repackage failed: Unable to find main class -> [Help 1]
This is expected as this sub-module is not a Spring Boot application and does not have a main class. I tried to fix this by overriding the Spring Boot Maven plugin in the pom file of that sub-module so that it is treated as a standard 'thin' jar: -
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<dependencies>
<!-- The following enables the "thin jar" deployment option. -->
<!-- This creates a normal jar, not an executable springboot jar -->
<dependency>
<groupId>org.springframework.boot.experimental</groupId>
<artifactId>spring-boot-thin-layout</artifactId>
<version>1.0.11.RELEASE</version>
</dependency>
</dependencies>
</plugin>
However, I am still seeing exactly the same error in my Maven build. I would be most grateful for any hints or pointers on this one.
You can skip the execution of the repackage plugin for your utility module by overriding the configuration in that module.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
Let's say I want to install project-local dependencies (jar files) to my local maven repository (~/.m2) prior to compiling the project so I can reference them in my POM just like I would reference any dependency from Maven Central. Currently, I'm using Maven install plugin's install-file goal attached to the 'clean' phase (because my IDE uses it), like so:
<dependencies>
<dependency>
<groupId>group.id</groupId>
<artifactId>artifact.id</artifactId>
<version>artifact.version</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
<executions>
<execution>
<id>install-my-local-dependency</id>
<phase>clean</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<groupId>group.id</groupId>
<artifactId>artifact.id</artifactId>
<version>artifact.version</version>
<file>${project.basedir}/lib/local-dep.jar</file>
<packaging>jar</packaging>
<generatePom>true</generatePom>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
When I execute mvn clean (or its equivalent in the IDE), everything runs as I'd expect:
--- maven-clean-plugin:2.5:clean (default-clean) # MyProject ---
--- maven-install-plugin:2.5.2:install-file (install-...) # MyProject ---
Installing ${project.basedir}/lib/local-dep.jar to ~/.m2/repository/group.id/artifact.id/local-dep.jar
But when I execute mvn clean install instead (or its equivalent in the IDE), I get the following error:
Failed to execute goal on project MyProject: Could not resolve dependencies for project com.example.MyProject:jar:1.0: Could not find artifact group.id:artifact.id:jar:artifact.version in central (https://repo.maven.apache.org/maven2) -> [Help 1]
For some reason, Maven install plugin's install-file goal either does not run in this case, or doesn't run soon enough. Why? The other StackOverflow answers I found explain differences between both commands but in my eyes, they do not explain this particular difference as my project has no modules.
Is there a better way of doing the same thing cross-platform, even on build servers (e.g. Jenkins) and with at least one other dependent project?
Should it be any help, I have the following Maven versions:
CLI: 3.6.0
IDE: 3.3.9
Maven first analyses the pom.xml and then calls the goals/phases. The analysis itself is complicated and has different depths, so I guess that calling clean alone will not make Maven analyse the dependencies, but calling clean install does so. Note that the analysis of the POM only happens once, not again for every goal/phase.
Generally, your approach cannot be recommended. Usually, you put project dependencies into remote Maven repositories, so that they can be resolved through them. If you work inside a company, you should set up a Nexus/Artifactory server that handles your artifacts.
If you want people outside your company to build the artifact, you need to find a provider for Maven repositories. I guess that github/gitlab can help you here. Then you need to add those repositories to the POM.
my team and I have a maven project using jdk1.8 (not open jdk) and javaFX for our UI. It's working well and there still a lot of work to do and we'd like to use the pipelines from Bitbucket to make continuous integration on the go.
I tried to use a simple .yml file :
image: maven:3.3.9-jdk-8
pipelines:
default:
- step:
caches:
- maven
script: # Modify the commands below to build your repository.
- mvn -B verify # -B batch mode makes Maven less verbose
But there is my problem, We are developping with IntelliJ and jdk1.8 where javaFX is standard and automatically included in the project. But the pipelines tries to use openjdk1.8, and can't find the javaFX classes (especially the jfxrt.jar file).
If I do nothing and try as it is, the Maven error is :
[ERROR] /opt/atlassian/pipelines/agent/build/src/main/java/JFX/MainJFX.java:[3,26] package javafx.application does not exist
[ERROR] /opt/atlassian/pipelines/agent/build/src/main/java/JFX/MainJFX.java:[4,19] package javafx.fxml does not exist
[ERROR] /opt/atlassian/pipelines/agent/build/src/main/java/JFX/MainJFX.java:[5,20] package javafx.scene does not exist
[ERROR] /opt/atlassian/pipelines/agent/build/src/main/java/JFX/MainJFX.java:[6,20] package javafx.scene does not exist
[ERROR] /opt/atlassian/pipelines/agent/build/src/main/java/JFX/MainJFX.java:[7,20] package javafx.stage does not exist
I tried to include the jfxrt.jar file to maven to my pom.xml as a system dependency like that :
<dependency>
<groupId>javafx</groupId>
<artifactId>jfxrt</artifactId>
<version>${java.version}</version>
<scope>system</scope>
<systemPath>${java.home}/lib/ext/jfxrt.jar</systemPath>
</dependency>
But then Maven warns me he does not find the jfxrt.jar file :
[WARNING] 'dependencies.dependency.systemPath' for javafx:jfxrt:jar refers to a non-existing file /usr/lib/jvm/java-8-openjdk-amd64/jre/lib/ext/jfxrt.jar # line 34, column 25
Mainly because he is using openjdk and not jdk.
I also tried to put the jfxrt.jar file inside the repository and make a dependency to it, it works but Maven warns me it's not proper to do it like that :
<dependency>
<groupId>com.oracle</groupId>
<artifactId>javafx</artifactId>
<version>2.0</version>
<scope>system</scope>
<systemPath>${basedir}/dependency/jfxrt.jar</systemPath>
</dependency>
and the warning :
[WARNING] 'dependencies.dependency.systemPath' for com.oracle:javafx:jar should not point at files within the project directory, ${basedir}/dependency/jfxrt.jar will be unresolvable by dependent projects # line 34, column 25[WARNING]
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.[WARNING]
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
My question is how to either force Maven to use JDK and not OpenJDK, or how to make a nice dependency to javaFX so Maven can verify our project everytime we push and not warn us.
Thank you all for your future responses.
Due to Oracle's licensing of Java, Docker Hub no longer hosts official images containing the Oracle JDK. All the official images, including the Maven one you're using, are now based on OpenJDK instead.
To use Oracle Java, you'll need to build your own Docker image as the Pipelines build environment (relatively simple), or find a trusted source for a Docker image with the JDK in it. (It's pretty easy to find these via Google search, because this is a common problem.)
Frist: JavaFX ist part of the OpenJDK. This setup works for me since the open beta of piplines:
the yaml file
image: maven:3.3.3
pipelines:
default:
- step:
script: # Modify the commands below to build your repository.
- mvn clean install
and here the 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>my.group.id</groupId>
<artifactId>my.artifact.id</artifactId>
<name>my.app.name</name>
<version>1.0.0</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/</sourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<!-- goal is 'mvn jfx:jar' -->
<plugin>
<groupId>com.zenjava</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>8.7.0</version>
<configuration>
<mainClass>package.to.my.main.class</mainClass>
</configuration>
<executions>
<execution>
<id>create-jfxjar</id>
<phase>package</phase>
<goals>
<goal>build-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
I have a project made up of several modules.
I'm trying to analyse these with SonarQube.
I've included the Sonar Maven plugin as a dependency in each module:
<dependency>
<groupId>org.codehaus.sonar</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>5.1</version>
</dependency>
Then I'm running Maven using:
mvn clean verify sonar:sonar
Maven completes successfully and I can see the Sonar analysis happening however when I open the Sonar UI, the modules aren't visible in projects.
However...
If I run the Maven command from an individual module directory, it is visible in projects.
Feel I'm missing something very simple, appreciate any help!
Instead of as a dependency, put the sonar-maven-plugin in the <build> section of the root pom.xml, as follows:
<build>
<plugins>
<plugin>
<groupId>org.sonarsource.scanner.maven</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>3.0.1</version>
</plugin>
</plugins>
</build>
And since it's a multi-module project, you should first perform an install from the root project and then run the sonar:sonar goal as a dedicated step, as follows:
mvn clean install
mvn sonar:sonar
To configure the sonarqube server URL, specify a project property of sonar.host.url in your settings.xml or pom.xml as follows:
<properties>
<!-- Optional URL to server. Default value is http://localhost:9000 -->
<sonar.host.url>http://myserver:9000</sonar.host.url>
</properties>
SonarQube supports multi-module projects just like Maven does. This means that a Maven project containing multiple modules maps to a SonarQube project containing multiple modules/components, not multiple projects.
Take SonarQube code for example (it's a multi-module Maven project): the parent project aggregates all info from sub-modules, then if you check its structure (or its code page) you can see the list of all sub-components (for example: SonarQube::Core)
The bottom line is that you're seeing expected behaviour. Sub-modules of a Maven project are not meant to be analysed as projects, you should always analyse the parent project and SonarQube will handle modules natively.
Maven project structure
I have a trivial multi module Maven project:
parent-project
child-project1 (war)
child-project2 (jar)
parent-project's pom.xml references both child projects in its <modules> section. Both child projects reference the parent in their <parent> sections.
child-project1 depends on child-project2 (it references it in the <dependencies> section).
The problem
I am trying to use the License Maven Plugin on the parent-project to generates a file containing a list of all dependencies and their licenses:
mvn license:aggregate-add-third-party
I get an error:
Failed to execute goal on project child-project1: Could not resolve dependencies
for project ... child-project1 ... : Could not find artifact ... child-project2 ...
When I comment out the dependency of child-project1 on child-project2 the plugin works with no problem. So I can use the plugin, but I have to comment out the dependency each time I do it.
What is the problem? Is there a way to fix it?
The problem you are facing is that the maven-license-plugin by default looks in your local repository for the child artifacts.
I suppose, your plugin configuration in the parent pom.xml looks like the following:
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>1.6</version>
<configuration>
<!-- your own config goes here -->
</configuration>
</plugin>
</plugins>
You have to install your multi-module project to your local Maven repository using
mvn install
After that, you run
mvn license:aggregate-add-third-party
again and the build will succeed.
If you configured an <execution> in your plugin, this will fail, since the maven-license-plugin by default binds to the generate-resources phase [1] and this is always executed prior to install [2].
Cheers,
PK