CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-loader-tools

Tools for generating executable JAR/WAR files with embedded containers for Spring Boot applications

Pending
Overview
Eval results
Files

build-integration.mddocs/

Build Integration

Utilities for integrating with build tools and generating build metadata for Spring Boot Actuator endpoints. The build integration system provides seamless integration with Maven, Gradle, and other build systems while generating runtime metadata for monitoring and management.

Capabilities

Build Properties Writer

Utility class for generating build-info.properties files consumed by Spring Boot Actuator's info endpoint.

public final class BuildPropertiesWriter {
    /**
     * Create a build properties writer for the specified output file.
     * 
     * @param outputFile the file where build properties will be written
     */
    public BuildPropertiesWriter(File outputFile);
    
    /**
     * Write build properties for the given project details.
     * Creates a properties file compatible with Spring Boot Actuator's info endpoint.
     * 
     * @param projectDetails the project details to write
     * @throws IOException if writing fails
     */
    public void writeBuildProperties(ProjectDetails projectDetails) throws IOException;
    
    /**
     * Project details containing build metadata.
     */
    public static final class ProjectDetails {
        // Contains project information like name, version, build time, etc.
        // Used to generate build-info.properties for actuator endpoints
    }
    
    /**
     * Exception thrown when an additional property has a null value.
     */
    public static class NullAdditionalPropertyValueException extends IllegalArgumentException {
        public NullAdditionalPropertyValueException(String name);
    }
}

Java Executable

Utility for locating and working with Java executables in the runtime environment.

public class JavaExecutable {
    // Provides access to the Java executable used to run the current process
    // Useful for spawning Java processes with consistent JVM configuration
}

Process Execution

Utility for running external processes, commonly used for build tool integration and system commands.

public class RunProcess {
    /**
     * Run an external process with the specified arguments.
     * 
     * @param waitForProcess whether to wait for the process to complete
     * @param args the command line arguments
     * @return the process exit code (if waitForProcess is true)
     * @throws IOException if process execution fails
     */
    public int run(boolean waitForProcess, String... args) throws IOException;
}

Usage Examples

Basic Build Properties Generation

import org.springframework.boot.loader.tools.BuildPropertiesWriter;
import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.Properties;

// Create build properties for actuator endpoint
File outputFile = new File("target/classes/META-INF/build-info.properties");
BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);

// Create project details
ProjectDetails details = new ProjectDetails() {{
    setGroup("com.example");
    setArtifact("myapp");
    setName("My Application");
    setVersion("1.0.0");
    setTime(Instant.now());
    
    // Add custom build information
    getAdditional().put("build.user", System.getProperty("user.name"));
    getAdditional().put("build.java.version", System.getProperty("java.version"));
    getAdditional().put("build.os", System.getProperty("os.name"));
}};

try {
    writer.writeBuildProperties(details);
    System.out.println("Build properties written to: " + outputFile.getAbsolutePath());
} catch (IOException e) {
    System.err.println("Failed to write build properties: " + e.getMessage());
}

// The generated file will be available at /actuator/info endpoint:
// {
//   "build": {
//     "group": "com.example",
//     "artifact": "myapp",
//     "name": "My Application",
//     "version": "1.0.0",
//     "time": "2024-01-15T10:30:00.000Z",
//     "build.user": "developer",
//     "build.java.version": "17.0.1",
//     "build.os": "Linux"
//   }
// }

Maven Integration

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.Properties;

// Maven plugin integration example
public class MavenBuildPropertiesGenerator {
    
    public void generateBuildProperties(MavenProject project, File outputFile) throws IOException {
        BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);
        
        ProjectDetails details = new ProjectDetails();
        details.setGroup(project.getGroupId());
        details.setArtifact(project.getArtifactId());
        details.setName(project.getName());
        details.setVersion(project.getVersion());
        details.setTime(Instant.now());
        
        // Add Maven-specific properties
        Properties additional = details.getAdditional();
        additional.put("build.maven.version", getMavenVersion());
        additional.put("build.java.target", project.getProperties().getProperty("maven.compiler.target"));
        additional.put("build.java.source", project.getProperties().getProperty("maven.compiler.source"));
        
        // Add SCM information if available
        if (project.getScm() != null) {
            additional.put("build.scm.url", project.getScm().getUrl());
            additional.put("build.scm.connection", project.getScm().getConnection());
        }
        
        // Add CI/CD information
        String buildNumber = System.getenv("BUILD_NUMBER");
        if (buildNumber != null) {
            additional.put("build.number", buildNumber);
        }
        
        String gitCommit = System.getenv("GIT_COMMIT");
        if (gitCommit != null) {
            additional.put("build.git.commit", gitCommit);
        }
        
        writer.writeBuildProperties(details);
    }
    
    private String getMavenVersion() {
        // Implementation to get Maven version
        return "3.8.1";
    }
}

Gradle Integration

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.Properties;

// Gradle plugin integration example
public class GradleBuildPropertiesGenerator {
    
    public void generateBuildProperties(String group, String name, String version, 
                                      File outputFile, Properties gradleProperties) throws IOException {
        BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);
        
