web-dev-qa-db-fra.com

Gradle: Construire 'Fat jar' avec Spring Dependencies

J'utilise Gradle pour créer et conditionner une application très simple de démarrage printanier (contenu statique à 99%) dans un bocal avec Tomcat intégré.

J'ai essayé de créer ledit fichier. Au début, le résultat était 86k et n'a pas été lancé, car certaines classes de démarrage Spring lui manquaient. J'ai conclu que ce pot que je fabriquais ne contenait aucune des dépendances de l'application, et puisque je voulais un pot complètement autonome, je devrais faire plus de recherches.

C'est à ce moment-là que j'ai découvert le conseil d'ajouter la section from {configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } au «pot», ce qui l'a amené à extraire toutes les dépendances. (J'espère). Je connais bien l’idée de l’opérateur ternaire et je vois ce que l’on essaie de faire ici.

Malheureusement, cela ne fonctionne toujours pas! Voici l'erreur que je reçois au lancement, et ci-dessous est mon build.gradle. 

Je veux une application de démarrage de printemps avec Tomcat intégré entièrement contenu dans un bocal. Est-ce que je fais quelque chose de très peu conventionnel?
Toute aide à ce stade serait grandement appréciée. 

(About 80 lines of successful Spring Boot launch messages followed immediately by:
18:16:54.890 [main] WARN  o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:132) [SpringWsTest1.jar:na]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:474) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.Java:117) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:689) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:321) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:969) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:958) [SpringWsTest1.jar:na]
    at ws.Application.main(Application.Java:11) [SpringWsTest1.jar:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.Java:182) [SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.Java:155) [SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:129) [SpringWsTest1.jar:na]
    ... 7 common frames omitted
18:16:54.891 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@3b084709: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,application,org.springframework.context.annotation.ConfigurationClassPostProcessor.importAwareProcessor,org.springframework.context.annotation.ConfigurationClassPostProcessor.enhancedConfigurationProcessor,demoController,greetingController,org.springframework.boot.autoconfigure.AutoConfigurationPackages]; root of factory hierarchy
18:16:54.891 [main] ERROR o.s.boot.SpringApplication - Application startup failed
org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:132) ~[SpringWsTest1.jar:na]
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:474) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.Java:117) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:689) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:321) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:969) [SpringWsTest1.jar:na]
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:958) [SpringWsTest1.jar:na]
    at ws.Application.main(Application.Java:11) [SpringWsTest1.jar:na]
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.Java:182) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.Java:155) ~[SpringWsTest1.jar:na]
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:129) ~[SpringWsTest1.jar:na]
    ... 7 common frames omitted
Exception in thread "main" org.springframework.context.ApplicationContextException: Unable to start embedded container; nested exception is org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:132)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.Java:474)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.Java:117)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.Java:689)
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:321)
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:969)
    at org.springframework.boot.SpringApplication.run(SpringApplication.Java:958)
    at ws.Application.main(Application.Java:11)
Caused by: org.springframework.context.ApplicationContextException: Unable to start EmbeddedWebApplicationContext due to missing EmbeddedServletContainerFactory bean.
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.getEmbeddedServletContainerFactory(EmbeddedWebApplicationContext.Java:182)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.createEmbeddedServletContainer(EmbeddedWebApplicationContext.Java:155)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.onRefresh(EmbeddedWebApplicationContext.Java:129)
    ... 7 more

build.gradle j'utilise:

println System.getProperty("Java.home")

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:1.2.7.RELEASE")
    }
}

apply plugin: 'Java'
apply plugin: 'Eclipse'
apply plugin: 'idea'
apply plugin: 'spring-boot'


jar {
    manifest {
        attributes 'Main-Class': 'ws.Application'
    }

    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}


repositories {
    mavenCentral()
}


dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    testCompile("junit:junit")
}

task wrapper(type: Wrapper) {
    gradleVersion = '2.3'
}

sourceCompatibility = 1.8
targetCompatibility = 1.8
9
user1445967

Vous n'avez pas besoin de créer vous-même des configurations de gradles supplémentaires pour construire un artefact fat-jar de l'application spring-boot, car vous utilisez un plugin gradle spring boot. Il a déjà une tâche bootRepackage de le faire pour vous. Vous pouvez lire à ce sujet dans le guide de l'utilisateur officiel ici et ici .

Supprimez simplement tout ce que vous avez fait pour décompresser le contenu des dépendances et utilisez cette tâche pour obtenir un seul fichier JAR avec votre application.

En passant, vous pouvez être intéressé par une autre solution, qui pourrait éventuellement fournir une meilleure taille d'archive, vous pouvez en savoir plus sur l'une d'entre elles, appelée Capsule, dans cet article .

21
Stanislav

Avec les versions actuelles de gradle, ajoutez ceci en haut de votre fichier build.gradle:

plugins {
    id "org.springframework.boot" version "2.0.0.RELEASE"
}

alors juste gradle build - vous n'avez rien à faire de plus.

Voir la page d'accueil de ce plugin pour trouver la dernière version.

1
Bohemian