BuildProperties Spring Boot 2.1.5 和 eclipse 的自动装配失败

ROO*_*ILL 23 java autowired spring-boot

我正在使用一些 REST API 创建一个非常简单的应用程序,并且在我尝试在我的健康检查 API 上使用 BuildProperties 之前,它目前可以正常工作。在启动我的应用程序时,我收到以下错误:

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.
Run Code Online (Sandbox Code Playgroud)

我去了构建文件,我还查看了构建创建的 jar 文件,我看到 build-info.properties 实际上在那里。在 jar 文件中,文件路径为“BOOT-INF\classes\META-INF\”。我还有其他没有问题的“自动连线”元素。

我的代码失败的地方:

@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;
    }
Run Code Online (Sandbox Code Playgroud)

我的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()
}
Run Code Online (Sandbox Code Playgroud)

构建信息.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
Run Code Online (Sandbox Code Playgroud)

小智 22

在 pom.xml 末尾添加/修改:

<build>
        <finalName>{NAME_YOUR_PROJECT}</finalName>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
Run Code Online (Sandbox Code Playgroud)


Ana*_*ant 19

只需运行一个 mvn clean 包,然后从 eclipse/intelliJ 中重新启动启动应用程序

  • 这对我有用。有谁知道为什么? (8认同)
  • @JamesHackett 这个文件(build-info.properties)由 Spring 从类路径 META-INF/ 文件夹中读取。通过这样做,它是由您的构建工具(maven、gradle 等)构建的。 (4认同)
  • 有效,谢谢!`mvn 干净包`。 (3认同)

inv*_*bl3 18

正如@Andr\xc3\xa9 Schonrock正确提到的,问题的原因在这里

\n
\n

Maven 插件和 Gradle 插件都允许生成包含项目的坐标、名称和版本的构建信息。还可以将插件配置为通过配置添加其他\n属性。当存在这样的文件时,Spring\nBoot 会自动配置一个 BuildProperties bean。

\n
\n

所以你需要添加 for spring-boot-maven-pluginin POM

\n
<executions>\n    <execution>\n        <goals>\n            <goal>build-info</goal>\n        </goals>\n    </execution>\n</executions> \n
Run Code Online (Sandbox Code Playgroud)\n

或添加build.gradle

\n
springBoot {\n    buildInfo()\n}\n
Run Code Online (Sandbox Code Playgroud)\n

作为替代方式,可以以比@djangofanBean显示的更短的形式显式添加:

\n
@Bean @ConditionalOnMissingBean(BuildProperties.class)\nBuildProperties buildProperties() {\n    return new BuildProperties(new Properties());\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在配置文件中。

\n

注意:如果您更新了POMbuild.gradle,但错误仍然出现,请尝试使用(例如 for Maven)生命周期命令clean,然后install 再次运行项目。

\n


Ram*_*ams 15

如果使用 Intelli 和 Maven,这里是有关如何更改运行器和使用 Maven 运行器的屏幕截图。理想情况下,这是最好的建议,因为我们也可以按照 Maven 在 IDE 中运行的方式运行。

在此输入图像描述


Bos*_*jin 11

简而言之:此问题与 IDE 相关(我在 Eclipse 和 Idea 上进行了检查),这不会影响通过 gradle 构建系统在启动脚本中运行/调试 spring boot 应用程序。

此外,Eclipse 和 JDK 的引导插件产生此问题的前提并不完全正确。

此问题的根源:使用不同编译器编译的构建工件的不同位置,并且缺少build-info.properties.

解释:

当 gradle 执行构建时,它通常使用 JDK 编译器来生成 Java 工件并将输出放置到构建目录中。

另一方面,当 eclipse 执行构建时,它会使用 Eclipse JDT 生成 arifacts,并将输出放置到 bin 目录中。

请注意,将这两者混合可能会导致意外行为。这个“功能”已经被 eclipse 团队分析过,它被拒绝(关闭为无效)。更多信息在这里

根据 gradle 任务buildInfo由 gradle 运行的事实,这解释了build-info.properties文件存在于 gradle 的默认输出文件夹中的事实(默认情况下,它必须位于此处:)build/resources/main/META-INF/

从@ROOTKILL 的问题来看,可见的是他试图从 BuildProperties 类中获取信息。在后台,当 Spring 检测到类路径上有 build-info.properties 文件时,它会创建 BuildProperties bean,除非它被明确声明。有用的信息在这里

请看一下这个方法:

@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"));
}
Run Code Online (Sandbox Code Playgroud)

根据 IDE 使用不同输出目录的事实,缺少 build-info.properties 文件,这会产生显示错误 ( Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not loaded because @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}')。另一方面,这解释了为什么一切都可以用 gradle 运行。

解决方案:

根据这些事实,解决方案很明确:eclipse 和 IntelliJ Idea IDE 都必须使用 gradle 的任务而不是它自己的任务来运行/调试。

  • 对于Eclipse IDE:应用程序可以通过 gradle 任务(从 gradle 任务视图 bootRun)启动。
  • 对于Idea IDE:可以添加将 IDE 构建/运行操作委托给 gradle 的设置,这是 @user666 之前已经指出的。

由于此解决方案使用 gradle,build-info.properties文件将从build/resources/main/META-INF/位置使用(gradle 的默认值),当然它会是可见的。因此,bean BuildProperties 将被创建并可用。


ROO*_*ILL 8

正如@Borislav Markov 建议我尝试通过命令行运行它,无论我使用 JDK 12 还是 JDK 8,它似乎都能完美运行。我认为这个问题与我用来通过 IDE 运行应用程序的 eclipse 插件有关。

  • 对于我的情况,我使用 Intellij 执行了以下操作:settings &gt; build &gt; gradle &gt; runner &gt; check delegate IDE build/run actions to gradle (8认同)
  • @user666 现在位于设置 &gt; 构建、执行、部署 &gt; 构建工具 &gt; Gradle 下,然后是一个名为“构建并运行使用”的功能。 (2认同)