9

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

simpatico
  • 10,709
  • 20
  • 81
  • 126
  • possible duplicate of [Maven exec plugin- how to include "system" classpath?](http://stackoverflow.com/questions/5286279/maven-exec-plugin-how-to-include-system-classpath) – Joe Sep 28 '13 at 08:44
  • You should probably use the java mojo instead of the exec mojo, and see options listed there: http://mojo.codehaus.org/exec-maven-plugin/java-mojo.html. Especially executableDependency, includePluginDependencies and includeProjectDependencies I guess. – Tome Sep 30 '13 at 08:39

3 Answers3

5

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.

subhasish
  • 84
  • 1
  • 4
  • What section should this `...` block be put in? I tried adding it to `...` to add a directory `/etc/hbase/conf` to the classpath, but it seems to have no effect. – Ken Williams Apr 16 '14 at 14:38
  • 2
    What if you want a dependency AND a local path in exec:exec, is that possible? – niken Jul 21 '16 at 14:58
3

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..

alexgirao
  • 885
  • 9
  • 9
0

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

  • 5
    Surefire is the plugin used to run the unit tests. The question is related to adding additional jars at runtime using the exec plugin so modifying his POM as you describe will not help/work. From your link "The surefire plugin builds the **test** classpath in the following order" – Steven Magana-Zook Mar 21 '14 at 17:48
  • 4
    While this answer links to maven-surefire-plugin, it shows a proper example how to extend the classpath. exec-maven-plugin supports it but does not provide an example, see http://www.mojohaus.org/exec-maven-plugin/java-mojo.html#additionalClasspathElements – Konstantin Pelepelin Oct 03 '16 at 16:08