How to set classpath for mvn exec:exec? - maven

I'm trying to have mvn exec:exec (or mvn exec:java) run my program with a local jar in the classpath. However the jar fails to load:
Exception in thread "main" java.lang.Error: Unable to load voice directory. java.lang.ClassNotFoundException: com.sun.speech.freetts.en.us.cmu_us_slt_arctic.ArcticVoiceDirectory
at com.sun.speech.freetts.VoiceManager.getVoiceDirectories(VoiceManager.java:211)
at com.sun.speech.freetts.VoiceManager.getVoices(VoiceManager.java:111)
at com.sun.speech.freetts.VoiceManager.getVoice(VoiceManager.java:521)
at xpress.audio.TTS.<init>(TTS.java:66)
at xpress.audio.TTS.<init>(TTS.java:62)
at xpress.audio.AudioProducer.main(AudioProducer.java:18)
Running the program directly from the CLI using java works:
C:\XpressAudio\target\classes>java -cp "C:\XpressAudio\target\XpressAudio-1.0-SN
APSHOT-jar-with-dependencies.jar;C:\XpressAudio\cmu_us_slt_arctic.jar;C:\XpressA
udio\en_us.jar;C:\XpressAudio\*" xpress.audio.AudioProducer
Here's the <build> part of my pom.xml:
<build>
<plugins>
<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>java</executable>
<mainClass>xpress.audio.AudioProducer</mainClass>
</configuration>
<dependencies>
<dependency>
<groupId>cmu_us</groupId>
<artifactId>slt_arctic</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/cmu_us_slt_arctic.jar</systemPath>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
Could someone tell me how should I edit the pom.xml such that mvn exec:exec works like the java command above?
com.sun.speech.freetts.en.us.cmu_us_slt_arctic.ArcticVoiceDirectory is a class in cmu_us_slt_arctic.jar

In maven it is possible to include a local jar (which is outside of maven repository) using systemPath. But since the scope is system (for dependencies declared with systemPath), there are few limitations and because of that it only works with exec:java.
For exec:exec, the above solution will not work because maven does not include system scoped dependencies in its generated (runtime) classpath (%classpath) so the solution is to use your own classpath instead of maven generated classpath as shown below.
<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>java</executable>
<arguments>
<argument>-classpath</argument>
<argument>local.jar;target/project-jar-with-dependencies.jar</argument>
<argument>xpress.audio.AudioProducer</argument>
</arguments>
</configuration>
</plugin>
Replace local.jar with all the jar files that are required to be present at some fixed location (here project root is assumed, where pox.xml is located). Also note the use of 'project-jar-with-dependencies.jar', in your case it should be target\XpressAudio-1.0-SN
APSHOT-jar-with-dependencies.jar.

standard java does not allow us to specify multiple -cp arguments, but exec-maven-plugin does, so
<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>./java.pl</executable>
<arguments>
<argument>-ea</argument>
<argument>-cp</argument><argument>.</argument>
<argument>-cp</argument><argument>my.jar</argument>
<argument>-cp</argument><classpath/>
<argument>org.example.ConfigByXml</argument>
</arguments>
</configuration>
</plugin>
note the call to java.pl above, this is the trick
#!/usr/bin/env perl
while (#ARGV) {
$arg = shift;
if ($arg eq '-cp' or $arg eq '-classpath') {
push #cp, shift;
next;
}
push #args, $arg;
}
unshift #args, 'java', '-cp', join(':', #cp);
# print 'args: ', join(' --- ', #args); # uncomment to debug
exec #args;
understand what java.pl does and use it or do the equivalent in bash, cmd, powershell, whatever..

To set additional classpath in maven you should use in your maven configuration file as below:
<additionalClasspathElements>
<additionalClasspathElement>path/to/additional/jar</additionalClasspathElement>
</additionalClasspathElements>
For more detail:
http://maven.apache.org/surefire/maven-surefire-plugin/examples/configuring-classpath.html

Related

Passing vm arguments to exec-maven-plugin

