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

library-management.mddocs/

Library Management

Comprehensive system for handling dependency libraries including scope classification, coordinate tracking, inclusion/exclusion logic, and integration with build tools. The library management system ensures proper dependency resolution and packaging for executable archives.

Capabilities

Library Representation

Core class representing a single library dependency with metadata and packaging instructions.

public class Library {
    /**
     * Create a library with basic file and scope information.
     * 
     * @param file the library JAR file
     * @param scope the library scope (COMPILE, RUNTIME, PROVIDED, CUSTOM)
     */
    public Library(File file, LibraryScope scope);
    
    /**
     * Create a library with complete metadata and packaging options.
     * 
     * @param name the library name (derived from file if null)
     * @param file the library JAR file
     * @param scope the library scope
     * @param coordinates the Maven/Gradle coordinates
     * @param unpackRequired whether the library needs to be unpacked
     * @param local whether this is a local/project library
     * @param included whether to include this library in the archive
     */
    public Library(String name, File file, LibraryScope scope, LibraryCoordinates coordinates, 
                   boolean unpackRequired, boolean local, boolean included);
    
    /**
     * Get the library name (typically the JAR filename without extension).
     * 
     * @return the library name
     */
    public String getName();
    
    /**
     * Get the library file.
     * 
     * @return the JAR file for this library
     */
    public File getFile();
    
    /**
     * Get the library scope.
     * 
     * @return the scope (COMPILE, RUNTIME, PROVIDED, CUSTOM)
     */
    public LibraryScope getScope();
    
    /**
     * Get the library coordinates (group:artifact:version).
     * 
     * @return the coordinates, or null if not available
     */
    public LibraryCoordinates getCoordinates();
    
    /**
     * Check if this library requires unpacking.
     * Some libraries need to be unpacked rather than included as nested JARs.
     * 
     * @return true if unpacking is required
     */
    public boolean isUnpackRequired();
    
    /**
     * Check if this is a local library (part of the project).
     * 
     * @return true if this is a local/project library
     */
    public boolean isLocal();
    
    /**
     * Check if this library should be included in the archive.
     * 
     * @return true if the library should be included
     */
    public boolean isIncluded();
}

Library Collections

Interface for providing collections of libraries to the packaging process.

public interface Libraries {
    /**
     * Process all libraries using the provided callback.
     * The callback is invoked once for each library that should be included.
     * 
     * @param callback the callback to process each library
     * @throws IOException if library processing fails
     */
    void doWithLibraries(LibraryCallback callback) throws IOException;
    
    /**
     * Empty libraries collection.
     */
    Libraries NONE = callback -> {
        // No libraries to process
    };
}

Library Processing

Callback interface for processing individual libraries during packaging.

@FunctionalInterface
public interface LibraryCallback {
    /**
     * Process a single library.
     * Called once for each library that should be included in the archive.
     * 
     * @param library the library to process
     * @throws IOException if library processing fails
     */
    void library(Library library) throws IOException;
}

Library Scopes

Interface defining the different scopes for library dependencies.

public interface LibraryScope {
    /**
     * Compile-time and runtime dependency.
     * Included in the final archive.
     */
    LibraryScope COMPILE = /* implementation */;
    
    /**
     * Runtime-only dependency.
     * Included in the final archive but not needed for compilation.
     */
    LibraryScope RUNTIME = /* implementation */;
    
    /**
     * Provided by the runtime environment.
     * Not included in the final archive.
     */
    LibraryScope PROVIDED = /* implementation */;
    
    /**
     * Custom scope with user-defined behavior.
     */
    LibraryScope CUSTOM = /* implementation */;
}

Library Coordinates

Interface for Maven/Gradle artifact coordinates providing metadata about library origins.

public interface LibraryCoordinates {
    /**
     * Get the group ID (Maven) or organization (Gradle).
     * 
     * @return the group ID
     */
    String getGroupId();
    
    /**
     * Get the artifact ID or module name.
     * 
     * @return the artifact ID
     */
    String getArtifactId();
    
    /**
     * Get the version string.
     * 
     * @return the version
     */
    String getVersion();
    
    /**
     * Create coordinates from individual components.
     * 
     * @param groupId the group ID
     * @param artifactId the artifact ID
     * @param version the version
     * @return new coordinates instance
     */
    static LibraryCoordinates of(String groupId, String artifactId, String version);
    
    /**
     * Convert coordinates to standard notation string (group:artifact:version).
     * 
     * @param coordinates the coordinates to convert
     * @return the standard notation string
     */
    static String toStandardNotationString(LibraryCoordinates coordinates);
}

