1

I am honestly about to just give up, i've tried so many different possibilities, for multiple weeks now, almost a month, of multiple problems.

I am a new-ish programmer, especially with java, but i have a good understanding about java

I am able to create a maven project no problem, i have no problems with the structure of java itself, but i don't fully understand the pom.xml.

The file compiles just fine, but when i go to start it with java -jar (filename), i get the following output;

Exception in thread "main" java.lang.NoClassDefFoundError: com/pi4j/Pi4J at com.pi.rasberri.Main.main(Main.java:16) Caused by: java.lang.ClassNotFoundException: com.pi4j.Pi4J at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ... 1 more

Heres my pom that i have figuratively almost dismembered;

   (The long links)
<modelVersion>4.0.0</modelVersion>
<groupId>com.pi</groupId>
<artifactId>Rasberri</artifactId>
<version>3.6.1</version>
<packaging>jar</packaging>
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <maven.compiler.source>11</maven.compiler.source>
    <maven.compiler.target>11</maven.compiler.target>
</properties>  <dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.32</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
    </dependency>
    <dependency>
        <groupId>com.pi4j</groupId>
        <artifactId>pi4j-core</artifactId>
        <version>2.0</version>
    </dependency>
    <dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-raspberrypi</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-pigpio</artifactId>
    <version>2.0</version>
</dependency>
</dependencies> <build>
  <plugins>
      <plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2</version> </plugin>    <plugin>    <groupId>org.apache.maven.plugins</groupId>   

maven-jar-plugin 3.1.0 true com.pi.rasberri.Main lib/ true true com.pi.rasberri.Main false true

And my code, which is com.pi.rasberri.Main

    package com.pi.rasberri;

import com.pi4j.Pi4J;
import com.pi4j.io.gpio.digital.DigitalOutput;
import com.pi4j.io.gpio.digital.DigitalState;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main {
   
    private static final int PIN_LED = 6;
    
    public static void main(String[] args) throws Exception{
        
       var pi4j = Pi4J.newAutoContext();
        int x = 0;
        
        var ledConfig = DigitalOutput.newConfigBuilder(pi4j)
           .id("led")
           .name("LED Flasher")
           .address(PIN_LED)
           .shutdown(DigitalState.LOW)
           .initial(DigitalState.LOW)
           .provider("pigpio-digital-output");
      
        var led = pi4j.create(ledConfig);
        
        
        while(x != 5){
        
            led.high();
            sleep(1000);
            led.low();
            sleep(500);
            x++;
        }
    }
    
    static void sleep(int z){
    
        try {
           Thread.sleep(z);
        }   catch (InterruptedException ex) {
           System.out.println("Thread.sleep went fucky wucky");
        }
    }
    }

I would appreciate anything that can even direct me somewhere, because i am quite lost at this point, and of course, if i figure out the answer, i will let everyone know! Thanks in advance

                       **UPDATE**

Thank you, tgdavies, the article you linked https://stackoverflow.com/a/574650/17644313 was the answer to that specific problem!**

Just in case anyone else has the same chain of issues as me;

But with that being said, i ran directly into another error;

[main] INFO com.pi4j.Pi4J - New auto context [main] INFO com.pi4j.Pi4J - New context builder [main] INFO com.pi4j.platform.impl.DefaultRuntimePlatforms - adding platform to managed platform map [id=raspberrypi; name=RaspberryPi Platform; priority=5; class=com.pi4j.plugin.raspberrypi.platform.RaspberryPiPlatform] Exception in thread "main" com.pi4j.provider.exception.ProviderNotFoundException: Pi4J provider [pigpio-digital-output] could not be found. Please include this 'provider' JAR in the classpath. at com.pi4j.provider.impl.DefaultRuntimeProviders.get(DefaultRuntimeProviders.java:238) at com.pi4j.provider.impl.DefaultProviders.get(DefaultProviders.java:147) at com.pi4j.provider.Providers.get(Providers.java:253) at com.pi4j.context.Context.create(Context.java:316) at com.pi4j.internal.IOCreator.create(IOCreator.java:58) at com.pi4j.internal.IOCreator.create(IOCreator.java:96) at com.pi4j.internal.IOCreator.create(IOCreator.java:176) at com.pi.rasberri.Main.main(Main.java:27)

