I'm trying to build an executable jar in Spring Boot + Gradle project, but for now nothing works. Here is the simplest possible structure. Possibly, something is missing in Gradle configuration.
Gradle:
buildscript {
ext {
springBootVersion = '1.5.8.RELEASE'
}
repositories {
mavenCentral()
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
}
}
apply plugin: 'java'
apply plugin: 'org.springframework.boot'
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
repositories {
mavenCentral()
}
jar {
manifest {
attributes 'Main-Class': 'com.example.demo.DemoApplication'
}
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
}
dependencies {
compile('org.springframework.boot:spring-boot-starter-web')
}
Main config file:
#RestController
#SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#GetMapping(value = "/")
public String index() {
return "index";
}
}
When I ran the jar file like java -jar 1.jar, I got this exception:
[main] ERROR org.springframework.boot.SpringApplication - Applicati
on startup failed
org.springframework.beans.factory.BeanDefinitionStoreException: Failed to proces
s import candidates for configuration class [com.example.demo.DemoApplication];
nested exception is java.lang.IllegalArgumentException: No auto configuration cl
asses found in META-INF/spring.factories. If you are using a custom packaging, m
ake sure that file is correct.
at org.springframework.context.annotation.ConfigurationClassParser.proce
ssDeferredImportSelectors(ConfigurationClassParser.java:556)
at org.springframework.context.annotation.ConfigurationClassParser.parse
(ConfigurationClassParser.java:185)
at org.springframework.context.annotation.ConfigurationClassPostProcesso
r.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:308)
at org.springframework.context.annotation.ConfigurationClassPostProcesso
r.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:228)
at org.springframework.context.support.PostProcessorRegistrationDelegate
.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.ja
va:272)
at org.springframework.context.support.PostProcessorRegistrationDelegate
.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:92)
at org.springframework.context.support.AbstractApplicationContext.invoke
BeanFactoryPostProcessors(AbstractApplicationContext.java:687)
at org.springframework.context.support.AbstractApplicationContext.refres
h(AbstractApplicationContext.java:525)
at org.springframework.boot.context.embedded.EmbeddedWebApplicationConte
xt.refresh(EmbeddedWebApplicationContext.java:122)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.
java:693)
at org.springframework.boot.SpringApplication.refreshContext(SpringAppli
cation.java:360)
at org.springframework.boot.SpringApplication.run(SpringApplication.java
:303)
at org.springframework.boot.SpringApplication.run(SpringApplication.java
:1118)
at org.springframework.boot.SpringApplication.run(SpringApplication.java
:1107)
at com.example.demo.DemoApplication.main(DemoApplication.java:13)
Caused by: java.lang.IllegalArgumentException: No auto configuration classes fou
nd in META-INF/spring.factories. If you are using a custom packaging, make sure
that file is correct.
at org.springframework.util.Assert.notEmpty(Assert.java:277)
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelecto
r.getCandidateConfigurations(AutoConfigurationImportSelector.java:153)
at org.springframework.boot.autoconfigure.AutoConfigurationImportSelecto
r.selectImports(AutoConfigurationImportSelector.java:95)
at org.springframework.context.annotation.ConfigurationClassParser.proce
ssDeferredImportSelectors(ConfigurationClassParser.java:547)
... 14 common frames omitted
What might be wrong?
In Boot 2.x, the bootJar and bootWar tasks are responsible for packaging the application.
The bootJar task is responsible for creating the executable jar file. This is created automatically once the java plugin is applied.
In case the executable jar/war file is not generated run the below gradle task manually.
$./gradlew bootJar
Similarly, bootWar generates an executable war file and gets created once the war plugin is applied.
We can execute the bootWar task using:
$./gradlew bootWar
Note that for Spring Boot 2.x, we need to use Gradle 4.0 or later.
I created a project with all the sources you provided. Running "gradle build" from terminal, switching to /build/libs and then running "java -jar artifactname" works just fine.
Have you tried to clean and recompile? Which Version of Gradle are you using?
In spring boot you can directly create executable jar file by
springBoot {
executable = true
}
Please try
jar{
baseName = 'myapp'
version = 'version'
}
It will create jar with name myapp-version.jar
Do ./myapp-version.jar from command line.it will execute
Refer following link for more info. https://docs.spring.io/spring-boot/docs/current/reference/html/deployment-install.html
I just recently tried a Spring boot application with 2.1.4.Release with Gradle build.
I ran the following command from the directory in Windows CMD.
gradlew clean build
(upon required JDK8 installed in the system), I was able to see the JAR generated under,
<project-directory>/build/libs/<project-name-version.jar>
Hope this helps though older question.
Reference:
My two cents.
When using spring-boot if you want to customize the MANIFEST.MF file, you need to set the bootJar task, it won't work on the default jar task.
bootJar {
manifest {
attributes 'Start-Class': 'com.baeldung.DemoApplication'
}
}
https://www.baeldung.com/spring-boot-main-class
If you're trying to make your .jar file executable, for use such as in a systemd service. You'll have to edit the bootJar task and enable launchScript.
build.gradle
bootJar {
launchScript()
}
or with Gradle Kotlin DSL build.gradle.kts
tasks {
bootJar {
launchScript()
}
}
You should now be able to run your project's .jar file as an executable.
I use the "org.springframework.boot" plugin and use the bootWar task to generate a war file of my spring boot project.
I would like to have a task that creates an exploded version of this war file.
The standard way to do that with the 'war' plugin is :
task explodedWar(type: Sync) {
into "${war.archivePath.parentFile.getAbsolutePath()}/exploded/${war.archivePath.name}"
with war
}
How can i do the same thing with the spring-boot/bootWar plugin?
Try with:
task explodeBootWar(type: Sync) {
dependsOn bootWar
into "$buildDir/boot_war_exploded"
from project.zipTree(bootWar.archiveFile)
}
You can use the with method on the normal war task because it is basically just a copySpec. However, the bootWar task does some additional things, so you have to build and unzip the actual archive.
Starting from version 5 gradle changed Archive Tasks behavior
This breaks shadowJar task default behavior which doesn't create <name>-<version>-all.jar artifact any more.
How to revert this behavior and create *-all.jar?
Instead of using deprecated classifier and archiveName configure shadowJar plugin the following way:
shadowJar {
archiveClassifier = 'all'
}
Or since Gradle 5.1 using Property:
shadowJar {
archiveClassifier.set('all')
}
See more about the issue discussion:
https://github.com/johnrengelman/shadow/issues/446#issuecomment-460328699
https://github.com/johnrengelman/shadow/issues/450
apply plugin: 'war'
war {
...
}
From what I understand:
There is a gradle war plugin which I get available from the apply plugin: 'war' line, that allows me to use the war task declared via the war { ... } which is of type war?
If you apply the Gradle War plugin, a task with the name war is created automatically. When you refer to war { ... } in your build script, you are effectively configuring the war task instance with the help of a closure.
war {
baseName = 'example'
}
does the same thing as
war.baseName = 'example'
The benefit of the closure syntax is that you can configure the task instance through multiple statements. It also becomes more readable and looks more like a DSL.
The actual type of the task named war is War. You can always find out the type of task from the command line via gradle help --task <task-name>.
You can also get some information about the type of variable in your build script:
task printType {
doLast {
println war
}
}
Executing the task will print out the following:
$ gradle printType
:printType
task ':war'
The "war" block below the "apply" isn't defining a task, it's simply a configuration block used by the plugin.
Without Gradle War Plugin, bootRepackage task depends on jar task but with Gradle War Plugin, it depends on war task.
How can I change it to depend on jar task even though I'm using Gradle War Plugin?
UPDATE:
I'm using war task to create a war file including documents to be deployed to a documentation server and I want to use bootRepackaged jar file to provide a service. My war task depends on asciidoctor task which depends on test task (I'm using Spring REST Docs.) but I don't want to run asciidoctor task or test task when using bootRepackage task.
I solved my problem with the following setup:
ext {
mainClassName = 'com.izeye.throwaway.Application'
}
task myBootRepackage(type: BootRepackage, dependsOn: jar) {
}
but I'm not sure this is a good practice.
This is a sample project having the above configuration:
https://github.com/izeye/spring-boot-throwaway-branches/tree/war
You should have been able to do this:
bootRepackage {
withJarTask jar
}
While this correctly causes the jar task's jar to be repackaged, it doesn't remove the dependency on the war task. This is another symptom of this Spring Boot issue.
Until this issue has been resolved, the approach that you've taken – declaring your own BootRepackage task and manually configuring the tasks that it depends upon – is your best option.