Search code examples
javamavenjogl

Executable jar with dependencies and dll dependency using maven


I have a Java project using 4 OpenGL jars and 1 dll that I've received to work with as a Project for a course in Computer Graphics. I want to make maven build it for me into an executable jar so I could just git clone my repo from a different computer and build it using maven for execution. (Preferably using maven clean install)

What I did so far:

  • Installed the 4 jars and the dll into a local repository inside the project. This way, I am just setting the dependencies and the files are copied from the git repo, for example:

      <repositories>
          <repository>
              <id>local-maven-repo</id>
              <url>file:///${project.basedir}/local-maven-repo</url>
          </repository>
      </repositories>
    
      <dependencies>
          <dependency>
              <groupId>com.computer.graphics</groupId>
              <artifactId>jogl</artifactId>
              <version>1.0</version>
          </dependency>
          <dependency>
              <groupId>com.computer.graphics</groupId>
              <artifactId>gluegenrt</artifactId>
              <version>1.0</version>
              <scope>runtime</scope>
              <type>dll</type>
          </dependency>
          ...
    
  • Set maven assembly plugin with an assembly.xml in src/assembly.xml:

          <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-assembly-plugin</artifactId>
    
              <configuration>
                  <!--        Configure a class for executable jar        -->
                  <archive>
                      <manifest>
                          <mainClass>Main class</mainClass>
                      </manifest>
                  </archive>
                  <!--          Points to the assembly descriptor to use          -->
                  <descriptors>
                      <descriptor>src/assembly.xml</descriptor>
                  </descriptors>
              </configuration>
    
              <!--        Bind goal assembly:single into build process        -->
              <executions>
                  <execution>
                      <id>make-assembly</id> <!-- this is used for inheritance merges -->
                      <phase>package</phase> <!-- bind to the packaging phase -->
                      <goals>
                          <goal>single</goal>
                      </goals>
                  </execution>
              </executions>
          </plugin>
    
  • Tried to include the jars and the dll into the executable jar:

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.1.0 http://maven.apache.org/xsd/assembly-2.1.0.xsd">

    <id>graphics-assembly</id>
    <formats>
        <format>jar</format>
    </formats>
    <includeBaseDirectory>false</includeBaseDirectory>

    <dependencySets>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <useProjectArtifact>true</useProjectArtifact>
            <scope>runtime</scope>
            <unpack>true</unpack>
            <includes>
                <include>*:jar:*</include>
            </includes>
        </dependencySet>
        <dependencySet>
            <outputDirectory>/</outputDirectory>
            <includes>
                <include>*:dll*</include>
            </includes>
        </dependencySet>
    </dependencySets>
</assembly>

From what I understood, the dll file should be in target folder near the executable jar, but even if I do copy manualy the file, when I try to run the jar using java -jar executable-jar.jar for example, I get the following error:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 1
        at jogamp.opengl.windows.wgl.awt.WindowsAWTWGLGraphicsConfigurationFactory.chooseGraphicsConfigurationImpl(WindowsAWTWGLGraphicsConfigurationFactory.java:170)
        at javax.media.nativewindow.GraphicsConfigurationFactory.chooseGraphicsConfiguration(GraphicsConfigurationFactory.java:422)
        at javax.media.opengl.awt.GLCanvas.chooseGraphicsConfiguration(GLCanvas.java:1516)
        at javax.media.opengl.awt.GLCanvas.addNotify(GLCanvas.java:614)
        at java.desktop/java.awt.Container.addNotify(Container.java:2801)
        at java.desktop/java.awt.Window.addNotify(Window.java:787)
        at java.desktop/java.awt.Frame.addNotify(Frame.java:493)
        at java.desktop/java.awt.Window.show(Window.java:1049)
        at java.desktop/java.awt.Component.show(Component.java:1720)
        at java.desktop/java.awt.Component.setVisible(Component.java:1667)
        at java.desktop/java.awt.Window.setVisible(Window.java:1032)
  • I am using intellij and simply linked the files using File -> Project Structure -> Libraries -> added the folder containing the jars and the dll. When I run / build the project using intellij, everything works.

What am I doing wrong? is there a better way to do that?


Solution

  • I ended up deleting the dependencySet of the dll from the assembly file and copy the dll dependency with maven-dependency-plugin as follow:

    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-dependency-plugin</artifactId>
        <version>3.1.2</version>
        <executions>
            <execution>
                <id>copy</id>
                <phase>package</phase>
                <goals>
                    <goal>copy</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <artifactItems>
                <artifactItem>
                    <groupId>com.computer.graphics</groupId>
                    <artifactId>gluegenrt</artifactId>
                    <version>1.0</version>
                    <type>dll</type>
                    <outputDirectory>${project.build.directory}</outputDirectory>
                    <destFileName>gluegen-rt.dll</destFileName>
                </artifactItem>
            </artifactItems>
        </configuration>
    </plugin>
    

    The ArrayIndexOutOfBoundsException occurred because I was using jdk 16 instead of jdk 12 to run the jar. Hope this helps others.