'Pi4j to use java with raspberry Pi not working
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,
- The code just needs to be run on the raspberry pi
- 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
Solution 1:[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/
Solution 2:[2]
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 yourmain
-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.
Solution 3:[3]
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
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | vanOekel |
Solution 3 | Roberto Shaba |