Jar packaging in Spring boot - java

I am creating a Spring Boot multi module project.. Module A has a dependency on Module B ..
Module A runs fine when I run in exploded form..
mvn spring-boot:run
But I am unable to package the jar along with dependencies
so that I can execute it as
java -jar Module-A.jar
Module A pom.xml is below:
<parent>
<artifactId>Module-Test</artifactId>
<groupId>com.module</groupId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>Module-A</artifactId>
<packaging>jar</packaging>
<properties>
<start-class>com.NotifyApp</start-class>
<main.class>com.NotifyApp</main.class>
</properties>
<dependencies>
<dependency>
<groupId>com.module</groupId>
<artifactId>Module-B</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:repackage (default) on project Module-A: Execution default of goal org.springframework.boot:spring-boot-maven-plugin:1.4.2.RELEASE:repackage failed: Source must refe
r to an existing file
Parent pom.xml
<modelVersion>4.0.0</modelVersion>
<artifactId>Module-Test</artifactId>
<groupId>com.module</groupId>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>Module-A</module>
<module>Module-B</module>
<module>Module-C</module>
</modules>
<packaging>pom</packaging>
<parent>
<artifactId>Module-Parent</artifactId>
<groupId>com.parent</groupId>
<version>1.0.2</version>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.module</groupId>
<artifactId>Module-A</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.module</groupId>
<artifactId>Module-B</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.module</groupId>
<artifactId>Module-C</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.module</groupId>
<artifactId>starter-service</artifactId>
<version>${starter.version}</version>
<scope>import</scope>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>

