gradle and dependency on spring-boot subproject - spring-boot

I've created a project with several gradle subprojects, including: "app" and "tests".
Tests have "app" in their dependencies. Tests use classes from "app"
When I run:
./gradlew clean test build
Everything works, tests run and pass.
But when I run:
./gradlew clean build
then the tests compilation fails with an error saying that a class is missing - in this case it's a spring-boot configuration class. I run this with --debug and it turns out that in the failing case app:bootRepackage task is executed before tests:test, the jar generated by app compilation is altered and that's why the classes cannot be found.
How can I make "./gradlew clean build" work properly?
Using: spring-boot 1.5, gradle 4.0 (and 4.1 too), io.spring.dependency-management plugin 1.0.0.RELEASE

Ideally, you shouldn't use a Spring Boot application (something that's been repackaged) as a dependency. From the documentation:
Like a war file, a Spring Boot application is not intended to be used as a dependency. If your application contains classes that you want to share with other projects, the recommended approach is to move that code into a separate module. The separate module can then be depended upon by your application and other projects.
If the proposed solution isn't possible in your situation, the documentation goes on to describe an alternative:
If you cannot rearrange your code as recommended above, Spring Boot’s Maven and Gradle plugins must be configured to produce a separate artifact that is suitable for use as a dependency. The executable archive cannot be used as a dependency as the executable jar format packages application classes in BOOT-INF/classes. This means that they cannot be found when the executable jar is used as a dependency.
To produce the two artifacts, one that can be used as a dependency and one that is executable, a classifier must be specified. This classifier is applied to the name of the executable archive, leaving the default archive for use as dependency.
To configure a classifier of exec … when using Gradle, the following configuration can be used:
bootRepackage {
classifier = 'exec'
}

Related

Hot reloading a multi-module spring boot application with gradle

I'm trying to convert a project from maven to gradle, but I'm having trouble getting hot reloading to work the same way. I can't show the actual project so I've created two identical very simple projects. One with maven one with gradle. These projects contain two modules:
project
|____api
|____lib
The /api module contains a spring-boot app which depends on code from the /lib module
In the maven project I can change code in either of these modules and recompile either with my IDE (intellij) or with the maven cli and spring-boot-devtools will hot reload the application. However in the gradle version it only successfully hot reloads code that has changed in the /api module.
From what I gathered this seems like a classpath issue. If you run gradle or maven in debug mode it prints out the classpath it passes when it starts the application. Maven includes <project_dir>/lib/target/classes/kotlin/main. However gradle only includes <project_dir>/lib/build/libs/lib.jar
I'm very new to gradle to I might have some of the build configuration messed up. Here are the two project repo's:
Maven: https://github.com/Perry-Olsson/mvn-hot-reload
Gradle: https://github.com/Perry-Olsson/gradle-hot-reload

Fat jar is missing with junit dependency

I am building a fat jar using maven-assembly-plugin. The jar is generated successfully. The only dependency I have for my project is: JUnit. But in the fat jar, I am unable to see this included (using jar tf command). Is JUnit dependency not included in fat jar usually ?
junit is usually a test scoped dependency, and then it will not be included.
Dependencies with scope test are meant to used during the build for tests, so there is no need to include them into the final JAR.
If, for some reason, you need junit in the final JAR, you need to change the scope to compile.

How to add a runtime library on Gradle in the build command

I have a build.gradle file that I want to use to build a Spring Boot microservice for multiple projects. I have created a custom library with some classes that should not be in all of the projects but I don't want to have to edit the build.gradle file when I build the microservice depending on which project I will use it in.
How can I add a command/parameter to gradle build that can add runtime libraries to the Spring Boot app?
Something like (just an exaple):
gradle buildDocker -PaddRuntime=com.skios.lib:lib-common:0.2.35
Thanks for any directions
I am not sure I understand your issue fully and thus not convinced this is the best solution.
But since a Gradle build script accepts code, you can have conditionals in a dependencies block:
dependencies {
if (project.hasProperty('addRuntime')) {
runtimeOnly('com.skios.lib:lib-common:0.2.35')
}
}
and then on the command line: ./gradlew buildDocker -PaddRuntime

Setup maven pom to work with dependencies across environments

I have a Java projects a-1.0.jar with ojdbc.jar dependency and b.jar that depends on a-1.0.jar and ojdbc.jar. I am trying to make it work on my machine, new user machine and a Bamboo server.
Desired behavior:
On local machine git clone <git_url>, mvn clean install, java -jar b.jar project should run. Bamboo should checkout and run project.
On Bamboo: a plan can check out a project and run it. Build should track version of b.jar built and a.jar used.
So far I saw these options:
<systemPath>${project.basedir}/lib/a-1.0.jar</systemPath>: maven warns that it will fail to resolve dependencies
A Perl script to run mvn install for each dependent jar before building the project
(1) defeats the purpose of DevOps automation
(2) makes it unclear which version of a jar was used
(3) installs the jar, but java -jar b.jar fails a.jar is missing
I can overcome this with another Perl script that adds the dependent jars to a classpath
These are basic tasks and as a build tool Maven should be able to do it.
How to tell Maven to three goals below?
(1) For each unknown import - get a jar from lib folder
(2) Make a set of dependent jars. That is don't import ojdbc twice
(3) Pack a self sufficient jar that runs, not fails with "stuff is missing"
Seems like you need to create an executable jar - and for this, you can use various approaches.
One of them is, add maven-shade-plugin which puts all dependencies into single jar, while taking care of potential resource collisions.
Try non-maven-jar-maven plugin. It adds jars that are not in the maven central.

How to manage compile time dependencies in Maven

Trying to avoid the use of jargon, so that I don't get misinterpreted.
Here is the scenario, My project requires a jar in order to get compiled(let say x.jar). My project get once compiled gets converted into a WAR file, which gets deployed somewhere.
Now I want x.jar just to be there for my project to compile and it should not be packed(or part of) inside WAR file.
How can I do this in Maven ? should I used dependency scope as "provided"
You are right, as stated in the Maven FAQs, the scope to use is provided,
How do I prevent including JARs in WEB-INF/lib? I need a "compile only" scope!
The scope you should use for this is provided. This indicates to Maven that the dependency will be provided at run time by its container or the JDK, for example.
Dependencies with this scope will not be passed on transitively, nor will they be bundled in an package such as a WAR, or included in the runtime classpath.
To quickly try it out, you can use
mvn archetype:generate -DarchetypeGroupId=org.apache.maven.archetypes -DarchetypeArtifactId=maven-archetype-webapp
to generate a "toy webapp" project, add a dependency to your project and set it to <scope>provided</scope>.

Resources