1

I have an example app with a main class in Groovy and a main class in Java. maven-jar-plugin successfully builds an executable jar when the Java class is specified as the main class but not when the Groovy class is. Let me demonstrate. Here is my build:

<build>
  <plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-jar-plugin</artifactId>
      <version>3.0.2</version>
      <configuration>
        <archive>
          <manifest>
            <mainClass>com.example.hello.JavaHello</mainClass>
          </manifest>
        </archive>
      </configuration>
    </plugin>
    <plugin>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <compilerId>groovy-eclipse-compiler</compilerId>
        <verbose>false</verbose>
        <source>${java.compiler.version}</source>
        <target>${java.compiler.version}</target>
      </configuration>
      <dependencies>
        <dependency>
          <groupId>org.codehaus.groovy</groupId>
          <artifactId>groovy-eclipse-compiler</artifactId>
          <version>${groovy-eclipse-compiler.version}</version>
        </dependency>
        <dependency>
          <groupId>org.codehaus.groovy</groupId>
          <artifactId>groovy-eclipse-batch</artifactId>
          <version>2.4.3-01</version>
        </dependency>
      </dependencies>
    </plugin>
  </plugins>
</build>

Then compiling and running:

$ mvn -q clean package && \
>   jar xf target/hello-world-1.0-SNAPSHOT.jar META-INF/MANIFEST.MF && \
>   cat META-INF/MANIFEST.MF && rm -r META-INF && \
>   java -jar target/hello-world-1.0-SNAPSHOT.jar
Manifest-Version: 1.0
Built-By: tytk
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_66
Main-Class: com.example.hello.JavaHello

Hello from Java!

Then, changing the mainClass to:

<mainClass>com.example.hello.GroovyHello</mainClass>

And running the same command:

$ mvn -q clean package && \
>   jar xf target/hello-world-1.0-SNAPSHOT.jar META-INF/MANIFEST.MF && \
>   cat META-INF/MANIFEST.MF && rm -r META-INF && \
>   java -jar target/hello-world-1.0-SNAPSHOT.jar
Manifest-Version: 1.0
Built-By: tytk
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_66
Main-Class: com.example.hello.GroovyHello

Error: Could not find or load main class com.example.hello.GroovyHello

Each class just has a main method with a println statement.

So how can I get an executable jar with my groovy classes? maven-shade-plugin works but I don't want a fat jar - I want dependencies excluded.

tytk
  • 2,082
  • 3
  • 27
  • 39
  • can you show us the project structure? where is the `GroovyHello` class located (folder path) ? – AlinG Nov 06 '16 at 14:52
  • both `GroovyHello` and `JavaHello` are located at `hello-world/src/main/java/com/example/hello/` – tytk Nov 07 '16 at 03:46

1 Answers1

1

I see your note about dependencies excluded, which is why you don't want to use maven-shaded-plugin. I'm not sure how well that will work with a Groovy class.

(But it's worth noting explicitly to myself and other Java newbies: maven-jar-plugin does not include dependencies)

First possibility: is Java barfing because it can't find Groovy, and really wants it?

I found a SO answer about ability to load main classes that extend from dependent classes.

I know that a plain Groovy script file, without an explicit class declaration, that the compiler wraps that up in a class it extends from (Groovy's) Script. I don't know what happens if you write your own explicit class - I'd unpackage the .jar and use a Java Decompiler to look at the generated code, to see if that gives you any clues.

Second possibility: package name

That feature about Groovy creating a class for you if you haven't explicitly declared one, doesn't seem to be able to put that implicit Java class inside a package based on the directory structure. I thought this worked in the past: not sure if I'm seeing a bug here, a new feature, or if I'm mis-remembering.

So, two ways to fix this:

  1. Add a package declaration to your Groovy script.

    package com.example.hello
    println "I'm Groovy!"
    
  2. Have your maven mainClass tag refer to the class without package namespace (ie: GroovyHello instead of com.example.hello.GroovyHello

Community
  • 1
  • 1
RyanWilcox
  • 13,890
  • 1
  • 36
  • 60