I usually use this plugin https://maven.apache.org/plugins/maven-dependency-plugin/examples/copying-project-dependencies.html for maven, which will put all of the dependency jars into target/dependencies when you run
mvn clean package
Then I copy the jars into a folder (which I usually call lib) and I include lib/* in my classpath. The final run script usually looks like
java -cp lib/*: my.package.MySpringBootMain

Remove the
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
It's not needed.

Add dependency of module B in module A's pom.xml
<dependencies>
<dependency>
<groupId>com.module</groupId>
<artifactId>Module-B</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
Use maven clean compile package install command for module B, to build module B first and then run maven clean compile package on Module A. This will out Module B into Module A.
There is no module A's reference required in Module B's pom.xml

you sure know, but you can initialize your project from this link
Spring Initializr
, it automatically generates the configuration with what you need

Related

Maven not recognizing added packages

I am developing a project with Maven for the first time. I have an external package that I have converted into a .jar file and installed into maven in order to use its classes. However, even tho the package is already in the .m2 folder maven still says that it cannot find the package(util):
[ERROR]/home/luis/Desktop/git/sifu/Challenges/Java/java_0002_SN/stringNorm/src/main/java/stringNorm/MyDetector.java:[14,27] cannot find symbol
symbol: class report
location: class stringNorm.MyDetector
[ERROR]/home/luis/Desktop/git/sifu/Challenges/Java/java_0002_SN/stringNorm/src/main/java/stringNorm/MyDetector.java:[9,1] package util does not exist
[ERROR]/home/luis/Desktop/git/sifu/Challenges/Java/java_0002_SN/stringNorm/src/main/java/stringNorm/MyDetector.java:[19,23] cannot find symbol
symbol: class report
location: class stringNorm.MyDetector
I have already tried to add this new dependency(util) to the pom file and so far it looks like this:
<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.sifu</groupId>
<artifactId>stringNorm</artifactId>
<version>1.0</version>
<properties>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<spotBugsVersion>4.0.0</spotBugsVersion>
</properties>
<description>My SpotBugs plugin project</description>
<dependencies>
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>${spotBugsVersion}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>util</groupId>
<artifactId>util</artifactId>
<version>1.0.0</version>
<scope>system</scope>
</dependency>
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>test-harness</artifactId>
<version>${spotBugsVersion}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19.1</version>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>xml-maven-plugin</artifactId>
<version>1.0.2</version>
<executions>
<execution>
<id>validate-spotbugs-configuration</id>
<goals>
<goal>validate</goal>
</goals>
<configuration>
<validationSets>
<validationSet>
<dir>src/main/resources</dir>
<includes>
<include>findbugs.xml</include>
</includes>
<systemId>findbugsplugin.xsd</systemId>
</validationSet>
<validationSet>
<dir>src/main/resources</dir>
<includes>
<include>messages.xml</include>
</includes>
<systemId>messagecollection.xsd</systemId>
</validationSet>
</validationSets>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs</artifactId>
<version>${spotBugsVersion}</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
I am using spotbugs to perform analysis on my code, as you can see from the snipet.
The class within the unit package I want to use, is the report one, my import statement looks like this `import util.*;
I installed my jar file to maven using this command: mvn install:install-file -Dfile=<path-to-file> -DgroupId=<group-id> -DartifactId=<artifact-id> -Dversion=<version> -Dpackaging=<packaging>
and after doing it I added it into the pom file.
My util package is composed of 3 classes, I did jar cfv util.jar * inside the util folder and gave me a jar file.

How can I generate a maven repository-ready library with swagger-codegen-maven-plugin?

I'm using the Maven plugin swagger-codegen-maven-plugin to generate a Java client jar. I put my swagger.json in the src/main/resources folder and ran mvn clean install. Here is my 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>com.example</groupId>
<artifactId>my-java-client</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-java-client</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<swagger.version>1.5.13</swagger.version>
</properties>
<dependencies>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>okhttp</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp</groupId>
<artifactId>logging-interceptor</artifactId>
<version>2.7.5</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>com.squareup.okio</groupId>
<artifactId>okio</artifactId>
<version>1.12.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-maven-plugin</artifactId>
<version>2.2.2</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<inputSpec>src/main/resources/swagger.json</inputSpec>
<modelPackage>mypackage.model</modelPackage>
<apiPackage>mypackage</apiPackage>
<invokerPackage>mypackage.invoker</invokerPackage>
<language>java</language>
<configOptions>
<interfaceOnly>true</interfaceOnly>
<dateLibrary>java8</dateLibrary>
<java8>true</java8>
</configOptions>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
When I run mvn clean install, a jar file my-java-client-1.0-SNAPSHOT.jar is made in the target folder. It has source code in it, but no pom.xml file. There is a pom.xml file in the target/generated-sources/swagger folder but it has the groupId and artifactId:
<groupId>io.swagger</groupId>
<artifactId>swagger-java-client</artifactId>
The README.md file in the target/generated-sources/swaggersays to include the following in your pom.xml to use the generated jar:
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-java-client</artifactId>
<version>1.0.0</version>
<scope>compile</scope>
</dependency>
I'm guessing these are just defaults because if I generated multiple swagger clients they would conflict over the name, and I can see in the swagger-codegen source code that these fields are generated from placeholders like {{artifactId}}. I haven't been able to find where I can set these placeholders.
How can I get the jar to include a pom.xml with an artifactId and groupId of my choosing, so I can upload it to a Maven repository like Artifactory, and use it in my Maven dependencies?
It's not particularly well documented, but it appears you are able to override the artifactId, groupId etc from within the configOptions:
<configOptions>
<groupId>com.your.group.id</groupId>
<artifactId>your-artifact-id</artifactId>
<artifactVersion>0.0.1-SNAPSHOT</artifactVersion>
</configOptions>
Many of the properties inside CodegenConstants.java can be set in the same way.
I updated it using below config Properties (gradle)
'groupId' : 'your.group.id',
'artifactId' : 'your-artifact-id'
you can also go through document which is helpful for reference of the properties.
https://openapi-generator.tech/docs/generators/kotlin/

Maven EAR multimodule project not packaging persistence.xml

I`m working in a EAR project with Maven which has 2 modules. Images speaks louder than words, so let me show you the structure:
Parent pom project and modules
sigea-model contains model, repository and service layers (The "M" in MVC). sigea-web contains web pages and controller beans (VC) and sigea-ear is just a wrapper to package the other 2 modules in a EAR package.
Configuration files in modules
As you can see, sigea-ear has an empty META-INF folder. Both beans.xml files in sigea-model and sigea-web are just empty marker files because AFAIK, CDI by default search in all annotated classes (but this is not the problem right now). persistence.xml is a simple file which uses JTA transactions with a connection pool (which is working because I ping from the Glassfish's admin console and is successful).
Finally, when I package the application I get the following:
As you can see, there's no persistence.xml. All this came out because I deployed the application successfully but in the first click I got the Exception
javax.ejb.TransactionRolledbackLocalException: Exception thrown from bean
...
Caused by: java.lang.IllegalStateException: Unable to retrieve EntityManagerFactory for unitName null
Here are my pom files:
pom.xml[sigea-app] (parent project)
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>ar.edu.unt.sigea</groupId>
<artifactId>sigea-app</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<modules>
<module>sigea-model</module>
<module>sigea-web</module>
<module>sigea-ear</module>
</modules>
<build>
<pluginManagement>
...
</pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencyManagement>
<!-- I suppress some lines for brevity -->
<dependencies>
<dependency>
<artifactId>sigea-model</artifactId>
</dependency>
<dependency>
<artifactId>sigea-model</artifactId>
<type>ejb</type>
</dependency>
<dependency>
<artifactId>sigea-model</artifactId>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<artifactId>sigea-web</artifactId>
<type>war</type>
</dependency>
<dependency>
<artifactId>sigea-web</artifactId>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
...
</dependencies>
</project>
pom.xml[sigea-ear]
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ar.edu.unt.sigea</groupId>
<artifactId>sigea-app</artifactId>
<version>1.0</version>
</parent>
<artifactId>sigea-ear</artifactId>
<packaging>ear</packaging>
<dependencies>
<dependency>
<artifactId>sigea-model</artifactId>
<type>ejb</type>
</dependency>
<dependency>
<artifactId>sigea-web</artifactId>
<type>war</type>
</dependency>
<dependency>
<artifactId>sigea-web</artifactId>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<defaultLibBundleDir>lib/</defaultLibBundleDir>
<skinnyWars>true</skinnyWars>
<modules>
<webModule>
<groupId>${project.groupId}</groupId>
<artifactId>sigea-web</artifactId>
<contextRoot>/sigea</contextRoot>
</webModule>
<ejbModule>
<groupId>${project.groupId}</groupId>
<artifactId>sigea-model</artifactId>
</ejbModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom.xml[sigea-web]
<project ...>
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>sigea-app</artifactId>
<groupId>ar.edu.unt.sigea</groupId>
<version>1.0</version>
</parent>
<groupId>ar.edu.unt.sigea</groupId>
<artifactId>sigea-web</artifactId>
<version>1.0</version>
<packaging>war</packaging>
<name>sigea-web</name>
<dependencies>
<!-- Some dependencies including sigea-model -->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<packagingExcludes>WEB-INF/lib/*.jar</packagingExcludes>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
pom.xml[sigea-model] is not important as it just defines some dependencies for test and is configured to generate a package with the test classes, which are used in sigea-web for test purposes also.
Finally the question: What's failing in my configuration that doesn't package the persistence.xml file? If that's not the problem for the IllegalStateException with the message shown above: What are posible causes for that exception?
Thanks in advance for your answers.
I solved the problem by changing a dependency. In sigea-model I had
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.0.Final</version>
<scope>test</scope>
</dependency>
Which I used to manage the persistence context for my test methods. I didnt inquire very much in the Glassfish JPA provided implementation but maybe it's Eclipse Link instead of Hibernate. Apparently there are some incompatibility issue between those libraries. I movedhibernate-entitymanager` to compile scope, like this:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>5.1.0.Final</version>
</dependency>
And now the projects compile with no problem. It was also useful the comment made by khmarbaise, it simplified the project configuration, thank you very much.

maven 3 interproject depedency with war packaging

I have Eclipse Indigo and M2E plugin installed.
So essentially I have a standard maven web project (let's call it proj-service) that is built into a war file in the package phase. This all works fine. My issue comes in when I have my other project (lets call it proj1) that needs to use classes from proj-service. I know that this is possible in maven+eclipse but it does not seem to be working at the moment. I have the following in proj1's pom right now:
<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>com.mycompany.foo</groupId>
<artifactId>proj1</artifactId>
<packaging>war</packaging>
<version>1.0</version>
<name>proj1</name>
<properties>
<spring.version>3.1.0.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Maven Repo Libraries -->
.........
<!-- Interproject dependencies -->
<dependency>
<groupId>com.mycompany.foo</groupId>
<artifactId>proj-service</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<finalName>lsoap</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
Unfortunately with Maven's war packaging you can't reuse classes from war project, because there is no direct build artifact you can use for the class path.
So, in order to do share classes properly you need to extract those common classes into a 3rd common project (jar packaging) and make it as dependency in both of your other projects.
First you have to change the configuration of your proj-service project in the way to change the configuration of the maven-war-plugin:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<attachClasses>true</attachClasses>
<archiveClasses>true</archiveClasses>
...
</configuration>
</plugin>
This will it make possible to use the classes from the proj-service project in other projects via the following dependencies:
<dependency>
<groupId>myGroup</groupId>
<artifactId>myArtifact</artifactId>
<version>myVersion</myVersion>
<classifier>classes</classifier>
</dependency>
This will result in changing your dependency from:
<dependency>
<groupId>com.mycompany.foo</groupId>
<artifactId>proj-service</artifactId>
<version>1.0</version>
<type>war</type>
</dependency>
into:
<dependency>
<groupId>com.mycompany.foo</groupId>
<artifactId>proj-service</artifactId>
<version>1.0</version>
<classifier>classes</classifier/>
</dependency>

How do I use mvn test with multiple modules?

I have two maven modules, A and AB, with AB depending on test files in A. Both reference a parent pom.
I discovered the magic of test-jar which allowed me to compile my program, but I still cannot run tests with mvn test.
Strangely enough, mvn package tests seems to work.
Here's my basic configuration:
...
<parent>
<groupId>com.acme.parent</groupId>
<artifactId>parent</artifactId>
<relativePath>../pom.xml</relativePath>
<version>1.0</version>
</parent>
<groupId>com.acme</groupId>
<artifactId>A</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
Project AB (depends on A)
...
<parent>
<groupId>com.acme.parent</groupId>
<artifactId>parent</artifactId>
<relativePath>../pom.xml</relativePath>
<version>1.0</version>
</parent>
<artifactId>AB</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<dependency>
<groupId>com.acme</groupId>
<artifactId>A</artifact>
<version>1.0</version>
</dependency>
<dependency>
<groupId>com.acme</groupId>
<artifactId>A</artifact>
<version>1.0</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
...
And finally, the relevant bits from the parent pom:
...
<groupId>com.acme.parent</groupId>
<artifactId>parent</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>A</module>
<module>AB</module>
</module>
...
So, with all that said, how do I make mvn tests run as expected?
I'm using maven 2.2.1 by the way.
This may be related to one of the unresolved bugs like MNG-3559.
Essentially, the test classes of Project A are not visible to Project AB if only mvn test is run from parent pom. They are visible once the jar for package A is created (during the package phase).

Categories

Resources