I cleaned the pom.xml a littlebit;

<dependencies>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-simple</artifactId>
        <version>1.7.32</version>
    </dependency>
    <dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.32</version>
    <scope>runtime</scope>
    </dependency>
    <dependency>
        <groupId>com.pi4j</groupId>
        <artifactId>pi4j-core</artifactId>
        <version>2.0</version>
    </dependency>
    <dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-raspberrypi</artifactId>
    <version>2.0</version>
</dependency>
<dependency>
    <groupId>com.pi4j</groupId>
    <artifactId>pi4j-plugin-pigpio</artifactId>
    <version>2.0</version>
</dependency>
</dependencies>
  

<build>
      <plugins>  <!--Package all libraries classes into one runnable jar -->
        <plugin>
            <artifactId>maven-assembly-plugin</artifactId>
            <executions>
              <execution>
                <phase>package</phase>
                <goals>
                  <goal>single</goal>
                </goals>
              </execution>
            </executions>
            <configuration>
                <archive>
                    <manifest>
                <mainClass>com.pi.rasberri.Main</mainClass>
                    </manifest>
                </archive>
              <descriptorRefs>
                <descriptorRef>jar-with-dependencies</descriptorRef>
              </descriptorRefs>
            </configuration>
        </plugin>    
</plugins>
</build>
</project>

At this point, i know of atleast 2 possibilities,

  1. The code just needs to be run on the raspberry pi
  2. I have entered the classpaths incorrectly

But i honestly dont really know as to where to start troubleshooting I've tried a few things, one of which being to try another method of compiling the files, but the other method just resulted in a even longer string of errors.

What should i try next? Thanks in advance! And thanks to anyone who has suggested troubleshooting steps thus far!

Oh, and the target is to hopefully just create a singular jar file to execute on the raspberry pi

update

I tried to run it on the Raspberri pi, and it resulted in the same error so it's not that