Default Coordinates Implementation

public class DefaultLibraryCoordinates implements LibraryCoordinates {
    /**
     * Create coordinates with group, artifact, and version.
     * 
     * @param groupId the group ID
     * @param artifactId the artifact ID
     * @param version the version
     */
    public DefaultLibraryCoordinates(String groupId, String artifactId, String version);
}

Special Library Types

public class JarModeLibrary extends Library {
    /**
     * Special library for JAR mode support.
     * Provides tools functionality for JAR introspection and manipulation.
     */
    public static final JarModeLibrary TOOLS = /* implementation */;
}

Usage Examples

Basic Library Collection

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.util.List;

// Create a simple library collection
List<File> libraryFiles = List.of(
    new File("lib/spring-boot-3.2.0.jar"),
    new File("lib/spring-context-6.0.0.jar"),
    new File("lib/logback-classic-1.4.5.jar"),
    new File("lib/jackson-core-2.15.0.jar")
);

Libraries libraries = callback -> {
    for (File libFile : libraryFiles) {
        // Determine scope based on naming convention
        LibraryScope scope = libFile.getName().contains("test") 
            ? LibraryScope.PROVIDED 
            : LibraryScope.COMPILE;
        
        callback.library(new Library(libFile, scope));
    }
};

// Use with repackager
Repackager repackager = new Repackager(new File("myapp.jar"));
repackager.repackage(libraries);

Advanced Library Configuration

import org.springframework.boot.loader.tools.*;
import java.io.File;

// Create libraries with full metadata
Libraries libraries = callback -> {
    // Runtime dependency with coordinates
    LibraryCoordinates springCoords = LibraryCoordinates.of(
        "org.springframework", "spring-core", "6.0.0"
    );
    callback.library(new Library(
        "spring-core-6.0.0.jar",
        new File("lib/spring-core-6.0.0.jar"),
        LibraryScope.RUNTIME,
        springCoords,
        false, // no unpacking required
        false, // not local
        true   // include in archive
    ));
    
    // Local project dependency that needs unpacking
    callback.library(new Library(
        "my-custom-lib.jar",
        new File("build/libs/my-custom-lib.jar"),
        LibraryScope.COMPILE,
        LibraryCoordinates.of("com.example", "my-custom-lib", "1.0.0"),
        true,  // requires unpacking
        true,  // local library
        true   // include in archive
    ));
    
    // Provided dependency (excluded from final archive)
    callback.library(new Library(
        "servlet-api.jar",
        new File("provided/servlet-api.jar"),
        LibraryScope.PROVIDED,
        LibraryCoordinates.of("javax.servlet", "servlet-api", "3.1.0"),
        false, // no unpacking needed
        false, // not local
        false  // exclude from archive (provided by container)
    ));
};

Gradle Integration Example

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.util.Set;

// Example integration with Gradle dependency resolution
public class GradleLibraries implements Libraries {
    private final Set<File> compileClasspath;
    private final Set<File> runtimeClasspath;
    private final Set<File> providedClasspath;
    
    public GradleLibraries(Set<File> compileClasspath, Set<File> runtimeClasspath, Set<File> providedClasspath) {
        this.compileClasspath = compileClasspath;
        this.runtimeClasspath = runtimeClasspath;
        this.providedClasspath = providedClasspath;
    }
    
    @Override
    public void doWithLibraries(LibraryCallback callback) throws IOException {
        // Process compile dependencies
        for (File file : compileClasspath) {
            callback.library(new Library(file, LibraryScope.COMPILE));
        }
        
        // Process runtime-only dependencies
        for (File file : runtimeClasspath) {
            if (!compileClasspath.contains(file)) {
                callback.library(new Library(file, LibraryScope.RUNTIME));
            }
        }
        
        // Process provided dependencies (marked as excluded)
        for (File file : providedClasspath) {
            callback.library(new Library(
                file.getName(),
                file,
                LibraryScope.PROVIDED,
                null, // no coordinates
                false, false, false // exclude from archive
            ));
        }
    }
}

Maven Integration Example

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.util.List;

// Example integration with Maven dependency resolution
public class MavenLibraries implements Libraries {
    private final List<MavenArtifact> artifacts;
    
    public MavenLibraries(List<MavenArtifact> artifacts) {
        this.artifacts = artifacts;
    }
    
