Java BuildProperties Spring Boot 2.1.5的自动连线失败&;日食
我正在用一些RESTAPI创建一个非常简单的应用程序,在我尝试在我的健康检查API上使用BuildProperties之前,它目前工作正常。启动应用程序时,出现以下错误:Java BuildProperties Spring Boot 2.1.5的自动连线失败&;日食,java,spring-boot,autowired,Java,Spring Boot,Autowired,我正在用一些RESTAPI创建一个非常简单的应用程序,在我尝试在我的健康检查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 --- [
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
我建议尝试在JDK 8下运行,并使用
java-jar
只是为了确保正确获得构建属性
也许JDK12还不适合spring boot。我想你可能还有其他问题。许多Java框架并没有100%通过JDK12的认证
我认为计划是从Spring Boot 2.2开始正式支持Java 12,正如@Borislav Markov所建议的那样,我尝试通过命令行运行它,无论我使用JDK 12还是JDK 8,它似乎都能完美工作。我认为这个问题与我用来通过IDE运行应用程序的eclipse插件有关。我认为您的IDE被“胖jar”覆盖了普通jar的事实弄糊涂了。IDE理解“build-info.properties”的普通jar+生成资源的类路径 我总是以不同的名称构建jar,因此我可以避免使用部分构建时出现此类问题 为了避免将可执行存档和普通存档写入同一位置,应将其中一个配置为使用不同的位置。一种方法是配置分类器:
在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>
{命名你的项目}
org.springframework.boot
springbootmaven插件
构建信息
简而言之:这个问题与IDE有关(我在Eclipse和Idea上进行了检查),这不会影响在gradle构建系统的启动脚本中运行/调试spring boot应用程序
另外,eclipse和JDK引导插件产生这个问题的前提也不完全正确
此问题的根源:使用不同编译器编译的生成工件的不同位置,缺少build info.properties
说明:
当gradle执行构建时,它通常使用JDK编译器生成Java工件,并将输出放在构建目录中
另一方面,当eclipse执行构建时,它使用EclipseJDT生成arifacts,并将输出放在bin目录中
请注意,将这两者混合在一起可能会导致意外行为。eclipse团队已经对该“功能”进行了分析,并将其拒绝(关闭为无效)。更多信息
根据gradle任务buildInfo
由gradle运行的事实,这解释了buildInfo.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"));
}
根据IDE使用不同的输出目录的事实,缺少build-info.properties文件,这会产生显示的错误(projectinfo自动配置中的Bean方法'buildProperties'未加载,因为@ConditionalOnResource未找到资源'${spring.info.build.location:classpath:META-INF/build-info.properties}“
)。
另一方面,这也解释了为什么gradle的一切都是可以运行的
解决方案:
根据这些事实,解决方案是明确的:eclipse和IntelliJ Idea都必须使用gradle的任务,而不是自己的任务来运行/调试
- 对于EclipseIDE:可以通过gradle任务启动应用程序(从gradle任务视图启动)
- 对于Idea:可以添加将IDE构建/运行操作委托给gradle的设置,gradle在前面已经指出了@user666
由于此解决方案使用gradle,
build info.properties
文件将从build/resources/main/META-INF/
位置(gradle的默认位置)使用,当然它将是可见的。因此,,bean BuildProperties将被创建并可用。只需运行一个mvn clean包,然后从eclipse/intelliJ重新启动启动应用程序我的Spring启动服务在Maven Spring启动插件中有一个Maven build info部分,因此当我尝试运行当服务不是来自.jar存档时提供的服务。因此,为了将我的服务作为常规的Spring引导运行配置运行,我必须添加这个条件bean,现在一切都可以运行,既可以作为.jar版本运行,也可以作为调试非版本运行:
@ConditionalOnMissingBean
@Bean
public BuildProperties buildProperties() {
Properties properties = new Properties();
properties.put("group", "com.example");
properties.put("artifact", "demo");
properties.put("version", "not-jarred");
return new BuildProperties(properties);
}
正如其他答案所表明的,这是由于IDE没有创建文件。对于vscode,我通过定义一个任务将build info.properties文件从Gradle的build/resources/main/META-INF目录复制到vscode的bin/main/META-INF中来解决这个问题,这样它就可以在构建希望找到它的地方 通常我最近运行了一个Gradle构建,而且
@ConditionalOnMissingBean
@Bean
public BuildProperties buildProperties() {
Properties properties = new Properties();
properties.put("group", "com.example");
properties.put("artifact", "demo");
properties.put("version", "not-jarred");
return new BuildProperties(properties);
}
{
"version": "2.0.0",
"tasks": [
{
// This task keeps vscode from failing when using BuildProperties
"label": "Copy build-info from Gradle",
"type": "shell",
"command": "mkdir -p ./bin/main/META-INF/ && cp ./build/resources/main/META-INF/build-info.properties ./bin/main/META-INF/build-info.properties"
}
]
}
{
"configurations": [
{
"type": "java",
"name": "Spring Boot-Application<example>",
"request": "launch",
"cwd": "${workspaceFolder}",
"console": "internalConsole",
"mainClass": "com.example.Application",
"projectName": "example",
"args": "",
"preLaunchTask": "Copy build-info from Gradle"
}
]
}
@ConditionalOnMissingBean(BuildProperties.class)
@Bean
public BuildProperties buildProperties() throws IOException {
Resource r = this.properties.getBuild().getLocation();
if (r.exists())
// build-info.properties exists in my jar
return new BuildProperties(
loadFrom(r, "build")); // see ProjectInfoAutoConfiguration code
else {
// No, we running via IDE. So let's build a stub:
Properties properties = new Properties();
properties.put("group", "com.example");
properties.put("artifact", "demo");
properties.put("version", "not-jarred");
return new BuildProperties(properties);
}
}
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>build-info</id>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
</plugin>