I have the following structure in pom.xml:
<profile>
<id> x </id>
<build>
<finalName> y </finalName>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<!-- DELETE SOME FOLDERS AND SOME FILES -->
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<!-- MOVE A FILE -->
</plugin>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version> 1.6 </version>
<executions>
<execution>
<phase> <!-- WHAT COMES HERE ? --> </phase>
<configuration>
<!-- I EXECUTE CMD FILE HERE -->
</configuration>
<goals>
<goal> run </goal>
</goals>
<execution>
<executions>
</plugin>
</plugins>
</build>
</profile>
I want to achieve a serial execution for plugins:
Delete some folders and some files (1st plugin)
Move a file (2nd plugin)
Run cmd file (3rd plugin)
What should I use for <phase> to have the order above (sequential execution)? Is it relevant ? Is it ok to use pre-integration-test for example ?
P.S.: Here are the phases: http://maven.apache.org/ref/3.2.2/maven-core/lifecycles.html
Maven doesn't support adding steps to the life cycle (without writing a new plugin).
If you have complex build steps and you absolutely need a certain order and this order violates the standard life cycle, then Maven might not be the right tool for you. Consider Gradle instead.
If you have to use Maven, then stop using plugins for this. Instead, replicate all the build steps using the antrun plugin so everything is done with a single Ant script. Afterwards, find a place in the life cycle where you want all the steps to be executed at once.
generate-sources is a good place if you need something to be done before anything is compiled. If you want to run code after compilation and tests, use prepare-package.
See here for the complete life cycle: http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference
If you like to add the execution of different plugins to the same life cycle phase the execution order is defined by the order of the definition in the pom file.
So if you choose to bind all the above three plugins to the package phase than they will be executed in the given order.
You can of course use the antrun plugin which will work also and will implicit execute the steps in the defined order without thinking about the default behaviour of Maven.
You can also use the exec-maven-plugin to execute a script in a particular life cycle phase but which might be not a good solution cause the script is OS dependent. Or you can use the groovy plugin to execute some steps in groovy code.
Related
Background:
I am working on a open source tool called draw.io which is based on ANT build system and uses Java servelets to handle request. I am supposed to migrate it to spring boot with using same front end files. I put those files in static folder and tried to build the project. I figured that the front end js files were not getting build (i.e. were not getting converted to app.min.js, which is the main entry point for front end files), in the process and none of the js changes were getting reflected in the file.
I figured that this process was mentioned in build.xml as part of various steps which is ANT specific configuration. Now, I have to achieve the same in maven as the migration process.
How do we convert build.xml to maven or what is the maven alternative of achieving the tasks mentioned in the build.xml as part of build process?
This is the high level view of build.xml:->
I am also providing the link of build.xml here...
Please provide me with some direction.
Before migrating to maven, I hope you understand why you are moving to maven from ant.
You should try for finding alternative plugins for the relevant ant task. The below plugin might do what you are trying to achieve in ant
<plugin>
<groupId>com.github.blutorange</groupId>
<artifactId>closure-compiler-maven-plugin</artifactId>
<version>2.16.0</version>
<configuration>
<!-- Base configuration for all executions (bundles) -->
<baseSourceDir>${project.basedir}/src/main/resources</baseSourceDir>
<baseTargetDir>${project.build.directory}/generated-resources</baseTargetDir>
</configuration>
<executions>
<!-- Process all files in the "includes" directory individually-->
<execution>
<id>default-minify</id>
<configuration>
<encoding>UTF-8</encoding>
<sourceDir>includes</sourceDir>
<targetDir>includes</targetDir>
<includes>**/*.js</includes>
<skipMerge>true</skipMerge>
<closureLanguageOut>ECMASCRIPT5</closureLanguageOut>
</configuration>
<goals>
<goal>minify</goal>
</goals>
<phase>generate-resources</phase>
</execution>
</executions>
</plugin>
More details about the plugin : closure-compiler-maven-plugin
There are few cases during my ant to maven migration, I came across some custom tasks which I was not able to find appropriate plugins.
I used maven-antrun-plugin which keeps existing ant tasks in maven.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
...
</executions>
</plugin>
More details about how to use the maven antrun plugin : See this
tutorial
For Maven, you need a pom.xml. There you need to define and configure the plugins you need. If you have a specific procedure written in Ant that you want to reuse, you can call it with the Maven Antrun Plugin.
Generally, Maven is very different from Ant. You don't write procedural code, but configure plugins running in a lifecycle.
I've got a web project where I'd like to have the major version number in the final build name. So for example, it should be myproject-v2.
Using the build-helper-maven-plugin I've managed to get this working in my normal Maven build process by adding the following to my pom:
<build>
<finalName>${project.artifactId}-v${parsedVersion.majorVersion}</finalName>
<plugins>
<!-- Used to build the parsedVersion property for use above -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.9.1</version>
<executions>
<execution>
<id>parse-version</id>
<goals>
<goal>parse-version</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
That works great via Maven & I get a myproject-v0.war at the end that I can deploy.
But within Eclipse, it always gets deployed as myproject-v${parsedVersion.majorVersion}. So it's not found the new variable - fair enough. But no matter what I try, I can't seem to get Eclipse to pick up the result from the build helper plugin
Does anyone have any suggestions on what I could try? Here's what I have tried already:
* Setting the final build name, the warName property on the maven-war-plugin and the m2eclipse.wtp.contextRoot property to my build name pattern.
* Binding the parse-version to a number of different goals (e.g. clean, package)
But I'm running low on ideas. If I can't do it automatically, I'll just hard code the value but it would be nice to have it done automatically.
I have written a console app (.java class with main function), and I'd like to call this main (or, for example some static method before execution of my big project) how to do this with Maven (script?)?
go and look at the exec maven plugin. you can use it to execute either a native executable, a script, or a java main() at any point in the build. like so:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3.2</version>
<executions>
<execution>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>com.example.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
you cannot run just any java method you want, but writing a small class with a main() method that invokes whatever you want is pretty easy.
another gotcha is that the class you want to run has to be compiled before you run it. this means that either this execution has to happen after the compile phase or you need to split your project into 2 modules - one containing the main class and the other containing the rest of you code (that will depend on the 1st module to get proper build order)
if you still insist on arbitrary code, there's always the groovy maven plugin, which allows you to write groovy code inline to be executed during the build.
As an alternative to the exec-maven-plugin you can also use the Apache Maven Scripting Plugin. It can execute scripts in any JSR223 compatible scripting language.
For references on the scripting library options you have, see the following questions:
Java ScriptEngine supported languages
Where can I find a list of available JSR-223 scripting languages?
I have written a more detailed answer on how this plugin works in the following answer:
https://stackoverflow.com/a/73067375/18699445
For your needs on executing any piece of Java code from the current project, you can use the following plugin setup:
<!-- Scripting Plugin: run ScriptEngine compatible scripts -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-scripting-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>run-script</id>
<phase>compile</phase>
<goals>
<goal>eval</goal>
</goals>
</execution>
</executions>
<configuration>
<engineName>beanshell</engineName>
<!-- <scriptFile>use this when possible; no code in the POM is preferred</scriptFile> -->
<script>
log.info("Hello from " + project.getArtifact());
// run code from the current project
// new my.package.MyClass().myMethodToExecute();
</script>
</configuration>
<dependencies>
<!-- Script Engine: Beanshell -->
<dependency>
<groupId>org.apache-extras.beanshell</groupId>
<artifactId>bsh</artifactId>
<version>2.0b6</version>
</dependency>
<!-- Dependency to current project (self) for executing code -->
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
You can use any id you like in the execution element.
The phase needs to be compile or later, otherwise you can't use the code from your current project. If you need to execute it earlier, you could put this code in a different artifact or module and depend on that.
By changing the dependency and engineName you can use any other compatible scripting language. You'll need to pick a Java-like language that is capable of calling & executing Java code.
This gives the following example output in the maven build log:
[INFO] --- maven-scripting-plugin:3.0.0:eval (run-script) # tests ---
[INFO] Hello from local:tests:jar:1.0
You can of course remove the "Hello world" and just execute the code you want.
I have the wsimport plugin in my project.
I would like to execute the wsimport. According to the website, the string to execute is "mvn jaxws:wsimport".
Firstly, is this string deductable from the XML ?
The artifact ID is :
<artifactId>jaxws-maven-plugin</artifactId>
and goal :
<goal>wsimport</goal>
so is the artifact-part just the substring of the artifactid leading up to "-maven-plugin" ?
..And when I execute my plugin goal "mvn jaxws:wsimport" does this completely ignore which phase I am in? Ie. is this running outside of the phase? And if no, is there a way to run this standalone?
ie. is there a way I can set the phase to none? (eg [phase]none[/phase]).
Pom code :
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jax-ws-commons</groupId>
<artifactId>jaxws-maven-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<id>wsimport-from-jdk</id>
<goals>
<goal>wsimport</goal>
</goals>
<configuration>
<executable>${tool.wsimport}</executable>
<wsdlUrls>
<wsdlUrl>http://WorkPC:8080/server-web/AirlineWS?wsdl</wsdlUrl>
</wsdlUrls>
<packageName>com.bluewalrus</packageName>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
When you issue a command like mvn [plugin]:[goal], it launches Maven out of any lifecycle, so if you do not intend to perform that goal inside a lifecycle, but only via such commands, you shouldn't have any <execution> defined, just place <configuration> right after <version>.
About how Maven can shorten the plugin call (i.e. mvn dependency:tree instead of mvn org.apache.maven.plugins:maven-dependency-plugin:2.1:tree), it is based on several conventions:
When no version defined, it tries to take the latest from available repositories
When the groupId is omitted, it looks among the predefined or user-defined pluginGroups to find a suitable one. See here for more information (Configuring Maven to Search for Plugins)
On the same page, you can see how plugins prefixes are used to shorten the plugin prefix, by using a prefix instead of the artifactId of the plugin. Thirdparty plugins should use [prefix]-maven-plugin construction, and it looks OK here.
And to disable the default execution of a plugin (although it might not be useful in this case), you can use this answer
when i instrument my classes using Maven 2 using the command
mvn cobertura:instrument
The output (the instrumented classes) are put in \target\generated-classes. Is there a way to change the output location to \target\classes?
I checked the instrumentation tasks of the cobertura-maven plugin but this does not give me a solution sofar.
You have not said why you want to overwrite the default location, but I assume it is so that you can use the instrumented classes from another project, or perhaps include them in a web archive or something similar.
I added the following to my pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>instrumented-classes</id>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<classifier>instrumented</classifier>
<classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory>
</configuration>
</execution>
</executions>
</plugin>
This makes maven generate an additional jar file called projectname-instrumented.jar
It is then possible to depend on this jar file from any other pom (including for example a web module) using
<depends>
<group>mygroup</group>
<project>projectname</project>
<version>1</version>
<classifier>instrumented</classifier>
</depends>
I did not test this 100% but have used similar mechanisms in the past
As far as I understand, the instrumented classes are only needed by cobertura for report generation. If you create them in target/classes, they will overwrite the original class files.
If you need the instrumented files in a jar as a result, you can configure the maven-jar-plugin to pick up the files from the target/generated-classes directory instead of or in addition to the files from the standard ${build.project.outputDirectory}.
Edit
Have a look at the maven-jar-plugin description. To only use target/generated-classes, the following addition to your POM should work - try it and modify it to your needs:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version> <!-- replace with correct version nbr! -->
<configuration>
<includes>
<include>${project.build.directory}/generated-classes/**/*.class</include>
</includes>
<excludes>
<exclude>${project.build.directory}/classes/**/*.class</include>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
${project.build.directory} points to your target folder, ${project.build.ouputDirectory} to target/classes. I do not know if you can simply set ${project.build.ouputDirectory} to a new value - have a look at the this chapter of the maven book, maybe you find some hints
Edit 2
Alternativly or additionally you can use maven to copy the files from target/generated-classes to target/classes after coberture:instrument has finished. This question has one answer with an example POM (fragment), you just have to identify the correct phase (process-resources is definitely too early for your case)
Did you try "mvn cobertura:instrument install"? It will generate a jar file including all the cobertura version classes.
If you want to change back original version, just run the command without "cobertura:instrument".
I just implemented the solution proposed by Andreas_D, modified my pom and uses the maven-resources-plugin. So on some stage of my build the Cobertura generated files are copied to the /target/classes directory.
You can configure it using <classesDirectory>[Your DIR]</classesDirectory>
In cobertura-maven-plugin version 2.4 this is still not supported. I've just created an improvement ticket, patch is attached to the ticket.