Executable jar built with spring-boot gradle-plugin missing dependency - java

I have an executable JAR that I've built with Spring Boot's Gradle plugin. It has the following dependencies in the build file:
build.gradle
compile('org.apache.activemq:activemq-client:5.9.0')
compile('org.apache.activemq:activemq-broker:5.9.0')
compile('org.apache.activemq:activemq-kahadb-store:5.9.0')
compile('org.apache.activemq.protobuf:activemq-protobuf:1.1')
The problem is that after I run
./gradlew clean build
the created artifact does not contain the activemq-protobuf jar, only the other activemq jars:
[] jar -tf build/libs/application-0.1.0.jar | grep activemq
lib/activemq-client-5.9.0.jar
lib/activemq-broker-5.9.0.jar
lib/activemq-kahadb-store-5.9.0.jar
lib/activemq-openwire-legacy-5.9.0.jar
So when I try to run the jar, I got an Exception that a class from this dependency cannot be found:
java.lang.ClassNotFoundException: org.apache.activemq.protobuf.Message
During the build the dependency gets downloaded and it can be found in my gradle cache, it seems that for some reason Spring Boot's Gradle plugin doesn't include it during the bootRepackage task.
This dependency is also there in Eclipse, and the project can be run from there.
Any ideas about why it gets missing?

This looks like a bug in Spring Boot. I've opened an issue so that we can investigate. Thanks for bringing it to our attention.

the following is a quick fix, while the bug is resolved.
try this
in your gradle.build file
jar {
baseName = 'gs-accessing-data-rest'
version = '0.1.0'
into('lib') {
from 'oraDrv'
}
}
where oraDrv is a folder in which you have your custom jars or the missing jars. it is assumed that the oraDrv is relative the build.gradle file location.

Related

Spring Boot Gradle multi-project build not seeing internal dependencies during tests

I'm having a problem on a larger multi-project build that I was migrating from Gradle 4 to 5, and replicated the issue on a smaller, more concise build to demonstrate the issue.
I have 2 projects in the build. One is a dependency (basic library) used by the other.
demo (root project)
|- build.gradle
|
|--- demo-web
|---|- build.gradle
|
|--- demo-dependency
|---|- build.gradle
Snippet of demo-web: build.gradle
...
dependencies {
implementation project(':demo-dependency')
...
}
...
The dependency project defines one class that is used in the web project, DownstreamThing.
The web project attempts to use that to construct its own object, but during a build on the root project level, it fails.
> ./gradlew build
> Task :demo-web:test
com.example.demo.ThingTest > testThing FAILED
java.lang.NoClassDefFoundError at ThingTest.java:12
Caused by: java.lang.ClassNotFoundException at ThingTest.java:12
ThingTest.java
#Test
public void testThing() {
DownstreamThing t = new DownstreamThing(); //line 12, ClassNotFoundException
assertTrue(t != null);
}
I didn't have any trouble with this in Gradle 4, but only in Gradle 5. Why is the dependency not being found during the test task?
Full source for the example is here: https://bitbucket.org/travelsized/gradle-problem/src/master/
I believe he reason you are getting that exception is because you have applied the Spring Boot plugin to the demo-dependency project. What this plugin does is to repackage the jar file to a fat jar that needs a special classloader to load the content.
You can still use the Spring Boot dependencies (e.g. the starters) in the dependency project without the plugin. So if you can, just remove it.
If there is a particular reason why you have it, you will need to keep the original jar file so that is used as the actual dependency. For Spring Boot 1.5.x, you can do that with something like this:
bootRepackage {
classifier = "boot"
}
bootJar {
enabled = true
}
But do note that I don't think Spring Boot 1.5 is fully compatible with Gradle 5 and later (at this time we are on 6.0), so you might need to either downgrade Gradle or upgrade Spring Boot.
Bjørn Vester's answer got me pointed in the right direction. The spring-boot plugin was causing the jar tasks to go awry. I needed to make sure that the bootJar task was disabled for the dependency while the jar task was enabled.
The changes in the configuration to do this between versions of Gradle and the Spring Boot plugin made this get lost in the upgrades.
Previously, I could specify a classifier for the jar post-boot:
bootRepackage {
classifier = 'exec'
}
Now, I need to enable and disable the appropriate tasks:
bootJar {
enabled = false
}
jar {
enabled = true
archiveBaseName = "demo-dependency"
}
In the larger project, I previously had a jar task that specified the archiveBaseName, but didn't explicitly enable it to override the bootJar task. Once I made the above changes (while keeping the boot plugins in place), things started working.

How to build executable jar of a submodule with gradle + spring boot 1.5

