hypfvieh / dbus-java

Improved version of java DBus library provided by freedesktop.org (https://dbus.freedesktop.org/doc/dbus-java/)
https://hypfvieh.github.io/dbus-java/
MIT License
185 stars 73 forks source link

Missing class def #122

Closed mdford closed 3 years ago

mdford commented 3 years ago

Hi, I am trying to implement a project using your dbus library. I have very little experience with Java, but I have inherited a project that needs to use a java dbus library. I have it working in my IDE (IntelliJ). But, when I build it and run it on my target system, I get

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.NoClassDefFoundError: org/freedesktop/dbus/interfaces/DBusInterface
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetMethodRecursive(Class.java:3048)
    at java.lang.Class.getMethod0(Class.java:3018)
    at java.lang.Class.getMethod(Class.java:1784)
    at sun.launcher.LauncherHelper.validateMainClass(LauncherHelper.java:650)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:632)
Caused by: java.lang.ClassNotFoundException: org.freedesktop.dbus.interfaces.DBusInterface
    at java.net.URLClassLoader.findClass(URLClassLoader.java:382)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:418)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:352)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:351)
    ... 7 more

If I view my generated jar file with the java decompiler app, it shows that dbus-java-3.2.3.jar is included in the created jar and the "missing" class (org.freedesktop.dbus.interfaces.DBusInterface) is also shown as being in the jar file.

image

Are there "external" libraries that I need to have on my target system? Or, could you perhaps shed some light on what I am missing? Thanks!

hypfvieh commented 3 years ago

This has nothing to do with dbus-java or any missing third party library. Your project setup is completely wrong.

You cannot add dependency JARs to your own JAR without repacking. The classloader will not load JARs which are inside of another JAR. So the whole packaging shown in your screenshot is wrong.

If you use maven and want to have a single JAR with all dependencies, you have to configure the maven-shade plugin to create one (often referred to as uber-jar or fat-jar). But be careful when using shade, as it may break strong encapsulation (if any of your dependencies requires that) and also may overwrite classes and resources if they are in multiple JARs and have the same name/FQCN.

The other option is not to create a shaded uber/fat-jar and provide all dependencies as individual JARs, which will require that the caller (user) adds all JARs to the classpath when starting your application (e.g. java -cp dependency1.jar:dependency2.jar...:my.jar com.package.MyMainClass)

mdford commented 3 years ago

Hi, thanks for the quick reply. Just to be clear, if I want to simply use this package in my project (not modify, etc), then what do I need to do to use it? Sorry, I am an experienced C++, Go, Python dev but no experience with Java (although I am learning by fire :-) )

I have this in my project pom file:

    <dependency>
        <groupId>com.github.hypfvieh</groupId>
        <artifactId>dbus-java</artifactId>
        <version>3.2.3</version>
        <type>pom</type>
    </dependency>

I thought that with this entry, it would pull the requisite jar files from the maven repo. (It must, because although I cannot run from command line, it WILL run in IntelliJ).

When I run mvn package on the command line, it complains about missing org.freedesktop.dbus files:

[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.0:compile (default-compile) on project jserial: Compilation failure: Compilation failure: 
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/gozer.java:[6,45] package org.freedesktop.dbus.connections.impl does not exist
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/gozer.java:[7,39] package org.freedesktop.dbus.exceptions does not exist
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/GozerInterface.java:[3,39] package org.freedesktop.dbus.interfaces does not exist
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/GozerInterface.java:[4,39] package org.freedesktop.dbus.exceptions does not exist
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/GozerInterface.java:[5,37] package org.freedesktop.dbus.messages does not exist
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/GozerInterface.java:[7,41] cannot find symbol
[ERROR]   symbol: class DBusInterface
[ERROR] /home/mford/projects/duke/jserial/jserial/src/main/java/com/dukeenergy/gozer.java:[62,13] cannot find symbol

So, could you possibly help me with what else I need to add to my pom.xml file (or in IntelliJ) project settings to get it to build?
Again, I apologize for the noob questions and thank you for any suggestions.

Regards

hypfvieh commented 3 years ago

The dependency declaration is wrong. You don't want to include the pom, you want to include the artifact, so the 'type' is not 'pom' but 'jar'. Even better is to remove the 'type' element because 'jar' is the default and does not need to be specified. If the build is still failing, then please provide a full pom or upload your project to github and share the link.

I guess Intellij will ignore the fact that you specify 'pom' as type, but maven will try to resolve that. This means maven will download the pom (the project object model, which is the definition of this project) and not the compiled package. Therefore all required classes cannot be found.

I would also recommend to stick to java conventions in terms of code style. As I see in the error output, you use class names with lower case.

In Java classes/interfaces always starts with an uppercase letter, while methods and variables are always lower case. All classes, interfaces, variables, static variables are written in camel-case (while in C/C++ you usually would use snake case). Static final variables (which are more or less constants) are written in upper-case using underscore for delimiting words (snake-case). These are the usual conventions one should follow when writing java code.

mdford commented 3 years ago

Thank you! I am very grateful for your help. It is very much appreciated as I learn to navigate the intricacies of a new language.