Code Monkey home page Code Monkey logo

Comments (4)

JuicyDragon avatar JuicyDragon commented on June 28, 2024 1

When you run the project all the JAR files in the root of lib of the engine distribution need to be on the class path. This is so that when code attempts to create an instance of a class Java knows where it can look for the code of that class.

The Gradle build file accomplishes this with these lines:

testRuntimeOnly(fileTree(baseDir = engineLibDir) {
    include("*.jar")
})

This is including the Engine lib JARs for the testRuntimeOnly configuration. The testRuntimeOnly (as the name implies) only defines dependencies to include while running a test. In context of a Java project, a test isn't just running the code, but specifically running methods annotated with @Test (example). The intent being you write one or more methods that automatically test the correctness of your code by performing some action and then verifying the outcome.

Based on your description above, it sounds like you are directly executing a main method in a class that is not annotated as a test. I believe this means the Gradle file is not configuring the class path to include the Engine JARs.

The simple solution would probably be to change that dependency definition to this:

runtimeOnly(fileTree(baseDir = engineLibDir) {
    include("*.jar")
})

I believe that will cover both test and ad-hoc invocations. The other approach is to ensure that the JVM that is running your code has the class path specified so that the Engine lib directory is included. This becomes especially relevant once you wish to execute your code outside of Gradle. See the information located here, specifically noting the -cp argument: https://github.com/Nuix/Nuix-Java-Engine-Baseline#construct-the-command

I think if you do either of those that should fix this particular issue.

from nuix-java-engine-baseline.

JuicyDragon avatar JuicyDragon commented on June 28, 2024

Hello @Trekky12 the NoClassDefFoundError I believe tends to be indicative of a JAR not being on the class path such that the class loader is unable to resolve it at run-time.

When you run your code, do you get any other output? Perhaps other warnings or errors?

How are you running this? The Gradle build file in the project does some things to get this working when you run a test, so depending on how you are running it, that setup step might not be happening.

These lines define where a Nuix Engine distribution is located on disk. Note that is determines the root directory using the environment variable NUIX_ENGINE_DIR. For example, mine is set to C:\EngineRelease because that is where I extracted it to. release

val nuixEngineDirectory: String = System.getenv("NUIX_ENGINE_DIR")
if(nuixEngineDirectory.isNullOrEmpty()){
    throw InvalidUserDataException("Please populate the environment variable 'NUIX_ENGINE_DIR' with directory containing a Nuix Engine release")
}
val engineLibDir = "${nuixEngineDirectory}\\lib"
val engineBinDir = "${nuixEngineDirectory}\\bin"
val engineBinX86Dir = "${nuixEngineDirectory}\\bin\\x86"

These lines ensure that all the JAR files in the lib sub-directory are on the class path when a test is ran.

testRuntimeOnly(fileTree(baseDir = engineLibDir) {
    include("*.jar")
})

These lines make sure that the tests are ran using JUnit and that the environment is configured before the test by calling the function configTestEnv.

tasks.getByName<Test>("test") {
    useJUnitPlatform()
    configTestEnv(this)
}

Finally, this is the test configuration function. It ensures that the JVM process started for a test has some specific arguments provided. It also is making sure certain environment variables are populated/forwarded to the test process.

fun configTestEnv(test: Test) {
    // Define a temp directory that we should be able to write to.  Used in several places to
    // provide a temp directory that engine can use!
    val nuixTempDirectory = findProperty("tempDir") ?: "${System.getenv("LOCALAPPDATA")}\\Temp\\Nuix"

    // Necessary for newer versions of Nuix.  Without this you will likely see
    // an error regarding loading the BouncyCastle crypto library at run-time
    test.jvmArgs(
            "--add-exports=java.base/jdk.internal.loader=ALL-UNNAMED",
            "-Xmx4G",
            "-Djava.io.tmpdir=\"${nuixTempDirectory}\"",
    )

    // Going to pass location of test data so tests can obtain, extract and otherwise use
    // test data they may need.  For example, if your test needs a Nuix case and there is a zip
    // file containing that case hosted online, your test might first see if the zip is already present
    // in the TestData directory, if not it can download it there and reuse it on future invocations.
    val testDataDirectory = "${projectDir}\\..\\TestData"

    // Specify output directory that tests can use to store output for post test review
    val testOutputDirectory = "${projectDir}\\..\\TestOutput\\${System.currentTimeMillis()}"

    test.setEnvironment(
            // Add our engine release's bin and bin/x86 to PATH
            Pair("PATH","${System.getenv("PATH")};${engineBinDir};${engineBinX86Dir}"),

            // Define where tests can place re-usable test data
            Pair("TEST_DATA_DIRECTORY",testDataDirectory),

            // Define where tests can write output produce for later review
            Pair("TEST_OUTPUT_DIRECTORY",testOutputDirectory),

            // Forward ENV username and password
            Pair("NUIX_USERNAME",System.getenv("NUIX_USERNAME")),
            Pair("NUIX_PASSWORD",System.getenv("NUIX_PASSWORD")),

            // Forward LOCALAPPDATA and APPDATA
            Pair("LOCALAPPDATA",System.getenv("LOCALAPPDATA")),
            Pair("APPDATA",System.getenv("APPDATA")),
            Pair("PROGRAMDATA",System.getenv("PROGRAMDATA")),
            Pair("SYSTEMDRIVE",System.getenv("SYSTEMDRIVE")),

            // We need to make sure we set these so workers will properly resolve temp dir
            // (when using a worker based operation via EngineWrapper).
            Pair("TEMP",nuixTempDirectory),
            Pair("TMP",nuixTempDirectory),

            Pair("NUIX_ENGINE_DIR", nuixEngineDirectory)
    )
}

