SlideShare a Scribd company logo
1 of 9
HOW TO WRITE A NEW APACHE MAVEN PLUGIN
This tutorial explain how to create an Apache Maven 2.x plugin using Java 1.5 annotations.
Requirements:
Elipse IDE (optional)
Java 1.5 (or greater)
Apache Maven 2.x
Is assumed that the above tools are already installed and the reader have a minimum knowledge about them (in
particular with Maven).
Why this guide
I have written it during the development of my plugin as “collections of notes”.
It can be find at:
http://code.google.com/p/maven-properties-checker/
You could use it as example associated with this guide.
It won't be a replacement for the official documentations, but only a quick start with tips and tricks and clarify
some possible doubts of a beginner Maven plugin developer.
Base concepts
A Maven plugin is composed of one or more "unit" named Mojo, each one is mapped to a plugin goal.
In Maven terminology, a goal represents a specific task that can be bound to zero or more build phases.
If is not bound with a build phase, the plugin can be executed only invoking it directly.
The general sintax to invoke a specific plugin goal is:
mvn plugin-name:goal-name
It execute the Mojo owned by "plugin-name" and associated with goal named “goal-name”.
A Maven plugin is packaged as a JAR file.
At least, a plugin is composed of two Mojo : one that perform the plugin business logic, and one with the help page
(shown with mvn plugin-name:help).
The "help Mojo" can be generated in automatic (see below) so that the simplest Maven plugin can have only one
Mojo.
The Maven specifications require the presence of a plugin descriptor named plugin.xml and placed in the META-
INF/maven folder of the final JAR file.
Don't worry about it: will be generated in automatic using an existing Maven plugin that exploit your javadoc
comments placed in the Mojo class.
Steps to create your first plugin
Let's see the single steps necessary to create a plugin.
step 1) create a Maven project for the new plugin with:
mvn archetype:generate -DgroupId=property.maven.plugin -DartifactId=maven-property-checker -DarchetypeArtifactId=maven-archetype-mojo
Obviously "groupId" and "artifactId" variables should set with custom values according with requirements.
Follow the wizard providing the required informations (they can be modifyed after editing the pom.xml).
step 2) If the previous command was executed successfully, a folder named with the provided “artifactId” is
created. Also in the source folder a simple Mojo is created.
Now open the generated pom.xml file to apply some customizations.
a) As you can note, the previous command has already added the necessary dependency with this plugin:
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
<version>2.0</version>
</dependency>
don't modify it because offer the necessary API to create a Maven 2.0 plugin.
Inside the <dependencies> section add some new required dependencies:
<!-- A lightweight IOC container already used by Maven for dependency injection -->
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId>
<version>3.0.9</version>
</dependency>
<!-- Necessary to use Java 5 annotations in plugin Mojos (See below for more informations) -->
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<version>3.2</version>
<scope>provided</scope>
</dependency>
c) Inside the <plugins> section add this plugin:
<!-- Necessary to import the project in Eclipse -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
<!--
Plugin that create in auto the plugin.xml descriptor that will be placed under META-INF/maven folder
-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
<!-- Use a versione equal or greater to 3.0 to use java 5 annotation (See below for more info) -->
<version>3.2</version>
<configuration>
<!-- see http://jira.codehaus.org/browse/MNG-5346 -->
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
<executions>
<!-- This goal is used to generate in automatic the plugin descriptor -->
<execution>
<id>mojo-descriptor</id>
<goals>
<goal>descriptor</goal>
</goals>
</execution>
<!-- To generate in auto the Mojo associated at the help goal using your javadoc comments -->
<execution>
<id>help-goal</id>
<goals>
<goal>helpmojo</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- optional: add this plugin to use the "Modello" project (See dedicated section below for more info) -->
<plugin>
<groupId>org.codehaus.modello</groupId>
<artifactId>modello-maven-plugin</artifactId>
<version>1.7</version>
<!-- The location of the file with the Modello definitions -->
<configuration>
<models>
<model>src/main/mdo/checks.mdo</model>
</models>
<version>1.0.0</version>
</configuration>
<executions>
<!-- this phase will execute the goals "java" and "xpp3-reader" to create java bean and xpp reader object -->
<execution>
<id>myModel</id>
<phase>generate-sources</phase>
<goals>
<goal>java</goal>
<goal>xpp3-reader</goal>
</goals>
</execution>
<!-- During this phase will be executed the goals "xsd" which generate an XML Schema for the model -->
<execution>
<id>myModel-site-xsd</id>
<phase>pre-site</phase>
<goals>
<goal>xsd</goal>
</goals>
<configuration>
<!-- (optional) the folder where place the generated xsd -->
<outputDirectory>target/generated-site/resources/xsd</outputDirectory>
</configuration>
</execution>
<execution>
<id>myModel-site-doc</id>
<phase>pre-site</phase>
<goals>
<goal>xdoc</goal>
</goals>
</execution>
</executions>
</plugin>
step 3)
Create the Eclipse project so that when can develop in an IDE. Open the command line and execute:
mvn eclipse:clean eclipse:eclipse
Now import the project in Eclipse (File --> Import --> Existing project into workspace...)
step 4) Working inside Eclipse project, we can create our first Mojo and develop our plugin.
The creation command has created a simple Mojo that you can customize instead of create a new one, but
i suggest to create a new one to have a clean situation.
To create a Mojo, is necessary implements a class that extends "org.apache.maven.plugin.AbstractMojo" and implement
the "execute" method, which will contains the business logic of the Mojo.
The naming convention recommend to append the “Mojo” suffix at the class name.
The next two sections will explain how pass input parameters to a plugin and how bind a Mojo with a goal.
Plugin input parameters
At this point of the tutorial we have configured the plugin project in Eclipse and created a base Mojo.
The next step is understand how work the parameters injection system for plugin.
To use our new plugin is necessary that another Maven project declare the dependency in his pom.xml (ie using a
<plugin> block).
To pass input parameters at our plugin, that <plugin> block must contains a child node named <configuration> where
place that parameters.
For example, the pom.xml of the project that want use our plugin will contain:
<plugin>
<!-- group, artifactId, version of our plugin omitted for simplicity -->
<configuration>
<!-- Put here the input parameters for our plugin -->
</configuration>
</plugin>
The input parameters are injected in the plugin Mojo fields by Plexus framework (http://plexus.codehaus.org/) already
used by Maven for other tasks.
In order that the injection work correctly is necessary respect some rules and naming conventions in the Mojo and
in the above <configuration> block.
In the Mojo class is necessary mark the fields with custom annotations; this can be done using a java 5 or javadoc
style.
This tutorial focus on the use of java 5 annotations (for that reason is necessary use the plugin "maven-plugin-plugin"
with version greater 3.0 and declare the use of the plugin "maven-plugin-annotations").
Example:
suppose that our Mojo have that field:
@Parameter
private File verificationFile;
In the pom.xml the <configuration> block must be:
<plugin>
<!-- other plugin data omitted for simplicity -->
<configuration>
<verificationFile>
src/test/verifier/property-check-input.xml
</verificationFile>
</configuration>
</plugin>
As you can note, the Mojo field name is identical at the tag name inside the <configuration> block (ie
“verificationFile”). In this manner the field will be set to the value “src/test/verifier/property-check-input.xml” and you
can use it in the Mojo class (remember the setter method in your Mojo class).
Don't worry about the parameter type conversion, just assign the desired type at the field.
See: http://maven.apache.org/guides/plugin/guide-java-plugin-development.html for more examples with different parameters
type (eg. use a parameter with multiple values).
Is possible inject in a Mojo field also properties values already offered by Maven, not only custom values. For
example, we want the project base directory which is kept in the Maven property named "basedir", in that case we
have:
@Parameter (property = "basedir")
private File projectBasedir;
To pass that types of properties is not necessary add a tag in the <configuration> block (as above) but only annote
the field and provide the setter method.
See: https://cwiki.apache.org/MAVEN/java-5-annotations-for-plugins.html for more info about the available annotations.
Is possible provide a default value in case of a parameter is missing in the <configuration> block, for example:
@Parameter( property = "myFileld", defaultValue = "this is default value" )
private String myFileld;
Note: the javadoc comments that you place in the Mojo class and fields will be inserted in the plugin descriptor
(plugin.xml) by "maven-plugin-tools" plugin.
In case we want execute our Mojo by command line rather than invoke it from another project, as explained
above, the input prameters can be passed from the command line as "system property". In the source code is
necessary use the attribute "property" for the "parameter" annotation, for example:
@Parameter(property = "query.url")
private String myParameter;
To inject a value in the above parameter is necessary build the project using the the "-D" option followed by the
property name (ie “query.url”):
mvn clean package -Dquery.url=http://maven.apache.org
In case of more input parameters we have many -D<property-name>=<property-value> block.
Tip: the name of the system property can be different from the field name (ie “myParameter”) but is not a good
idea.
Annotation for the Mojo class
This section is about the annotations to use at class level in the Mojo.
For example:
@Mojo( name = "check" )
@Execute( goal = "verify", phase = LifecyclePhase.COMPILE)
public class PropertiesCheckerMojo extends AbstractMojo
{
//fields and methods omitted for simplicity
}
The class "PropertiesCheckerMojo" is a Mojo.
The attribute "name" of the @Mojo annotation define the name of the goal which the Mojo is associated (remember
that a Mojo is binded with a goal).
In the example above the Mojo named “check” is associated with the goal “verify”.
So that, to execute the above Mojo directly from the command line, the sintax is:
mvn <plugin-group-id>:<plugin-name>:<plugin-version>:check
Tip: that command can be shorted (See: http://maven.apache.org/guides/plugin/guide-java-plugin-development.html section
"Shortening the Command Line").
Or that command:
mvn <plugin-group-id>:<plugin-name>:<plugin-version>:help -Ddetail=true
executes the Mojo associated with the goal named "help" (remember that “help” Mojo is generated in automatic,
this means that there insn't the associate Mojo class in the plugin source tree).
The not mandatory option “-Ddetail=true” display also informations about Mojo input fields.
The “@Execute” annotation define also the Maven build lifecycle phase when the plugin (invoked by command line)
must be executed.
To invoke the plugin from another Maven project is necessary define his dependency and provide an <execution>
block to attach the goal of our plugin to a particular phase of the Maven build lifecycle.
So that when the user execute "mvn clean package install" will be executed the goal of our plugin, for example:
<plugin>
<groupId>property.maven.plugin</groupId>
<artifactId>maven-property-checker</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<configuration>
<verificationFile>src/test/verifier/property-check-input.xml</verificationFile>
</configuration>
</plugin>
Looking at the above code, the goal "check" of the plugin "maven-property-checker" is binded with the "compile" phase:
when that phase will be executed also our plugin goal will be executed too.
Use the Maven logging system
Inside our Mojo is possible use the logging system already provided by Maven to print messages in the console
during the execution.
To use it simply invoke the inherited "getLog" method, for example:
getLog().info("Hello world !");
Are also available others priority level (like log4j framework).
Apache Maven and Modello project
What is
Modello is a “Data Model toolkit” (http://modello.codehaus.org/) already used inside Maven.
It is used only during the build time of your project (not a runtime)
As input receives a model file (written with an xml-like sintax) and generates the Java pojo that respect it
structure (like Jaxb framework) .
Why use Modello instead of existing similar tools? because, as state of his web site, "Modello was created to
serve the needs of Apache Maven 2“.
When use it
Suppose that our plugin must receives in input many parameters that must be structured to
reflect a precise relation between elements.
Using the traditional <configuration> block is not applicable for obvious reasons.
The solution is pass in input an xml file and read it from the Mojo.
But must be validated and parsed to read his values ! This gap is filled by Modello.
If your plugin need only few not structerd parameters, Modello is not neccessary, is enough the
<configuration> block, so that you can skip this section.
How use it and how it works
a) In the plugin source code tree:
- Create a "model" file (.mdo) (see below) that describe the structure of the xml input file (think the .mdo file like
an XSD). Usually that file is placed in a folder named "src/main/mdo/checks.mdo".
- Configure the "modello-plugin" passing it the path of the .mdo file (See sections “Steps to create your first plugin”)
- Build your plugin (mvn clean package)
- During the build, Modello read the ".mdo" file and generates Java pojo that will be used to access at the input
xml from the Mojo. The pojo structure reflect the relations expressed in the .mdo file.
The generated pojo will be placed by default in the folder "target/generated-sources/modello" of the project source
tree (or in the one set inside <outputDirectory> configuration block of the modello-plugin).
That folder will be added in automatic as a source folder of the Eclipse project (press F5 to refresh the
workspace).
- Now in your Mojo we can use the Java pojo representing xml file content.
- Modello creates also a class that act as dedicated “reader” for the xml content (See below for example).
b) In the pom.xml of the project that uses our plugin:
- configure the dependency to our plugin and his <configuration> section providing the relative path at input xml:
<plugin>
<!-- out plugin data omitted for simplicity →
<configuration>
<!-- This is the input file that will be mapped to java pojo previously created by Modello using .mdo file -->
<verificationFile>src/test/verifier/property-check-input.xml</verificationFile>
</configuration>
.....
<plugin>
Obviously the provided xml file must be conform with the .mdo model, otherwise his content can't be mapped in
the previously generated java pojo and the build fail when our Mojo will be executed.
When you build the project and our plugin Mojo will be executed, the content of the provided xml file will be
mapped in automatic in the Java pojo contained in the plugin (previously generated by Modello) and our plugin
Mojo can read xml content and perform his business logic.
The xml reading is done using some readers generated by Modello when generates the pojo (See section “Using the
Modello readers from Mojo”).
An example Modello file
The following is a mdo file that describe the concept "a CheckBlock object has associated many Check".
Translating it in xml file, we have one ore more <checkBlock>, with one or more child <check> blocks.
<model>
<!-- unique identifier of this model (can be empty). -->
<id>propertty-checker-model</id>
<!-- the prefix assigned at the generated reader for xml input (In this case will be PropertyCheckerXpp3Reader.java) -->
<name>PropertyChecker</name>
<description>
A description for our model file
</description>
<!--
A list of many <default> block, each one is composed of <key><value> pair
The values allowed inside the <key> block must be contained in a default list
-->
<defaults>
<default>
<!-- this pair key-value specify the PACKAGE where put the generated java pojo
(NOTE: the folder that contains it is specified in the "Modello plugin " configuration)
-->
<key>package</key>
<value>org.apache.maven.plugin.verifier.model</value>
</default>
</defaults>
<!-- This section contains a set of <class> </class> blocks each one will be mapped in a java class -->
<classes>
<!-- The class that represents the most outer xml node must have the rootElement="true".
The"xml.tagName" attribute state the name of the xml tag map this object: use it in case of you want use a
java class name different from the xml tag name.
-->
<class rootElement="true" xml.tagName="propertyChecker">
<name>PropertyChecker</name>
<version>1.0.0</version>
<description>
Root element of the property checks file.
</description>
<!-- The fields are the child nodes of the element -->
<fields>
<field>
<name>checkBlocks</name>
<version>1.0.0</version>
<description>
<![CDATA[ A block the contains the file location an the checks to performs on it. ]]>
</description>
<!-- Means that this type is associated with another type -->
<association xml.itemsStyle="wrapped">
<!-- The type name CheckBlock is defined with another class (see below )-->
<type>CheckBlock</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
</class>
<!-- represents a "<checkBlock>" xml block -->
<class>
<name>CheckBlock</name>
<version>1.0.0</version>
<fields>
<field>
<name>checks</name>
<version>1.0.0</version>
<required>true</required>
<description>
<![CDATA[ The name of the check to apply at the properties file picked up from a default list ]]>
</description>
<association xml.itemsStyle="wrapped">
<!-- Means that there is an xml tag with named "check" enveloped inside a tag named "Checks" -->
<type>Check</type>
<multiplicity>*</multiplicity>
</association>
</field>
</fields>
</class>
<!-- Represents a "check" xml block -->
<class>
<name>Check</name>
<version>1.0.0</version>
<fields>
<field>
<name>checkName</name>
<version>1.0.0</version>
<required>true</required>
<description>
<![CDATA[ The field description ]]>
</description>
<!-- See http://modello.codehaus.org/Data+Model for supported data type -->
<type>String</type>
</field>
</fields>
</class>
</classes>
<model>
Note the attribute 'xml.itemsStyle="wrapped"' in the association. It means that the tag is enveloped in a tag with his
same name, but plural:
<checks>
<check>
....
</check>
....
</checks>
In case of a tag is not “enveloped”, use the option 'xml.itemsStyle="flat"'.
This is an example xml file compliant with the .mdo file describe above:
<propertyChecker>
<checkBlocks>
<checkBlock>
<checks>
<check>
<checkName>checkName1</checkName>
</check>
<check>
<checkName>checkName2</checkName>
</check>
</checks>
</checkBlock>
</checkBlocks>
</propertyChecker>
If you look at the Java pojo generated by Modello you should find a class like this:
public class CheckBlock {
private List<Checks> Check;
…....
}
This is the same concepts in the mdo file, but expressed with Java sintax.
See: http://modello.codehaus.org/Data+Model for more examples about model file.
Using the Modello readers from Mojo
Modello, together with the Java pojo, generates also an utility class that works as "java reader" for the xml input.
His name follow the naming convention <prefix>Xpp3Reader where <prefix> is the value of the tag <name> of the .mdo
file.
Suppose that our Mojo receives in input a File (field "verificationFile" in the example below) and we want read it:
......
// "verificationFile" is a file path passed to the Mojo with the <configuration> block
Reader reader = new FileReader(this.verificationFile);
//Using the reader class generated by Modello is possible access at the provided input file
PropertiesCheckerNameXpp3Reader xppReader = new PropertiesCheckerNameXpp3Reader();
// "PropertyChecker" is a pojo generated by Modello that corresponds at the most external tag in the input xml (ie <propertyChecker>)
PropertyChecker propertyChecker = xppReader.read( reader );
......
Now, using the "propertyChecker" getters methods, is possible access at the inner xml elements with an object
oriented manner.
External links
For more detailed informations about Maven plugin development, see:
http://docs.codehaus.org/display/MAVENUSER/Mojo+Developer+Cookbook
Author: fulvio999@gmail.com

More Related Content

What's hot

How to Webpack your Django!
How to Webpack your Django!How to Webpack your Django!
How to Webpack your Django!David Gibbons
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend DevelopersSergio Nakamura
 
An Introduction to Django Web Framework
An Introduction to Django Web FrameworkAn Introduction to Django Web Framework
An Introduction to Django Web FrameworkDavid Gibbons
 
Tellurium At Rich Web Experience2009
Tellurium At Rich Web Experience2009Tellurium At Rich Web Experience2009
Tellurium At Rich Web Experience2009John.Jian.Fang
 
Plug in development
Plug in developmentPlug in development
Plug in developmentLucky Ali
 
Tellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.TestingTellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.TestingJohn.Jian.Fang
 
Add Custom Model and ORM to Node.js
Add Custom Model and ORM to Node.jsAdd Custom Model and ORM to Node.js
Add Custom Model and ORM to Node.jsDev_Events
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Alessandro Molina
 
Automation Testing using Selenium Webdriver
Automation Testing using Selenium WebdriverAutomation Testing using Selenium Webdriver
Automation Testing using Selenium WebdriverPankaj Biswas
 
Ctools presentation
Ctools presentationCtools presentation
Ctools presentationDigitaria
 
Empowering users: modifying the admin experience
Empowering users: modifying the admin experienceEmpowering users: modifying the admin experience
Empowering users: modifying the admin experienceBeth Soderberg
 
Testing android apps with espresso
Testing android apps with espressoTesting android apps with espresso
Testing android apps with espressoÉdipo Souza
 
Working with AngularJS
Working with AngularJSWorking with AngularJS
Working with AngularJSAndré Vala
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java DevelopersJoonas Lehtinen
 
android training_material ravy ramio
android training_material ravy ramioandroid training_material ravy ramio
android training_material ravy ramioslesulvy
 
POLITEKNIK MALAYSIA
POLITEKNIK MALAYSIAPOLITEKNIK MALAYSIA
POLITEKNIK MALAYSIAAiman Hud
 

What's hot (20)

How to Webpack your Django!
How to Webpack your Django!How to Webpack your Django!
How to Webpack your Django!
 
Introduction to React for Frontend Developers
Introduction to React for Frontend DevelopersIntroduction to React for Frontend Developers
Introduction to React for Frontend Developers
 
An Introduction to Django Web Framework
An Introduction to Django Web FrameworkAn Introduction to Django Web Framework
An Introduction to Django Web Framework
 
Gwt portlet
Gwt portletGwt portlet
Gwt portlet
 
Tellurium At Rich Web Experience2009
Tellurium At Rich Web Experience2009Tellurium At Rich Web Experience2009
Tellurium At Rich Web Experience2009
 
Plug in development
Plug in developmentPlug in development
Plug in development
 
Tellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.TestingTellurium.A.New.Approach.For.Web.Testing
Tellurium.A.New.Approach.For.Web.Testing
 
Add Custom Model and ORM to Node.js
Add Custom Model and ORM to Node.jsAdd Custom Model and ORM to Node.js
Add Custom Model and ORM to Node.js
 
Extend sdk
Extend sdkExtend sdk
Extend sdk
 
Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2Rapid Prototyping with TurboGears2
Rapid Prototyping with TurboGears2
 
Jsf 2.0 in depth
Jsf 2.0 in depthJsf 2.0 in depth
Jsf 2.0 in depth
 
Automation Testing using Selenium Webdriver
Automation Testing using Selenium WebdriverAutomation Testing using Selenium Webdriver
Automation Testing using Selenium Webdriver
 
Ctools presentation
Ctools presentationCtools presentation
Ctools presentation
 
Empowering users: modifying the admin experience
Empowering users: modifying the admin experienceEmpowering users: modifying the admin experience
Empowering users: modifying the admin experience
 
Installing the java sdk
Installing the java sdkInstalling the java sdk
Installing the java sdk
 
Testing android apps with espresso
Testing android apps with espressoTesting android apps with espresso
Testing android apps with espresso
 
Working with AngularJS
Working with AngularJSWorking with AngularJS
Working with AngularJS
 
Web Components for Java Developers
Web Components for Java DevelopersWeb Components for Java Developers
Web Components for Java Developers
 
android training_material ravy ramio
android training_material ravy ramioandroid training_material ravy ramio
android training_material ravy ramio
 
POLITEKNIK MALAYSIA
POLITEKNIK MALAYSIAPOLITEKNIK MALAYSIA
POLITEKNIK MALAYSIA
 

Similar to How to Create an Apache Maven Plugin in Java

How to create a skeleton of a Java console application
How to create a skeleton of a Java console applicationHow to create a skeleton of a Java console application
How to create a skeleton of a Java console applicationDmitri Pisarenko
 
Java, Eclipse, Maven & JSF tutorial
Java, Eclipse, Maven & JSF tutorialJava, Eclipse, Maven & JSF tutorial
Java, Eclipse, Maven & JSF tutorialRaghavan Mohan
 
Maven, Eclipse and OSGi Working Together - Carlos Sanchez
Maven, Eclipse and OSGi Working Together - Carlos SanchezMaven, Eclipse and OSGi Working Together - Carlos Sanchez
Maven, Eclipse and OSGi Working Together - Carlos Sanchezmfrancis
 
Introduction to maven, its configuration, lifecycle and relationship to JS world
Introduction to maven, its configuration, lifecycle and relationship to JS worldIntroduction to maven, its configuration, lifecycle and relationship to JS world
Introduction to maven, its configuration, lifecycle and relationship to JS worldDmitry Bakaleinik
 
Java EE 7 Recipes
Java EE 7 RecipesJava EE 7 Recipes
Java EE 7 RecipesJosh Juneau
 
Maven 3… so what?
Maven 3… so what?Maven 3… so what?
Maven 3… so what?Abel Muíño
 
M2ModuleDevelopmenteBook
M2ModuleDevelopmenteBookM2ModuleDevelopmenteBook
M2ModuleDevelopmenteBookTrọng Huỳnh
 
How to-create-a-simple-module-in-magento-2.0
How to-create-a-simple-module-in-magento-2.0How to-create-a-simple-module-in-magento-2.0
How to-create-a-simple-module-in-magento-2.0Daniele Crupi
 
Write your first WordPress plugin
Write your first WordPress pluginWrite your first WordPress plugin
Write your first WordPress pluginAnthony Montalbano
 
Mageguru - magento custom module development
Mageguru -  magento custom module development Mageguru -  magento custom module development
Mageguru - magento custom module development Mage Guru
 
Creating Your First WordPress Plugin
Creating Your First WordPress PluginCreating Your First WordPress Plugin
Creating Your First WordPress PluginBrad Williams
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-AppsSelenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Appschrisb206 chrisb206
 
CQCON CQ Maven Methods
CQCON CQ Maven MethodsCQCON CQ Maven Methods
CQCON CQ Maven MethodsAndrew Savory
 
Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)Robert Scholte
 

