0

I created a console application. This app can generate a pdf. I use itextpdf. I added in build gradle:

compile group: 'com.itextpdf', name: 'itextpdf', version: '5.5.10'

When I start my program in command line I see a this log:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: com/itextpdf/text/DocumentException
        at java.lang.Class.getDeclaredMethods0(Native Method)
        at java.lang.Class.privateGetDeclaredMethods(Unknown Source)
        at java.lang.Class.privateGetMethodRecursive(Unknown Source)
        at java.lang.Class.getMethod0(Unknown Source)
        at java.lang.Class.getMethod(Unknown Source)
        at sun.launcher.LauncherHelper.validateMainClass(Unknown Source)
        at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
Caused by: java.lang.ClassNotFoundException: com.itextpdf.text.DocumentException
        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)
        ... 7 more

When I start my app in IntelliJ it works corretly.

build.gradle :

      group 'Harmonogramy'
version '1.0-SNAPSHOT'

task wrapper(type: Wrapper) {
  gradleVersion = '3.1'
  distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
}

apply plugin: 'java'

sourceCompatibility = 1.5

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.11'
    // https://mvnrepository.com/artifact/mysql/mysql-connector-java
    compile group: 'mysql', name: 'mysql-connector-java', version: '5.1.34'
    // https://mvnrepository.com/artifact/commons-dbutils/commons-dbutils
    compile group: 'commons-dbutils', name: 'commons-dbutils', version: '1.6'
// https://mvnrepository.com/artifact/org.apache.commons/commons-csv
    compile group: 'org.apache.commons', name: 'commons-csv', version: '1.4'
    // https://mvnrepository.com/artifact/com.itextpdf/itextpdf
    compile group: 'com.itextpdf', name: 'itextpdf', version: '5.5.10'
// https://mvnrepository.com/artifact/net.sf.opencsv/opencsv
    compile group: 'net.sf.opencsv', name: 'opencsv', version: '2.3'

}

jar {
    archiveName = 'Harmonogramy.jar'

    manifest {
        attributes 'Main-Class': 'Main',
                'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' '),
                'Implementation-Version': version
    }

    from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) })
}
Krzysztof Pokrywka
  • 1,356
  • 4
  • 27
  • 50

2 Answers2

1

You need to pack your libraries with your app to make it runnable and have all dependencies needed on runtime. In example in your build.gradle

As well looking into your code I have a feeling that you don't follow the src/main/java structure, therefore gradle doesn't know where to get the source files from as the default is src/main/java. you can amend SourceSets but I suggest to just follow the structure convention.

apply plugin: 'java'

sourceCompatibility = 1.5
targetCompatibility = 1.5

version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

dependencies {
    compile 'mysql:mysql-connector-java:5.1.34'
    compile 'commons-dbutils:commons-dbutils:1.6'
    compile 'org.apache.commons:commons-csv:1.4'
    compile 'com.itextpdf:itextpdf:5.5.10'
    compile 'net.sf.opencsv:opencsv:2.3'
    testCompile 'junit:junit:4.11'
}

jar {
    archiveName = 'Harmonogramy.jar'

    manifest {
        attributes 'Main-Class': 'Main',
                'Class-Path': configurations.runtime.files.collect { "lib/$it.name" }.join(' '),
                'Implementation-Version': version
    }
    from(configurations.compile.collect { it.isDirectory() ? it : zipTree(it) })
}

the jar task will extend the default gradle task to build a jar, and will pack all your compile dependencies within - remember to point your main class out to make it executable.

Or you can try to use a shadow plugin found here https://github.com/johnrengelman/shadow

LazerBanana
  • 6,865
  • 3
  • 28
  • 47
  • I did what you said but it doesn't work I edited my post maybe I did something wring – Krzysztof Pokrywka Feb 23 '17 at 11:59
  • attributes 'Main-Class': 'Path to your main' is the Reference to your Main class with your main method. archiveName is the name of the jar is being build by gradle. and take the exclude out if you dotn want to exclude anything . i will update my answer for you. – LazerBanana Feb 23 '17 at 12:40
  • This is my Main full Main.class : https://paste.ofcode.org/kNuxJAiqneJqQ2FVLDQath and I edit my post. I think I did what you said but it doesn't work – Krzysztof Pokrywka Feb 23 '17 at 13:15
  • I have just tested it and all works like a charm. I hope you are running it with java -jar name.jar in your app dir – LazerBanana Feb 23 '17 at 14:45
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/136471/discussion-between-krystian-k-and-krzysztof-pokrywka). – LazerBanana Feb 23 '17 at 14:52
0

The console application needs access to the itext jar at runtime. IntelliJ supplies this dependency automatically, but if you run the code from a console, it's up to you to supply the dependency.

You have two main choices

  • start the program with java -cp <path/to/itext.jar> yourprogram
  • build a "fat jar" using gradle and run that ( the fat jar bundles your code and all its dependencies in to a single executeable jar file )
DaveH
  • 7,187
  • 5
  • 32
  • 53