July 12, 2010 by Rajesh Kumar
Comments (0)
writing a custom plugin for maven
In this article, we will learn about Maven which is a project management framework that provides a configurable approach for managing software projects. Maven covers all the necessary phases that happen right from project creation, building, documentation, reporting, installation and deployment. This article begins with the basics of Maven along with the concepts like Project Object Model (aka POM), the various life-cycles in Maven etc. Then it continues with using Maven for creating a project till installation of the project in a local repository. The latter part of the article provides details about creating custom Maven plugins that can be executed in stand-alone mode as well as part of some Maven life-cycle.
In this section, we will see the basics of Maven concepts like Project Object Model, the standard lifecycles available in Maven as well as the dependency scope that comes up while dealing with dependency with projects.
Project information, its dependencies and the artifacts that can be built are described in POM which is essentially a configuration file in XML. POM basically contains instructions on what needs to be done during the various life-cycles that happen during a build. Note that the POM is not coupled to java projects, in fact the project can be written in any language like C, C# etc. For example, consider the sample minimal POM,
<project>
<modelVersion>4.0.0</modelVersion>
<name>adder</name>
<url>http:// www.javabeat.net/ adder</ url>
<groupId>net.javabeat.adder</groupId>
<artifactId>adder</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Have a look at the above POM. It defines the information about the project and its dependant projects. We will look into more details about the various POM elements.
In the next section in the POM, we have included the dependencies of the project. Note that this section is optional. If there are no dependencies for a project (which is unlikely the case), this can be omitted. However, in this example case, we have declared a dependency to junit and it is expected that the project will contain some test resources. It is always a good idea to define the version of the artifact while defining a dependency, so that during runtime, we are not facing any issues because of version match. We have mentioned the scope as test, more details about this element will follow in the forthcoming section.
A project can depend on a number of dependent projects and Maven provides a way for defining the dependencies among projects through configuration. One can control the level of dependency through scope and the default being 'compile'. The following scopes are available.
A life-cycle defines the execution for achieving a set of goals. Each life-cycle defines a sequence of phases for achieving the goals. The
In this section, we will see how to use maven for creating, compiling, building, packaging and installing a project. Download the latest version of Maven from here. Installation of maven will be as simple as un-zipping the downloaded file into a desired directory. In this example, we will be seeing the usage of various maven plugins and goals that contributes to the entire project life-cycle. Before proceeding with the sample, create an environment variable MAVEN_HOME that points to the Maven installation directory and ensure that the PATH variable contains %MAVEN_HOME/bin.
Execute the following command which is used to create the initial project structure.
mvn archetype:create -DgroupId=net.javabeat.emailservice -DartifactId=emailservice
Note that in archetype:create, archetype represents the plugin prefix and create represents the goal. This goal creates a project with the name emailservice. As soon as this command is executed, one can see a directory called emailservice which has the src folder for holding the main java files, along with java files representing test-cases. The POM file with the name pom.file will also be created with the structure as follows,
pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>net.javabeat.emailservice</groupId>
<artifactId>emailservice</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>emailservice</name>
<url>http:// maven.apache.org</ url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
This step is optional for those who are not working with Eclipse being the IDE for developing the project. Change the current directory to emailservice and issue the following command. This goal eclipse creates the project metadata files that are complaint with Eclipse. As soon as the following goal is executed there will be two files generated in the current directory which are .project and .classpath. This is for Eclipse to understand so that the newly created project can be imported in Eclipse IDE to work with.
mvn eclipse:eclipse
Now, for importing the project into Eclipse, Open Eclipse, go to File -> Import -> Existing Projects into Workspace and navigate to the directory containing the .project and .classpath files and Click OK. Now this project gets imported into Eclipse workspace.
To make the project meaningful, we will add the following files into the main source folder.
EMail.java
package net.javabeat.emailservice;
public class EMail {
private String fromAddress;
private String toAddress;
private String subject;
private String message;
private String status;
public String getFromAddress() {
return fromAddress;
}
public void setFromAddress(String fromAddress) {
this.fromAddress = fromAddress;
}
public String getToAddress() {
return toAddress;
}
public void setToAddress(String toAddress) {
this.toAddress = toAddress;
}
public String getSubject() {
return subject;
}
public void setSubject(String subject) {
this.subject = subject;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
}
The above class represents the Email model object that will be used by EmailService class for sending email. Given below is the code listing for EMailService class.
EMailService.java
package net.javabeat.emailservice;
public class EMailService {
public EMail sendEmail(String fromAddress, String toAddress, String subject, String message){
EMail emailObject = new EMail();
emailObject.setFromAddress(fromAddress);
emailObject.setToAddress(toAddress);
emailObject.setSubject(subject);
emailObject.setMessage(message);
emailObject.setStatus("SUCCESS");
System.out.println("Sending email from " + fromAddress + " to " + toAddress + "with subject "
+ subject + " having the message contents " + message);
return emailObject;
}
In this section we will see how to write custom maven plugins. It is possible that the custom maven can be made to run outside the standard life-cycle phase or it can be made to be executed as part of the standard life-cycle phase. We will see how to accomplish both of these items in the following sections.
In this section, we will write a custom plugin and will see how to write it in stand-alone mode – i.e running the plugin directly without establishing any dependencies on any of the standard life-cycles available in Maven.
The first step is to create the project containing the custom maven plugin. This project is quite different from the regular java project because it is not a regular java artifact like JAR, WAR etc. Instead it is going to be a maven plugin. Issue the following command to create the maven plugin project.
mvn archetype:create -DgroupId=net.javabeat.maven -DartifactId=environment-info -DarchetypeArtifactId=maven-archetype-mojo
The above command creates a project with the name environment-info with the standard directory layout containing the source and test resources. If you look into the POM file, the package type will be maven-plugin to indicate that this is a maven plugin project.
This step is optional and this is for someone who wishes to work with the project in Eclipse IDE. Issuing the following with the current directory being environment-info creates the Eclipse .project and .classpath files. Now, open Eclipse and go to File -> Import -> Existing Project into Workspace and specify the directory to <<path to environment-info>> directory.
mvn eclipse:eclipse
In Maven, the plugin that achieves a specific task is called by the name MOJO (Maven Old Java Object similar to POJO). A MOJO defines the goal which is nothing but the custom action which is executed upon user's request. In this example, we will see a custom MOJO that will define the goal of storing all the environmental properties in a text file upon execution. Have a look at the following code,
EnvironmentInfoTask.java
package net.javabeat.maven; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.util.Iterator; import java.util.Map; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * @goal env-info */ public class EnvironmentInfoTask extends AbstractMojo{ /** * @parameter * default-value="log.txt" * expression="${environment.filename}" */ private String fileName; /** * @parameter * default-value="C:\\temp" * expression="${environment.base_dir}" */ private File baseDirectory; /** * @parameter * default-value="true" * expression="${environment.loggingRequired}" */ private boolean loggingRequired; public void execute() throws MojoExecutionException, MojoFailureException { StringBuilder fileContents = new StringBuilder(); if (baseDirectory.exists()){ baseDirectory.mkdirs(); log("Created base directory '" + baseDirectory.getAbsolutePath() + "'"); } Map<String, String> environment = System.getenv(); Iterator<Map.Entry<String, String>> entries = environment.entrySet().iterator(); fileContents.append("Environment Information:" + newLine()); fileContents.append("-----------------------------------------------------------" + newLine()); while (entries.hasNext()){ Map.Entry<String, String> entry = entries.next(); fileContents.append(entry.getKey() + "------------->" + entry.getValue() + newLine()); } fileContents.append("-----------------------------------------------------------" + newLine()); writeToFile(fileContents); log("File contents written"); } private void log(String message){ if (loggingRequired){ System.out.println(message); } } private static String newLine(){ return System.getProperty("line.separator"); } private void writeToFile(StringBuilder fileContents){ FileWriter fWriter = null; BufferedWriter bWriter = null; try{ fWriter = new FileWriter(baseDirectory + File.separator + fileName); bWriter = new BufferedWriter(fWriter); bWriter.write(fileContents.toString()); }catch (Exception e){ log("Error in writing the contents to file ->" + e.getMessage()); }finally{ try{ if (bWriter != null){ bWriter.close(); } if (fWriter != null){ fWriter.close(); } }catch (Exception e){ log("Error in closing the resources ->" + e.getMessage()); } } } }
The first thing to notice is the class EnvironmentInfoTask which is going to persist the environmental information into a file extends AbstractMojo class which in turn extends the Mojo interface. Note that the goal for this MOJO is annotated using XDoclet using goal attribute with the name env-info. The method that will be called during execution of the MOJO is execute(). This method does the job of persisting the environmental properties by taking information from the various properties .
Issue the following command for compiling the maven plugin project.
mvn compile
The following command is used to package the plugin project.
mvn package
For installing the project into the local Maven repository, issue the following command.
mvn install
Usually, on Windows, the local repository is %USER_HOME%/.m2/repository. On Windows XP, USER_HOME will expand to "C:\\Document and Settings\\<<UserName>>", however in Windows Vista it is "C:\\Users\\<<UserName>>".
There are several ways to run the maven plugin. We will see them one by one. Generally running a Maven plugin takes the following form,
mvn groupId:artifactId:version:goalName
In our case, the group id is net.javabeat.maven, artifact id is environment-info, version is 1.0-SNAPSHOT and goal name is env-info. So running the following command will run the custom plugin
mvn net.javabeat.maven:environment-info:1.0-SNAPSHOT:env-info
Running the above command will create a directory C:\\temp (if not present) and create a file name with log.txt with the environment information. Because logging is enabled by default, the text 'Created base directory C:\temp' and 'File contents are written' will be displayed in the console.
It is also possible to configure the plugin by passing alternate input values. Have a look at the following command. This command specifies an alternate base directory C:\\temp-new for the log file newLog.txt with logging turned off. Note that for passing a property to a plugin the standard way is –DpropertyName=propertyValue.
mvn net.javabeat.maven:environment-info:1.0-SNAPSHOT:env-info -Denvironment.base_dir=C:\temp-new -Denvironment.filename=newLog.txt -Denvironment.loggingRequired=false
It is also possible to omit the version information while running the plugin in which case, Maven tries to find the recent version for the plugin by comparing the version strings. In our case, this wouldn't happen, because we have only one version which is 1.0-SNAPSHOT. So the following command will also work.
mvn net.javabeat.maven:environment-info:env-info
Another approach to run the plugin is by omitting the group id and just specifying the artifact id along with the goal name. However, for this to happen, we have to add the group id to the default list of groups that Maven will look for. Open the file %MAVEN_HOME%/conf/settings.xml and add the following line under the element pluginsGroup.
<pluginGroup>net.javabeat.maven</pluginGroup>
This ensures that we have added the group net.javabeat.maven to the list of default groups that Maven will search for, because of which the following command will work.
mvn environment-info:env-info
So far, we have seen how to run a custom plugin in stand-alone mode. This is not of much-use and Maven provides a way for binding the goals of any custom plugin into existing build cycle. For example, let us consider that we have written a custom plugin which will simply print the current date and we want this plugin to be executed during the compilation phase and the installation phase of a project. We will see how to accomplish this goal in this section.
The following listing shows the custom plugin which will simply emit the date information.
DateInfo.java
package net.javabeat.maven; import java.util.Date; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; /** * @goal date-info */ public class DateInfo extends AbstractMojo { public void execute() throws MojoExecutionException, MojoFailureException { Date currentDate = new Date(); getLog().info("Current date is " + currentDate); } }
Follow the same process of creating the project, then creating the plugin, compilation, packaging and installation as we have discussed before. We will see how to attach this custom plugin during the compile and the install phase. Open POM.xml file and add the following after the project dependencies element,
<build> <plugins> <plugin> <groupId>net.javabeat.maven</groupId> <artifactId>environment-info</artifactId> <version>1.0-SNAPSHOT</version> <executions> <execution> <id>date-info-compile</id> <phase>compile</phase> <goals> <goal>date-info</goal> </goals> </execution> <execution> <id>date-info-install</id> <phase>install</phase> <goals> <goal>date-info</goal> </goals> </execution> </executions> </plugin> </plugins> </build>
Though the above XML fragment is big, it is fairly simple. First thing is, it defines the execution element where we can define goals for executions. We have defined two execution elements one for the compile phase and the other for the install phase and we have given appropriate id for each execution element. Have a note at the goals section. We have included our custom goal date-info which will display the current date information. Note that where to search for the goal's group id and the artifact id along with optional version is defined just above the executions element.
After this whenever we run mvn compile and mvn install for any project that contains the above definition we will see that the goal date-info getting invoked during the phases.
In this article, we have seen how to use Maven for creating projects and to manage dependencies between projects. We have seen Maven simplifying the task of creating, compiling, packaging, installing projects thereby reducing the pain from developers and build managers. Also discussed in the article are the extension capabilities provided by Maven for pluging-in custom plugins in the form of MOJOs.
}
Note that there is no real functionality in the above, all it does is to accept the various user inputs and constructs an email object before returning it.
The next step is to compile to project, by default the compilation process will create a folder called target and it will place the java class files along with any resource files, if present.
mvn compile
Note that the location of the target folder as well as the location of the target folder is also configurable.
This step will package the project with the packaging type mentioned in POM, which is JAR. Before packaging it will also execute the test cases (if specified) in the test folder and the packaged jar will be placed in the target folder.
mvn package
The final step is to install the jar in a local repository so that other projects, if they are dependant on this project can make references to this project. The following command will install (i.e copy the jar) to the local repository.
mvn install
Note that, by default, the local repository path will be %USER_HOME%/.m2/repository.
Rajesh Kumar
80 days ago
Quantitative Matrices & RSM
Rajesh Kumar
80 days ago
Identify the Process of setting up smartBuild Server.
sgcommadmin
80 days ago
How we reduced build time?
Rajesh Kumar
84 days ago
Advance Features of Smart Build Tools - SMART BUILD - ADVANCED FEATURES
April 29, 2010 by Rambabu Muppuri
Comments (3)
can u pl help me anyone introduction of msbuild?
software configuration management, software configuration management tools, build tools, scripting, build management system, release tools, deployment tools, configuration management, build managent, release managment, automation practice
Hi Guys,
can u pl help me anyone Introduction of MSbuild?
Regards,
Rambabu.M
April 26, 2010 by Rajesh Kumar
Comments (0)
introdcution of perl, why perl, why not perl
What is Perl
WHY PERL.
There are a many reasons why Perl is a great language for use in development and general processing.
Following are some of them…
WHY NOT PERL.
All languages have areas that they excel in, and others that they don't. Perl is no different. Technically, you could write anything in Perl, even a complete operating system. but that does not mean you should. Its a matter of considering your requirements and deciding on the best language to suit them. Here are some reasons why Perl might not be your best choice:
Reference:
http:/
Last updated 37 days ago by Rajesh Kumar
April 19, 2010 by Rajesh Kumar
Comments (0)
types of build, remote agent, distributed processing build, parallel processing build, multi-language builds
software configuration management, build tools, build management system, build managent
Types of Build in Remote Agent
Build Management tools has one one capability where they can share the infrasture to build the product in less time with the help of Remote Agent Machine.
There are following types of build in remote Agent.
Distributed processing Build:
A distributed build is one in which individual steps in the Workflow are sent to be executed on multiple machines. In doing this you are able to leverage more machine power instead of attempting to run the entire Workflow on a single machine.
Parallel processing build
Remote Agents also support parallel processing. A Parallel process executes Workflows for each unique stage of the development lifecycle including continuous integration builds for developers, pre-production builds for testers and emergency builds for production control. A Remote Agent can be configured to execute builds according to the location that the binaries will be distributed.
Multi-platform builds
Workflows can be configured to call Remote Agents that are running different operating systems This allows you to execute a Workflow that builds the application across multiple operating systems or build specific components of the application on the appropriate machine. For example, a Workflow that needs to build Windows .Net components as well as AIX Oracle back-end components would use two Remote Agents one for Windows and one for AIX.
Multi-language builds
Workflows can be configured to call Remote Agents that are running different languages. This allows you to execute a Workflow that builds the application across multiple operating systems or build specific components of the application on the appropriate machine. For example, a Workflow that needs to build Windows .Net components as well as AIX Oracle back-end components would use two Remote Agents one for Windows and one for AIX.
Dedicated builds
Remote Agents can also be used as 'dedicated build machines'. A dedicated “Build Machine” is often bigger and faster than a regular desktop machine. The dedicated build machine would be configured as a Remote Agent in which Workflows could be executed in order to improve the workflow processing. In addition, if you are using Meister's Build Automation, a dedicated machine with multi-processing power can be used to manage the calls to the compilers and linkers and accelerate the building of C and Java applications.
Rajesh Kumar
146 days ago
This files contains Maven Interview Questions and Answers.
Please let me know your point of view.