Maven exec plugin - user args from console after hardcoded args - java

I'm implementing a simple RMI server and client. I wanted to speed up the tedious task of adding server codebase each time (lots of terminal-bloating text), so I decided to use the maven exec plugin. Here's how a part of my pom.xml looks now:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<executable>java</executable>
<arguments>
<argument>-classpath</argument>
<argument>/media/files/EclipseWorkspace/JavaSE/rozprochy/lab2/RmiServer/target/classes</argument>
<argument>-Djava.rmi.server.codebase=file:/media/files/EclipseWorkspace/JavaSE/rozprochy/lab2/RmiServer/target/classes/</argument>
<argument>engine.ComputeEngine</argument>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
Everything's fine when i run mvn exec:exec in the console. The problem arises when I want to let the user specify the rmiregistry port for instance as an argument to the program. Basically, I'd like to add extra arguments from console, in addition to those specified in the POM file. All the solutions I've found overwrote the hardcoded args, when specifying new args from console, and this undesirable. Is it possible to do this somehow?

This is kind of a twisted workaround but I couldn't think of any other way to achieve what you want
Define a property in your pom with the default value for your additional parameter
<properties>
<extra.argument.from.console>extra.argument.from.console.default.value</extra.argument.from.console>
</properties>
In your execution add that property as an argument
<argument>${extra.argument.from.console}</argument>
When invoking maven give value to that property if you don't want to use the default value
mvn exec:exec -Dextra.argument.from.console=value.you.want

Related

run mvn release with several profiles

Is it possible to run maven with several profiles?
I have a java class annotated with #WebService. Depending on the maven profile the targetNamespace will change. If I run the
mvn release:prepare release:perform
twice, each time with a different profile, I will achieve what I want but the jar versions will not be same regarding the pom version.
So I thought running the release with 2 profiles could do it. Unfortunately when I enter
-P profile-1, -P profile-2
or
-P profile-1,profile-2
only one profile gets executed.
Here ary ma profiles:
<profiles>
<profile>
<id>profile-1</id>
<properties>
<target-namespace>sample-1.org</target-namespace>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>clean</phase>
<configuration>
<target>
<echo>${target-namespace}</echo>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>profile-2</id>
<properties>
<target-namespace>sample-2.org</target-namespace>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>clean</phase>
<configuration>
<target>
<echo>${target-namespace}</echo>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skipTests>true</skipTests>
</configuration>
</plugin>
</plugins>
</build>
</profile>
I do print out the target-namespace properties to verify that in fact both profiles are running which is not the case.
Thanks
The second command-line (comma-separated profiles) is more correct, but won't quite do what you're trying to do, given your pom.
When you specify multiple profiles, they are all active in the same maven process -- it doesn't mean "run each goal with the first profile and then again with the second". So in the command that you are running, maven attempts to run with both profiles active.
Unfortunately, the contents of your profiles are overlapping. Well, the properties are. The <build> section is identical in each, which means that it could even be moved outside of the profiles and just declared once.
But the <properties> are completely overlapping ... hopefully it's clear that the target-namespace property cannot have two different values at once.
I wrote an answer below for some ways to address this properties question, which was posed in a very general way. But honestly, for anyone who ever reads this: there might easily be other, better ways to accomplish whatever you're actually trying to do. The OP was clearly attempting to do something more specific and this multiple profile thing was the method they were deciding to try, but they were confused when it wasn't working. A question about how to best solve their actual specific problem would probably have been a more productive question. But just in case this is a good way to solve your problem, here goes.
For the purposes of discussion I'm going to ignore the <build> contents above, which appear completely nonsensical, and assume that you need separate profiles because you'll sometimes want to activate each one independently of the other (maybe when not running release).
You can't use two values at once for the same property. You need to have multiple executions occur instead. You have a few different options for this...
Multiple commands. No changes needed to your pom, but this requires that your profiles have no real applicability to the actions in release:prepare, which you'll only run once. If that's not the case, this won't work. The first two commands could be combined into one but the third one has to be separate:
mvn release:prepare
mvn release:perform -P profile-1
mvn release:perform -P profile-2
Multiple <executions> of the release plugin itself, with different releaseProfiles in each one. This is a minor variation on option 1, but might be more appealing depending on your needs:
...
<artifactId>maven-release-plugin</artifactId>
<executions>
<execution>
<id>id-1</id>
<configuration>
<releaseProfiles>profile-1</releaseProfiles>
</configuration>
</execution>
<execution>
<id>id-2</id>
<configuration>
<releaseProfiles>profile-2</releaseProfiles>
</configuration>
</execution>
...
Because the release plugin isn't bound to any phase (you run it directly), you'll have to specify both executions separately on the command line, like mvn release:prepare release:perform#id-1 release:perform#id-2.
Use unique plugin execution ids within each profile -- then run mvn release:prepare release:perform -P profile-1,profile-2 as usual. You'd also have to change the profiles so that they use different property names. e.g.
...
<profile>
<id>profile-1</id>
<properties>
<namespace-1>sample-1.org</namespace-1>
...
<execution>
<id>antrun-1</id>
<configuration>
<target>
<echo>${namespace-1}</echo>
...
<profile>
<id>profile-2</id>
<properties>
<namespace-2>sample-2.org</namespace-2>
...
<id>antrun-2</id>
<configuration>
<target>
<echo>${namespace-2}</echo>
...
... this assumes that the all the plugin executions are such that they would be fine to run in a round-robin order like this for each phase of the overall build (clean phase = antrun 1 then antrun 2; test phase = surefire 1 then surefire 2; etc).
Due to Maven Documentation your second option is correct:
Profiles can be explicitly specified using the -P CLI option.
This option takes an argument that is a comma-delimited list of profile-ids to use. When this option is specified, the profile(s) specified in the option argument will be activated in addition to any profiles which are activated by their activation configuration or the section in settings.xml.
Hence you need to use next command format:
mvn <goals_list> -P profile-1,profile-2
If behaviour is incorrect there could be wrong profile configuration in your POM file. Could you please provide its content?
-P profile-1,profile-2 should be the right form, if it doesn't work it might be due to some conflicts etc. in the profiles themselves.
As an alternative you could try and play with the <activation> tags in settings.xml to activate the profiles based on some property, e.g.
<activation>
<property>
<name>releaseProfile</name>
</property>
</activation>
Then set the property in your mvn call: mvn -DreleaseProfile release:prepare release:perform. (You might have to pass a value for the property, it's been a while since I used that).

Serial execution of plugins in Maven using <phase>

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.

Error in Maven building?

After i wrote
mvn -f pom.xml compile exec:java -Dexec.classpathScope=Compile-Dexec.main Class=storm.starter.WordCountTopology
and found this !!
[INFO] One or more required plugin parameters are invalid/missing for
'exec:java'
[0] Inside the definition for plugin 'exec-maven-plugin' specify the
following:
... VALUE
-OR-
on the command line, specify: '-Dstorm.topology=VALUE
If you link your pom.xml then this would be easier. I'm guessing you're using Storm. Have you written your own topologyClass? From the documentation:
topologyClass
The class name of the topology driver (e.g. "com.foo.bar.MyTopology")
Command line override: -Dmaven.storm.topology=
The documentation also gives you the code for your pom but you might want to add exec-maven-plugin to your pom.xml like so:
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<configuration>
<mainClass>com.domain.yourApp</mainClass>
</configuration>
</plugin>
</plugins>
</build>
One thing to note: you need to alter mainClass to match the class in your project that contains the main method you want to execute.
Then you can just run mvn exec:java.

Preventing checkstyle from running in a specific maven submodule

I would like to define a checkstyle run in a pom file, and have it run on all the submodules except certain specified ones.
In other words, I need some sort of <excludes> (which exists but applies to filenames) but which targets modules. Any idea anyone?
If you do not want to change your pom.xml you may set the skip to true from command line using the –D option.
This was mentioned above as "overridden the skip parameter within an execution".
This is quite similar to -Dmaven.test.skip=true usage.
mvn site -Dcheckstyle.skip=true
Put the following in the projects that you want checkstyle disabled for:
<project>
...
<properties>
...
<checkstyle.skip>true</checkstyle.skip>
...
</properties>
...
</project>
Checkstyle will still run, but will perform a no-op...
That is unless you override the default binding of maven-checkstyle-plugin's skip parameter in which case you could achieve the same effect with the following in the specific project
<project>
...
<build>
...
<plugins>
...
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
...
</plugins>
...
</build>
...
</project>
Unless of course you have overridden the skip parameter within an execution... but if you know what that is you also know the solution and would not be asking this question ;-)

