I have a multi-module maven application which uses Spring boot:
- spring boot parent
- myproject parent (both parent and module pom)
- module1
- module2
- module-it (integration tests)
In my module-it, I add the other modules as dependencies.
When I build my project with maven, I get "Build Success":
mvn clean install
So far so good.
Yet I would like each of my modules to be an executable jar at the end of the build. With the above settings, the manifest is not defined and the jar is not executable.
To fix this issue, I've added the following in my module1 and module2 pom files:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
With this setting, my jar file is executable but I cannot build anymore. Classes that I use in my module-it are not found.
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:testCompile (default-testCompile) on project module-it: Compilation failure: Compilation failure:
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/greeting/GreetingControllerIT.java:[20,17] cannot find symbol
[ERROR] symbol: class GreetingController
[ERROR] location: class com.mycompany.testing.greeting.GreetingControllerIT
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/hello/HelloControllerIT.java:[20,17] cannot find symbol
[ERROR] symbol: class HelloController
[ERROR] location: class com.mycompany.testing.hello.HelloControllerIT
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/greeting/GreetingControllerIT.java:[16,27] cannot find symbol
[ERROR] symbol: class GreetingController
[ERROR] /home/user/<path-to-project>/testing/module-it/src/test/java/com/mycompany/testing/hello/HelloControllerIT.java:[16,27] cannot find symbol
[ERROR] symbol: class HelloController
Can you please help me understand why spring-boot-maven-plugin makes my build fail and how I can solve the issue?
Thanks in advance for your help.
To solve this issue, we can add a classifier as described in the documentation custom repackage classifier
The plugin then becomes:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
Also you could set repackage goal parameter attach to false:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<attach>false</attach>
</configuration>
</execution>
</executions>
</plugin>
At least for the spring-boot-starter-parent:2.6.0 pom the configuration for the spring-boot-maven-plugin contains an <id>repackage</id> for the execution of the repackage goal
So I had to add the line <id>repackage</id> too.
Full configuration:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
Late answer to an old question but i've just been working on this for the past hours. Even though the previous answers were helpfull they don't explain why this problem is happening.
For others that may comes accross this issue here is a detailed explnation why it's not working
In a Nutshell
Usualy Maven package your application as a regular .jar with all compiled class being in a well known location in the .jar file.
So it's pretty straighforward for a compiler to import the .jar as a library and to load the available .class.
But the spring-boot-maven-plugin is actually modifying the .jar structure to leverage spring-boot logic when you start the .jar application.
In short, the .class are not available to be imported as a "library" from the resulting .jar, because the spring class have took the well known location for itself.
Detailed explanation
Let's explore the problem with an example
Project structure
Let's imagine a project with multiple maven modules like so
my-app/ -- The parent project
├─ pom.xml
├─ application/
│ ├─ pom.xml
├─ integration-tests/
│ ├─ pom.xml
Given the following pom.xml files:
my-app/pom.xml:
<project [...]>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.0</version>
<relativePath/>
</parent>
<groupId>com.me</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>application</module>
<module>integration-tests</module>
</modules>
</project>
my-app/application/pom.xml:
<project [...]>
<parent>
<groupId>com.me</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>application</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
my-app/integration-tests/pom.xml:
<project [...]>
<parent>
<groupId>com.me</groupId>
<artifactId>my-app</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>integration-tests</artifactId>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.me</groupId>
<artifactId>application</artifactId>
</dependency>
</dependencies>
</project>
Why is it not building
Let's try to package our app
/my-app$ mvn package
Of course it will miserably fail with an error cannot find symbol, but why is it so?
Let's take a look at our architecture after the failed build:
my-app/ -- The parent project
├─ pom.xml
├─ application/
│ ├─ pom.xml
│ ├─ target/
│ │ ├─ application-1.0.0-SNAPSHOT.jar
│ │ ├─ application-1.0.0-SNAPSHOT.jar.original
├─ integration-tests/
│ ├─ pom.xml
│ ├─ target/
The spring-boot-maven-plugin has done several things to the application module output:
renamed the compiled application-1.0.0-SNAPSHOT.jar to application-1.0.0-SNAPSHOT.jar.original
created it's own .jar with the name of application-1.0.0-SNAPSHOT.jar
Let's explore the structure of the application-1.0.0-SNAPSHOT.jar:
BOOT-INF/
├─ classes/
│ ├─ com/
│ │ ├─ me/ -- The compiled .class of your project reside here
META-INF/
org/
├─ springframework/
│ ├─ boot/ -- contains the spring boot loader classes
As you can see the .class files at the root of your .jar are the spring boot loader classes, not our own .class that are relegated to the BOOT-INF/classes/ folder.
This is not conventional, and when the .jar is imported as a dependency it won't search here for class to import.
Because of that, when maven try to package the integration-tests module, it fails because the class present in the application-1.0.0-SNAPSHOT.jar are actually a bunch of spring class instead of the one you are trying to import from application module.
If you were to look at the structure of the application-1.0.0-SNAPSHOT.jar.origial it would be something like so:
META-INF/
com/
├─ me/ -- contains the spring boot loader classes
Solution
Getting rid of spring-boot-maven-plugin is not an acceptable solution; Of course your project will be buildable, but the resulting .jar won't be a spring boot standalone running .jar.
Instead you can instruct the spring-boot-maven-plugin to not replace the original jar and to build to spring boot jar with another name.
To do so you'll need to configure the spring-boot-maven-plugin in the application module:
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<id>repackage</id>
<configuration>
<classifier>exec</classifier>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Now when you build your project you'll have something like that:
my-app/ -- The parent project
├─ pom.xml
├─ application/
│ ├─ pom.xml
│ ├─ target/
│ │ ├─ application-1.0.0-SNAPSHOT.jar -- the original untouched .jar
│ │ ├─ application-1.0.0-SNAPSHOT-exec.jar -- the spring boot executable .jar
├─ integration-tests/
│ ├─ pom.xml
│ ├─ target/
│ │ ├─ integration-tests-1.0.0-SNAPSHOT.jar
Related
I am building an eclipse plugin with Tycho. I want to create an Update Site for it. I have the following components:
parent (pom)
the plugin (eclipse-plugin)
the feature (eclipse-feature)
the update site (eclipse-repository)
But when I run mvn clean package in the target folder of my update site project I have:
├── lorem-ipsum-eclipse-update-1.0.1-SNAPSHOT.zip
├── local-artifacts.properties
├── p2agent
│ ├── org.eclipse.equinox.p2.core
│ │ └── cache
│ │ └── artifacts.xml
│ └── org.eclipse.equinox.p2.engine
│ └── profileRegistry
├── p2artifacts.xml
├── p2content.xml
├── repository
│ ├── artifacts.jar
│ ├── artifacts.xml.xz
│ ├── content.jar
│ ├── content.xml.xz
│ └── p2.index
└── targetPlatformRepository
└── content.xml
As you can see the plugin and feature folders are missing in target/repository.
This is my parent pom:
<?xml version="1.0" encoding="UTF-8"?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.lorem.ipsum.eclipse</groupId>
<version>1.0.1-SNAPSHOT</version>
<artifactId>lorem-ipsum-eclipse-parent</artifactId>
<packaging>pom</packaging>
<properties>
<tycho-version>2.2.0</tycho-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<modules>
<module>lorem-ipsum-eclipse-feature</module> <!-- packaging: eclipse-feature -->
<module>lorem-ipsum-eclipse-plugin</module> <!-- packaging: eclipse-plugin -->
<module>lorem-ipsum-eclipse-update</module> <!-- packaging: eclipse-repository -->
</modules>
<repositories>
<repository>
<id>2020-12</id>
<layout>p2</layout>
<url>http://download.eclipse.org/releases/2020-12</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-maven-plugin</artifactId>
<version>${tycho-version}</version>
<extensions>true</extensions>
</plugin>
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-p2-repository-plugin</artifactId>
<version>${tycho-version}</version>
<configuration>
<includeAllDependencies>true</includeAllDependencies>
<createArtifactRepository>true</createArtifactRepository>
<compress>true</compress>
</configuration>
</plugin>
<!--Enable the replacement of the SNAPSHOT version in the final product configuration-->
<plugin>
<groupId>org.eclipse.tycho</groupId>
<artifactId>tycho-packaging-plugin</artifactId>
<version>${tycho-version}</version>
<executions>
<execution>
<phase>package</phase>
<id>package-feature</id>
<configuration>
<finalName>${project.artifactId}_${unqualifiedVersion}.${buildQualifier}</finalName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
What am I doing wrong?
Thanks in advance.
UPDATE: As howlger requested here is update site's category.xml.
<?xml version="1.0" encoding="UTF-8"?>
<site>
<feature id="com.lorem.ipsum.eclipse.feature" version="0.0.0">
<category name="com.lorem.ipsum.eclipse.category"/>
</feature>
<category-def name="com.lorem.ipsum.eclipse.category" label="Lorem Ipsum">
<description>
Contains features for Lorem Ipsum plugin
</description>
</category-def>
</site>
By the way my file is named site.xml because if I named category.xml I have this error when i tried to run any maven goal:
$ mvn clean
...
[ERROR] Cannot resolve project dependencies:
[ERROR] Software being installed: lorem-ipsum-eclipse-update raw:1.0.1.'SNAPSHOT'/format(n[.n=0;[.n=0;[-S]]]):1.0.1-SNAPSHOT
[ERROR] Missing requirement: lorem-ipsum-eclipse-update raw:1.0.1.'SNAPSHOT'/format(n[.n=0;[.n=0;[-S]]]):1.0.1-SNAPSHOT requires 'org.eclipse.equinox.p2.iu; com.lorem.ipsum.eclipse.feature.feature.group 0.0.0' but it could not be found
[ERROR]
[ERROR] See https://wiki.eclipse.org/Tycho/Dependency_Resolution_Troubleshooting for help.
[ERROR] Cannot resolve dependencies of MavenProject: com.globant.augmented.coding.eclipse:lorem-ipsum-eclipse-update:1.0.1-SNAPSHOT # /home/me/workspaces/java/lorem-ipsum-eclipse-project/lorem-ipsum-eclipse-update/pom.xml: See log for details -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MavenExecutionException
I followed the instructions of the book Eclipse 4 Plug-in Development by Example Beginners Guide by Dr Alex Blewitt which uses an old version of tycho (0.18.0) and I have used 2.2.0. Maybe in this version they fixed the fact of renaming site to category since in the same book they mentioned that it was a meaningless change.
I quote:
Rename the site.xml file to category.xml . (This is an entirely
pointless change required by p2 since the files are identical in
format.)
According the the error message (... lorem-ipsum-eclipse-update ... Missing requirement: ... com.lorem.ipsum.eclipse.feature.feature.group ...) the update site category.xml refers a missing feature.
Make sure to use the same feature ID (<feature id="...") in the following two files:
<your-feature>/feature.xml
<your-update-site>/category.xml
See also the vogella tutorial Eclipse Tycho for building Eclipse Plug-ins and RCP applications: in category.xml the feature is referenced via the ID com.vogella.tycho.feature.
com.vogella.tycho.feature
I am trying to make a spring boot multistage build, I have a spring boot project X that contains two util projects as dependencies in other folder, when I try to make the build it fails because this dependencies does not exist.
I tried using multi module maven project but this utils will be used in other projects.
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 08:23 min
[INFO] Finished at: 2019-09-27T01:29:09Z
[INFO] Final Memory: 44M/228M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal on project projectX: Could not resolve dependencies for project com.demo:projectX:jar:0.1: The following artifacts could not be resolved: com.util:util1:jar:0.1, com.util:util2:jar:0.1: Could not find artifact com.util:util1:jar:0.1 in spring-milestones (https://repo.spring.io/milestone) -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
ERROR: Service 'projectX' failed to build: The command '/bin/sh -c ./mvnw dependency:go-offline -B' returned a non-zero code: 1
(edit) Here is dockerfile for multistage maven build
(edit) the docker build command and context path is from parent folder
FROM openjdk:8-jdk-alpine as build-util1
WORKDIR /util1
COPY ./components/util1/mvnw .
COPY ./components/util1/.mvn .mvn
COPY ./components/util1/pom.xml .
COPY ./components/util1/src src
RUN ./mvnw clean install
FROM openjdk:8-jdk-alpine as build-util2
WORKDIR /util
COPY --from=build-util1 /root/.m2 /root/.m2
COPY ./components/util2/mvnw .
COPY ./components/util2/.mvn .mvn
COPY ./components/util2/pom.xml .
COPY ./components/util2/src src
RUN ./mvnw clean install
FROM openjdk:8-jdk-alpine as build
WORKDIR /app
COPY --from=build-util2 /root/.m2 /root/.m2
COPY mvnw .
COPY .mvn .mvn
COPY pom.xml .
RUN ./mvnw dependency:go-offline -B
COPY src src
RUN ./mvnw -X package -DskipTests
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../*.jar)
FROM openjdk:8-jre-alpine
ARG DEPENDENCY=/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
ENTRYPOINT ["java","-cp","app:app/lib/*","com.demo.projectx.ProjectX"]
Here is the pom.xml for the project X
<?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>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.7.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.demo</groupId>
<artifactId>projectX</artifactId>
<version>0.1</version>
<name>projectX</name>
<description>projectX</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR3</spring-cloud.version>
<docker.image.prefix>jxssw</docker.image.prefix>
<docker.image.name>${project.artifactId}</docker.image.name>
<docker.image.tag>${project.version}</docker.image.tag>
</properties>
<dependencies>
<!-- utils -->
<dependency>
<groupId>com.util</groupId>
<artifactId>util1</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>com.util</groupId>
<artifactId>util2</artifactId>
<version>0.1</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- Dockerfile Maven -->
<plugin>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.10</version>
<configuration>
<googleContainerRegistryEnabled>false</googleContainerRegistryEnabled>
<repository>${docker.image.prefix}/${docker.image.name}</repository>
<tag>${project.version}</tag>
</configuration>
<executions>
<execution>
<id>build</id>
<phase>clean</phase>
<goals>
<goal>build</goal>
<goal>tag</goal>
</goals>
</execution>
<execution>
<id>push</id>
<phase>deploy</phase>
<goals>
<goal>push</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Dockerfile Maven -->
</plugins>
<finalName> ${project.artifactId}</finalName>
</build>
<repositories>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
</repository>
</repositories>
</project>
(edit) add the folder structure:
.(parent)
├── projects
| └── projectX
│ ├── pom.xml
│ ├── Dockerfile
│ └── src
│ └── main
├── components
| └── util1
│ ├── pom.xml
│ └── src
│ └── main
| └── util2
│ ├── pom.xml
│ └── src
│ └── main
I began my first pure front end project. I want to deploy it the java/maven. So i set up a normal war project:
│ package.json
│ pom.xml
│ tsconfig.json
│ typings.json
│
│
├───src
│ └───main
│ ├───resources
│ └───webapp
│ │ index.html
│ │
│ ├───app
│ │ app.component.ts
│ │ main.ts
│ │
│ ├───css
│ │ styles.css
│ │
│ └───WEB-INF
│ web.xml
│
My problem is how to set the path to index.html/the source relative to package. json? Since this is an angular/typescript project there is also some typescript specific stuff. but my hope is to set the "source" path once and for all in package json?!
I am also not sure if i want to deploy the stuff in "webapp" directly since there are Compiling steps. So any advice how to structure a pur front end project for maven/war deployment are welcome.
In order to integrate NPM with Maven, you could make use of frontend-maven-plugin which I think will be a great tool for your compiling steps.
So, in order to configure everything together this how your pom.xml should look like:
<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>group.id</groupId>
<artifactId>artifact-id</artifactId>
<version>2.0.14-SNAPSHOT</version>
<name>Artifact Name</name>
<packaging>war</packaging>
<!-- Plug-in definition -->
<build>
<plugins>
<!-- frontend-maven plug-in -->
<plugin>
<groupId>com.github.eirslett</groupId>
<artifactId>frontend-maven-plugin</artifactId>
<version>0.0.29</version>
<configuration>
<nodeVersion>v5.10.1</nodeVersion>
<npmVersion>3.8.6</npmVersion>
<installDirectory>target</installDirectory>
<workingDirectory>${basedir}</workingDirectory>
</configuration>
<executions>
<!-- install node & npm -->
<execution>
<id>install node and npm</id>
<goals>
<goal>install-node-and-npm</goal>
</goals>
</execution>
<!--npm install -->
<execution>
<id>npm install</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>install</arguments>
</configuration>
</execution>
<!-- npm run build -->
<execution>
<id>npm run build</id>
<goals>
<goal>npm</goal>
</goals>
<configuration>
<arguments>run build</arguments>
</configuration>
</execution>
</executions>
</plugin>
<!-- Maven WAR plug-in -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
</configuration>
</plugin>
</plugins>
</build>
</project>
As you can see, first we define the usage of frontend-maven-plugin:
we use the most recent stable NodeJS version: v5.10.1;
the most recent version of NPM: 3.8.6;
since the plugin downloads and installs NodeJS and NPM, one needs to declare the installation directory (installDirectory). I've opted to store everything on Maven's target directory;
then it's necessary to define one's working directory (workingDirectory), which basically is the directory where our package.json will be. In your case, it will be at the same level as your pom.xml file, so we use ${basedir} for that;
following, it will be necessary to define the executions: the first two I believe that are quite straightforward; the last one simply assumes that, inside your package.json, there's a script target named build which will, for example, call the browserify command in order to build a bundle.js file:
"scripts": {
"build": "browserify src/main/webapp/app.js -o src/main/webapp/modules/bundle.js"
}
In your case, instead of the app.js, the package.json would interact with your typescript files.
Finally, one has the definition of the Maven WAR plugin. The only configuration made was the mention to the location where the web.xml is.
Notice that, by definition, Maven will package everything that's inside src/main/webapp directory. So, if there are any files (or folders) that you'd like to exclude, you should make use of the configuration parameter <packagingExcludes>:
<!-- Maven WAR plug-in -->
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<webXml>src/main/webapp/WEB-INF/web.xml</webXml>
<packagingExcludes>app/**</packagingExcludes>
</configuration>
</plugin>
The configuration above would exclude the folder app.
Again, this is a starting point. From here, you could play with Maven in order to custom build your application.
The <archiveClasses> option has no effect.
Running mvn clean compile war:exploded produces a war directory with .class files in the classes directory, and they are not archived into a jar in the lib directory neither. war:war produces same result.
Plugin configuration:
...
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>
...
Workarounds?
Maven version 3.3.3, maven-war-plugin version 2.6.
JIRA ticket – https://issues.apache.org/jira/browse/MWAR-355
This is the project in question: https://bitbucket.org/dmos62/raudondvaris
The first thing is you should move the plain configuration into a pluginManagement block like this:
<build>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.6</version>
<configuration>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
If you do the above the classes will be created within the war archive by using: mvn clean compile war:war
~/ws-git/so-questions/so-5 (master)$ unzip -t target/web-1.0.0-SNAPSHOT.war
Archive: target/web-1.0.0-SNAPSHOT.war
testing: META-INF/ OK
testing: META-INF/MANIFEST.MF OK
testing: WEB-INF/ OK
testing: WEB-INF/classes/ OK
testing: WEB-INF/lib/ OK
testing: WEB-INF/lib/commons-fileupload-1.1.1.jar OK
testing: WEB-INF/lib/commons-io-1.1.jar OK
testing: WEB-INF/lib/web-1.0.0-SNAPSHOT.jar OK
testing: WEB-INF/web.xml OK
testing: META-INF/maven/com.soebes.examples.so/web/pom.xml OK
testing: META-INF/maven/com.soebes.examples.so/web/pom.properties OK
testing: META-INF/INDEX.LIST OK
No errors detected in compressed data of target/web-1.0.0-SNAPSHOT.war.
This will also working for your call mvn clean compile war:exploded.
└── web-1.0.0-SNAPSHOT
├── META-INF
└── WEB-INF
├── classes
├── lib
│ ├── commons-fileupload-1.1.1.jar
│ ├── commons-io-1.1.jar
│ └── web-1.0.0-SNAPSHOT.jar
└── web.xml
The reason for this behaviour is simply cause by using a goal like war:war, or war:exploded there will be no life cycle started which means the configuration in the pom is not taken into account. If you like having a configuration for your command line calls you can do this by using a special configuration for command line calls like this (The id default-cli is the important part):
<project>
<build>
<plugins>
<plugin>
<groupId...>
<artifactId...>
<executions>
<execution>
<id>default-cli</id>
<configuration>
.....
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
which means having a special configuration for command line calls. Starting with Maven 3.3.1 it is possible having more than one configuration for command line calls by using it like:
<project...>
<build>
<plugins>
<plugin>
<groupId>...</groupId>
<artifactId>...</artifactId>
<executions>
<execution>
<id>first-cli</id>
<configuration>
....
</configuration>
</execution>
<execution>
<id>second-cli</id>
<configuration>
....
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
This can be used by maven via the following:
mvn plugin:goal#second-cli
mvn plugin:goal#first-cli
See also the release notes for Maven 3.3.1.
I am having some issues with my multi-project Maven project.
The problem is the following:
I have a project that organized in the following way:
root
+-- pom.xml
!
+-- module1
! +-- pom.xml
+-- module2
+-- pom.xml
Where module2 depends on module1.
Module1 is packaged as war, it also generates jar file that module2 depends on.
Everything is fine whenever the changes are only in module2 i.e. module1.jar is already in remote repo, however whenever there are changes in both modules during mvn clean release:clean release:prepare release:perform I get an error saying that module1.jar could not be found in remote repo.
So to fix that I have added maven-install-plugin to the Module1's pom file like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
<!-- <packaging>jar</packaging> -->
</configuration>
<executions>
<execution>
<id>install</id>
<phase>compile</phase>
<goals>
<goal>install</goal>
</goals>
</execution>
</executions>
whenever i comment out <packaging>jar</packaging> it tries to install Module1 jar file into local repo as war file (I am guessing that by default it would pick up packaging from the POM file). So i get something like this:
[INFO] [INFO] [jar:jar {execution: creation}]
[INFO] [INFO] Building jar: ${project.build.directory}/${project.artifactId}-${project.version}.jar
[INFO] [INFO] [install:install {execution: install}]
[INFO] [INFO] Installing ${project.build.directory}/${project.artifactId}-${project.version}.jar to <.m2_local_repo>/<proper_path>/${project.version}/${project.artifactId}-${project.version}.war
However if i un-comment <packaging>jar</packaging> it complains that i am attempting to set a read-only property.
So the question i have, how can i install jar file to my local repo during my build?
Updating the question w/ some parts of module1 and module2 pom files:
module2 pom parts:
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>1.01-SNAPSHOT</version>
</parent>
<artifactId>module2</artifactId>
<version>1.08-SNAPSHOT</version>
<packaging>war</packaging>
...
<dependency>
<groupId>...</groupId>
<artifactId>module1</artifactId>
<version>4.18-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
module1 pom:
<parent>
<groupId>...</groupId>
<artifactId>...</artifactId>
<version>1.01-SNAPSHOT</version>
</parent>
<artifactId>module1</artifactId>
<version>4.18-SNAPSHOT</version>
<packaging>war</packaging>
i added install plugin to make sure that module1.4.18.jar will be installed locally so that module2.0.18.war will be able to use module1.4.18.jar
eventually i went with <goal>install-file</goal> instead of <goal>install</goal>
this way i was able to specify proper packaging (it turns out that packaging on install goal is read only, but you can override it for install-file)
so this is what i end up with:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>install</id>
<phase>compile</phase>
<goals>
<goal>install-file</goal>
</goals>
<configuration>
<file>${project.build.directory}/${project.artifactId}-${project.version}.jar</file>
<packaging>jar</packaging>
</configuration>
</execution>
</executions>
</plugin>
#MariuszS and #WIll- thank you for your insight on this matter
I think your project has wrong configuration (not in maven way). Proper configuration looks like this
* parent (root)
* module1 (war1)
* module2 (war2)
* jar (shared code from war2)
Move your code from war to separate module and add this module as depdency to both war modules.