        ProjectDetails details = new ProjectDetails();
        details.setGroup(group);
        details.setArtifact(name);
        details.setName(name);
        details.setVersion(version);
        details.setTime(Instant.now());
        
        // Add Gradle-specific properties
        Properties additional = details.getAdditional();
        additional.put("build.gradle.version", getGradleVersion());
        
        // Add project properties
        gradleProperties.forEach((key, value) -> {
            if (key.toString().startsWith("build.")) {
                additional.put(key.toString(), value.toString());
            }
        });
        
        // Add system information
        additional.put("build.java.vendor", System.getProperty("java.vendor"));
        additional.put("build.java.vm.name", System.getProperty("java.vm.name"));
        
        writer.writeBuildProperties(details);
    }
    
    private String getGradleVersion() {
        // Implementation to get Gradle version
        return "7.6";
    }
}

Custom Build Information

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Properties;

// Generate comprehensive build information
public class ComprehensiveBuildInfo {
    
    public void generateBuildInfo(String group, String artifact, String version, 
                                File outputFile) throws IOException {
        BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);
        
        ProjectDetails details = new ProjectDetails();
        details.setGroup(group);
        details.setArtifact(artifact);
        details.setName(artifact);
        details.setVersion(version);
        details.setTime(Instant.now());
        
        Properties additional = details.getAdditional();
        
        // Build environment
        additional.put("build.user", System.getProperty("user.name"));
        additional.put("build.host", getHostname());
        additional.put("build.time.formatted", 
            DateTimeFormatter.ISO_LOCAL_DATE_TIME
                .withZone(ZoneId.systemDefault())
                .format(Instant.now()));
        
        // Java environment
        additional.put("build.java.version", System.getProperty("java.version"));
        additional.put("build.java.vendor", System.getProperty("java.vendor"));
        additional.put("build.java.home", System.getProperty("java.home"));
        
        // Operating system
        additional.put("build.os.name", System.getProperty("os.name"));
        additional.put("build.os.version", System.getProperty("os.version"));
        additional.put("build.os.arch", System.getProperty("os.arch"));
        
        // Runtime information
        Runtime runtime = Runtime.getRuntime();
        additional.put("build.runtime.processors", String.valueOf(runtime.availableProcessors()));
        additional.put("build.runtime.max.memory", String.valueOf(runtime.maxMemory()));
        
        // Custom application properties
        additional.put("build.profile", System.getProperty("spring.profiles.active", "default"));
        additional.put("build.type", "executable-jar");
        
        try {
            writer.writeBuildProperties(details);
            System.out.println("Comprehensive build info written to: " + outputFile);
        } catch (BuildPropertiesWriter.NullAdditionalPropertyValueException e) {
            System.err.println("Null value detected for property: " + e.getMessage());
            throw e;
        }
    }
    
    private String getHostname() {
        try {
            return java.net.InetAddress.getLocalHost().getHostName();
        } catch (Exception e) {
            return "unknown";
        }
    }
}

Process Execution for Build Tools

import org.springframework.boot.loader.tools.RunProcess;
import java.io.IOException;
import java.util.Arrays;

// Execute build commands and capture results
public class BuildToolRunner {
    private final RunProcess processRunner = new RunProcess();
    
    public void runMavenBuild(String... goals) throws IOException {
        String[] command = new String[goals.length + 1];
        command[0] = "mvn";
        System.arraycopy(goals, 0, command, 1, goals.length);
        
        System.out.println("Executing: " + Arrays.toString(command));
        int exitCode = processRunner.run(true, command);
        
        if (exitCode != 0) {
            throw new IOException("Maven build failed with exit code: " + exitCode);
        }
        
        System.out.println("Maven build completed successfully");
    }
    
    public void runGradleBuild(String... tasks) throws IOException {
        String[] command = new String[tasks.length + 1];
        command[0] = "./gradlew";
        System.arraycopy(tasks, 0, command, 1, tasks.length);
        
        System.out.println("Executing: " + Arrays.toString(command));
        int exitCode = processRunner.run(true, command);
        
        if (exitCode != 0) {
            throw new IOException("Gradle build failed with exit code: " + exitCode);
        }
        
        System.out.println("Gradle build completed successfully");
    }
    
    public void runGitCommands() throws IOException {
        // Get git information for build metadata
        int exitCode;
        
        // Get current commit hash
        exitCode = processRunner.run(true, "git", "rev-parse", "HEAD");
        if (exitCode != 0) {
            System.out.println("Warning: Could not get git commit hash");
        }
        
        // Get current branch
        exitCode = processRunner.run(true, "git", "rev-parse", "--abbrev-ref", "HEAD");
        if (exitCode != 0) {
            System.out.println("Warning: Could not get git branch");
        }
        
        // Check if working directory is clean
        exitCode = processRunner.run(true, "git", "diff-index", "--quiet", "HEAD", "--");
        if (exitCode != 0) {
            System.out.println("Warning: Working directory has uncommitted changes");
        }
    }
}