Similar to How to Create an Apache Maven Plugin in Java (20)

How to create a skeleton of a Java console application
How to create a skeleton of a Java console applicationHow to create a skeleton of a Java console application
How to create a skeleton of a Java console application
 
Java, Eclipse, Maven & JSF tutorial
Java, Eclipse, Maven & JSF tutorialJava, Eclipse, Maven & JSF tutorial
Java, Eclipse, Maven & JSF tutorial
 
Maven, Eclipse and OSGi Working Together - Carlos Sanchez
Maven, Eclipse and OSGi Working Together - Carlos SanchezMaven, Eclipse and OSGi Working Together - Carlos Sanchez
Maven, Eclipse and OSGi Working Together - Carlos Sanchez
 
Introduction to maven, its configuration, lifecycle and relationship to JS world
Introduction to maven, its configuration, lifecycle and relationship to JS worldIntroduction to maven, its configuration, lifecycle and relationship to JS world
Introduction to maven, its configuration, lifecycle and relationship to JS world
 
Exploring Maven SVN GIT
Exploring Maven SVN GITExploring Maven SVN GIT
Exploring Maven SVN GIT
 
Java EE 7 Recipes
Java EE 7 RecipesJava EE 7 Recipes
Java EE 7 Recipes
 
Maven
MavenMaven
Maven
 
