Custom maven plugin example

Maven has a lot of custom plugins build by people all over the world so searching for them on the web is always a first but it could be that you can’t find what you are looking for. In that case you can always write your own plugin. It is quite simple. Start of my creating a maven project based on the maven-archetype-mojo. Fill in your artifactId en groupId and you are good to go. My plugin is going to be one that displays a custom text as ascii art. Quite useless but funny. My project setup looks like this:
ascii-art-project
As you can see I have only 1 class and 1 test class. Let’s look at the class where all the magic happens.

package nl.redrock.maven.plugins.misc;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.image.BufferedImage;

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

/**
 * Goal which shows a cool ascii art at start of the run
 * 
 * @goal ascii
 * 
 */
public class AsciiArtMojo extends AbstractMojo {

	/**
	 * The string to print in ascii art
	 * 
	 * @parameter property="developerName" default-value="${project.artifactId}"
	 */
	private String developerName;

	@Override
	public void execute() throws MojoExecutionException, MojoFailureException {

		int width = 100;
		int height = 30;

		System.out.println("Building: \n");
		BufferedImage image = new BufferedImage(width, height,
				BufferedImage.TYPE_INT_RGB);
		Graphics g = image.getGraphics();
		g.setFont(new Font("Arial", Font.BOLD, 16));

		Graphics2D graphics = (Graphics2D) g;
		graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
				RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
		graphics.drawString(developerName, 10, 20);

		for (int y = 0; y < height; y++) {
			StringBuilder sb = new StringBuilder();
			for (int x = 0; x < width; x++) {

				sb.append(image.getRGB(x, y) == -16777216 ? " " : "$");

			}

			if (sb.toString().trim().isEmpty()) {
				continue;
			}

			System.out.println(sb);
		}

	}

	/**
	 * For testing purpose
	 * 
	 * @param designerDirectory
	 */
	public void setDeveloperName(String aName) {
		this.developerName = aName;
	}

}

As you can see the class has to extend AbstractMojo and override the execute method. In the class comment you can set the goal name, ascii in my case. You can also declare parameters which can be set in your plugin configuration in the project which will use your plugin:

	/**
	 * The string to print in ascii art
	 * 
	 * @parameter property="developerName" default-value="${project.artifactId}"
	 */
	private String developerName;

After this you can write a simple testcase to see if your plugin works like intended. I just wrote a simple testcase using junit which looks like this:

package nl.redrock.maven.plugins.misc;

import junit.framework.TestCase;
import nl.redrock.maven.plugins.misc.AsciiArtMojo;

import org.junit.Test;

public class AsciiArtMojoTest extends TestCase {
	
	@Test
	public void testMojo() throws Exception{
		AsciiArtMojo mojo = new AsciiArtMojo();
		mojo.setDeveloperName("RedRock");
		mojo.execute();
	}
}

When i run this test you hopefully will see the following:


-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running nl.redrock.maven.plugins.misc.AsciiArtMojoTest
Building: 

           $$$$$$$$$                  $$  $$$$$$$$$                      $$                         
           $$$$$$$$$$                 $$  $$$$$$$$$$                     $$                         
           $$    $$$$                 $$  $$    $$$$                     $$                         
           $$      $$   $$$$$    $$$$$$$  $$      $$   $$$$$$    $$$$$$  $$  $$$$                   
           $$    $$$$  $$$$$$$  $$$$$$$$  $$    $$$$  $$$$$$$$  $$$$$$$  $$ $$$$                    
           $$$$$$$$$$  $$$ $$$  $$$$$$$$  $$$$$$$$$$  $$$$$$$$  $$$$$$$  $$$$$$                     
           $$$$$$$$$   $$$$$$$  $$$  $$$  $$$$$$$$$   $$$  $$$  $$$      $$$$$                      
           $$ $$$$$$   $$$$$$$  $$    $$  $$ $$$$$$   $$    $$  $$       $$$$$$                     
           $$   $$$$   $$$      $$$  $$$  $$   $$$$   $$$  $$$  $$$      $$$$$$                     
           $$    $$$$  $$$$$$$  $$$$$$$$  $$    $$$$  $$$$$$$$  $$$$$$$  $$  $$$                    
           $$     $$$$ $$$$$$$  $$$$$$$$  $$     $$$$ $$$$$$$$  $$$$$$$  $$  $$$                    
           $$     $$$$  $$$$$    $$$$$$$  $$     $$$$  $$$$$$    $$$$$   $$   $$$                   
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.09 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