Guys I have upgraded my project to Java 17 that's why I need these lines to VM to my program works without error.
=--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED
My project is working but I have another sub project which I use for testing purposes.It is run on JavaFX and it need previous arguments to work correctly.
I have tried adding as CommandLineArgs and arguments but still arguments are not passing through to vm and giving errors.
<profile>
<id>smoke</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy jars for tests</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>false</includePluginDependencies>
<stripVersion>true</stripVersion>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
</execution>
</executions>
<configuration>
<classpathScope>test</classpathScope>
<includeProjectDependencies>false</includeProjectDependencies>
<includePluginDependencies>false</includePluginDependencies>
<executable>${env.HOME}/java/bin/java.exe</executable>
<workingDirectory>${project.build.directory}</workingDirectory>
<arguments>
<argument>-javaagent:${env.HOME}/wildfly/standalone/lib/ext/agent.jar</argument>
<argument>-classpath</argument>
<argument>lib/*;classes</argument>
<argument>-DJBOSS_HOME=${JBOSS_HOME}</argument>
<argument>-DJAVA_HOME=${env.HOME}/java</argument>
<argument>-Duser.home=${env.USERPROFILE}</argument>
<argument>-Djava.library.path=${JBOSS_HOME}/bin</argument>
<argument>-DTESTING_FROM_COMMANDLINE=true</argument>
<mainClass>com.test.GenerateSmoke</mainClass>
<commandlineArgs>-Dexec.args=--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED</commandlineArgs>
</arguments>
</configuration>
</plugin>
</plugins>
</build>
</profile>
If you have any idea please let me know.Thanks
I had a similar issue when running tests with the maven-surefire-plugin.
In my case I added it like this into the pom:
<configuration>
<argLine>${argLine} --add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.util=ALL-UNNAMED</argLine>
</configuration>
Maybe it is the same in your case.
The plugins configuration options are documented here: https://www.mojohaus.org/exec-maven-plugin/exec-mojo.html
commandlineArgs or -Dexec.args are both an alternative option to override the entire executed command line you specify. These can not be used together with (other) arguments.
So you either define the entire java command line to execute as:
arguments in the pom, or
commandlineArgs in the pom, or
exec.args as an environment variable (so mvn exec:exec -Dexec.args=...)
You should be able to add the arguments to your current plugin configuration like so:
<configuration>
<arguments>
<argument>...</argument>
<argument>--add-opens</argument>
<argument>java.base/java.lang=ALL-UNNAMED</argument>
<argument>--add-opens</argument>
<argument>java.base/java.util=ALL-UNNAMED</argument>
<argument>...</argument>
</arguments>
</configuration>
Depending on what you run these arguments might need to be inserted in a specific place, so the order of these arguments matters.
That is where you can experiment with substituting the ... in my example with your current arguments.
As a test i've ran a java -jar with these options, and that works. I've enabled the maven argument -X for debug logging.
[DEBUG] Executing command line: [some\path\jdk-17.0.2\bin\java.exe, --add-opens, java.base/java.lang=ALL-UNNAMED, --add-opens, java.base/java.util=ALL-UNNAMED, -jar, my.jar]
And if i make an "accidental" typo in my add-opens we see that these arguments are indeed parsed by the java process:
[DEBUG] Executing command line: [some\path\jdk-17.0.2\bin\java.exe, --add-typo, java.base/java.lang=ALL-UNNAMED, --add-opens, java.base/java.util=ALL-UNNAMED, -jar, my.jar]
Unrecognized option: --add-typo
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.

Wrapping Ant in Maven - JAVA_HOME points to the JRE but works with just Ant

I have an Ant project that builds just fine on its own. I'm now trying to wrap it in a Maven build that will kick off the Ant build using maven-antrun-plugin. When I do this the build fails and I get this error,
[ERROR] C:\Users\bobby\workspace\libraries\build-targets\common-targets.xml:170: Unable to find a javac compiler;
[ERROR] com.sun.tools.javac.Main is not on the classpath.
[ERROR] Perhaps JAVA_HOME does not point to the JDK.
[ERROR] It is currently set to "C:\Java\jdk1.8.0_65\jre"
There are a lot of SOF posts on this error but I feel like mine is unique since it only happens when I'm wrapping the Ant build in Maven i.e., I do not get this error on the same project when I just say $ ant build.
This is part of my pom.xml file
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>process-resources</phase>
<configuration>
<tasks>
<ant antfile="build.xml" target="build" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.3</version>
<executions>
<execution>
<id>add-jar</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>build/bin/myWarFile.war</file>
<type>war</type>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
My JAVA_HOME Environment Variable is set to C:\Java\jdk1.8.0_65.
The file that is mentioned in the error is from a library my work maintains where we keep all of our Jars. In that file here is what's on line 170
<target name="compile-src">
<!-- Compile source -->
<javac srcdir="${java.src.dir}"
destdir="${class.dir}"
debug="${debug.flag}"
deprecation="${deprecation.flag}"
nowarn="${warnings.flag}"
optimize="off"
source="${source.value}">
<classpath refid="compile.classpath"/>
</javac>
</target>
The line with source= is line 170.
It's a common issue. Try with this configuration:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
...
<!-- Add this dependency to your ant-run configuration -->
<dependencies>
<dependency>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
<version>1.5.0</version>
<scope>system</scope>
<systemPath>${java.home}/../lib/tools.jar</systemPath>
</dependency>
</dependencies>
...
</plugin>
Maven uses Java's system property java.home, which is not the same as the environment variable JAVA_HOME, but it is using it to compute its java.home by tacking on the jre sub-directory, as witnessed. Consequently, stuff needed by Ant is simply not available in the jre directory.
However, this configuration ensures that Ant's plugin dependencies are correctly satisfied.
You need to point to JDK not JRE. Just remove ire and try.
It is currently set to "C:\Java\jdk1.8.0_65\jre"
And if your JDK is set - another workaround - Can you copy tools.jar from jdk lib to jre lib and see if it works.

Logging configuration for the Apache Tomcat Maven plugin exec-war-only goal?

I would like to specify a logging configuration file via the extraResources tag described # http://tomcat.apache.org/maven-plugin-2.1/tomcat7-maven-plugin/exec-war-only-mojo.html#extraResources and am getting the following maven error
Failed to execute goal org.apache.tomcat.maven:tomcat7-maven-plugin:2.1:exec-war-only (tomcat-run) on project iot-service-embedded-tomcat: Unable to parse configuration of mojo org.apache.tomcat.maven:tomcat7-maven-plugin:2.1:exec-war-only for parameter extraResource: Cannot configure instance of org.apache.tomcat.maven.plugin.tomcat7.run.ExtraResource from log4j.properties
Here's the maven plugin entry:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<id>tomcat-run</id>
<goals>
<goal>exec-war-only</goal>
</goals>
<phase>package</phase>
<configuration>
...
<extraResources>
<extraResource>
log4j.properties
</extraResource>
</extraResources>
<extraDependencies>
...
<extraDependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>compile</scope>
</extraDependency>
</extraDependencies>
...
</configuration>
</execution>
</executions>
</plugin>
What is the proper syntax?
I was able to find the answer by looking at the the getters/setters in the Maven model Resource class. The proper syntax is:
<extraResources>
<extraResource>
<directory>path/to/resource/</directory>
<includes>
<include>resource.file.name</include>
</includes>
</extraResource>
</extraResources>

Specify javaagent argument with Maven exec plugin

I have a similar question to: this previous question
I am converting a Java project using Netbeans to Maven. In order to launch the program, one of the command-line arguments we need is the -javaagent setting. e.g.
-javaagent:lib/eclipselink.jar
I'm trying to get Netbeans to launch the application for development use (we will write custom launch scripts for final deployment)
Since I'm using Maven to manage the Eclipselink dependencies, I may not know the exact filename of the Eclipselink jar file. It may be something like eclipselink-2.1.1.jar based on the version I have configured in the pom.xml file.
How do I configure the exec-maven-plugin to pass the exact eclipselink filename to the command line argument?
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Xmx1000m</argument>
<argument>-javaagent:lib/eclipselink.jar</argument> <==== HELP?
<argument>-classpath</argument>
<classpath/>
<argument>my.App</argument>
</arguments>
</configuration>
</plugin>
I figured out a way that seems to work well.
First, setup the maven-dependency-plugin to always run the "properties" goal.
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.5.1</version>
<executions>
<execution>
<id>getClasspathFilenames</id>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
Later on, use the property it sets as documented here with the form:
groupId:artifactId:type:[classifier]
e.g.
<argument>-javaagent:${mygroup:eclipselink:jar}</argument>
Simply define a property for the eclipse link version and use the property in your <dependency> and the exec plugin:
<properties>
<eclipselink.version>2.4.0</eclipselink.version>
</properties>
<dependency>
<groupId>org.eclipse.persistence</groupId>
<artifactId>eclipselink</artifactId>
<version>${eclipselink.version}</version>
</dependency>
...
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<configuration>
<executable>java</executable>
<arguments>
<argument>-Xmx1000m</argument>
<argument>-javaagent:lib/eclipselink-${eclipselink.version}.jar</argument>
<argument>-classpath</argument>
<classpath/>
<argument>my.App</argument>
</arguments>
</configuration>
</plugin>
the maven-dependency-plugin and exec-maven-plugin should be put under the node ,otherwise it will not work

exec-maven-plugin not evaluating <classpath> dependencies properly

Context: I have a Maven goal that calls an executable (it happens to be a Groovy script, but it doesn't matter) which needs as an argument the path to a runtime ibrary (it happens to be a JDBC driver, but it doesn't matter either).
Instead of hardcoding the path to the driver, I'm constructing it as a classpath dependency, so that it's picked from whererever the Maven repository will happen to be (we have different environments with different OSes).
<classpath>
<dependency>postgresql:postgresql</dependency> <!-- groupId:artifactId -->
</classpath>
Problem: the classpath is not resolved as expected, instead of the path to the library, it is empty (and therefore the invocation fails).
The relevant parts of the pom.xml are below:
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901.jdbc4</version>
<scope>provided</scope>
</dependency>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>initialize-rule-plugin</id>
<phase>compile</phase>
<goals><goal>exec</goal></goals>
<configuration>
<executable>full\path\to\groovy</executable>
<arguments>
<argument>-cp</argument>
<classpath>
<dependency>postgresql:postgresql</dependency>
</classpath>
<argument>myscript.groovy</argument>
</arguments>
</configuration>
</execution>
</executions>
</plugin>
The debug output is:
[DEBUG] Configuring mojo 'org.codehaus.mojo:exec-maven-plugin:1.2.1:exec' with basic configurator -->
[DEBUG] (s) dependency = postgresql:postgresql
[DEBUG] (f) arguments = [-cp, Classpath { postgresql:postgresql}, ]
[...]
[DEBUG] Collected project artifacts [org.springframework:spring-context:jar:3.1.2.RELEASE:compile, org.springframework:spring-aop:jar:3.1.2.RELEASE:compile, org.springframework:spring-beans:jar:3.1.2.RELEASE:compile, org.springframework:spring-core:jar:3.1.2.RELEASE:compile, org.springframework:spring-expression:jar:3.1.2.RELEASE:compile, org.springframework:spring-asm:jar:3.1.2.RELEASE:compile, org.springframework:spring-webmvc:jar:3.1.2.RELEASE:compile, org.springframework:spring-context-support:jar:3.1.2.RELEASE:compile, org.springframework:spring-web:jar:3.1.2.RELEASE:compile, org.springframework:spring-tx:jar:3.1.2.RELEASE:compile, aopalliance:aopalliance:jar:1.0:compile, org.springframework:spring-orm:jar:3.1.2.RELEASE:compile, org.springframework:spring-jdbc:jar:3.1.2.RELEASE:compile, org.slf4j:slf4j-api:jar:1.7.1:compile, org.slf4j:jcl-over-slf4j:jar:1.7.1:runtime, org.slf4j:slf4j-log4j12:jar:1.7.1:runtime, log4j:log4j:jar:1.2.17:compile, javax.validation:validation-api:jar:1.0.0.GA:compile, org.hibernate:hibernate-validator:jar:4.3.0.Final:compile, org.jboss.logging:jboss-logging:jar:3.1.0.CR2:compile, org.hibernate:hibernate-entitymanager:jar:4.1.7.Final:compile, org.jboss.spec.javax.transaction:jboss-transaction-api_1.1_spec:jar:1.0.0.Final:compile, dom4j:dom4j:jar:1.6.1:compile, org.javassist:javassist:jar:3.15.0-GA:compile, org.hibernate:hibernate-core:jar:4.1.7.Final:compile, antlr:antlr:jar:2.7.7:compile, org.hibernate.common:hibernate-commons-annotations:jar:4.0.1.Final:compile, org.hibernate.javax.persistence:hibernate-jpa-2.0-api:jar:1.0.1.Final:compile, org.codehaus.jackson:jackson-mapper-asl:jar:1.9.10:compile, org.codehaus.jackson:jackson-core-asl:jar:1.9.10:compile, javax.servlet:jstl:jar:1.2:compile, commons-dbcp:commons-dbcp:jar:1.4:compile, commons-pool:commons-pool:jar:1.5.4:compile, org.codehaus.groovy:groovy-all:jar:2.0.5:compile]
[DEBUG] Collected project classpath [C:\projects\myproject\target\classes]
[DEBUG] Toolchains are ignored, 'executable' parameter is set to c:\full\path\to\groovy
[DEBUG] Executing command line: cmd /c c:\full\path\to\groovy.bat -cp C:\projects\myproject\target\classes myscript.groovy
As it can be seen, it does not pick up the classpath to the driver (which exists).
I have tried with and without also including the dependency's version number in the reference.
Thank you in advance.
As per my comment, I found a different way to do the same thing. Since there was no other solution posted, I'll post it as an answer if anyone runs into the same problem.
The key is to use a different plugin, which creates, on-the-fly, properties populated with the path to a jar.
<plugin>
<groupId>org.bitstrings.maven.plugins</groupId>
<artifactId>dependencypath-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<id>set-all</id>
<goals>
<goal>set</goal>
</goals>
<configuration>
<propertySets>
<propertySet>
<includes>
<include>postgresql:postgresql:jar</include>
</includes>
</propertySet>
</propertySets>
</configuration>
</execution>
</executions>
</plugin>
[...]
<execution>
<id>my-script</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>path/to/groovy</executable>
<arguments>
<argument>-cp</argument>
<argument>${postgresql:postgresql:jar}</argument>
<argument>my-script.groovy</argument>
</arguments>
</configuration>
</execution>

Resources