#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
–
–
–
–
<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>
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 that build-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:
@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"));
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.
For the Eclipse IDE: Application can be started over the gradle task (bootRun from gradle tasks view).
For the Idea IDE: There can be added setting that delegates IDE build/run actions to gradle, which is @user666 already pointed before.
Since this solution uses gradle, build-info.properties
file will be used from build/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.
As correctly mentioned by @André Schonrock, the cause of issue is here:
Both the Maven plugin and the Gradle plugin allow generating build
information containing the coordinates, name, and version of the
project. The plugins can also be configured to add additional
properties through configuration. When such a file is present, Spring
Boot auto-configures a BuildProperties bean.
So you need either to add for spring-boot-maven-plugin
in POM
:
<executions>
<execution>
<goals>
<goal>build-info</goal>
</goals>
</execution>
</executions>
or to add in build.gradle
:
springBoot {
buildInfo()
As alternative way can be explicitly added Bean
in a shorter form than was shown by @djangofan:
@Bean @ConditionalOnMissingBean(BuildProperties.class)
BuildProperties buildProperties() {
return new BuildProperties(new Properties());
in configuration file.
Notice: if you updated POM
or build.gradle
, but the error still appears, try to use (e.g. for Maven
) lifecycle commands clean
and then install
and run again the project.
–
–
–
–
If you are using lombok, make sure to exclude it configuration for spring-boot-maven-plugin, e.g.,
<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>
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:
@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);
–
–
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:
"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"
Then add the task as a preLaunchTask in your .vscode/launch.json:
"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"
–
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
–
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
To avoid the executable archive and the normal archive from being written to the same location, one or the other should be configured to use a different location. One way to do so is by configuring a classifier:
bootJar {
classifier = 'boot'
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:
@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);
–
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
@Component
public BuildValues{
@Autowired(required = false)
private buildProperties;
public getBuildProperties(){
if(buildProperties==null) {
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource r = resourceLoader.getResource("classpath:META-INF/build-
info.properties");
if (r.exists()) {
// build-info.properties exists in my jar
Properties prop = PropertiesLoaderUtils.loadProperties(r);
buildProperties = new BuildProperties(prop);
}else {
// No, we running via IDE. So let's build a stub:
Properties properties = new Properties();
properties.put("buildTime", "2022-01-13T14:38:06.567Z");
buildProperties = new BuildProperties(properties);
return buildProperties;
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.