Context
Maven plugins are described in META-INF/maven/plugin.xml descriptor, which is in general generated by maven-plugin-plugin. Information for the generator are written as javadoc annotations in java source: see maven-plugin-tools-java.
Using java 5 annotations instead of javadoc ones have multiple benefits:
- compile-time checks for plugin metadata, with enums for some annotations
- inheritance support
- annotations are supported in most IDEs, providing code-completion and syntactic checks
see plexus-component-annotations for an example of such a work done on Plexus.
Existing implementations
Multiple implementations of such annotations exist:
- JFrog's Maven Anno Mojo: see the wiki or annotations source,
the idea is having as much annotations as actual javadoc annotations, each with only 1 attribute - Maven MNG-2521, with its proposal from 2007 providing a source branch and its annotations,
the idea is having only 4 annotations each with multiple attributes: Goal + Execute and Parameter + Component
Proposal
Continue the work started on MNG-2521 before plugin-tools extraction from Maven Core.
Annotations:
- 4 annotations: @Mojo and @Execute at class-level, @Parameter and @Component at field level
- java package: org.apache.maven.tools.plugin.annotations (consistent with maven-plugin-tools-api
- a new maven-plugin-tools-annotations component in plugin-tools
Extractor: addition into existing maven-plugin-tools-java
New features
- use annotations from parents classes coming from reactors and external dependencies.
Implementation
Initial work done in trunk http://svn.apache.org/repos/asf/maven/plugin-tools/trunk/
The maven-plugin-plugin version has been bump to 3.0-SNAPSHOT.
State of the development as of 22/5/2012
Following usage for a plugin developer is working, with annotations near previous javadoc tags:
import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.InstanciationStrategy; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; /** * Mojo Description. @Mojo( name = "<goalName>" ) is the minimal required annotation. * @since <since-text> * @deprecated <deprecated-text> */ @Mojo( name = "<goalName>", aggregator = <false|true>, configurator = "<roleHint>", executionStrategy = "<once-per-session|always>", inheritByDefault = <true|false>, instantiationStrategy = InstanciationStrategy.<strategy>, defaultPhase = "<phaseName>", requiresDependencyResolution = ResolutionScope.<scope>, requiresDependencyCollection = ResolutionScope.<scope>, // (since Maven 3.0) requiresDirectInvocation = <false|true>, requiresOnline = <false|true>, requiresProject = <true|false>, requiresReports = <false|true>, // (unsupported since Maven 3.0) threadSafe = <false|true> ) // (since Maven 3.0) @Execute( goal = "<goalName>", phase = LifecyclePhase.<phase> lifecycle = "<lifecycleId>" ) public class MyMojo extends AbstractMojo { /** * @since <since-text> * @deprecated <deprecated-text> */ @Parameter( alias = "myAlias", property = "aProperty", defaultValue = "${anExpression}", readonly = <false|true> required = <false|true> ) private String parameter; /** * @since <since-text> * @deprecated <deprecated-text> */ @Component( role = MyComponentExtension.class, roleHint = "..." ) private MyComponent component; public void execute() { ... } }
Improvement Idea HBO-1
rename roleHint to hint to match Plexus @Requirement
@Component( role = MyComponentExtension.class, hint = "..." ) private MyComponent component;
Improvement Idea HBO-2
Remove readonly attribute from @Parameter (was used for Maven components like ${project} to mark that it should not be configured by plugin user), and replace by a new attribute of @Component which is mutually exclusive with role+hint
@Component( expression = "project" ) private MavenProject project;
Improvement Idea HBO-3
Introduce JSR-330, by requiring plugin developer to mark injected fields with standard @Inject and make @Parameter and @Component standard Qualifier.
Costs more writing for plugin developer (these @Inject) without much win other than mark the intent in a standard way (and should change much for maven-plugin-tools)
/** * @since <since-text> * @deprecated <deprecated-text> */ @Inject @Parameter( alias = "myAlias", property = "aProperty", defaultValue = "${anExpression}", readonly = <false|true> required = <false|true> ) private String parameter; /** * @since <since-text> * @deprecated <deprecated-text> */ @Inject @Component( role = MyComponentExtension.class, roleHint = "..." ) private MyComponent component;