Exception seen in Jersey Init, Spring Boot 3.0.1, Spring Boot Jersey Starter, GraalVM 22.3, Java 17 & 19

663 Views Asked by At

Attempting to get sample application on Spring Boot 3.0.1, Spring Boot Jersey Starter, GraalVM 22.3, Java 17 & 19. Maven Native Image creation is successful, executable starts, but on the first request to sample end point, there seems to be an error. So trying to figure out what could be missed to get this setup on Native Executable working.

Error Seen

➜  target ./nativedemo-bin

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.1)

2023-01-26T20:53:34.975+05:30  INFO 25349 --- [           main] c.e.nativedemo.NativedemoApplication     : Starting AOT-processed NativedemoApplication using Java 19.0.1 with PID 25349 (/Volumes/data/experiments/nativedemo/target/nativedemo-bin started by demouser in /Volumes/data/experiments/nativedemo/target)
2023-01-26T20:53:34.975+05:30  INFO 25349 --- [           main] c.e.nativedemo.NativedemoApplication     : No active profile set, falling back to 1 default profile: "default"
2023-01-26T20:53:34.987+05:30  INFO 25349 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2023-01-26T20:53:34.987+05:30  INFO 25349 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2023-01-26T20:53:34.987+05:30  INFO 25349 --- [           main] o.apache.catalina.core.StandardEngine    : Starting Servlet engine: [Apache Tomcat/10.1.4]
2023-01-26T20:53:34.994+05:30  INFO 25349 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2023-01-26T20:53:34.994+05:30  INFO 25349 --- [           main] w.s.c.ServletWebServerApplicationContext : Root WebApplicationContext: initialization completed in 19 ms
2023-01-26T20:53:35.011+05:30  INFO 25349 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2023-01-26T20:53:35.011+05:30  INFO 25349 --- [           main] c.e.nativedemo.NativedemoApplication     : Started NativedemoApplication in 0.052 seconds (process running for 0.13)
2023-01-26T20:53:43.807+05:30 ERROR 25349 --- [nio-8080-exec-2] o.a.c.c.C.[Tomcat].[localhost].[/]       : Servlet.init() for servlet [com.example.nativedemo.config.ApplicationConfig] threw exception

java.lang.ExceptionInInitializerError: null
    at org.glassfish.jersey.server.internal.inject.FormParamValueParamProvider.<init>(FormParamValueParamProvider.java:82) ~[na:na]
    at org.glassfish.jersey.server.internal.inject.ValueParamProviderConfigurator.init(ValueParamProviderConfigurator.java:90) ~[na:na]
    at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$0(ApplicationHandler.java:307) ~[na:na]
    at [email protected]/java.util.Arrays$ArrayList.forEach(Arrays.java:4204) ~[na:na]
    at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:307) ~[na:na]
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:274) ~[na:na]
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311) ~[na:na]
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154) ~[nativedemo-bin:na]
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:338) ~[nativedemo-bin:na]
    at jakarta.servlet.GenericServlet.init(GenericServlet.java:158) ~[nativedemo-bin:6.0]
    at jakarta.servlet.http.HttpServlet.init(HttpServlet.java:140) ~[nativedemo-bin:6.0]
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:992) ~[na:na]
    at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:695) ~[na:na]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:118) ~[na:na]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97) ~[na:na]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542) ~[nativedemo-bin:10.1.4]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119) ~[na:na]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) ~[nativedemo-bin:10.1.4]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78) ~[na:na]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357) ~[na:na]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400) ~[na:na]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) ~[nativedemo-bin:10.1.4]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859) ~[na:na]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734) ~[na:na]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[nativedemo-bin:10.1.4]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) ~[na:na]
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[na:na]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) ~[na:na]
    at [email protected]/java.lang.Thread.run(Thread.java:1589) ~[nativedemo-bin:na]
    at org.graalvm.nativeimage.builder/com.oracle.svm.core.thread.PlatformThreads.threadStartRoutine(PlatformThreads.java:775) ~[nativedemo-bin:na]
    at org.graalvm.nativeimage.builder/com.oracle.svm.core.posix.thread.PosixPlatformThreads.pthreadStartRoutine(PosixPlatformThreads.java:203) ~[na:na]
Caused by: java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
    at org.glassfish.jersey.server.internal.inject.FormParamValueParamProvider$MultipartFormParamValueProvider.<clinit>(FormParamValueParamProvider.java:239) ~[na:na]
    ... 31 common frames omitted

