I have a maven project and an SBT project as a module of the maven project. I need to create a single command maven build, which executes SBT package task too.
Is there any plugin which I can use to integrate SBT with maven?
Thanks.
One option is using "Exec Maven Plugin", and here is an example to do a "play compile"
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<executable>${path.to.play}</executable>
<workingDirectory>${path.to.project.root}</workingDirectory>
<arguments>
<argument>compile</argument>
</arguments>
</configuration>
</plugin>
Use the maven antrun plugin (my example is for building a Scala.js app).
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<phase>pre-integration-test</phase>
<configuration>
<target>
<exec executable="cmd.exe"
spawn="true">
<arg value="/c"/>
<arg value="C:\Program Files (x86)\sbt\bin\sbt.bat"/>
<arg value="fullOptJS"/>
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
Credit due to #checat for suggesting this in his comment and the discussion at Launching a windows batch script using Maven exec plugin blocks the build even though the script uses "start"
Other thoughts; it might still be worth using mvn-exec on non Windows systems, perhaps using maven profiles. If I go this route, I'll try to remember to update the answer.
Related
I would like to know if it is possible to resolve the path for a maven artifact without having this artifact as a dependency in the project?
What I am trying to do is to execute an external java code generator via exec-maven-plugin or maven-antrun-plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<executable>java</executable>
<arguments>
<argument>-jar ${de.powerstat.fb:generator:1.0-SNAPSHOT}</argument>
<argument>de.powerstat.fb.generator.CodeGenerator</argument>
<argument>${fb.hostname}</argument>
<argument>${fb.port}</argument>
<argument>${fb.username}</argument>
<argument>${fb.password}</argument>
<argument>${project.build.directory}</argument>
</arguments>
</configuration>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
</plugin>
So the point here is how to solve the jars path for ${de.powerstat.fb:generator:1.0-SNAPSHOT} without having it as a dependency of the whole project? Also using the exec:java goal is not a solution, because this one seems to have different problems, but thats another question.
Using the antrun plugin I come to the same problem:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<target>
<java fork="true" failonerror="true" module="de.powerstat.fb.generator" modulepath="${de.powerstat.fb:generator:1.0-SNAPSHOT}">
<arg value="${fb.hostname} ${fb.port} ${fb.username} ${fb.password} ${project.build.directory}"/>
</java>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
So question is again how to solve the modulepath="${de.powerstat.fb:generator:1.0-SNAPSHOT}"?
Solutions that use the maven dependency plugin with the goal dependency:properties will not work in this scenario.
I suggest to use dependency:copy to copy the JAR to some place in /target. Then you can add that path to the antrun or exec plugin.
i am trying to copy a file in my maven multi-module project via antrun plugin. the file is in root of parent project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<inherited>false</inherited>
<executions>
<execution>
<inherited>false</inherited>
<id>copy</id>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="copy and rename file">
<copy file="${basedir}/portal-ext.properties" tofile="${liferay.auto.deploy.dir}/../portal-ext.properties" />
</target>
</configuration>
</execution>
</executions>
i run this via mvn antrun:run the problem is i get "No ant target defined - SKIPPED" on parent and on every module. i need it to run only on parent and thought <inherited>false</inherited> would help but i doesn't. But why "No ant target defined"?
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>ant-execute</id>
<configuration>
<target>
<echo message="plugin classpath: " />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
command : mvn antrun:run#ant-execute
antrun:run will only consider the plugin's configuration, not that for a specific execution, so the execution you specify is ignored. As Run a single Maven plugin execution? states, you can give your execution an id of default-cli to have it picked up.
However, the execution you configure should already be taking effect during the regular build lifecycle.
just run it like this: mvn antrun:run#copy
Following the instructions on the usage page (http://maven.apache.org/plugins/maven-antrun-plugin/usage.html) and other Stackoverflow questions I've been attempting to get an Ant task to run from my Maven build. I've simplified what I what to do down to a simple echo of "Hello, Maven," but I'm not getting anything.
I'm executing Maven with:
mvn package
I want this particular task to run before packaging ("prepare-package"), so I tried that phase first, but when that didn't work I tried making my phase just "package."
Here's one plugin configuration I've tried:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>id.package.ant</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<echo message="Hello, maven"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
And here's another one I've tried:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>id.package.ant</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<echo message="Hello, maven"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
I have also tried these without the <id>.
I get no errors, no output at all. Even if I execute Maven -debug, the word "echo" appears nowhere in the output, the word "antrun" appears nowhere in the output, and the word "hello" appears nowhere in the output.
It's like the plugin configuration isn't even there.
Andrew had the correct answer in his comments. When I moved my maven-antrun-plugin AS-IS above (with the <target> instead of <tasks>) OUT of <pluginManagement> and into a standalone <plugins>, my Ant task started executing.
Amazing how many searches of Google and Stackoverflow didn't return the other question before, but now I understand pluginManagement better. Thanks, Andrew!
Change ant from 1.7 to 1.8 solved my problem.
I encountered similar problems and it only worked when I added the version 1.8 tag. It wouldn't work otherwise. This might help.
I was having a similar problem. In my case, it was because I didn't have the <id>...</id> tag set for the execution. Below is the XML that worked:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>test</id> <!-- has to be set -->
<phase>validate</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="test">
<echo message="testing 1 2 3"/>
</target>
</configuration>
</execution>
</executions>
</plugin>
I use maven-antrun-plugin for init config files for my project. But i need to init config files just once, when i first start to init my dev environment, not each time i launch jetty:run.
If I attach phase to process-resouces for example, each time I launch jetty, my config files are reseted.
So i configured antrun like this :
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target name="init_config_files">
<!-- init files -->
</target>
</configuration>
</execution>
</executions>
</plugin>
If I launch mvn antrun:run, it just return me this error : "[INFO] No ant target defined - SKIPPED". And it is the same thing, if I specify target : "mvn antrun:run -Dtarget=init_config_files".
Try this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>default-cli</id>
<configuration>
<target>
<property name="compile_classpath" refid="maven.compile.classpath" />
<echo message="compile classpath: ${compile_classpath}" />
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
and run this:
mvn antrun:run
Best solution I have found so far:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<id>go-live</id>
<configuration>
<target>
<!-- go live! -->
<exec executable="${basedir}/deploy2server.sh" failonerror="true" dir="${basedir}">
<arg value="deploy" />
<arg value="${deploy.to.server}" />
<arg value="${jetty.port.live}" />
</exec>
</target>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
and run this:
mvn antrun:run#go-live
This solution avoids the target being run by accident, ie. it does not run just by typing "mvn antrun:run" and it also does not run during regular maven runs. I'm using this for qa auto-deployment in my jenkins instance after all modules incl integration done against the final distribution package have been successfully executed.
I just ran into the same problem and finally figured it out: If you want to run the ant tasks only once, you can set the plugin up like this:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<configuration>
<target name="init_config_files">
<!-- init files -->
</target>
</configuration>
</plugin>
and use mvn antrun:run to execute it. That way, the ant stuff is not bound to any phase.
If you need to run some part of build on special conditions (e.g. once), you can put those parts into a Maven profile and then invoke Maven specifying profile name, e.g. mvn -p init_config_files package
For creating configuration of my application I need to run bash script.
Is it possible to integrate execution of Bash scripts in Maven, maybe there are some plugins?
Could the Bash Maven Plugin help you? (Disclaimer: I initiated it, so please send me feedback)
<build>
<plugins>
<plugin>
<!-- Run with:
mvn bash:run
mvn install
-->
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>bash-maven-plugin</artifactId>
<version>1.0-SNAPSHOT</version>
<executions>
<execution>
<id>test</id>
<phase>integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
<configuration>
<script>
# Here you can execute shell commands
echo "Tomcat will start"
/opt/apache-tomcat/bin/startup.sh
</script>
</configuration>
</plugin>
</plugins>
</build>
You will need to install this maven plugin in your own Maven repo.
Like Konstantin: When you execute a shell script, you're not portable anymore.
You can do this, see answer:
I want to execute shell commands from maven's pom.xml
But it is not advisable, as this produces not so portable builds. Why do you need this in first place? Using this plugin usually indicates some weird necessity in project build
Would look more like:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.8</version>
<executions>
<execution>
<id>generateSources</id>
<phase>generate-sources</phase>
<configuration>
<tasks>
<exec executable="/bin/bash">
<arg value="myFirst.sh" />
<arg value="inputOne" />
</exec>
<exec executable="/bin/bash">
<arg value="src/mySecond.sh" />
<arg value="inputTwo" />
</exec>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
With myFirst.sh:
echo "call to myFirst.sh, message ${1}"
Solved. The problem is, executable is working in a different way for bash. This code is working. Write it in pom.xml
<plugin>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<groupId>org.codehaus.mojo</groupId>
<executions>
<execution><!-- Run our version calculation script -->
<id>Renaming build artifacts</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>bash</executable>
<commandlineArgs>handleResultJars.sh</commandlineArgs>
</configuration>
</execution>
</executions>
</plugin>
If at all possible, I'd recommend using a scripting language that runs inside the JVM with dependencies that are captured either in your project or in the maven repository. That way your builds are platform independent and your dependencies are captured (i.e. you don't loose the build machine and realize your bash script was specific to that box). I showed an example in this post of using jacl. There are also good examples of using javascript and groovy inside antrun (though there may be more straightforward ways of calling them directly).
Use the maven-antrun-plugin artifact. This way, you can execute several executables sequentially more easily than exec-maven-plugin. Example:
* The <exec> tag is the important one here.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<exec executable="my1.sh">
<arg value="input1"/>
</exec>
<exec executable="my2.sh">
<arg value="input2"/>
</exec>
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
To experiment with commands you can use exec:exec:
$ mvn exec:exec -q -Dexec.executable=echo -Dexec.args="your arguments"
your arguments
$ mvn exec:exec -q -Dexec.executable=echo -Dexec.args="'your arguments'"
your arguments
This demonstrates:
passing arguments: if you need to pass several arguments: just split them with space
if you need to pass an argument with spaces: enclose it in quotes, as you would do in bash script/terminal
-q to shut up the mvn log