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

main-class-detection.mddocs/

Main Class Detection

Automatic discovery of classes with public static main methods using breadth-first search algorithms. The main class finder can analyze both directory structures and JAR files, with support for annotation-based filtering and validation.

Capabilities

Directory-Based Detection

Find main classes by scanning directory structures containing compiled Java classes.

public abstract class MainClassFinder {
    /**
     * Find the first main class in the given directory.
     * Uses breadth-first search to locate classes with public static main methods.
     * 
     * @param rootDirectory the root directory to search
     * @return the fully qualified name of the first main class found, or null if none found
     * @throws IOException if directory scanning fails
     */
    public static String findMainClass(File rootDirectory) throws IOException;
    
    /**
     * Find a single main class in the given directory.
     * Throws an exception if multiple main classes are found.
     * 
     * @param rootDirectory the root directory to search
     * @return the fully qualified name of the single main class
     * @throws IOException if directory scanning fails
     * @throws IllegalStateException if multiple main classes are found
     */
    public static String findSingleMainClass(File rootDirectory) throws IOException;
    
    /**
     * Find a single main class with a specific annotation.
     * Filters main classes to only include those with the specified annotation.
     * 
     * @param rootDirectory the root directory to search
     * @param annotationName the fully qualified annotation name to filter by
     * @return the fully qualified name of the annotated main class
     * @throws IOException if directory scanning fails
     * @throws IllegalStateException if multiple annotated main classes are found
     */
    public static String findSingleMainClass(File rootDirectory, String annotationName) throws IOException;
}

JAR-Based Detection

Find main classes by analyzing compiled classes within JAR files.

public abstract class MainClassFinder {
    /**
     * Find the first main class in the given JAR file.
     * Searches within the specified classes location inside the JAR.
     * 
     * @param jarFile the JAR file to search
     * @param classesLocation the location within the JAR where classes are stored (e.g., "BOOT-INF/classes/")
     * @return the fully qualified name of the first main class found, or null if none found
     * @throws IOException if JAR reading fails
     */
    public static String findMainClass(JarFile jarFile, String classesLocation) throws IOException;
    
    /**
     * Find a single main class in the given JAR file.
     * Throws an exception if multiple main classes are found.
     * 
     * @param jarFile the JAR file to search
     * @param classesLocation the location within the JAR where classes are stored
     * @return the fully qualified name of the single main class
     * @throws IOException if JAR reading fails
     * @throws IllegalStateException if multiple main classes are found
     */
    public static String findSingleMainClass(JarFile jarFile, String classesLocation) throws IOException;
    
    /**
     * Find a single main class with a specific annotation in a JAR file.
     * Filters main classes to only include those with the specified annotation.
     * 
     * @param jarFile the JAR file to search
     * @param classesLocation the location within the JAR where classes are stored
     * @param annotationName the fully qualified annotation name to filter by
     * @return the fully qualified name of the annotated main class
     * @throws IOException if JAR reading fails
     * @throws IllegalStateException if multiple annotated main classes are found
     */
    public static String findSingleMainClass(JarFile jarFile, String classesLocation, String annotationName) throws IOException;
}

Usage Examples

Basic Directory Scanning

import org.springframework.boot.loader.tools.MainClassFinder;
import java.io.File;
import java.io.IOException;

// Find any main class in the compiled classes directory
File classesDir = new File("target/classes");
try {
    String mainClass = MainClassFinder.findMainClass(classesDir);
    if (mainClass != null) {
        System.out.println("Found main class: " + mainClass);
    } else {
        System.out.println("No main class found");
    }
} catch (IOException e) {
    System.err.println("Error scanning directory: " + e.getMessage());
}

Single Main Class Detection

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

// Ensure only one main class exists
File classesDir = new File("target/classes");
try {
    String mainClass = MainClassFinder.findSingleMainClass(classesDir);
    System.out.println("Application main class: " + mainClass);
} catch (IllegalStateException e) {
    System.err.println("Multiple main classes found: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Error scanning directory: " + e.getMessage());
}

Annotation-Based Filtering

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

// Find main class with Spring Boot annotation
File classesDir = new File("target/classes");
try {
    String mainClass = MainClassFinder.findSingleMainClass(
        classesDir, 
        "org.springframework.boot.autoconfigure.SpringBootApplication"
    );
    System.out.println("Spring Boot main class: " + mainClass);
} catch (IllegalStateException e) {
    System.err.println("Multiple Spring Boot applications found: " + e.getMessage());
} catch (IOException e) {
    System.err.println("Error scanning directory: " + e.getMessage());
}

JAR File Analysis

import org.springframework.boot.loader.tools.MainClassFinder;
import java.io.File;
import java.util.jar.JarFile;

// Analyze an existing JAR file
File jarFile = new File("myapp.jar");
try (JarFile jar = new JarFile(jarFile)) {
    // Standard location for classes in a Spring Boot JAR
    String classesLocation = "BOOT-INF/classes/";
    
    String mainClass = MainClassFinder.findMainClass(jar, classesLocation);
    if (mainClass != null) {
        System.out.println("JAR main class: " + mainClass);
    }
    
    // For regular JAR files, classes are typically at the root
    String regularLocation = "";
    String regularMainClass = MainClassFinder.findMainClass(jar, regularLocation);
    if (regularMainClass != null) {
        System.out.println("Regular JAR main class: " + regularMainClass);
    }
} catch (IOException e) {
    System.err.println("Error reading JAR file: " + e.getMessage());
}

Integration with Repackaging

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

// Automatic main class detection during repackaging
File sourceJar = new File("myapp.jar");
Repackager repackager = new Repackager(sourceJar);

// Add timeout warning for main class detection
repackager.addMainClassTimeoutWarningListener((duration, mainClass) -> {
    if (duration.toSeconds() > 30) {
        System.out.println("Main class detection is taking longer than expected...");
    }
    if (mainClass == null) {
        System.err.println("Warning: No main class found after " + duration.toMillis() + "ms");
    } else {
        System.out.println("Detected main class: " + mainClass + " (took " + duration.toMillis() + "ms)");
    }
});

// Let repackager automatically detect main class
repackager.repackage(Libraries.NONE);

Manual Main Class Override

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

// Override automatic detection with explicit main class
File sourceJar = new File("myapp.jar");
Repackager repackager = new Repackager(sourceJar);

// Manually specify main class to skip detection
repackager.setMainClass("com.example.MyApplication");

// Repackage with specified main class
repackager.repackage(Libraries.NONE);

Search Algorithm

The main class finder uses a breadth-first search algorithm that:

  1. Scans class files in the target location (directory or JAR)
  2. Analyzes bytecode to identify classes with public static void main(String[] args) methods
  3. Filters by annotations when specified, checking class-level annotations
  4. Returns results in discovery order, with validation for single-class requirements
  5. Handles errors gracefully, continuing search even if individual class files are corrupted

The breadth-first approach ensures that classes in the root package are found before classes in nested packages, which typically aligns with application structure conventions.

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