pass a java parameter from maven

I need to execute some tests with maven, and pass a parameter from the command line.
My java code should get the parameter as:
System.getenv("my_parameter1");
and I define the parameter in the pom.xml file as the example below:
(and latter, I'd modify the pom.xml to get the parameter from the common line mvn clean install -Dmy_parameter1=value1)
but it does not work; System.getenv("my_parameter1") returns null.
how should I define the parameter in the pom.xml file?
pom.xml
<project>
...
<profiles>
<profile>
<properties>
<my_parameter1>value1</my_parameter1>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<executions>
<execution>
<id>slowTest</id>
<phase>test</phase>
<goals>
<goal>test</goal>
</goals>
<configuration>
<skip>false</skip>
<includes>
<include>**/*Test.java</include>
<include>**/*TestSlow.java</include>
</includes>
<properties>
<my_parameter1>value1</my_parameter1>
</properties>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
System.getenv() reads environment variables, such as PATH. What you want is to read a system property instead. The -D[system property name]=[value] is for system properties, not environment variables.
You have two options:
If you want to use environment variables, use the OS-specific method of setting the environment variable my_parameter1 before you launch Maven. In Windows, use set my_parameter1=<value>, in 'nix use export my_parameter1=<value>.
You can use System.getProperty() to read the system property value from within your code.
example:
String param = System.getProperty("my_parameter1");
In you surefire plugin configuration, you can use:
<configuration>
<systemPropertyVariables>
<my_property1>${my_property1}</my_property1>
</systemPropertyVariables>
</configuration>
Which takes the Maven property _my_property1_ and sets it also in your tests.
More details about this here.
I'm not sure if system properties from Maven are automatically passed to tests and/or whether fork mode affects whether this happens, so it's probably a good idea to pass them in explicitly.
Use
${env.my_parameter}
to access the environment variable in the pom.xml.
You can use the help plugin to see which variables are set with
mvn help:system
However the normal properties usage should work too. In the large context however I am wondering... what do you want to do? There might be a simpler solution.
The maven surefire plugin also has an option to set environment variables, just add this to your plugin configuration.
<environmentVariables>
<my_parameter1>value</my_parameter1>
</environmentVariables>
I think this requires that the plugin operates in fork mode, which is the default.

Categories

Resources