How can I print the applications version early in the log in Spring Boot?

Viewed 2435

I'm trying to print my applications version early in the log before any of my other code has a chance to execute, so that if an error happens the version is included in the log file.

@SpringBootApplication
public class Application {
    public static void main( String... args ) {
        var ctx = SpringApplication.run( Application.class, args );
        ctx.getBeanProvider( BuildProperties.class ).ifAvailable( bp -> {
            LogManager.getLogger( Application.class ).info( bp.getArtifact() );
        } );
    }
}

but the block in ifAvailable doesn't get executed, I'd like to print the version especially.

note: this is in build.gradle.kts

springBoot {
    buildInfo() // generates BOOT-INF/classes/META-INF/build-info.properties
}

update fails with no such bean...

@SpringBootApplication
public class Application {
    public static void main( String... args ) {
        SpringApplication.run( Application.class, args );
    }

    @Bean
    CommandLineRunner runner( BuildProperties bp ) {
        return args -> LogManager.getLogger( Application.class ).info( bp.getArtifact() );
    }
}

update 2: doesn't have to be after the banner, but has to be early enough that it prints before any validation/errors from custom code.

3 Answers

presuming you're fatpacking a jar (otherwise some modifications are needed)

tasks.withType<BootJar>().configureEach {
    enabled = true
    manifest {
        attributes(
            "Implementation-Title" to project.description,
            "Implementation-Version" to project.version
        )
    }
}

then customize your banner.txt; e.g.

${application.title} ${application.version}

You can your custom banner.txt with spring.banner.location property and use Gradle resource filtering with processResources task to replace placeholders in this file with the same properties that were used by build-info.

This answer contains something of a round about technique, but may be useful.

Assumptions First:

  1. You are building an executable, fat Jar.
  2. You are using the spring-boot-maven-plugin to build the jar.

Answer:

  1. Configure the spring-boot-maven-plugin to include build information in the artifact. See section 91.1 Generate Build Information (in the spring-boot reference) for instructions.
  2. Be sure to enable the build info contributor. This should be enabled by default (search the spring boot reference for "management.info.build.enabled" to find the property that enables his info contributor.
  3. Get the list of InfoContributor beans from the application context. I do this by autowiring a List in a component as follows:

    @Autowired
    private List<InfoContributor> infoContributorList;

  4. Run the list of InfoContributor objects (in your case there should only be one, the build info) and display the info.

Here is some code (poorly configured on my part)

final Info info;
final Info.Builder infoBuilder = new Info.Builder();
final Map infoMap;

for (final InfoContributor current : infoContributorList)
{
current.contribute(infoBuilder);
}

info = infoBuilder.build();

infoMap = info.getDetails();

Related