web-dev-qa-db-fra.com

Autowiring BuildProperties bean de Gradle - NoSuchBeanDefinitionException

J'essaye d'obtenir la version dans mon Java du fichier de construction Gradle. Je suis les instructions ici;

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-build.html

build.gradle

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

project.version = '0.1.0'

apply plugin: 'Java'
apply plugin: 'war'
apply plugin: 'idea'
apply plugin: 'org.springframework.boot'

springBoot  {
    buildInfo()
}

jar {
    baseName = 'ci-backend'
}

war {
   baseName = 'ci-backend'
}

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile("org.springframework.boot:spring-boot-starter-web")
    compile("org.springframework:spring-jdbc")
    compile("joda-time:joda-time")

    compile("com.opencsv:opencsv:3.9")
    compile("org.springframework.batch:spring-batch-core")

    testCompile('org.springframework.boot:spring-boot-starter-test')
    providedRuntime('org.springframework.boot:spring-boot-starter-Tomcat')
 }

Après avoir construit avec gradle le build-info.properties le fichier est présent dans build/resources/main/META-INF/build-info.properties

Dans mon @RestController J'essaie de câbler automatiquement le bean des propriétés de construction

@Autowired
private BuildProperties buildProperties;

Je reçois l'erreur suivante;

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.info.BuildProperties' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.Java:1493)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.Java:1104)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.Java:1066)
at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.Java:585)
... 41 more

Je suppose que le bean BuildProperties est automatiquement créé lorsque le build-info.properties est présent. Cela ne semble pas être le cas.

20
Jags

Le problème que j'avais peut-être était différent, mais j'ai atterri ici en essayant de rechercher la solution sur google, donc je posterai ceci ici au cas où quelqu'un d'autre rencontrerait le même problème. Mon message d'erreur était:

Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.info.BuildProperties' available

Ce n'est que lorsque vous essayez d'exécuter dans IntelliJ, pas lorsqu'il est exécuté avec gradle à partir de la ligne de commande. (ET cela est peut-être spécifique à SpringBoot)

Je devais juste définir "Déléguer IDE construire/exécuter des actions pour gradle" à partir de "Build, Execution, Deployment-> Build Tools-> Gradle" qui a ensuite obtenu la tâche "bootBuildInfo" à exécuter lors de la construction à partir de l'IDE.

4
Brian Deacon

Votre hypothèse est juste, le bean BuildProperties est automatiquement créé lorsque le META-INF/build-info.properties est présent .

Voir le code de configuration automatique suivant dans ProjectInfoAutoConfiguration

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

Cependant, si le bean n'est toujours pas disponible dans votre contexte d'application, essayez l'une des opérations suivantes:

  1. Assurez-vous que la tâche buildInfo gradle est correctement configurée, exécutez gradlew bootBuildInfo --debug et vérifier les résultats
  2. Vérifiez si votre répertoire de sortie IDE diffère du répertoire de construction de gradle, par exemple intellij utilise le répertoire out (dans mon cas, le build-info.properties le fichier n'était pas présent)
  3. Mettez à niveau votre plugin gradle, peut-être que vous rencontrez ce problème https://github.com/spring-projects/spring-boot/issues/12266 , où vous pouvez essayer d'utiliser le hack suivant si vous ne le faites pas ' Je ne veux pas attendre la sortie du patch

    def removeBootBuildInfoWorkaround12266 = task(type: Delete, 'removeBootBuildInfoWorkaround12266') {
        delete new File(buildDir, 'resources/main/META-INF/build-info.properties')
    }
    tasks.find { it.name == 'bootBuildInfo' }.dependsOn(removeBootBuildInfoWorkaround12266)
    

J'espère que ça aide.

3
Carlos Quijano

Vous devrez configurer Intelij pour utiliser Gradle Runner afin qu'il génère le fichier build.properties dans le dossier out. Activez Délégué IDE construire/exécuter des actions vers Gradle option dans Paramètres (Préférences) | Build, Execution, Deployment | Build Tools | Gradle | onglet Runner.

2
Casper

J'étais également confronté au même problème, c'était un problème de maven.J'ai mis à niveau ma version de maven (3.3.9) et intégré l'invite de commande au lieu de le construire dans l'IDE. Je sais que c'est quelque chose de bizarre mais OUI c'est ce qui a fonctionné pour moi.

1
Ravi Wadje

Je sais que cette question est ancienne, mais je l'ai rencontrée aujourd'hui et je voulais partager une solution alternative. J'exécutais des tests d'IntelliJ qui vivent dans un package séparé (bien que vous puissiez ajouter des annotations pour empêcher cette configuration de se charger, il pourrait simplement vivre dans le package principal)

L'exemple est en kotlin:

@Configuration
class IntegrationAppConfig {
    @Bean
    @ConditionalOnMissingBean(BuildProperties::class)
    fun buildProperties(): BuildProperties = BuildProperties(Properties()).also {
        logger.error("BuildProperties bean did not auto-load, creating mock BuildProperties")
    }
}

Cela vous permet de continuer à utiliser IntelliJ si vous le souhaitez, sans avoir à passer par Gradle si vous ne le souhaitez pas.

1
Mike Emery

La configuration ci-dessus était correcte mais je ne sais toujours pas quel était le problème.

En fin de compte, la meilleure solution est de passer à la place à l'actionneur Spring-boot. L'actionneur contient toutes les informations de construction dans un point de terminaison de repos préconfiguré.

0
Jags