Hot questions for Using Lightweight Java Game Library in maven

Question:

Im unable to successfully add proper dependencies for LWJGL in maven project. I have copied lwjgl dependency tempalte from maven repository, added it to my pom.xml and tried to run basic application from lwjgl.org, without success.

Below you have my pom.xml file, unfortunately when I try to run my first application i get:

Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to locate library: lwjgl.dll

I found some sollution that I need to download all jars and attach them as jar library, so I did. File > Project Structure > Librarires > added folder which store all jars for LWJGL, unfortunately this is still not working.

<dependencies>
<dependency>
    <groupId>org.lwjgl</groupId>
    <artifactId>lwjgl</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>org.lwjgl</groupId>
    <artifactId>lwjgl-glfw</artifactId>
    <version>3.2.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.lwjgl/lwjgl-opengl -->
<dependency>
    <groupId>org.lwjgl</groupId>
    <artifactId>lwjgl-opengl</artifactId>
    <version>3.2.1</version>
</dependency>
<dependency>
    <groupId>java3d</groupId>
    <artifactId>vecmath</artifactId>
    <version>1.3.1</version>
</dependency>
</dependencies>

Answer:

Please go to https://lwjgl.org/customize, select a variant (Release, Stable or Nightly), select "Mode" = "Maven", select all your needed/wanted modules and simply copy/paste the produced pom.xml snippet.

Question:

I'm using Maven for a project using LWJGL3 version 3.1.5. I used the pom generator on the LWJGL website and IntelliJ tells me the following on line 4:

Dependency 'org.lwjgl:lwjgl:3.1.5' not found

This is the problematic part of my pom.xml:

<dependency>
    <groupId>org.lwjgl</groupId>
    <artifactId>lwjgl</artifactId>
    <version>${lwjgl.version}</version>
</dependency>

How can I fix this?


Answer:

Try re-importing your dependencies.

In IntelliJ, you can right-click on the pom.xml and do maven > reimport

Also, make sure you have access to the repository you are importing from (i.e. internet access, no firewall or proxy blocking the repo, etc.)

Question:

I am trying to setup a LWJGL project using Maven. I am using the example "getting started" source code from the official website.

This includes a few lines accessing LWJGL's manifest attributes, such as a simple version check:

System.out.println("Hello LWJGL " + Version.getVersion() + "!");

This runs without any problems in the Eclipse environment (of course after having built the project with Maven), but when running clean install and then running **-jar-with-dependencies.jar through cmd, the following exception get's thrown:

java.lang.NullPointerException
        at org.lwjgl.system.APIUtil.apiGetManifestValue(APIUtil.java:97)
        at org.lwjgl.Version.getVersion(Version.java:33)
        at HelloWorld.run(HelloWorld.java:43)
        at HelloWorld.main(HelloWorld.java:130)

This is because the Manifest object created by APIUtil does not include any attributes - but only in the built version by Maven.

Why is this? Is my pom.xml buggy, or is LWJGL 3.0.0 just not ready for this?

This is my pom.xml:

<properties>
    <mainClass>HelloWorld</mainClass>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <finalName>${project.artifactId}-${project.version}.jar</finalName>
</properties>

<dependencies>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl</artifactId>
        <version>3.0.0</version>
    </dependency>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl-platform</artifactId>
        <version>3.0.0</version>
        <classifier>natives-windows</classifier>
    </dependency>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl-platform</artifactId>
        <version>3.0.0</version>
        <classifier>natives-linux</classifier>
    </dependency>
    <dependency>
        <groupId>org.lwjgl</groupId>
        <artifactId>lwjgl-platform</artifactId>
        <version>3.0.0</version>
        <classifier>natives-osx</classifier>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.5.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>single</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
                <archive>
                    <manifest>
                        <mainClass>${mainClass}</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

Answer:

This errors happens because LWJGL 3.0.0 is looking inside the Manifest a property called "Implementation-Version", but when you made the uber-jar, this property was not set.

This is not really an issue with how you made the uber-jar: the Manifest that was created by maven-assembly-plugin looks like:

Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: Me
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_102
Main-Class: HelloWorld

You can see it inside META-INF/MANIFEST.MF of the jar-with-dependencies. This file does not have a "Implementation-Version" property. This is normal: when this executable JAR was created, all the MANIFEST of all dependencies were (rightfully) ignored, only to generate one containing the "Main-Class", just so that the JAR is executable.

The uber-jar cannot contain what is inside each of the dependencies manifest. For example, "Implementation-Version" is a property that is present in the manifest of multiple libraries, so which one should it keep? (There can be only one Manifest at the end, in the uber-jar). So the issue comes up because we're making an executable JAR, which can only have 1 Manifest so it cannot aggregate all the properties inside each of the dependencies manifest.