Using Maven2
Using Maven2Using Maven2
Using Maven2
 
Maven
MavenMaven
Maven
 
Maven 3… so what?
Maven 3… so what?Maven 3… so what?
Maven 3… so what?
 
M2ModuleDevelopmenteBook
M2ModuleDevelopmenteBookM2ModuleDevelopmenteBook
M2ModuleDevelopmenteBook
 
How to-create-a-simple-module-in-magento-2.0
How to-create-a-simple-module-in-magento-2.0How to-create-a-simple-module-in-magento-2.0
How to-create-a-simple-module-in-magento-2.0
 
Write your first WordPress plugin
Write your first WordPress pluginWrite your first WordPress plugin
Write your first WordPress plugin
 
Mageguru - magento custom module development
Mageguru -  magento custom module development Mageguru -  magento custom module development
Mageguru - magento custom module development
 
Creating Your First WordPress Plugin
Creating Your First WordPress PluginCreating Your First WordPress Plugin
Creating Your First WordPress Plugin
 
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-AppsSelenium-Browser-Based-Automated-Testing-for-Grails-Apps
Selenium-Browser-Based-Automated-Testing-for-Grails-Apps
 
Maven Introduction
Maven IntroductionMaven Introduction
Maven Introduction
 
CQ Maven Methods
CQ Maven MethodsCQ Maven Methods
CQ Maven Methods
 