The pom file for the plugin is also quite simple. Something like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>nl.redrock.maven.plugins.misc</groupId>
	<artifactId>ascii-art-plugin</artifactId>
	<packaging>maven-plugin</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>Ascii Art plugin</name>

	<dependencies>
		<dependency>
			<groupId>org.apache.maven</groupId>
			<artifactId>maven-plugin-api</artifactId>
			<version>3.1.1</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.10</version>
			<type>jar</type>
			<scope>test</scope>
		</dependency>
	</dependencies>
</project>

Ok, the plugin is done now. The only thing we want to do is to install it so maven can find it in my repository next time I want to use it in one of my projects. This can be accomplished quite easily by running mvn clean install.

Now let’s make a new maven project and see if the plugin runs like we want it to. I created a simple maven project with a pom which looks like this:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>nl.redrock</groupId>
	<artifactId>plugintest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>plugintest</name>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>nl.redrock.maven.plugins.misc</groupId>
				<artifactId>ascii-art-plugin</artifactId>
				<version>1.0-SNAPSHOT</version>
				<executions>
					<execution>
						<phase>pre-clean</phase>
						<goals>
							<goal>ascii</goal>
						</goals>
					</execution>
				</executions>
				<configuration>
					<developerName>${artifactId}</developerName>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Lets look at the build plugins. You can see I declared my just uploaded plugin here and set the phase in which it should run on pre-clean. I also declared the goal and in the configuration part, I filled the property which will be printed as ascii art. In my case this will be the artifactId from the pom file. Ok…..time to see if it all works. Run mvn clean. The outcome should look this:

[INFO] Scanning for projects...
[WARNING] 
[WARNING] Some problems were encountered while building the effective model for nl.redrock:plugintest:jar:0.0.1-SNAPSHOT
[WARNING] The expression ${artifactId} is deprecated. Please use ${project.artifactId} instead.
[WARNING] 
[WARNING] It is highly recommended to fix these problems because they threaten the stability of your build.
[WARNING] 
[WARNING] For this reason, future Maven versions might no longer support building such malformed projects.
[WARNING] 
[INFO] 
[INFO] Using the builder org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder with a thread count of 1
[INFO]                                                                         
[INFO] ------------------------------------------------------------------------
[INFO] Building plugintest 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- ascii-art-plugin:1.0-SNAPSHOT:ascii (default) @ plugintest ---
Building: 

                     $$                      $$            $$                     $$                
                     $$                      $$            $$                     $$                
                     $$                                    $$                     $$                
           $$$$$$$   $$  $$    $$   $$$$$$$  $$  $$$$$$$$ $$$$$  $$$$$   $$$$$$$ $$$$$              
           $$$$$$$$  $$  $$    $$  $$$$$$$$  $$  $$$$$$$$ $$$$$ $$$$$$$  $$$$$$$ $$$$$              
           $$$$$$$$  $$  $$    $$  $$$$$$$$  $$  $$$$$$$$  $$   $$$ $$$  $$$ $$$  $$                
           $$$  $$$  $$  $$    $$  $$$  $$$  $$  $$$  $$$  $$   $$$$$$$  $$$$$$   $$                
           $$    $$  $$  $$    $$  $$    $$  $$  $$    $$  $$   $$$$$$$  $$$$$$$  $$                
           $$$  $$$  $$  $$$  $$$  $$$  $$$  $$  $$    $$  $$   $$$        $$$$$  $$                
           $$$$$$$$  $$  $$$$$$$$  $$$$$$$$  $$  $$    $$  $$$$ $$$$$$$  $$$ $$$  $$$$              
           $$$$$$$$  $$  $$$$$$$$  $$$$$$$$  $$  $$    $$  $$$$ $$$$$$$  $$$$$$$  $$$$              
           $$$$$$$   $$  $$$$$$$$   $$$$$$$  $$  $$    $$  $$$$  $$$$$   $$$$$$$  $$$$              
           $$                      $$$ $$$$                                                         
           $$                      $$$$$$$$                                                         
           $$                      $$$$$$$                                                          
[INFO] 
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ plugintest ---
[INFO] Deleting D:\Workspace\Java\plugintest\target
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 0.453 s
[INFO] Finished at: 2014-03-15T00:24:44+01:00
[INFO] Final Memory: 6M/154M
[INFO] ------------------------------------------------------------------------

Mission accomplished!

One Reply to “Custom maven plugin example”

  1. Pingback: Continuous Integration using Oracle Fusion Middleware 12C: Part 1 |

Leave a Reply

Your email address will not be published. Required fields are marked *

*

This site uses Akismet to reduce spam. Learn how your comment data is processed.