GraalVM

UShip stack is GraalVM native-image compatible, it means you can convert your application classpath to a native binary to optimize the resources consumption and performances of your application.

You can do it with a plain native-image command or use Geronimo Arthur to ease it.

Important
it requires Arthur 1.0.14 or more recent.

Here is the overall configuration for a standard application (using Yupiik Logging, Yupiik Batch simple configuration, Yupiik UShip JSON-RPC server and persistence layer with PostgreSQL driver), adapt it to your stack:

<plugin>
    <groupId>org.apache.geronimo.arthur</groupId>
    <artifactId>arthur-maven-plugin</artifactId>
    <version>1.0.4</version>
    <configuration>
      <main>org.apache.openwebbeans.se.CDILauncher</main>
      <graalVersion>22.0.0.2.r17</graalVersion>
      <attach>true</attach>
      <attachClassifier>${os.name}-${os.arch}</attachClassifier>
      <output>${project.build.directory}/${project.artifactId}</output>
      <buildStaticImage>false</buildStaticImage>
      <enableAllSecurityServices>false</enableAllSecurityServices>
      <resources>
        <!-- tomcat resources -->
        <resource>
          <pattern>org/apache/catalina/core/RestrictedServlets\.properties</pattern>
        </resource>
        <resource>
          <pattern>org/apache/catalina/core/RestrictedFilters\.properties</pattern>
        </resource>
        <resource>
          <pattern>org/apache/catalina/core/RestrictedListeners\.properties</pattern>
        </resource>
        <resource>
          <pattern>org/apache/catalina/util/ServerInfo\.properties</pattern>
        </resource>
      </resources>
      <includeResourceBundles>
        <!-- tomcat resource bundles -->
        <includeResourceBundle>jakarta.el.LocalStrings</includeResourceBundle>
        <includeResourceBundle>jakarta.servlet.LocalStrings</includeResourceBundle>
        <includeResourceBundle>jakarta.servlet.http.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.authenticator.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.authenticator.jaspic.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.connector.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.core.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.deploy.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.filters.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.loader.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.manager.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.manager.host.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.mapper.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.mbeans.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.realm.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.security.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.servlets.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.session.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.startup.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.users.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.util.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.valves.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.valves.rewrite.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.catalina.webresources.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.coyote.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.coyote.http11.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.coyote.http11.filters.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.coyote.http11.upgrade.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.coyote.http2.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.naming.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.naming.factory.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.naming.factory.webservices.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.buf.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.codec.binary.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.compat.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.descriptor.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.descriptor.tld.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.descriptor.web.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.digester.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.http.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.http.parser.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.json.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.modeler.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.net.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.net.jsse.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.net.openssl.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.net.openssl.ciphers.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.scan.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.security.LocalStrings</includeResourceBundle>
        <includeResourceBundle>org.apache.tomcat.util.threads.LocalStrings</includeResourceBundle>
      </includeResourceBundles>
      <reflections>
        <reflection>
          <!-- PG driver requires this in recent versions -->
          <name>org.postgresql.PGProperty</name>
          <allDeclaredFields>true</allDeclaredFields>
        </reflection>
        <reflection>
          <!-- Tomcat requires this but it can be replaced with a build time generation too -->
          <name>org.apache.coyote.AbstractProtocol</name>
          <allPublicMethods>true</allPublicMethods>
        </reflection>
      </reflections>
      <customOptions>
        <!-- ensure we use a known locale and support logging and http clients -->
        <customOption>-Djava.util.logging.manager=io.yupiik.logging.jul.YupiikLogManager</customOption>
        <customOption>-Djava.net.preferIPv4Stack=true</customOption>
        <customOption>-Duser.language=en</customOption>
        <customOption>-Duser.country=US</customOption>
        <customOption>-Dfile.encoding=UTF-8</customOption>
        <customOption>--enable-http</customOption>
        <customOption>--enable-https</customOption>
      </customOptions>
      <graalExtensions>
        <!-- enable openwebbeans "jakarta" flavor integration -->
        <graalExtension>org.apache.geronimo.arthur.knights:openwebbeans-knight:jar:jakarta:1.0.4?transitive=false</graalExtension>
      </graalExtensions>
      <extensionProperties>
        <!-- enable auto registration of configuration classes (@Param) and JSON-B models (@JsonbProperty) -->
        <extension.annotation.custom.annotations.properties>
          io.yupiik.batch.runtime.configuration.Param:allDeclaredConstructors=true|allDeclaredMethods=true|allDeclaredFields=true,
          jakarta.json.bind.annotation.JsonbProperty:allDeclaredConstructors=true|allDeclaredMethods=true|allDeclaredFields=true
        </extension.annotation.custom.annotations.properties>
        <!-- enable auto registration of entities and JSON-RPC models/wrapper (thanks JsonbPropertyOrder) -->
        <extension.annotation.custom.annotations.class>
          io.yupiik.uship.persistence.api.Table:allDeclaredConstructors=true|allDeclaredFields=true,
          jakarta.json.bind.annotation.JsonbPropertyOrder:allDeclaredConstructors=true|allDeclaredMethods=true|allDeclaredFields=true
        </extension.annotation.custom.annotations.class>
        <!-- avoid to start the whole application which uses @Observes @Initialized(ApplicationScoped.class) -->
        <extension.openwebbeans.container.se.properties>
          org.apache.webbeans.lifecycle.standalone.fireApplicationScopeEvents=false
        </extension.openwebbeans.container.se.properties>
      </extensionProperties>
    </configuration>
</plugin>
Important
this configuration will work for your models if they have at least one explicit @JsonbProperty otherwise you will need to register them explicitly in <reflections> section or use @RegisterClass on the model (from arthur-api package, it can be in provided scope).
Tip
if you want openrpc method to work properly, ensure to define the following reflections:
<reflection>
  <name>io.yupiik.uship.backbone.johnzon.jsonschema.Schema</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.backbone.johnzon.jsonschema.Schema$SchemaType</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.backbone.johnzon.jsonschema.Schema$SchemaTypeAdapter</name>
  <allPublicConstructors>true</allPublicConstructors>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$Server</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$RpcMethod</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$Components</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$License</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$Contact</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$Tag</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$ExternalDoc</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$Value</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$ErrorValue</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>
<reflection>
  <name>io.yupiik.uship.jsonrpc.core.openrpc.OpenRPC$Link</name>
  <allPublicMethods>true</allPublicMethods>
</reflection>

Finally, if you use io.yupiik.uship.persistence.impl.datasource.tomcat.TomcatDataSource you can need to define the following proxy:

<dynamicProxies>
  <dynamicProxy>
    <classes>java.sql.Connection</classes>
  </dynamicProxy>
</dynamicProxies>