The API for plugins - Mojos - development
—
Standardized logging interface for Maven plugins with support for debug, info, warn, and error levels. Integrates with Maven's output system and supports both message-only and message-with-throwable logging.
Main logging interface providing the standard Maven logging mechanism. Accepts CharSequence (not just String) for convenience and provides hierarchical log levels with enable/disable checking.
/**
* Logging interface for Maven plugins using standard Maven channels
*/
public interface Log {
/**
* Check if debug level is enabled
* @return true if debug messages will be output
*/
boolean isDebugEnabled();
/**
* Send debug message to user
* @param content message content (accepts CharSequence for convenience)
*/
void debug(CharSequence content);
/**
* Send debug message with exception to user
* @param content message content
* @param error exception whose stacktrace will be output
*/
void debug(CharSequence content, Throwable error);
/**
* Send exception to user at debug level
* @param error exception whose stacktrace will be output
*/
void debug(Throwable error);
/**
* Check if info level is enabled
* @return true if info messages will be output
*/
boolean isInfoEnabled();
/**
* Send info message to user
* @param content message content
*/
void info(CharSequence content);
/**
* Send info message with exception to user
* @param content message content
* @param error exception whose stacktrace will be output
*/
void info(CharSequence content, Throwable error);
/**
* Send exception to user at info level
* @param error exception whose stacktrace will be output
*/
void info(Throwable error);
/**
* Check if warn level is enabled
* @return true if warn messages will be output
*/
boolean isWarnEnabled();
/**
* Send warning message to user
* @param content message content
*/
void warn(CharSequence content);
/**
* Send warning message with exception to user
* @param content message content
* @param error exception whose stacktrace will be output
*/
void warn(CharSequence content, Throwable error);
/**
* Send exception to user at warn level
* @param error exception whose stacktrace will be output
*/
void warn(Throwable error);
/**
* Check if error level is enabled
* @return true if error messages will be output
*/
boolean isErrorEnabled();
/**
* Send error message to user
* @param content message content
*/
void error(CharSequence content);
/**
* Send error message with exception to user
* @param content message content
* @param error exception whose stacktrace will be output
*/
void error(CharSequence content, Throwable error);
/**
* Send exception to user at error level
* @param error exception whose stacktrace will be output
*/
void error(Throwable error);
}Usage Examples:
public class ExampleMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException {
Log log = getLog();
// Basic logging
log.info("Starting plugin execution");
log.debug("Debug mode enabled");
// Conditional logging to avoid expensive operations
if (log.isDebugEnabled()) {
log.debug("Processing files: " + files.stream()
.map(File::getName)
.collect(Collectors.joining(", ")));
}
// Logging with exceptions
try {
processFiles();
} catch (IOException e) {
log.error("Failed to process files", e);
throw new MojoExecutionException("Processing failed", e);
}
// Warning about deprecated usage
if (useDeprecatedOption) {
log.warn("The 'oldOption' parameter is deprecated. Use 'newOption' instead.");
}
// CharSequence support - can pass StringBuilder directly
StringBuilder report = new StringBuilder();
report.append("Processed ").append(fileCount).append(" files");
log.info(report);
}
}Default Log implementation that outputs to System.out and System.err. Used as fallback when no logger has been injected into the Mojo.
/**
* Default Log implementation using System.out and System.err streams
*/
public class SystemStreamLog implements Log {
// Debug level is disabled by default
// Info, warn, error levels are enabled by default
// Error messages go to System.err, others to System.out
}Characteristics:
System.errSystem.outAbstractMojo.getLog() when no logger is injectedLog implementation that bridges Maven Plugin API logging to Plexus logging system. Wraps a Plexus Logger and safely converts CharSequence to String. Located in package org.apache.maven.monitor.logging.
/**
* Log implementation bridging to Plexus logging (org.apache.maven.monitor.logging.DefaultLog)
*/
public class DefaultLog implements Log {
/**
* Create DefaultLog wrapping Plexus logger
* @param logger Plexus logger instance from org.codehaus.plexus.logging.Logger
*/
public DefaultLog(Logger logger);
}Features:
Debug Level: Detailed diagnostic information for plugin developers
log.debug("Analyzing file: " + file.getAbsolutePath());
log.debug("Configuration loaded: " + config.toString());
log.debug("Cache hit for key: " + cacheKey);Info Level: General information about plugin execution progress
log.info("Processing " + fileCount + " source files");
log.info("Generated " + outputFiles.size() + " output files");
log.info("Plugin execution completed successfully");Warn Level: Important issues that don't prevent execution
log.warn("No source files found in " + sourceDirectory);
log.warn("Parameter 'oldParam' is deprecated, use 'newParam' instead");
log.warn("Output file already exists and will be overwritten: " + outputFile);Error Level: Serious problems that may cause execution to fail
log.error("Failed to read configuration file: " + configFile);
log.error("Required dependency not found on classpath");
log.error("Unable to create output directory: " + outputDir);Always check if logging level is enabled before expensive operations:
// Good - avoids expensive string operations when debug is disabled
if (log.isDebugEnabled()) {
log.debug("Processing items: " + items.stream()
.map(Item::toString)
.collect(Collectors.joining(", ")));
}
// Bad - performs expensive operations even when debug is disabled
log.debug("Processing items: " + items.stream()
.map(Item::toString)
.collect(Collectors.joining(", ")));Include both message context and exception details:
try {
Files.copy(source, target);
} catch (IOException e) {
// Log the error with context
log.error("Failed to copy " + source + " to " + target, e);
// Then throw appropriate Mojo exception
throw new MojoExecutionException("File copy operation failed", e);
}Use consistent formatting for better readability:
// Good - consistent, structured format
log.info("=== Starting Code Generation ===");
log.info("Source directory: " + sourceDir);
log.info("Output directory: " + outputDir);
log.info("Template files: " + templateFiles.size());
// Process files...
log.info("=== Code Generation Complete ===");
log.info("Generated " + generatedCount + " files in " + duration + "ms");Take advantage of CharSequence support to avoid unnecessary string conversions:
// Can pass StringBuilder directly
StringBuilder message = new StringBuilder();
message.append("Processed ").append(count).append(" items");
log.info(message); // No need to call toString()
// StringBuffer also works
StringBuffer buffer = new StringBuffer();
buffer.append("Configuration: ").append(config.getName());
log.debug(buffer);Always use the injected Log interface instead of direct console output:
// Good - uses Maven logging system
getLog().info("Processing complete");
// Bad - bypasses Maven logging
System.out.println("Processing complete");Install with Tessl CLI
npx tessl i tessl/maven-org-apache-maven--maven-plugin-api