vaadin / flow

Vaadin Flow is a Java framework binding Vaadin web components to Java. This is part of Vaadin 10+.
Apache License 2.0
589 stars 164 forks source link

Hilla app with @PWA annotation fails when running as native compiled image on macOS #19497

Open rbrki07 opened 1 month ago

rbrki07 commented 1 month ago

Describe the bug

A Hilla app with @PWA annotation throws an exception when running as native compiled image:

java.lang.UnsatisfiedLinkError: No awt in java.library.path
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136) ~[na:na]

Expected-behavior

A Hilla app with @PWA annotation should not throw unexpected exceptions when running as native compiled image.

Reproduction

Create a new Hilla project:

npx @hilla/cli@latest init --next hilla-native-pwa

Add @PWA(name = "Hilla PWA", shortName = "PWA") to src/main/java/com/example/application/Application.java.

Compile Hilla app to native image:

./mvnw clean package -Pproduction -Pnative native:compile

Run Hilla app as native compiled image:

./target/hilla-native-pwa

System Info

Hilla: 24.4.0.beta5 Hilla CLI: 2.0.1 Java: 21.0.2 (OpenJDK Runtime Environment GraalVM CE 21.0.2+13.1 - build 21.0.2+13-jvmci-23.1-b30) OS: macOS Sonoma 14.4.1 (23E224)

mcollovati commented 1 month ago

vaadin/flow#19457 should fix the issue, but it is not yet released. You can try it out with 24.4-SNAPSHOT

rbrki07 commented 1 month ago

Thank you for the reference @mcollovati. I'll give it a try.

rbrki07 commented 1 month ago

I forked vaadin/flow, did mvn clean install -DskipTests in the fork, and then I added flow-server with version 24.5-SNAPSHOT in the pom.xml of the project hilla-native-pwa:

    <dependencies>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>flow-server</artifactId>
            <version>24.5-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>com.vaadin</groupId>
            <artifactId>vaadin</artifactId>
        </dependency>
      ...

After that, I created the native image again:

./mvnw clean package -Pproduction -Pnative native:compile

And then started it again:

./target/hilla-native-pwa

Now there is another error:

2024-06-01T12:01:38.281+02:00 ERROR 20447 --- [nio-8080-exec-5] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Servlet execution threw an exception] with root cause

java.lang.NoClassDefFoundError: Could not initialize class javax.imageio.ImageIO
        at com.vaadin.flow.server.PwaRegistry.getBaseImage(PwaRegistry.java:369) ~[na:na]
mcollovati commented 1 month ago

The fix is in the vaadin-spring artifact

mcollovati commented 1 month ago

BTW, there should also be a first alpha for Vaadin 24.5 that you can try without having to build flow locally

mcollovati commented 1 month ago

Also, if you are want to build flow locally but use Vaadin platform 24.4, maybe better build from the 24.4 branch instead of main

rbrki07 commented 1 month ago

Alright, obviously I was on the wrong path 😅 Thanks for your advice, you seem to know your repos, modules, artefacts and versions 👍 I'll give it another try later.

rbrki07 commented 1 month ago

Ok, next try with 24.5.0.alpha1:

Error:

2024-06-01T16:48:41.927+02:00 ERROR 23332 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[springServlet]        : Servlet.service() for servlet [springServlet] threw exception

java.lang.UnsatisfiedLinkError: No awt in java.library.path
        at org.graalvm.nativeimage.builder/com.oracle.svm.core.jdk.NativeLibrarySupport.loadLibraryRelative(NativeLibrarySupport.java:136) ~[na:na]
...
2024-06-01T16:48:41.956+02:00 ERROR 23332 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[springServlet]        : Servlet.service() for servlet [springServlet] threw exception

java.lang.NoClassDefFoundError: Could not initialize class javax.imageio.ImageIO
        at com.vaadin.flow.server.PwaRegistry.getBaseImage(PwaRegistry.java:369) ~[na:na]
...
mcollovati commented 1 month ago

That's weird. I tried it and it worked for me

mcollovati commented 1 month ago

I tested with GraalVM CE 21 and 22, and the native executable works fine with both. No errors at runtime and the application is working. I'm on Linux, I don't know if that makes a difference.

mcollovati commented 1 month ago

https://github.com/oracle/graal/issues/4124 could be related

rbrki07 commented 1 month ago

I tried again after a reboot and without any other interfering processes, but the error remains. I'll try it on Linux within the next days.

rbrki07 commented 1 month ago

I can confirm, that I don't get the described errors, when I create the native executable using Linux. I leave it to you @mcollovati to close this ticket or leave it open. Thank you, for your help on this 🫶

mcollovati commented 1 month ago

Thanks for testing. I'll change a bit the title to mention MacOS and transfer the issue to the flow repo for further investigation.

rbrki07 commented 1 month ago

There is one more thing I noticed, and I don't understand: Let's say I managed to create a native executable using Linux like described above. The next step would be to create a Docker image using this native executable. A simple Dockerfile could look like this:

FROM debian:bookworm-slim

WORKDIR /app

COPY target/hilla-native-pwa /app/hilla-native-pwa

CMD ["/app/hilla-native-pwa"]

Creating a Docker image from this Dockerfile works as expected:

docker build -t hilla-native-pwa-native-image .

Now, I'd like to start a new Docker container using this Docker image:

docker run -it --rm -p 8080:8080 hilla-native-pwa-native-image

From the console output, I can see that the app has been started. When I try to access the app in the browser, I'm getting the same UnsatisfiedLinkErrors like described above.

Why is that? Why do I get this error messages? I'm running a native executable inside a Docker container. Why is this native executable complaining about the missing AWT in java.library.path? Do I have to create a Docker image that provides AWT, because the native executable depends on it, but does not contain it?

mcollovati commented 1 month ago

I am not completely sure, and I can't check right now, but probably the executable is dinamically linked, so the required libraries should be present at runtime (there should be some library file in the target directory). IIRC, there should also be a native compilation option to make the executable statically linked, but I never tried it.

rbrki07 commented 1 month ago

Yes, you are right 😄 There are a couple of library files (.so) in the target directory of the project, after I did ./mvnw clean package -Pproduction -Pnative native:compile. If I change my Dockerfile to copy those library files...

FROM debian:bookworm-slim

WORKDIR /app

COPY target/*.so /app/
COPY target/hilla-native-pwa /app/hilla-native-pwa

CMD ["/app/hilla-native-pwa"]

... everything works fine! The Docker image is created as desired and when I start a Docker container from that image I can access the Hilla PWA without errors 🙌

Artur- commented 1 month ago

Would the correct fix here be to produce the images at production build time and not have a dependency on awt?