CQCON CQ Maven Methods
CQCON CQ Maven MethodsCQCON CQ Maven Methods
CQCON CQ Maven Methods
 
Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)Apache Maven supports all Java (JokerConf 2018)
Apache Maven supports all Java (JokerConf 2018)
 

Recently uploaded

Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Commit University
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clashcharlottematthew16
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Mattias Andersson
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Enterprise Knowledge
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupFlorian Wilhelm
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 

Recently uploaded (20)

Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!Nell’iperspazio con Rocket: il Framework Web di Rust!
Nell’iperspazio con Rocket: il Framework Web di Rust!
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Powerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time ClashPowerpoint exploring the locations used in television show Time Clash
Powerpoint exploring the locations used in television show Time Clash
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?Are Multi-Cloud and Serverless Good or Bad?
Are Multi-Cloud and Serverless Good or Bad?
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024Designing IA for AI - Information Architecture Conference 2024
Designing IA for AI - Information Architecture Conference 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
Streamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project SetupStreamlining Python Development: A Guide to a Modern Project Setup
Streamlining Python Development: A Guide to a Modern Project Setup
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 

How to Create an Apache Maven Plugin in Java

  • 1. HOW TO WRITE A NEW APACHE MAVEN PLUGIN This tutorial explain how to create an Apache Maven 2.x plugin using Java 1.5 annotations. Requirements: Elipse IDE (optional) Java 1.5 (or greater) Apache Maven 2.x Is assumed that the above tools are already installed and the reader have a minimum knowledge about them (in particular with Maven). Why this guide I have written it during the development of my plugin as “collections of notes”. It can be find at: http://code.google.com/p/maven-properties-checker/ You could use it as example associated with this guide. It won't be a replacement for the official documentations, but only a quick start with tips and tricks and clarify some possible doubts of a beginner Maven plugin developer. Base concepts A Maven plugin is composed of one or more "unit" named Mojo, each one is mapped to a plugin goal. In Maven terminology, a goal represents a specific task that can be bound to zero or more build phases. If is not bound with a build phase, the plugin can be executed only invoking it directly. The general sintax to invoke a specific plugin goal is: mvn plugin-name:goal-name It execute the Mojo owned by "plugin-name" and associated with goal named “goal-name”. A Maven plugin is packaged as a JAR file. At least, a plugin is composed of two Mojo : one that perform the plugin business logic, and one with the help page (shown with mvn plugin-name:help). The "help Mojo" can be generated in automatic (see below) so that the simplest Maven plugin can have only one Mojo. The Maven specifications require the presence of a plugin descriptor named plugin.xml and placed in the META- INF/maven folder of the final JAR file. Don't worry about it: will be generated in automatic using an existing Maven plugin that exploit your javadoc comments placed in the Mojo class. Steps to create your first plugin Let's see the single steps necessary to create a plugin. step 1) create a Maven project for the new plugin with: mvn archetype:generate -DgroupId=property.maven.plugin -DartifactId=maven-property-checker -DarchetypeArtifactId=maven-archetype-mojo Obviously "groupId" and "artifactId" variables should set with custom values according with requirements. Follow the wizard providing the required informations (they can be modifyed after editing the pom.xml). step 2) If the previous command was executed successfully, a folder named with the provided “artifactId” is created. Also in the source folder a simple Mojo is created. Now open the generated pom.xml file to apply some customizations.
  • 2. a) As you can note, the previous command has already added the necessary dependency with this plugin: <dependency> <groupId>org.apache.maven</groupId> <artifactId>maven-plugin-api</artifactId> <version>2.0</version> </dependency> don't modify it because offer the necessary API to create a Maven 2.0 plugin. Inside the <dependencies> section add some new required dependencies: <!-- A lightweight IOC container already used by Maven for dependency injection --> <dependency> <groupId>org.codehaus.plexus</groupId> <artifactId>plexus-utils</artifactId> <version>3.0.9</version> </dependency> <!-- Necessary to use Java 5 annotations in plugin Mojos (See below for more informations) --> <dependency> <groupId>org.apache.maven.plugin-tools</groupId> <artifactId>maven-plugin-annotations</artifactId> <version>3.2</version> <scope>provided</scope> </dependency> c) Inside the <plugins> section add this plugin: <!-- Necessary to import the project in Eclipse --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-eclipse-plugin</artifactId> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin> <!-- Plugin that create in auto the plugin.xml descriptor that will be placed under META-INF/maven folder --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-plugin-plugin</artifactId> <!-- Use a versione equal or greater to 3.0 to use java 5 annotation (See below for more info) --> <version>3.2</version> <configuration> <!-- see http://jira.codehaus.org/browse/MNG-5346 --> <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound> </configuration> <executions> <!-- This goal is used to generate in automatic the plugin descriptor --> <execution> <id>mojo-descriptor</id> <goals> <goal>descriptor</goal> </goals> </execution> <!-- To generate in auto the Mojo associated at the help goal using your javadoc comments --> <execution> <id>help-goal</id> <goals> <goal>helpmojo</goal> </goals> </execution> </executions> </plugin>
  • 3. <!-- optional: add this plugin to use the "Modello" project (See dedicated section below for more info) --> <plugin> <groupId>org.codehaus.modello</groupId> <artifactId>modello-maven-plugin</artifactId> <version>1.7</version> <!-- The location of the file with the Modello definitions --> <configuration> <models> <model>src/main/mdo/checks.mdo</model> </models> <version>1.0.0</version> </configuration> <executions> <!-- this phase will execute the goals "java" and "xpp3-reader" to create java bean and xpp reader object --> <execution> <id>myModel</id> <phase>generate-sources</phase> <goals> <goal>java</goal> <goal>xpp3-reader</goal> </goals> </execution> <!-- During this phase will be executed the goals "xsd" which generate an XML Schema for the model --> <execution> <id>myModel-site-xsd</id> <phase>pre-site</phase> <goals> <goal>xsd</goal> </goals> <configuration> <!-- (optional) the folder where place the generated xsd --> <outputDirectory>target/generated-site/resources/xsd</outputDirectory> </configuration> </execution> <execution> <id>myModel-site-doc</id> <phase>pre-site</phase> <goals> <goal>xdoc</goal> </goals> </execution> </executions> </plugin> step 3) Create the Eclipse project so that when can develop in an IDE. Open the command line and execute: mvn eclipse:clean eclipse:eclipse Now import the project in Eclipse (File --> Import --> Existing project into workspace...) step 4) Working inside Eclipse project, we can create our first Mojo and develop our plugin. The creation command has created a simple Mojo that you can customize instead of create a new one, but i suggest to create a new one to have a clean situation. To create a Mojo, is necessary implements a class that extends "org.apache.maven.plugin.AbstractMojo" and implement the "execute" method, which will contains the business logic of the Mojo. The naming convention recommend to append the “Mojo” suffix at the class name. The next two sections will explain how pass input parameters to a plugin and how bind a Mojo with a goal. Plugin input parameters At this point of the tutorial we have configured the plugin project in Eclipse and created a base Mojo. The next step is understand how work the parameters injection system for plugin. To use our new plugin is necessary that another Maven project declare the dependency in his pom.xml (ie using a <plugin> block). To pass input parameters at our plugin, that <plugin> block must contains a child node named <configuration> where place that parameters. For example, the pom.xml of the project that want use our plugin will contain: <plugin> <!-- group, artifactId, version of our plugin omitted for simplicity --> <configuration> <!-- Put here the input parameters for our plugin -->
  • 4. </configuration> </plugin> The input parameters are injected in the plugin Mojo fields by Plexus framework (http://plexus.codehaus.org/) already used by Maven for other tasks. In order that the injection work correctly is necessary respect some rules and naming conventions in the Mojo and in the above <configuration> block. In the Mojo class is necessary mark the fields with custom annotations; this can be done using a java 5 or javadoc style. This tutorial focus on the use of java 5 annotations (for that reason is necessary use the plugin "maven-plugin-plugin" with version greater 3.0 and declare the use of the plugin "maven-plugin-annotations"). Example: suppose that our Mojo have that field: @Parameter private File verificationFile; In the pom.xml the <configuration> block must be: <plugin> <!-- other plugin data omitted for simplicity --> <configuration> <verificationFile> src/test/verifier/property-check-input.xml </verificationFile> </configuration> </plugin> As you can note, the Mojo field name is identical at the tag name inside the <configuration> block (ie “verificationFile”). In this manner the field will be set to the value “src/test/verifier/property-check-input.xml” and you can use it in the Mojo class (remember the setter method in your Mojo class). Don't worry about the parameter type conversion, just assign the desired type at the field. See: http://maven.apache.org/guides/plugin/guide-java-plugin-development.html for more examples with different parameters type (eg. use a parameter with multiple values). Is possible inject in a Mojo field also properties values already offered by Maven, not only custom values. For example, we want the project base directory which is kept in the Maven property named "basedir", in that case we have: @Parameter (property = "basedir") private File projectBasedir; To pass that types of properties is not necessary add a tag in the <configuration> block (as above) but only annote the field and provide the setter method. See: https://cwiki.apache.org/MAVEN/java-5-annotations-for-plugins.html for more info about the available annotations. Is possible provide a default value in case of a parameter is missing in the <configuration> block, for example: @Parameter( property = "myFileld", defaultValue = "this is default value" ) private String myFileld; Note: the javadoc comments that you place in the Mojo class and fields will be inserted in the plugin descriptor (plugin.xml) by "maven-plugin-tools" plugin. In case we want execute our Mojo by command line rather than invoke it from another project, as explained above, the input prameters can be passed from the command line as "system property". In the source code is necessary use the attribute "property" for the "parameter" annotation, for example: @Parameter(property = "query.url") private String myParameter;
  • 5. To inject a value in the above parameter is necessary build the project using the the "-D" option followed by the property name (ie “query.url”): mvn clean package -Dquery.url=http://maven.apache.org In case of more input parameters we have many -D<property-name>=<property-value> block. Tip: the name of the system property can be different from the field name (ie “myParameter”) but is not a good idea. Annotation for the Mojo class This section is about the annotations to use at class level in the Mojo. For example: @Mojo( name = "check" ) @Execute( goal = "verify", phase = LifecyclePhase.COMPILE) public class PropertiesCheckerMojo extends AbstractMojo { //fields and methods omitted for simplicity } The class "PropertiesCheckerMojo" is a Mojo. The attribute "name" of the @Mojo annotation define the name of the goal which the Mojo is associated (remember that a Mojo is binded with a goal). In the example above the Mojo named “check” is associated with the goal “verify”. So that, to execute the above Mojo directly from the command line, the sintax is: mvn <plugin-group-id>:<plugin-name>:<plugin-version>:check Tip: that command can be shorted (See: http://maven.apache.org/guides/plugin/guide-java-plugin-development.html section "Shortening the Command Line"). Or that command: mvn <plugin-group-id>:<plugin-name>:<plugin-version>:help -Ddetail=true executes the Mojo associated with the goal named "help" (remember that “help” Mojo is generated in automatic, this means that there insn't the associate Mojo class in the plugin source tree). The not mandatory option “-Ddetail=true” display also informations about Mojo input fields. The “@Execute” annotation define also the Maven build lifecycle phase when the plugin (invoked by command line) must be executed. To invoke the plugin from another Maven project is necessary define his dependency and provide an <execution> block to attach the goal of our plugin to a particular phase of the Maven build lifecycle. So that when the user execute "mvn clean package install" will be executed the goal of our plugin, for example: <plugin> <groupId>property.maven.plugin</groupId> <artifactId>maven-property-checker</artifactId> <version>1.0-SNAPSHOT</version> <executions> <execution> <phase>compile</phase> <goals> <goal>check</goal> </goals> </execution> </executions> <configuration> <verificationFile>src/test/verifier/property-check-input.xml</verificationFile> </configuration> </plugin> Looking at the above code, the goal "check" of the plugin "maven-property-checker" is binded with the "compile" phase: when that phase will be executed also our plugin goal will be executed too.
  • 6. Use the Maven logging system Inside our Mojo is possible use the logging system already provided by Maven to print messages in the console during the execution. To use it simply invoke the inherited "getLog" method, for example: getLog().info("Hello world !"); Are also available others priority level (like log4j framework). Apache Maven and Modello project What is Modello is a “Data Model toolkit” (http://modello.codehaus.org/) already used inside Maven. It is used only during the build time of your project (not a runtime) As input receives a model file (written with an xml-like sintax) and generates the Java pojo that respect it structure (like Jaxb framework) . Why use Modello instead of existing similar tools? because, as state of his web site, "Modello was created to serve the needs of Apache Maven 2“. When use it Suppose that our plugin must receives in input many parameters that must be structured to reflect a precise relation between elements. Using the traditional <configuration> block is not applicable for obvious reasons. The solution is pass in input an xml file and read it from the Mojo. But must be validated and parsed to read his values ! This gap is filled by Modello. If your plugin need only few not structerd parameters, Modello is not neccessary, is enough the <configuration> block, so that you can skip this section. How use it and how it works a) In the plugin source code tree: - Create a "model" file (.mdo) (see below) that describe the structure of the xml input file (think the .mdo file like an XSD). Usually that file is placed in a folder named "src/main/mdo/checks.mdo". - Configure the "modello-plugin" passing it the path of the .mdo file (See sections “Steps to create your first plugin”) - Build your plugin (mvn clean package) - During the build, Modello read the ".mdo" file and generates Java pojo that will be used to access at the input xml from the Mojo. The pojo structure reflect the relations expressed in the .mdo file. The generated pojo will be placed by default in the folder "target/generated-sources/modello" of the project source tree (or in the one set inside <outputDirectory> configuration block of the modello-plugin). That folder will be added in automatic as a source folder of the Eclipse project (press F5 to refresh the workspace). - Now in your Mojo we can use the Java pojo representing xml file content. - Modello creates also a class that act as dedicated “reader” for the xml content (See below for example). b) In the pom.xml of the project that uses our plugin: - configure the dependency to our plugin and his <configuration> section providing the relative path at input xml: <plugin> <!-- out plugin data omitted for simplicity → <configuration> <!-- This is the input file that will be mapped to java pojo previously created by Modello using .mdo file --> <verificationFile>src/test/verifier/property-check-input.xml</verificationFile> </configuration> ..... <plugin> Obviously the provided xml file must be conform with the .mdo model, otherwise his content can't be mapped in the previously generated java pojo and the build fail when our Mojo will be executed. When you build the project and our plugin Mojo will be executed, the content of the provided xml file will be
  • 7. mapped in automatic in the Java pojo contained in the plugin (previously generated by Modello) and our plugin Mojo can read xml content and perform his business logic. The xml reading is done using some readers generated by Modello when generates the pojo (See section “Using the Modello readers from Mojo”). An example Modello file The following is a mdo file that describe the concept "a CheckBlock object has associated many Check". Translating it in xml file, we have one ore more <checkBlock>, with one or more child <check> blocks. <model> <!-- unique identifier of this model (can be empty). --> <id>propertty-checker-model</id> <!-- the prefix assigned at the generated reader for xml input (In this case will be PropertyCheckerXpp3Reader.java) --> <name>PropertyChecker</name> <description> A description for our model file </description> <!-- A list of many <default> block, each one is composed of <key><value> pair The values allowed inside the <key> block must be contained in a default list --> <defaults> <default> <!-- this pair key-value specify the PACKAGE where put the generated java pojo (NOTE: the folder that contains it is specified in the "Modello plugin " configuration) --> <key>package</key> <value>org.apache.maven.plugin.verifier.model</value> </default> </defaults> <!-- This section contains a set of <class> </class> blocks each one will be mapped in a java class --> <classes> <!-- The class that represents the most outer xml node must have the rootElement="true". The"xml.tagName" attribute state the name of the xml tag map this object: use it in case of you want use a java class name different from the xml tag name. --> <class rootElement="true" xml.tagName="propertyChecker"> <name>PropertyChecker</name> <version>1.0.0</version> <description> Root element of the property checks file. </description> <!-- The fields are the child nodes of the element --> <fields> <field> <name>checkBlocks</name> <version>1.0.0</version> <description> <![CDATA[ A block the contains the file location an the checks to performs on it. ]]> </description> <!-- Means that this type is associated with another type --> <association xml.itemsStyle="wrapped"> <!-- The type name CheckBlock is defined with another class (see below )--> <type>CheckBlock</type> <multiplicity>*</multiplicity> </association> </field> </fields> </class> <!-- represents a "<checkBlock>" xml block --> <class> <name>CheckBlock</name> <version>1.0.0</version> <fields> <field> <name>checks</name> <version>1.0.0</version> <required>true</required> <description> <![CDATA[ The name of the check to apply at the properties file picked up from a default list ]]> </description> <association xml.itemsStyle="wrapped"> <!-- Means that there is an xml tag with named "check" enveloped inside a tag named "Checks" --> <type>Check</type> <multiplicity>*</multiplicity> </association> </field> </fields> </class>
  • 8. <!-- Represents a "check" xml block --> <class> <name>Check</name> <version>1.0.0</version> <fields> <field> <name>checkName</name> <version>1.0.0</version> <required>true</required> <description> <![CDATA[ The field description ]]> </description> <!-- See http://modello.codehaus.org/Data+Model for supported data type --> <type>String</type> </field> </fields> </class> </classes> <model> Note the attribute 'xml.itemsStyle="wrapped"' in the association. It means that the tag is enveloped in a tag with his same name, but plural: <checks> <check> .... </check> .... </checks> In case of a tag is not “enveloped”, use the option 'xml.itemsStyle="flat"'. This is an example xml file compliant with the .mdo file describe above: <propertyChecker> <checkBlocks> <checkBlock> <checks> <check> <checkName>checkName1</checkName> </check> <check> <checkName>checkName2</checkName> </check> </checks> </checkBlock> </checkBlocks> </propertyChecker> If you look at the Java pojo generated by Modello you should find a class like this: public class CheckBlock { private List<Checks> Check; ….... } This is the same concepts in the mdo file, but expressed with Java sintax. See: http://modello.codehaus.org/Data+Model for more examples about model file. Using the Modello readers from Mojo Modello, together with the Java pojo, generates also an utility class that works as "java reader" for the xml input. His name follow the naming convention <prefix>Xpp3Reader where <prefix> is the value of the tag <name> of the .mdo file. Suppose that our Mojo receives in input a File (field "verificationFile" in the example below) and we want read it: ...... // "verificationFile" is a file path passed to the Mojo with the <configuration> block Reader reader = new FileReader(this.verificationFile); //Using the reader class generated by Modello is possible access at the provided input file
  • 9. PropertiesCheckerNameXpp3Reader xppReader = new PropertiesCheckerNameXpp3Reader(); // "PropertyChecker" is a pojo generated by Modello that corresponds at the most external tag in the input xml (ie <propertyChecker>) PropertyChecker propertyChecker = xppReader.read( reader ); ...... Now, using the "propertyChecker" getters methods, is possible access at the inner xml elements with an object oriented manner. External links For more detailed informations about Maven plugin development, see: http://docs.codehaus.org/display/MAVENUSER/Mojo+Developer+Cookbook Author: fulvio999@gmail.com