CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-apache-maven--maven-plugin-api

The API for plugins - Mojos - development

Pending
Overview
Eval results
Files

core-plugin-development.mddocs/

Core Plugin Development

Essential interfaces and base classes for creating Maven plugins. Provides the fundamental Mojo contract and ready-to-use AbstractMojo base class with logging and context support.

Capabilities

Mojo Interface

The main contract required for all Maven plugins to interact with the Maven infrastructure. Every plugin must implement this interface to define its execution behavior and integrate with Maven's logging system.

/**
 * Main contract for Maven plugins (Mojos) to interact with Maven infrastructure
 */
public interface Mojo {
    /** The component role hint for Plexus container */
    String ROLE = Mojo.class.getName();
    
    /**
     * Perform whatever build-process behavior this Mojo implements.
     * Main trigger for the Mojo inside the Maven system.
     * 
     * @throws MojoExecutionException if an unexpected problem occurs (BUILD ERROR)
     * @throws MojoFailureException if an expected problem occurs (BUILD FAILURE)
     */
    void execute() throws MojoExecutionException, MojoFailureException;
    
    /**
     * Inject a standard Maven logging mechanism
     * @param log a new logger
     */
    void setLog(Log log);
    
    /**
     * Get access to the Maven logging mechanism
     * @return logger for creating messages at debug, info, warn, and error levels
     */
    Log getLog();
}

AbstractMojo Class

Abstract base class that provides most infrastructure required to implement a Mojo except for the execute method. Includes built-in logging management with fallback to SystemStreamLog and plugin context support.

/**
 * Abstract class providing Mojo infrastructure except for execute method.
 * Use @Mojo annotation with goal name:
 * @Mojo(name = "<goal-name>")
 */
public abstract class AbstractMojo implements Mojo, ContextEnabled {
    
    /**
     * Set the logger for this Mojo
     * @param log the logger instance
     */
    public void setLog(Log log);
    
    /**
     * Get the logger, creating SystemStreamLog if none injected
     * @return logger instance, never null
     */
    public Log getLog();
    
    /**
     * Get the plugin container context
     * @return Map containing shared context data
     */
    public Map getPluginContext();
    
    /**
     * Set the plugin container context
     * @param pluginContext Map of shared context data
     */
    public void setPluginContext(Map pluginContext);
}

Usage Example:

import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;

/**
 * Example plugin demonstrating AbstractMojo usage
 * @goal process-files
 * @phase process-sources
 */
public class ProcessFilesMojo extends AbstractMojo {
    
    /**
     * Directory to process
     * @parameter property="processDir" default-value="${project.basedir}/src/main/resources"
     */
    private File processDirectory;
    
    /**
     * Skip processing
     * @parameter property="skip" default-value="false"
     */
    private boolean skip;
    
    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        if (skip) {
            getLog().info("Skipping file processing");
            return;
        }
        
        getLog().info("Processing files in: " + processDirectory);
        
        if (!processDirectory.exists()) {
            throw new MojoFailureException("Process directory does not exist: " + processDirectory);
        }
        
        try {
            // Your plugin logic here
            processFiles(processDirectory);
            getLog().info("File processing completed successfully");
        } catch (IOException e) {
            throw new MojoExecutionException("Failed to process files", e);
        }
    }
    
    private void processFiles(File directory) throws IOException {
        getLog().debug("Starting file processing in " + directory);
        // Implementation details...
    }
}

ContextEnabled Interface

Interface allowing Mojos to communicate with each other by sharing data through the plugin container context. The plugin manager populates the context before executing Mojos.

/**
 * Enables Mojos to share data with other Mojos beyond project's source root and attachments
 */
public interface ContextEnabled {
    /**
     * Set a new shared context Map to a mojo before executing it
     * @param pluginContext a new Map for sharing data
     */
    void setPluginContext(Map pluginContext);
    
    /**
     * Get the Map stored in the plugin container's context
     * @return Map containing shared context data
     */
    Map getPluginContext();
}

Usage Example:

public class DataProducerMojo extends AbstractMojo {
    @Override
    public void execute() throws MojoExecutionException {
        // Store data for other mojos
        getPluginContext().put("processedData", someProcessedData);
        getPluginContext().put("timestamp", System.currentTimeMillis());
    }
}

public class DataConsumerMojo extends AbstractMojo {
    @Override
    public void execute() throws MojoExecutionException {
        // Retrieve data from other mojos
        Object data = getPluginContext().get("processedData");
        Long timestamp = (Long) getPluginContext().get("timestamp");
        
        if (data != null) {
            getLog().info("Using data from previous mojo, created at: " + new Date(timestamp));
        }
    }
}

Mojo Annotations

When extending AbstractMojo, use these key annotations to configure your plugin:

@Mojo Annotation Attributes

@Mojo(
    name = "goal-name",                    // Required: Goal name users will invoke
    defaultPhase = LifecyclePhase.COMPILE, // Optional: Default lifecycle phase
    requiresDependencyResolution = ResolutionScope.COMPILE, // Optional: Dependency scope needed
    threadSafe = true                      // Optional: Can run in parallel builds
)

@Parameter Annotation

/**
 * @parameter property="propertyName" default-value="defaultValue"
 * @required
 */
private String configValue;

@Component Annotation

/**
 * @component
 */
private SomeComponent injectedComponent;

Error Handling Best Practices

  • Use MojoExecutionException for unexpected errors (system failures, I/O errors, etc.)
  • Use MojoFailureException for expected failures (validation errors, missing files that users should fix)
  • Always include meaningful error messages that help users understand what went wrong
  • Use the longMessage constructor for detailed error information in build output

Install with Tessl CLI

npx tessl i tessl/maven-org-apache-maven--maven-plugin-api

docs

core-plugin-development.md

exception-handling.md

index.md

logging-system.md

plugin-descriptors.md

tile.json