    @Override
    public void doWithLibraries(LibraryCallback callback) throws IOException {
        for (MavenArtifact artifact : artifacts) {
            LibraryScope scope = mapMavenScope(artifact.getScope());
            LibraryCoordinates coords = LibraryCoordinates.of(
                artifact.getGroupId(),
                artifact.getArtifactId(),
                artifact.getVersion()
            );
            
            boolean include = !LibraryScope.PROVIDED.equals(scope);
            
            callback.library(new Library(
                artifact.getFile().getName(),
                artifact.getFile(),
                scope,
                coords,
                artifact.requiresUnpacking(),
                artifact.isLocal(),
                include
            ));
        }
    }
    
    private LibraryScope mapMavenScope(String mavenScope) {
        switch (mavenScope) {
            case "compile": return LibraryScope.COMPILE;
            case "runtime": return LibraryScope.RUNTIME;
            case "provided": return LibraryScope.PROVIDED;
            case "test": return LibraryScope.PROVIDED; // exclude test deps
            default: return LibraryScope.CUSTOM;
        }
    }
}

Library Filtering and Transformation

import org.springframework.boot.loader.tools.*;
import java.io.File;
import java.util.function.Predicate;

// Wrapper for filtering libraries
public class FilteredLibraries implements Libraries {
    private final Libraries delegate;
    private final Predicate<Library> filter;
    
    public FilteredLibraries(Libraries delegate, Predicate<Library> filter) {
        this.delegate = delegate;
        this.filter = filter;
    }
    
    @Override
    public void doWithLibraries(LibraryCallback callback) throws IOException {
        delegate.doWithLibraries(library -> {
            if (filter.test(library)) {
                callback.library(library);
            }
        });
    }
}

// Usage examples
Libraries allLibraries = /* ... */;

// Only include compile and runtime libraries
Libraries filtered = new FilteredLibraries(allLibraries, library -> 
    LibraryScope.COMPILE.equals(library.getScope()) || 
    LibraryScope.RUNTIME.equals(library.getScope())
);

// Exclude snapshot versions
Libraries noSnapshots = new FilteredLibraries(allLibraries, library -> {
    LibraryCoordinates coords = library.getCoordinates();
    return coords == null || !coords.getVersion().contains("SNAPSHOT");
});

// Only local libraries
Libraries localOnly = new FilteredLibraries(allLibraries, Library::isLocal);

Library Inspection

import org.springframework.boot.loader.tools.*;
import java.io.IOException;

// Inspect libraries before packaging
public void inspectLibraries(Libraries libraries) throws IOException {
    System.out.println("Library Analysis:");
    System.out.println("==================");
    
    libraries.doWithLibraries(library -> {
        System.out.printf("Name: %s%n", library.getName());
        System.out.printf("  File: %s%n", library.getFile().getAbsolutePath());
        System.out.printf("  Scope: %s%n", library.getScope());
        System.out.printf("  Size: %,d bytes%n", library.getFile().length());
        System.out.printf("  Local: %s%n", library.isLocal());
        System.out.printf("  Included: %s%n", library.isIncluded());
        System.out.printf("  Unpack Required: %s%n", library.isUnpackRequired());
        
        LibraryCoordinates coords = library.getCoordinates();
        if (coords != null) {
            System.out.printf("  Coordinates: %s%n", 
                LibraryCoordinates.toStandardNotationString(coords));
        }
        System.out.println();
    });
}

JAR Mode Libraries

import org.springframework.boot.loader.tools.*;

// Include JAR mode tools for runtime introspection
Libraries librariesWithTools = callback -> {
    // Add your regular libraries
    // ... regular library processing ...
    
    // Add JAR mode tools for runtime capabilities
    callback.library(JarModeLibrary.TOOLS);
};

// Enable JAR mode in repackager
Repackager repackager = new Repackager(new File("myapp.jar"));
repackager.setIncludeRelevantJarModeJars(true);
repackager.repackage(librariesWithTools);

// The resulting JAR can be inspected at runtime:
// java -Djarmode=tools -jar myapp.jar

Library Processing Pipeline

The library management system processes dependencies through these stages:

  1. Collection: Libraries are gathered from build tools (Maven, Gradle) or custom sources
  2. Classification: Each library is assigned a scope (COMPILE, RUNTIME, PROVIDED, CUSTOM)
  3. Metadata Extraction: Coordinates and other metadata are collected
  4. Filtering: Libraries are filtered based on inclusion rules and scope policies
  5. Location Determination: The layout system determines where each library should be placed
  6. Packaging: Libraries are written to the appropriate locations in the archive

This pipeline ensures that only necessary dependencies are included while maintaining proper classpath organization for runtime execution.

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