There are 2 possible solutions:

  1. Ignore it. After all, this is not really an error.
  2. Don't make an executable jar by embedding all the dependencies inside a single JAR, but create a ZIP assembly with each dependencies inside a lib folder: this way, each Manifest will be kept. This is done by telling the maven-jar-plugin to add a Manifest entry for the main class with the addition of the classpath and creating a custom assembly descriptor.

    <plugin>
        <artifactId>maven-jar-plugin</artifactId>
        <version>3.0.2</version>
        <configuration>
            <archive>
                <manifest>
                    <mainClass>${mainClass}</mainClass>
                    <addClasspath>true</addClasspath>
                </manifest>
            </archive>
        </configuration>
    </plugin>
    <plugin>
        <artifactId>maven-assembly-plugin</artifactId>
        <version>2.6</version>
        <executions>
            <execution>
                <phase>package</phase>
                <goals>
                    <goal>single</goal>
                </goals>
            </execution>
        </executions>
        <configuration>
            <descriptors>
                <descriptor>/path/to/assembly.xml</descriptor>
            </descriptors>
        </configuration>
    </plugin>
    

    where /path/to/assembly.xml is the path to the assembly descriptor, relative to the location of the POM, being:

    <assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3" 
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
      <id>dist</id>
      <formats>
        <format>zip</format>
      </formats>
      <dependencySets>
        <dependencySet>
          <outputDirectory>lib</outputDirectory>
          <useProjectArtifact>true</useProjectArtifact>
        </dependencySet>
      </dependencySets>
    </assembly>
    

    With such a configuration, running mvn clean install will create a ZIP file artifactId-version-dist.zip. Unpacking it and running (replacing <finalName> with the finalName of your JAR)

    java -jar lib\<finalName>.jar
    

    will print the version without any issues.

Question:

I want to include LWJGL via Maven in my project. I get the .jar files but the natives are not in the classpath.

With the help of google I found out that I should use mavennatives in order to automatically extract and copy the natives. However mavennatives will only find the natives that start with native- and the LWJGL-natives all have names like {artifactId}-{version}-natives-{os}.jar.

Question: How can I get Maven to import the dependencies with the proper names and extract these natives?

My pom.xml:

<project ... >
     ...
    <build>
        <plugins>
            ...
            <plugin>
                <groupId>com.googlecode.mavennatives</groupId>
                <artifactId>maven-nativedependencies-plugin</artifactId>
                <version>0.0.7</version>
                <executions>
                    <execution>
                        <id>unpacknatives</id>
                        <goals>
                            <goal>copy</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

    <dependencies>
        ...
        <dependency>
            <groupId>org.lwjgl</groupId>
            <artifactId>lwjgl</artifactId>
            <version>3.0.0a</version>
        </dependency>
        <dependency>
            <groupId>org.lwjgl</groupId>
            <artifactId>lwjgl-platform</artifactId>
            <version>3.0.0a</version>
            <classifier>natives-linux</classifier>
        </dependency>
        <dependency>
            <groupId>org.lwjgl</groupId>
            <artifactId>lwjgl-platform</artifactId>
            <version>3.0.0a</version>
            <classifier>natives-windows</classifier>
        </dependency>
    </dependencies>
</project>

Answer:

From official documentation of the plugin:

This plugin unpacks every dependency with a classifier beginning with natives-.

That's exactly your use case, the documentation points to the classifier element, which in your case is natives-linux or natives-windows.

Accordingo to the documentation, theses cases will be handled:

This are the default values, when enabling separateDirs the plugin will unpack each native dependency to a subdir of the nativesTargetDir named like its classifier (for example: natives-windows will go to target/natives/windows)

Indeed the whole library's jar is in the form of {artifactId}-{version}-natives-{os}.jar but in Maven the classifier is exactly the string between the {version} and the extension of the file: in this case natives-{os}, which starts by natives and as such is handled by the library.

Question:

I've imported an existing multi-module Maven project into IntelliJ. The parent project itself builds and runs fine, but I'm trying to run one of the modules (a popup viewer window) on its own. When I do, I get this error:

[LWJGL] Failed to load a library. Possible solutions: a) Add the directory that contains the shared library to -Djava.library.path or -Dorg.lwjgl.librarypath. b) Add the JAR that contains the shared library to the classpath. [LWJGL] Enable debug mode with -Dorg.lwjgl.util.Debug=true for better diagnostics. [LWJGL] Enable the SharedLibraryLoader debug mode with -Dorg.lwjgl.util.DebugLoader=true for better diagnostics. Exception in thread "main" java.lang.UnsatisfiedLinkError: Failed to locate library: lwjgl.dll

I'm not sure how to fix this, and I'm confused on how the overall project builds and runs fine, but the module has issues running. lwjgl is included in the pom.xml, so shouldn't Maven take care of this dependency?


