Section 6.1. Writing a Simple JAR Execution Plug-in


6.1. Writing a Simple JAR Execution Plug-in

In this lab you'll write a plug-in which can run an executable JAR. This is a simple plug-in that should get you started with the basics of plug-in writing.

6.1.1. How do I do that?

The first thing to know is that a Maven plug-in is just another Maven project; any plug-in project will have the same structure as a normal Maven project: a project.xml file, a project.properties file, documentation in an xdocs/ directory, etc. The only difference with a standard Maven project is that the project.xml file should not reference elements defined in a parent Project Object Model (POM). This is because the parent POM is not included when the plug-in is deployed and the referenced elements won't be found at execution time. Of course this doesn't matter if the reference elements are not used by the plug-in at runtime.

In addition to these standard Maven files, a plug-in project has two specific files, as shown in Figure 6-1:


Note: Minimize references to parent POMs in a plug-in's project.xml file.

plugin.jelly

This file defines a plug-in's goals, and it is where you will put all the plug-in logic in the form of Jelly script. This file resembles maven.xml as seen in previous chapters. While plugin.jelly and maven.xml contain similar goal definitions, they are separated to avoid conflicts: the maven.xml file is used at build time to build your plug-in, whereas plugin.jelly is used at runtime by users of your plug-in.


plugin.properties

This file defines default values for plug-in properties. A plug-in property is a property that end users of your plug-in can modify to suit their setup. The format of the plugin.properties file is the same as that of the project.properties file but, like plugin.jelly, plugin.properties is separated from project.properties (project.properties is used at build time to build your plug-in, whereas plugin.properties is used at runtime).

Figure 6-1. Minimal Maven plug-in structure


In order to run an executable JAR you simply need to use the Ant java task, using the jar attribute (see http://ant.apache.org/manual/CoreTasks/java.html for the Ant Manual reference for the java task). Apply the plug-in's plugin.jelly file:

<?xml version="1.0"?>    <project     xmlns:j="jelly:core"     xmlns:ant="jelly:ant"     xmlns:maven="jelly:maven">      <goal name="jarexec:run" prereqs="jar:jar"       description="Runs an executable JAR">          <maven:get var="jarName" plugin="maven-jar-plugin"          property="maven.jar.final.name"/>        <ant:java jar="${maven.build.dir}/${jarName}" fork="true">       <ant:classpath>         <ant:path ref/>       </ant:classpath>     </ant:java>        </goal>    </project>


Tip: The maven.jar.final.name property was introduced in version 1.7 of the JAR plug-in, so be sure to use it. See Appendix A for directions on installing a specific version of a plug-in.

The jarexec:run goal depends on jar:jar and you've used the description attribute to describe what the goal does. This is useful for end users who can know the list of goals available in your plug-in by typing maven -P jarexec.


Note: Document your plug-in's public goals by adding a description to them.

One tricky part is getting the name of the JAR file that you wish to execute. As the user of this plug-in will have used the JAR plug-in to generate his JAR, you can ask the JAR plug-in for the JAR name using the maven:get tag (see Section 2.1 for more details on maven:get). Then you also need to add all the JARs defined as dependencies in the user's project.xml file to the java task execution classpath. You do this by using the predefined maven.dependency.classpath Maven property (internally it is an Ant PATH element).

So far, you've not had to provide support for any property customizable by the end user (your plugin.properties file is empty). Now you will add a property that will allow an end user to change the name of the JAR to execute, and use a default name of maven.jar.final.name in case the user does not modify it. It's good practice to always provide default values so that your plug-in can work as is without modification from the user. It's also good to provide possibilities for customization such as the ability to override the name of the JAR to execute. Let's call mdn.jarexec.jar the property for specifying which JAR to run. You could name it any way you wish, but the accepted convention is to name it using this pattern: [groupId].[plugin name].[some property name] (or just [plugin name].[some property] if the groupId and the plug-in name are the same).

You might be tempted to write the following line in the plugin.properties file:

mdn.jarexec.jar = ${maven.jar.final.name}

You might be shocked to hear that this will not always work! This is because the maven.jar.final.name property is a property of the JAR plug-in, and Maven loads plug-in properties in memory the first time they are called (this is also known as lazy loading). This is done to isolate plug-in namespaces (see Section 2.1 for more details).

Thus, the preceding line of code will work only if the JAR plug-in has been called before the Jarexec plug-in itself is executed. Thankfully there's a solution! The solution is to retrieve the property from the JAR plug-in using the maven:get tag, as you did earlier. This tag loads the plug-in passed to it if it's not already loaded in memory, and then fetches the property.

Use the maven:property tag to set a default value to the mdn.jarexec.jar property, or use the value provided by the user (if defined):

<?xml version="1.0"?>    <project     xmlns:j="jelly:core"     xmlns:ant="jelly:ant"     xmlns:maven="jelly:maven">      <goal name="jarexec:run" depends="jar:jar">          <maven:get var="defaultJarName" plugin="maven-jar-plugin"          property="maven.jar.final.name"/>     <j:set var="defaultJar" value="${maven.build.dir}/${defaultJarName}"/>     <maven:property var="jar" name="mdn.jarexec.jar"          defaultValue="${defaultJar}"/>            <ant:java jar="${jar}" fork="true">             <ant:classpath>         <ant:path ref/>       </ant:classpath>     </ant:java>        </goal>    </project>

6.1.2. What about...

...using the Javaapp plug-in?

There's an existing plug-in called Javaapp. It is used to generate a single JAR containing the project's Java classes and all classes from the project's dependencies. It has a javaapp:run goal, which runs an executable JAR.



Maven. A Developer's Notebook
Maven: A Developers Notebook (Developers Notebooks)
ISBN: 0596007507
EAN: 2147483647
Year: 2003
Pages: 125

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net