Brosbud
  • 21
  • 7
  • You need to have the jar in your classpath when running your code. – Thorbjørn Ravn Andersen Dec 18 '21 at 01:01
  • Does this answer your question? [How can I create an executable JAR with dependencies using Maven?](https://stackoverflow.com/questions/574594/how-can-i-create-an-executable-jar-with-dependencies-using-maven) – tgdavies Dec 18 '21 at 02:25
  • You have to make sure that when you "build" a maven project, you're also including the dependencies as part of the end product, for [example](https://stackoverflow.com/questions/24028921/in-maven-my-dependencies-are-set-up-but-i-get-a-classnotfoundexception-when-i-r/24030042#24030042), [example](https://stackoverflow.com/questions/24899985/this-project-cannot-be-added-because-it-does-not-produce-a-jar-file-using-an-ant/24900260#24900260) – MadProgrammer Dec 18 '21 at 02:34
  • Or you could make use of a "fat jar", for [example](http://tutorials.jenkov.com/maven/maven-build-fat-jar.html), [example](https://stackoverflow.com/questions/16222748/building-a-fat-jar-using-maven). As always, you'll need to do some research into Maven to verify all the properties, been awhile since I used Maven – MadProgrammer Dec 18 '21 at 02:34
  • Easiest would be to create an executable jar via maven-shade-plugin or maven-assembly-plugin to have all the dependencies available during execution... – khmarbaise Dec 18 '21 at 11:01
  • Thanks tgdavies, MadProgrammer, and khmarbaise for the answers, the fix was to create a fat jar, but with that i stumble into another issue, which i have now listed in the original post – Brosbud Dec 18 '21 at 13:13
  • Note that you could have saved yourself quite a bit of effort by investigating what the reported `NoClassDefFoundError` exception actually means. – Thorbjørn Ravn Andersen Dec 19 '21 at 11:02

3 Answers3

1

Thanks tgdavies, MadProgrammer, and khmarbaise for the answers, the fix was to create a fat jar, which is basically a jar file that contains all the dependencies in one file, example can be found in the original question/comments

UPDATE!!

Pi4j has posted instructions for the V2 fat jar on their website! I tried it and it works perfectly now

https://pi4j.com/getting-started/minimal-example-application-fatjar/

Brosbud
  • 21
  • 7
  • This is typically because it needs a native library and the system linker responsible for loading native libraries doesn't know how to load a zip file entry, but needs a plain file. – Thorbjørn Ravn Andersen Dec 19 '21 at 11:01
  • A fat jar example has recently been added to the Pi4J documentation website, see https://pi4j.com/documentation/building/fat-jar/ – Frank Feb 22 '22 at 08:42
1

I do not have a Raspberry Pi to do final testing but I think I found a work-around.

Using this answer I managed to get 2021-10-30-raspios-bullseye-armhf-lite.img running in Docker. I built a project using your code and copied all files needed and tried to start it (mypiapp is my jar containing your main-class):

java -cp mypiapp-0.0.1-SNAPSHOT.jar:lib/pi4j-core-2.1.1.jar:lib/pi4j-library-pigpio-2.1.1.jar:lib/pi4j-plugin-pigpio-2.1.1.jar:lib/pi4j-plugin-raspberrypi-2.1.1.jar:lib/slf4j-api-1.7.32.jar:lib/slf4j-simple-1.7.32.jar com.github.fwi.mypiapp.MyPiApp

which then gave me the error:

[main] ERROR com.pi4j.library.pigpio.util.NativeLibraryLoader - Unable to load [libpi4j-pigpio.so] using path: [/lib/armhf/libpi4j-pigpio.so]
java.lang.UnsatisfiedLinkError: /tmp/libpi4j-pigpio1770932771276400506.so: libpigpio.so.1: cannot open shared object file: No such file or directory

which is a bummer. But at least there was no ProviderNotFoundException (which I also could reproduce using the "fat jar with dependencies"). The long java-command appears to prevent that exception from happening.

And I could improve the situation somewhat by running (in Raspbian)

apt install pigpio

and now the long java-command shows:

[main] WARN com.pi4j.library.pigpio.impl.PiGpioNativeImpl - PIGPIO ERROR: PI_INIT_FAILED; pigpio initialisation failed

which is to be expected when running in a Docker container. But at least the native library was found and loaded.

Now for the work-around which might solve the "fat jar" problems. We are gonna borrow some Maven setup and code from Spring. Spring can also build fat-jars and does it a bit more complicated but also better. The pom now looks like (update where needed with your project names):

<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.6.1</version>
    </parent>
    
    <groupId>com.github.fwi</groupId>
    <artifactId>mypiapp</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <properties>
        <java.version>11</java.version>
        <start.class>com.github.fwi.mypiapp.MyPiApp</start.class>
        <pi4j.version>2.1.1</pi4j.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.pi4j</groupId>
            <artifactId>pi4j-plugin-raspberrypi</artifactId>
            <version>${pi4j.version}</version>
        </dependency>
        <dependency>
            <groupId>com.pi4j</groupId>
            <artifactId>pi4j-plugin-pigpio</artifactId>
            <version>${pi4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <mainClass>${start.class}</mainClass>
                    <layout>ZIP</layout>
                    <executable>false</executable>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

Simply run mvn clean package to build the fat-jar. Run it using java -jar mypiapp-fat.jar In my case, it gave the exact same error as when running with the long java-command (i.e. there was no ProviderNotFoundException). So I think this could work on a real Raspberry-Pi (the apt install pigpio might still be required though).

Some notes:

  • the Spring parent sets some good Maven defaults and also sets good defaults for the spring-boot-maven-plugin
  • Java version MUST be set using the java.version property.
  • update start.class with the name of the class containing your main-method.
  • the 3 dependencies in the pom.xml will pull in all other dependencies (dependencies of dependencies)
  • Spring documentation references: packaging and nested-jars launcher options.
vanOekel
  • 6,358
  • 1
  • 21
  • 56
  • 1
    As it appears, the reason why i couldn't make a fat jar, is that it isn't supported for pi4j v2 yet, i downgraded to 1.4 and it works fine. – Brosbud Dec 18 '21 at 23:03
1

I faced the same issue working with Raspberry P4, java 11 and pi4j v2. I solved it downloading pigpio library directly from the raspberry

sudo apt-get install pigpio

After the library was installed, the jar worked perfecrly. Remember also to run your program with sudo if you are not root user