BuildProperties Spring Boot 2.1.5 和 Spring Boot 2.1.5 的自动装配失败蚀
我正在使用一些 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.
我转到构建文件,还查看了构建创建的 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;
}
我的 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
I'm creating a very simple application with a few REST API's and it's currently working correctly until I try to use the BuildProperties on my health check API. While starting my application I get the following error:
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.
I went to the build file and I also looked in the jar file created by the build and I see the build-info.properties is in fact there. In the jar file the path to the file is "BOOT-INF\classes\META-INF\". I also have other "Autowired" elements that are not having issues.
Where my code fails:
@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;
}
My gradle build file:
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
只需运行
mvn clean package
,然后从 Eclipse/IntelliJ 重新启动 Spring Boot 应用程序。Just run a
mvn clean package
and then restart the spring boot application from either Eclipse/IntelliJ.在pom.xml末尾添加/修改:
Add/Modify at the end of pom.xml:
简而言之:这个问题与 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,除非显式声明它。
有用的信息是 这里。
请看一下这个方法:
根据 IDE 使用不同输出目录的事实,缺少 build-info.properties 文件,这会产生显示错误 (
Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not returned因为@ConditionalOnResource没有找到资源'${spring.info.build.location:classpath:META-INF/build-info.properties}'
)。另一方面,这解释了为什么一切都可以通过 gradle 运行。
解决方案:
根据这些事实,解决方案很明确:Eclipse 和 IntelliJ Idea IDE 都必须使用 gradle 的任务而不是它自己的任务来运行/调试。
由于此解决方案使用 gradle,因此将从
build/resources/main/META-INF/
位置(gradle 的默认值)使用build-info.properties
文件,当然它将可见。结果,bean BuildProperties 将被创建并且可用。In short: This problem is IDE related (I'm checked on Eclipse and Idea), and this is not affecting running/debugging spring boot application in startup scripts over the gradle build system.
Also, premise that boot plugin for eclipse and JDK are producing this problem is not entirely correct.
Root of this problem: Different location of build artifacts which are compiled with different compilers and missing
build-info.properties
.Explanation:
When gradle performs the build, it ussually uses JDK compiler to produce Java artifacts and output is placed into build directory.
On the other side, when eclipse performs the build, it produces arifacts with Eclipse JDT and output is placed into bin directory.
Note that mixing those two could lead to unexpected behaviours. This 'feature' is already analyzed by eclipse team and it is rejected (closed as invalid). More information here.
According to fact that gradle task
buildInfo
is ran by gradle, that is explaining the fact thatbuild-info.properties
file exists in gradle's default output folder (by default it has to be located here:build/resources/main/META-INF/
).From @ROOTKILL's question, visible is that he is tried to obtain information from BuildProperties class. Under the hood, when Spring detects there is build-info.properties file on the classpath, it creates BuildProperties bean unless it is explicitly declared.
Useful information is here.
Please, take a look at this method:
According to the fact that IDE is using different output dir, there is missing build-info.properties file and this produces displayed error (
Bean method 'buildProperties' in 'ProjectInfoAutoConfiguration' not loaded because @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}'
).And on other side, this explains why everything is runnable with gradle.
Solution:
According to those facts, solution is clear: Both eclipse and IntelliJ Idea IDE's must use gradle's tasks instead of it's own for running/debugging.
Since this solution uses gradle,
build-info.properties
file will be used frombuild/resources/main/META-INF/
location (gradle's default), and off course it will be visible. As a consequence, bean BuildProperties will be created and will be usable.正如 @André Schonrock 正确提到的,问题的原因是 此处:
因此,您需要在
POM
中添加spring-boot-maven-plugin
:或在
build.gradle
中添加:作为替代方式可以以比 @djangofan 显示的更短的形式显式添加
Bean
:在配置文件中。
注意:如果您更新了
POM
或build.gradle
,但错误仍然出现,请尝试使用(例如对于Maven)生命周期命令
clean
,然后install
并再次运行该项目。As correctly mentioned by @André Schonrock, the cause of issue is here:
So you need either to add for
spring-boot-maven-plugin
inPOM
:or to add in
build.gradle
:As alternative way can be explicitly added
Bean
in a shorter form than was shown by @djangofan:in configuration file.
Notice: if you updated
POM
orbuild.gradle
, but the error still appears, try to use (e.g. forMaven
) lifecycle commandsclean
and theninstall
and run again the project.如果使用 Intelli 和 Maven,这里是有关如何更改运行器和使用 Maven 运行器的屏幕截图。理想情况下,这是最好的建议,因为我们也可以按照 Maven 在 IDE 中运行的方式运行。
If using Intelli and maven, here is screenshot on how to change the runner and use maven runner. Ideally this is best suggested, as we can run exactly how maven runs in the ide also.
正如@Borislav Markov 建议的那样,我尝试通过命令行运行它,无论我使用 JDK 12 还是 JDK 8,它似乎都能完美工作。我认为这个问题与我用来通过 IDE 运行应用程序的 Eclipse 插件有关。
As @Borislav Markov suggested I tried running it via command line and it seems to work perfectly regardless if I use JDK 12 or JDK 8. I think the issue has to do with the eclipse plugin I am using to run the application via the IDE.
我的 Spring Boot 服务在 maven-spring-boot 插件中有一个 Maven 构建信息部分,因此当我尝试运行该服务时,如果该服务不是来自 . jar 存档。因此,为了将我的服务作为常规 Spring Boot 运行配置运行,我必须添加此条件 bean,现在一切正常,既作为 .jar 版本运行,又作为调试非版本运行:
My Spring Boot service has a Maven build-info section in the maven-spring-boot plugin and so I get this error
BuildProperties cannot be found
when I try to run the service when it is not from a .jar archive. So, to run my service as a regular Spring Boot run configuration, I had to add this condition bean and now everything works , both as a .jar release and also it runs as a debug non-release:如果您使用 lombok,请确保排除 spring-boot-maven-plugin 的配置,例如,
If you are using lombok, make sure to exclude it configuration for spring-boot-maven-plugin, e.g.,
正如其他人正确指出的那样,问题出在 IDE 上。对于 IntelliJ,替代解决方案是将 spring-boot:build-info 修改为“重建后执行”,如下所示。
As others rightly pointed, the problem is with the IDE. For IntelliJ, the alternative solution is modifying the spring-boot:build-info to "Execute After Rebuild" as shown below.
正如其他答案所明确的,这是由于 IDE 未创建该文件。对于 vscode,我通过定义一个任务将 build-info.properties 文件从 Gradle 的 build/resources/main/META-INF 目录复制到 vscode 的 来解决这个问题bin/main/META-INF 以便构建期望找到它。
通常我最近运行了 Gradle 构建,并且 build-info.properties 的稍微过时的版本对于我在 vscode 中的调试运行来说已经足够了。
创建与此类似的 .vscode/tasks.json:
然后将任务作为 preLaunchTask 添加到 .vscode/launch.json 中:
As other answers have made clear, this is due to the IDE not creating the file. For vscode, I solved it by defining a task to copy the build-info.properties file from Gradle's build/resources/main/META-INF directory into vscode's bin/main/META-INF so that it would be where the build expects to find it.
Normally I have run a Gradle build recently, and that slightly stale version of build-info.properties is good enough for my debugging run in vscode.
Create a .vscode/tasks.json similar to this:
Then add the task as a preLaunchTask in your .vscode/launch.json:
我建议尝试在 JDK 8 下运行并从命令行运行
java -jar
只是为了确保您正确获取构建属性。也许Jdk 12还不适合spring-boot。我想你可能还有其他问题。许多 Java 框架并未 100% 认证它们可以与 JDK 12 配合使用。
我认为计划是从 Spring Boot 2.2 开始正式支持 Java 12
I would suggest to try running under JDK 8 and to run from the command line with
java -jar <your jar name>
just to be sure you get the build properties correctly.Maybe Jdk 12 is not suitable for spring-boot yet. I think you might have other problems as well. Many Java frameworks are not 100% certified that they will work with JDK 12.
I think the plan is to officially support Java 12 as of Spring Boot 2.2
我认为您的 IDE 对“fat jar”覆盖普通 jar 的事实感到困惑。 IDE 理解普通 jar + 生成的 `build-info.properties 资源的类路径。
我总是以不同的名称构建 jar,因此我可以避免部分构建的此类问题。
https:// /docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-and-normal
I think your IDE is confused by the fact that the "fat jar" overwrites the normal jar. The IDE understands the classpath of the normal jar + generated resource of `build-info.properties.
I always build the jars under different names, so I can avoid this kind of issues with partial builds.
https://docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/html/#packaging-executable-and-normal
我试过 ProjectInfoAutoConfiguration 解决方案,并认为最好使用
@ConditionalOnMissingBean (BuildProperties.class)
代替@ConditionalOnResource(资源=“$ {spring.info.build.location:类路径:META-INF / build-info.properties}”)
。因为我可以控制
BuildProperties
的创建方式:I tried ProjectInfoAutoConfiguration solution and thought it was better to use
@ConditionalOnMissingBean (BuildProperties.class)
instead@ConditionalOnResource (resources = "$ {spring.info.build.location: classpath: META-INF / build-info.properties}")
.Because I can control the way
BuildProperties
are created:对于 Gradle 项目:将其添加到 build.gradle 文件中
For Gradle Project: add this on build.gradle file
问题是 STS 和 Intellij 在将应用程序作为 Spring Boot 应用程序运行时不运行 buildinfo 任务。由于大多数开发人员通过这种机制运行应用程序而不是使用 gradle / maven 构建,因此需要有一个适用于两者的解决方案。我遵循了 Sergey K 的回答,它适用于基于 IDE 的 Spring boot 运行。但对于 gradle run 来说,它失败了,因为 BuildProperties 是从配置文件而不是生成的 build-info.properties 文件自动装配的。
我能够通过使用以下组件并自动装配它来克服这个问题
The issue is STS and Intellij doesn't run the buildinfo task while running the application as a Spring Boot Application. Since most developers run the app through this mechanism rather than using gradle / maven build need to have a solution that works for both. I followed Sergey K's answer and it worked for IDE based Spring boot run. But for gradle run it failed because the BuildProperties was getting autowired from the Configuration file instead of the generated build-info.properties file.
I was able to overcome this by having the following Component and autowiring it