web-dev-qa-db-fra.com

Échec du câblage automatique de BuildProperties Spring Boot 2.1.5 et eclipse

Je crée une application très simple avec quelques REST API et cela fonctionne actuellement correctement jusqu'à ce que j'essaie d'utiliser les BuildProperties sur mon API de vérification de l'état. Lors du démarrage de mon application, j'obtiens l'erreur suivante:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2019-06-17 09:54:29.210 ERROR 10796 --- [           main] o.s.b.d.LoggingFailureAnalysisReporter   : 

***************************
APPLICATION FAILED TO START
***************************

Description:

Field buildProperties in com.controller.HealthCheck required a bean of type 'org.springframework.boot.info.BuildProperties' that could not be found.

The injection point has the following annotations:
    - @org.springframework.beans.factory.annotation.Autowired(required=true)

The following candidates were found but could not be injected:
    - Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not loaded because @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}'


Action:

Consider revisiting the entries above or defining a bean of type 'org.springframework.boot.info.BuildProperties' in your configuration.

Je suis allé dans le fichier de build et j'ai aussi regardé dans le fichier jar créé par la build et je vois que build-info.properties est en fait là. Dans le fichier jar, le chemin d'accès au fichier est "BOOT-INF\classes\META-INF \". J'ai également d'autres éléments "Autowired" qui n'ont pas de problèmes.

Où mon code échoue:

@RestController
public class HealthCheck {

    @Autowired
    Environment environment;

    @Autowired 
    BuildProperties buildProperties;


    @GetMapping("/health")
    public HealthCheckResponse healthCheck() {
        return getHealthCheckResponse();
    }

    private HealthCheckResponse getHealthCheckResponse(){
        HealthCheckResponse healthResponse = new HealthCheckResponse();
        String[] profiles = environment.getActiveProfiles();

        healthResponse.setServerTime(new Date());
        healthResponse.setVersion(buildProperties.getVersion());
        healthResponse.setEnvironment(profiles[0]);

        return healthResponse;
    }

Mon fichier de construction gradle:

plugins {
    id 'org.asciidoctor.convert' version '1.5.3'
    id 'org.springframework.boot' version '2.1.5.RELEASE'
    id 'Java'
}

apply plugin: 'io.spring.dependency-management'
apply plugin: 'Eclipse'
apply plugin: 'Java'

group = 'com'
version = '0.0.1'
sourceCompatibility = '12'

repositories {
    mavenCentral()
}

ext {
    set('snippetsDir', file("build/generated-snippets"))
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    implementation 'org.springframework.boot:spring-boot-starter-jersey'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:2.1.1'
    runtimeOnly 'mysql:mysql-connector-Java'
    annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.springframework.restdocs:spring-restdocs-webtestclient'
    testImplementation 'org.springframework.security:spring-security-test'
}

test {
    outputs.dir snippetsDir
}

asciidoctor {
    inputs.dir snippetsDir
    dependsOn test
}

springBoot {
    buildInfo()
}

build-info.properties:

#Properties
#Mon Jun 17 10:52:04 EDT 2019
build.version=0.0.1
build.group=com
build.name=app
build.artifact=app
build.time=2019-06-17T14\:52\:04.829909200Z
5
ROOTKILL

En bref: Ce problème est lié à IDE (je suis vérifié sur Eclipse et Idea), et ce n'est pas affectant l'exécution/le débogage de l'application de démarrage de printemps dans les scripts de démarrage sur le système de génération gradle.

En outre, la prémisse que le plug-in de démarrage pour Eclipse et JDK produisent ce problème n'est pas entièrement correcte.

Racine de ce problème: Emplacement différent des artefacts de génération qui sont compilés avec différents compilateurs et manquant build-info.properties.

Explication:

Lorsque gradle effectue la construction, il utilise généralement le compilateur JDK pour produire Java artefacts et la sortie est placée dans le répertoire de construction.

D'un autre côté, quand Eclipse effectue la construction, il produit des arifacts avec Eclipse JDT et la sortie est placée dans le répertoire bin.

Notez que le mélange de ces deux pourrait conduire à des comportements inattendus. Cette "fonctionnalité" est déjà analysée par l'équipe Eclipse et elle est rejetée (fermée comme non valide). Plus d'informations ici .

Selon le fait que la tâche gradle buildInfo est exécutée par gradle, cela explique le fait que build-info.properties le fichier existe dans le dossier de sortie par défaut de gradle (par défaut, il doit se trouver ici: build/resources/main/META-INF/).

D'après la question de @ ROOTKILL, il est visible qu'il essaie d'obtenir des informations de la classe BuildProperties. Sous le capot, lorsque Spring détecte qu'il y a un fichier build-info.properties sur le chemin de classe, il crée le bean BuildProperties sauf s'il est explicitement déclaré. Les informations utiles sont ici .

Veuillez jeter un œil à cette méthode:

@ConditionalOnResource(resources = "${spring.info.build.location:classpath:META-INF/build-info.properties}")
@ConditionalOnMissingBean
@Bean
public BuildProperties buildProperties() throws Exception {
    return new BuildProperties(
            loadFrom(this.properties.getBuild().getLocation(), "build"));
}

Étant donné que IDE utilise un répertoire de sortie différent, il manque le fichier build-info.properties et cela génère une erreur affichée (Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not loaded because @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}'). Et d'un autre côté, cela explique pourquoi tout est exécutable avec gradle.

Solution:

Selon ces faits, la solution est claire: les IDE Eclipse et IntelliJ Idea doivent utiliser les tâches de gradle au lieu des siennes pour l'exécution/le débogage.

  • Pour l'IDE Eclipse : l'application peut être démarrée sur la tâche gradle (bootRun à partir de la vue des tâches gradle).
  • Pour IDE IDE : Il peut être ajouté un paramètre qui délègue IDE construire/exécuter des actions à gradle, qui est @ user666 l'a déjà souligné.

Comme cette solution utilise gradle, build-info.properties le fichier sera utilisé à partir de build/resources/main/META-INF/ emplacement (par défaut de Gradle), et bien sûr, il sera visible. En conséquence, le bean BuildProperties sera créé et sera utilisable.

1
Bosko Mijin

Je pense que votre IDE est confondu par le fait que le "gros pot" écrase le pot normal. Le IDE comprend le chemin de classe du pot normal + la ressource générée) de `build-info.properties.

Je construis toujours les pots sous des noms différents, donc je peux éviter ce genre de problèmes avec les builds partiels.

https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-and-normal

Pour éviter que l'archive exécutable et l'archive normale ne soient écrites au même emplacement, l'un ou l'autre doit être configuré pour utiliser un emplacement différent. Pour ce faire, vous pouvez configurer un classificateur:

bootJar {
    classifier = 'boot'
}
0
Mateusz Stefek

Je suggère d'essayer de fonctionner sous JDK 8 et d'exécuter à partir de la ligne de commande avec Java -jar <your jar name> juste pour être sûr d'obtenir correctement les propriétés de construction.

Peut-être que Jdk 12 n'est pas encore adapté à la botte de printemps. Je pense que vous pourriez aussi avoir d'autres problèmes. De nombreux frameworks Java ne sont pas certifiés à 100% pour fonctionner avec JDK 12.

Je pense que le plan est de supporter officiellement Java 12 à partir de Spring Boot 2.2

0
Borislav Markov