Answer:

So my problem turned out to be that I'm on a Windows computer, but the project I've been given has its pom.xml configured so only lwjgl native-macos jars are downloaded. I fixed this by editing the main pom.xml to include two separate profiles for mac vs. windows and using them in the classifier for the lwjgl dependencies.

Before I figured this out, I found a workaround by downloading the lwjgl zip from https://www.lwjgl.org/download, extracting the jar files, and storing them as a library in IntelliJ under File > Project Structure. (I followed the instructions at http://wiki.lwjgl.org/wiki/Setting_Up_LWJGL_with_IntelliJ_IDEA.html)

Question:

I've started developing a 3D java game engine using OpenGL in Codenvy IDE, using Maven. I've configured to run Java 8, and I've set up the dependencies in pom.xml that is required for LWJGL. However, when I run a test window, I get a NoClassDefFoundError. I'm unsure why this happens, considering Maven is configured to store all .Jar dependencies into one filem so accessing them shouldn't be a concern. All the files have downloaded properly into the External Packages directory in my Codenvy project.

Here is the pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
   <modelVersion>4.0.0</modelVersion>
   <groupId>engineTester.First3DEngine</groupId>
   <artifactId>First3DEngine</artifactId>
   <version>1.5.7</version>
   <packaging>jar</packaging>

  <dependencies>  
    <dependency>
      <groupId>org.lwjgl.lwjgl</groupId>
      <artifactId>lwjgl</artifactId>
      <version>2.8.4</version>
    </dependency>

    <dependency>
      <groupId>org.lwjgl.lwjgl</groupId>
      <artifactId>lwjgl_util</artifactId>
      <version>2.8.4</version>
    </dependency>

    <dependency>
      <groupId>org.lwjgl.lwjgl</groupId>
      <artifactId>lwjgl_util_applet</artifactId>
      <version>2.8.4</version>
    </dependency>

    <dependency>
      <groupId>com.typesafe.slick</groupId>
      <artifactId>slick_2.10</artifactId>
      <version>3.1.1</version>
    </dependency>
    <dependency>
      <groupId>java3d</groupId>
      <artifactId>vecmath</artifactId>
  <version>1.3.1</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <!-- Build an executable JAR -->
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-jar-plugin</artifactId>
        <version>2.6</version>
        <configuration>
          <argLine>-Xmx1024m</argLine>
          <archive>
            <manifest>
          <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
        <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
              <addClasspath>true</addClasspath>
              <classpathPrefix>lib/</classpathPrefix>
              <mainClass>engineTester.MainGameLoop</mainClass>
            </manifest>
          </archive>
        </configuration>
      </plugin>
    </plugins>
   </build>
</project>

And here is where I'm getting the issue:

package engineTester;

import org.lwjgl.opengl.Display;

import renderEngine.DisplayManager;
import util.Console;

public class MainGameLoop {
    public static void main(String[] args){
        new Console();
        DisplayManager.createDisplay();  <-- line which throws the error
        while(!Display.isCloseRequested()){
            //game logic
            //render
            DisplayManager.updateDisplay();
        }

        DisplayManager.closeDisplay();

    }
}

DisplayManager.createDisplay() method:

public static void createDisplay(){
    ContextAttribs attribs = new ContextAttribs(3,2);
    attribs.withForwardCompatible(true);
    attribs.withProfileCore(true);

    try{
        Display.setDisplayMode(new DisplayMode(WIDTH,HEIGHT));
        Display.create(new PixelFormat(), attribs);
    } catch (LWJGLException e){
        e.printStackTrace();
    }

    GL11.glViewport(0,0,WIDTH,HEIGHT);
}

And finally the full error:

Exception in thread "main" java.lang.NoClassDefFoundError:     org/lwjgl/LWJGLException
    at engineTester.MainGameLoop.main(MainGameLoop.java:11)
Caused by: java.lang.ClassNotFoundException: org.lwjgl.LWJGLException
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    ... 1 more

Thanks for your help!


Answer:

You can either use maven-assembly-plugin to make a fat jar that can be run by itself or you can run your program using maven so that the compile time jars will be added to your classpath.

To run using maven:

mvn exec:java -Dexec.mainClass="engineTester.MainGameLoop"

To use the assembly plugin:

<build>
    <plugins>
         <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.5.5</version>
            <configuration>
                <archive>
                    <manifest>
                        <mainClass>engineTester.MainGameLoop</mainClass>
                    </manifest>
                </archive>
                <descriptorRefs>
                    <descriptorRef>jar-with-dependencies</descriptorRef>
                </descriptorRefs>
            </configuration>
            <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>
    </plugins>
</build>

This will create a jar with -jar-with-depencencies added to the name in the target directory. That can then just be run with java -jar jarfile.