// Usage
BuildToolRunner runner = new BuildToolRunner();
try {
    runner.runGitCommands();
    runner.runMavenBuild("clean", "compile", "test");
    // or
    // runner.runGradleBuild("clean", "build");
} catch (IOException e) {
    System.err.println("Build process failed: " + e.getMessage());
}

Actuator Integration

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.util.Properties;

// Generate build properties specifically for Spring Boot Actuator
public class ActuatorBuildInfoGenerator {
    
    public void generateForActuator(ProjectDetails projectDetails, File outputFile) throws IOException {
        // Ensure output directory exists
        outputFile.getParentFile().mkdirs();
        
        BuildPropertiesWriter writer = new BuildPropertiesWriter(outputFile);
        
        // Add actuator-specific properties
        Properties additional = projectDetails.getAdditional();
        
        // Health check information
        additional.put("build.health.check.url", "/actuator/health");
        additional.put("build.info.url", "/actuator/info");
        additional.put("build.metrics.url", "/actuator/metrics");
        
        // Build pipeline information
        String pipelineId = System.getenv("CI_PIPELINE_ID");
        if (pipelineId != null) {
            additional.put("build.pipeline.id", pipelineId);
        }
        
        String buildUrl = System.getenv("BUILD_URL");
        if (buildUrl != null) {
            additional.put("build.url", buildUrl);
        }
        
        // Application configuration
        additional.put("build.spring.boot.version", getSpringBootVersion());
        additional.put("build.spring.version", getSpringVersion());
        
        writer.writeBuildProperties(projectDetails);
        
        System.out.println("Actuator build info generated: " + outputFile.getAbsolutePath());
        System.out.println("Available at: /actuator/info");
    }
    
    private String getSpringBootVersion() {
        // Get Spring Boot version from classpath
        Package pkg = org.springframework.boot.SpringBootVersion.class.getPackage();
        return pkg != null ? pkg.getImplementationVersion() : "unknown";
    }
    
    private String getSpringVersion() {
        // Get Spring Framework version
        Package pkg = org.springframework.core.SpringVersion.class.getPackage();
        return pkg != null ? pkg.getImplementationVersion() : "unknown";
    }
}

Build Properties Validation

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;

// Validate generated build properties
public class BuildPropertiesValidator {
    
    public void validateBuildProperties(File buildPropertiesFile) throws IOException {
        if (!buildPropertiesFile.exists()) {
            throw new IOException("Build properties file not found: " + buildPropertiesFile);
        }
        
        Properties props = new Properties();
        try (FileInputStream fis = new FileInputStream(buildPropertiesFile)) {
            props.load(fis);
        }
        
        // Validate required properties
        validateRequired(props, "build.group", "Build group is required");
        validateRequired(props, "build.artifact", "Build artifact is required");
        validateRequired(props, "build.version", "Build version is required");
        validateRequired(props, "build.time", "Build time is required");
        
        // Validate property formats
        validateVersion(props.getProperty("build.version"));
        validateTime(props.getProperty("build.time"));
        
        System.out.println("Build properties validation passed");
        
        // Print summary
        System.out.println("Build Properties Summary:");
        System.out.println("========================");
        props.forEach((key, value) -> {
            if (key.toString().startsWith("build.")) {
                System.out.println(key + " = " + value);
            }
        });
    }
    
    private void validateRequired(Properties props, String key, String message) throws IOException {
        if (!props.containsKey(key) || props.getProperty(key).trim().isEmpty()) {
            throw new IOException(message + ": " + key);
        }
    }
    
    private void validateVersion(String version) throws IOException {
        if (version == null || !version.matches("\\d+\\.\\d+\\.\\d+.*")) {
            throw new IOException("Invalid version format: " + version);
        }
    }
    
    private void validateTime(String time) throws IOException {
        try {
            Instant.parse(time);
        } catch (Exception e) {
            throw new IOException("Invalid build time format: " + time, e);
        }
    }
}

Integration Patterns

Maven Plugin Integration

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <version>3.2.0</version>
    <executions>
        <execution>
            <goals>
                <goal>build-info</goal>
            </goals>
            <configuration>
                <additionalProperties>
                    <build.user>${user.name}</build.user>
                    <build.java.target>${maven.compiler.target}</build.java.target>
                    <build.maven.version>${maven.version}</build.maven.version>
                </additionalProperties>
            </configuration>
        </execution>
    </executions>
</plugin>

Gradle Plugin Integration

springBoot {
    buildInfo {
        properties {
            additional = [
                'build.user': System.getProperty('user.name'),
                'build.java.target': project.targetCompatibility,
                'build.gradle.version': gradle.gradleVersion
            ]
        }
    }
}

The build integration system provides comprehensive support for capturing and exposing build metadata, enabling better application monitoring, debugging, and operational visibility through Spring Boot's Actuator endpoints.

Install with Tessl CLI

npx tessl i tessl/maven-org-springframework-boot--spring-boot-loader-tools

docs

build-integration.md

image-packaging.md

index.md

jar-writing.md

launch-scripts.md

layer-support.md

layout-management.md

library-management.md

main-class-detection.md

repackaging.md

tile.json