I have a multi-module project:
Root project 'platform'
+--- Project ':api'
+--- Project ':common'
and in the :common module I include all the dependencies, in the :api module, I only have
apply(plugin = "org.springframework.boot")
dependencies {
implement(project(":common"))
}
The problem is that when I build the :api module, from the jar file I can't see any of the dependencies inside the jar file, there's no BOOT-INF/libs/ only BOOT-INF/classes/.
When I run the jar with java -jar, it says NoClassFound for one of the class in the :common module.
gradle :api:bootRun works fine.
Is there any other config I should do?
I'm using gradle 4.9 kotlin dsl and spring boot plugin 1.5.15.RELEASE
The reason is that the spring boot 1.5 gradle plugin is only targeted for gradle 2 & 3, which does not support the implementation configuration (introduced in gradle 4).
Based on this documentation, it describes that by default only compile and runtime configurations are included. That being said, it is possible to include a custom configuration to make it work.
If you look at the hierarchy of gradle configurations for gradle 5 Illustrated here, runtimeClasspath is the root of implementation, and therefore has all the dependencies you need for your runnable jar.
This means that for spring boot 1.5, you can point it to a custom configuration to get it to correctly build the runnable jar:
build.gradle:
bootRepackage {
customConfiguration = 'runtimeClasspath'
}
build.gradle.kts:
import org.springframework.boot.gradle.repackage.RepackageTask
// more of the build file
tasks {
"bootRepackage"(RepackageTask::class) {
setCustomConfiguration("runtimeClasspath")
}
}
Turns out it's because of spring-boot-plugin 1.5.x somehow doesn't recognize the implement(project(:common)), by changing to compile(project(:common)) it works fine.

Gradle spring boot with assembly module

I'm new to Gradle and I'm facing a problem ( using Gradle 2.14)
My project has 3 subprojects: assembly, sprinBootProject, E2E
The assembly module is responsible of zipping the jar of the spring boot application along with properties files.
The E2E module is an 'end to end' tests module for testing the spring boot application.
I'm using the distribution plugin in assembly/build.gradle like this:
apply plugin: 'distribution'
distributions {
main {
baseName "project-assembly"
contents{
from project(':springBootProject').fileTree(dir: 'build/libs', include: ['*.jar'])
from project(':springBootProject').fileTree(dir: 'build/resources/main', includes: ['*.properties', 'conf/*.properties'])
}
}
}
but I need to make sure that springBootProject will be evaluated before the assembly subproject, so I used dependsOn like that:
distZip.dependsOn(':springBootProject:build')
when I added this line I see that the E2E module is failing in compileTestJava task, so this line is effecting how the spring boot application is generated (I think)
E2E/build.gradle:
dependencies {
testCompile project(":springBootProject")
}
so my question is am I doing it right? why when I added the dependsOn line the E2E module is effected, and how can I force Gradle to evaluate the spring boot application before the assembly module?
I figure it out.
Gradle will evaluate modules by alphabetic order
so the evaluation will be: assembly -> E2E -> springBootProject
when adding this line to assembly/build.gradle:
distZip.dependsOn(':springBootProject:build')
the order of the evaluation changed to be: assembly -> springBootProject -> E2E
now in 'springBootProject' module I am using the spring boot plugin in order to generate an executable jar, this executable jar is generated by the task :springBootProject:bootRepackage which uses the jar generated by the :springBootProject:jar task and convert it to executable.
now because the 'E2E' module depends on 'springBootProject' it will use it's jar, but now this jar is executable, and because of that I had a compilation error in 'E2E'.
so I have to make sure that the 'E2E' module gets the original jar and not the executable one.
so I added this line in springBootProject/build.gradle:
bootRepackage.mustRunAfter(':E2E:test')
which seem to solve the problem

Java Gradle find out dependency's jar file name

I have a java gradle project. I have a dependency.
dependencies {
compile project(":mymodule")
compile 'org.springframework:spring-context:4.1.2.RELEASE'
}
Where can I find and use exact jar file name of both my custom module and spring dependency jar to process it further in composing application's libs, folders, etc?
Stick this in a new task:
project.configurations.compile.each{ println it}
Or, for just one specific dependency:
println project.configurations.compile.find {it.name.startsWith("something") }
However, if you're looking to create distributable packages including dependencies, you really should look into the gradle application plugin.

Grails - Maven Error installing Spring Security Plugin 3.0.4 on IntellJ Idea

I have a problem installing Spring Security Core 3.0.4 plugin into my Grails 3.1.5 project. Here what I am using:
Grails: 3.1.5
IntellJ Idea: Ultimate 2016.1.1
Maven: 3.0.5
In build.gradle, I have:
buildscript {
...
repositories {
mavenLocal()
maven { url "https://repo.grails.org/grails/core" }
}
...
}
...
dependencies {
compile "org.grails.plugins:spring-security-core:3.0.4"
...
}
When I do "Tools" > "Grails" > "Synchronize Grails settings", I get this error:
Configuring > 1/1 projects| Error Error initializing classpath: Could not find spring-security-core.zip (org.grails.plugins:spring-security-core:3.0.4).
Searched in the following locations:
https://repo.grails.org/grails/core/org/grails/plugins/spring-security-core/3.0.4/spring-security-core-3.0.4.zip (Use --stacktrace to see the full trace)
So, for some reason, it is looking for a .zip file. However, looking at the directory https://repo.grails.org/grails/core/org/grails/plugins/spring-security-core/3.0.4/ there is no .zip file in there. Any clue on how to resolve this? Thank you!
You can try new version Spring Security eg:
compile 'org.springframework.security:spring-security-core:3.2.9.RELEASE'

Categories

Resources