from nuix-java-engine-baseline.

Trekky12 avatar Trekky12 commented on June 28, 2024

I thought I did everything correct:

  • Downloaded nuix engine zip-file and extracted to local disk
  • Added NUIX_ENGINE_DIR as environment variable with the path to the extracted folder of the engine
  • Added engine/bin and engine/bin/x86 to the system PATH variable
  • Cloned this repository
  • Opened the project in IntellJ Idea CE
  • Let the dependencies download and index
  • Added a new file Main.java in src/main/java/com.nuix.enginebaseline with the content from above
  • Changed the run configuration for this Main.java and added the JVM arguments: --add-exports=java.base/jdk.internal.loader=ALL-UNNAMED
  • Run the project with gradle
  • Get the error message
Executing ':Main.main()'...

Starting Gradle Daemon...
Gradle Daemon started in 1 s 260 ms
> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE

> Task :Main.main() FAILED
Obtained value 'P:\Nuix\engine' from ENV var 'NUIX_ENGINE_DIR'
No log directory specified, assuming local app data log directory: C:\Users\user\AppData\Local\Engine-20230901-083038
No user data directory was specified, assuming directory relative to engine distribution: P:\Nuix\engine\user-data
'bin' Successfully found on PATH: P:\Nuix\engine\bin
'bin\x86' Successfully found on PATH: P:\Nuix\engine\bin\x86
08:30:38.035 [main] INFO  com.nuix.enginebaseline.NuixEngine - Engine Distribution Directory: P:\Nuix\engine
08:30:38.035 [main] INFO  com.nuix.enginebaseline.NuixEngine - Log Directory: C:\Users\user\AppData\Local\Engine-20230901-083038
08:30:38.035 [main] INFO  com.nuix.enginebaseline.NuixEngine - User Data Directory: P:\Nuix\engine\user-data
2 actionable tasks: 1 executed, 1 up-to-date
[Fatal Error] log4j2.yml:1:1: Content is not allowed in prolog.
Exception in thread "main" java.lang.NoClassDefFoundError: org/picocontainer/MutablePicoContainer
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174)
	at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:802)
	at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:700)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:623)
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	at com.nuix.common.dependency.Dependencies.a(SourceFile:66)
	at com.nuix.common.dependency.Dependencies.bootstrap(SourceFile:55)
	at com.nuix.engine.e.<init>(SourceFile:46)
	at com.nuix.engine.DefaultGlobalContainerFactory.createSpi(SourceFile:26)
	at nuix.engine.GlobalContainerFactory.newContainer(SourceFile:66)
	at com.nuix.enginebaseline.NuixEngine.ensureGlobalContainer(NuixEngine.java:479)
	at com.nuix.enginebaseline.NuixEngine.getUtilities(NuixEngine.java:314)
	at com.nuix.enginebaseline.NuixEngine.run(NuixEngine.java:337)
	at com.nuix.enginebaseline.Main.main(Main.java:12)
Caused by: java.lang.ClassNotFoundException: org.picocontainer.MutablePicoContainer
	at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
	at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
	... 18 more

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':Main.main()'.
> Process 'command 'P:/Java/jdk-11.0.2/bin/java.exe'' finished with non-zero exit value 1

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 4s
08:30:38: Execution finished ':Main.main()'.

I even tried different JDK Versions (11 in this case, 16 and 20).

Do you have an idea?

from nuix-java-engine-baseline.

Trekky12 avatar Trekky12 commented on June 28, 2024

Thank you very much for the explanation @JuicyDragon!

It is working with the suggested dependency for runtimeOnly and also from outside of Gradle with -cp.
Unfortunately I was not able to modify the run configuration to include the engine libs because IntelliJ IDEA adds a custom -cp and multiple -cp are not possible. So inside of IntelliJ IDEA the only possible solution is to use the adjusted Gradle file.

from nuix-java-engine-baseline.

Related Issues (12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.