2023-01-26T20:53:43.818+05:30 ERROR 25349 --- [nio-8080-exec-2] a.c.c.C.[.[.[.[.e.n.c.ApplicationConfig] : Allocate exception for servlet [com.example.nativedemo.config.ApplicationConfig]

java.lang.ArrayIndexOutOfBoundsException: Index 0 out of bounds for length 0
    at org.glassfish.jersey.server.internal.inject.FormParamValueParamProvider$MultipartFormParamValueProvider.<clinit>(FormParamValueParamProvider.java:239) ~[na:na]
    at org.glassfish.jersey.server.internal.inject.FormParamValueParamProvider.<init>(FormParamValueParamProvider.java:82) ~[na:na]
    at org.glassfish.jersey.server.internal.inject.ValueParamProviderConfigurator.init(ValueParamProviderConfigurator.java:90) ~[na:na]
    at org.glassfish.jersey.server.ApplicationHandler.lambda$initialize$0(ApplicationHandler.java:307) ~[na:na]
    at [email protected]/java.util.Arrays$ArrayList.forEach(Arrays.java:4204) ~[na:na]
    at org.glassfish.jersey.server.ApplicationHandler.initialize(ApplicationHandler.java:307) ~[na:na]
    at org.glassfish.jersey.server.ApplicationHandler.<init>(ApplicationHandler.java:274) ~[na:na]
    at org.glassfish.jersey.servlet.WebComponent.<init>(WebComponent.java:311) ~[na:na]
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:154) ~[nativedemo-bin:na]
    at org.glassfish.jersey.servlet.ServletContainer.init(ServletContainer.java:338) ~[nativedemo-bin:na]
    at jakarta.servlet.GenericServlet.init(GenericServlet.java:158) ~[nativedemo-bin:6.0]
    at jakarta.servlet.http.HttpServlet.init(HttpServlet.java:140) ~[nativedemo-bin:6.0]
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:992) ~[na:na]
    

POM -

<?xml version="1.0" encoding="UTF-8"?>
<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>3.0.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>nativedemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>native-demo</name>
    <packaging>jar</packaging>
    <description>native-demo</description>
    <properties>
        <java.version>19</java.version>
        <maven.test.skip>true</maven.test.skip>
        <main.class>com.example.nativedemo.NativedemoApplication</main.class>
    </properties>

    <dependencyManagement>
        <dependencies>
            <dependency><!-- Import dependency management from Spring Boot -->
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-dependencies</artifactId>
                <version>3.0.1</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jersey</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.glassfish.jersey.core</groupId>
            <artifactId>jersey-server</artifactId>
            <version>3.1.0</version>
        </dependency>

        <dependency>
            <groupId>org.graalvm.buildtools</groupId>
            <artifactId>graalvm-reachability-metadata</artifactId>
            <version>0.9.19</version>
        </dependency>

        <dependency>
            <groupId>org.graalvm.sdk</groupId>
            <artifactId>graal-sdk</artifactId>
            <version>22.3.0</version>
        </dependency>

    </dependencies>

    <profiles>
        <profile>
            <id>native</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.graalvm.buildtools</groupId>
                        <artifactId>native-maven-plugin</artifactId>
                        <executions>
                            <execution>
                                <phase>package</phase>
                                <id>build-native</id>
                                <goals>
                                    <goal>compile-no-fork</goal>
                                </goals>
                                <configuration>
                                    <classesDirectory>${project.build.outputDirectory}</classesDirectory>
                                    <fallback>false</fallback>
                                    <imageName>${project.artifactId}-bin</imageName>
                                    <metadataRepository>
                                        <enabled>true</enabled>
                                    </metadataRepository>
                                    <requiredVersion>22.3</requiredVersion>
                                    <verbose>true</verbose>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <id>repackage</id>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>

Jersey Config

package com.example.nativedemo.config;

import com.example.nativedemo.rest.Endpoints;
import jakarta.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.stereotype.Component;

@Component
@ApplicationPath("/demo")
public class ApplicationConfig extends ResourceConfig {
    public ApplicationConfig(){
        register(Endpoints.class);
    }
}

Endpoint Class

package com.example.nativedemo.rest;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import org.springframework.stereotype.Component;

@Component
@Path("/api/v1")
public class Endpoints {

    @GET
    @Path("/health")
    public String getHealth(){
        return "Ok";
    }
}

Spring Boot Main Class

package com.example.nativedemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication
public class NativedemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(NativedemoApplication.class, args);
    }

}

I have tried options to pack the jar via maven plugins with respect to a normal jar, i.e without the BOOT-INF structure using the WAR layout and tried to build the native image out of it. Still with the same error.

Its quite a path to get the simple application on Spring Boot with GraalVM, yet with errors.

So my ask is, any settings is missed out to get the native image working, should there be any hints to graalvm inspite of using libraries which support the native image generation.

1

There are 1 best solutions below

0
On

Found the issue, the solution was to run the spring boot jar with the following options

$JAVA_HOME/bin/java -agentlib:native-image-agent=config-output-dir=[output_location] -jar [app_name].jar 

This generates reflect-config.json, resource-config.json and proxy-config.json. Once generated these needs to be configured in the maven plugin.

<buildArg>-H:ResourceConfigurationFiles=target/classes/resource-config.json, -H:ReflectionConfigurationFiles=target/classes/reflect-config.json,-H:DynamicProxyConfigurationFiles=target/classes/proxy-config.json</buildArg>