Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting ArtifactId and Version in Spring Boot Starter

I am currently developing a Spring Boot Starter which will host a Restful web service with some meta-data about the running application.

I am having difficulties extracting my artifactId and versionId from my mainfest file. I believe my issue is that the autoconfiguration classes are being loaded before the main Test application so the manifest is not yet available to be discovered. I am not sure if my logic here is correct of if I am approaching the problem from the wrong angle.

I originally followed the following tutorial for setup.

This gave me 3 separate projects

Generic Spring Services with no context AutoConfiguration project for these services Spring Boot starter

I paired the starter with a test project as an end result.

Currently maven is being used with Spring Boot to generate a manifest file.

Implementation-Title: MyExampleProjectWithCustomStarter Implementation-Version: 0.0.1-SNAPSHOT Archiver-Version: Plexus Archiver Built-By: mcf Implementation-Vendor-Id: com.coolCompany Spring-Boot-Version: 1.5.4.RELEASE Implementation-Vendor: Pivotal Software, Inc. Main-Class: org.springframework.boot.loader.JarLauncher Start-Class: com.coolcompany.SpringBootExampleApplication Spring-Boot-Classes: BOOT-INF/classes/ Spring-Boot-Lib: BOOT-INF/lib/ Created-By: Apache Maven 3.5.0 Build-Jdk: 1.8.0_131 Implementation-URL: http://someurl

However, when I attempt to locate the manifest file for the Example project from my generic service package I cannot find the file.

  private String getApplicationVersion(String applicationName, List<Attributes> manifests) {
    String unknownVersion = "0.0.0-UNKNOWN";

    for (Attributes attr : manifests) {
      String title = attr.getValue(IMPL_TITLE);
      String version = attr.getValue(IMPL_VERSION);
      if (version != null) {
        if (applicationName.equalsIgnoreCase(title)) {
          return title + ' ' + version;
        }
      }
    }
    log.warn(
        "Could not find MANIFEST file with '" + applicationName + "' as Implementation-Title."
        + " Meta-API will return buildVersion '" + unknownVersion + "'.");

    return applicationName + ' ' + unknownVersion;
  }

  private List<Attributes> loadManifestFiles() {
    List<Attributes> manifests = new ArrayList<>();
    try {
      Enumeration<URL> resources =
          Thread.currentThread().getContextClassLoader().getResources("/META-INF/MANIFEST.MF");
      while (resources.hasMoreElements()) {
        URL url = resources.nextElement();
        try (InputStream is = url.openStream()) {
          manifests.add(new Manifest(is).getMainAttributes());
          System.out.println("Manifest size:" + manifests.size());
        } catch (IOException e) {
          log.error("Failed to read manifest from " + url, e);
        }
      }
    } catch (IOException e) {
      log.error("Failed to get manifest resources", e);
    }
    return manifests;
  }

Current manifest Implementation-Titles:

Spring Boot Web Starter Spring Boot Starter Spring Boot Spring Boot AutoConfigure Spring Boot Logging Starter null null jcl-over-slf4j null log4j-over-slf4j null Spring Boot Tomcat Starter Apache Tomcat Apache Tomcat Apache Tomcat hibernate-validator null JBoss Logging 3 ClassMate jackson-databind Jackson-annotations Jackson-core spring-web spring-aop spring-beans spring-context spring-webmvc spring-expression Spring Boot Actuator Starter Spring Boot Actuator null ** MyCustom-spring-boot-starter ** MyGenericSpringService null null null Metrics Core JVM Integration for Metrics null null Jackson datatype: JSR310 ** MyService-spring-boot-autoconfigure slf4j-api spring-core ** Missing MyExampleProjectWithCustomStarter

count of manifest records: 44

like image 367
Matthew Fontana Avatar asked Jun 27 '17 17:06

Matthew Fontana


People also ask

How do I find my spring boot version?

Having access to version and build information at runtime can be quite useful. In Spring boot application, you can easily obtain the info by altering the Spring Boot Maven/Gradle plugin configuration to generate the build. properties file and then accessing it through BuildProperties object.

Where is spring boot version in POM xml?

You can find the Spring Framwork version of spring-boot-starter-X by checking its pom. xml . Navigate to its parent pom until you get to spring-boot-dependencies-VERSION. pom .

What is spring boot artifactId?

Artifact: project coordinates (id of the artifact, as referred by the artifactId attribute in Apache Maven). Also infers the name of the project. Name: display name of the project that also determines the name of your Spring Boot application.


2 Answers

After a lot of effort, I found a surprisingly simple answer. This is how spring-boot-actuator gets the information.

The Spring Boot Maven plugin comes equipped with a build-info goal. As long as this goal is triggered in the main project Spring has a BuildProperties class you can wire in for the information.

            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <id>build-info</id>
                        <goals>
                            <goal>build-info</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

You can access the properties in your starter like:

@Autowired
BuildProperties buildProperties;

...
buildProperties.getArtifact();
buildProperties.getVersion();

You can even specify additional properties from the plugin. See the plugin documentation for more details: https://docs.spring.io/spring-boot/docs/current/maven-plugin/build-info-mojo.html

Unfortunately I never quite got to fully understand why I could not access the correct manifest, but this should help anyone else trying to solve this problem.

like image 92
Matthew Fontana Avatar answered Sep 30 '22 17:09

Matthew Fontana


The other answer is completely correct. Just for others finding this question in case you are using Gradle instead of Maven:

Generating build info is as simple as adding this to your build.gradle file:

plugins {
    id 'org.springframework.boot' version '<your-boot-version>.RELEASE'
}

// ...    

springBoot {
    buildInfo()
}

And if you want to pass custom properties:

springBoot {
    buildInfo {
        properties {
            additional = [
                'property.name': 'property value',
                'other.property': 'different.value'
            ]
        }
    }
}

Then the usage in Java code is the same using BuildProperties. You can find more info about the plugin in this guide.

like image 30
Vojtech Ruzicka Avatar answered Sep 30 '22 18:09

Vojtech Ruzicka