Articles in this section

Running and Migrating Java Applications on Upsun

Overview

Upsun provides a high-performance, containerized environment for Java applications. Whether you are deploying a Spring Boot monolith, a Quarkus microservice, or a legacy Java EE app, following these best practices ensures your application remains stable, performant, and easy to manage.

This guide consolidates recommendations for Java development on Upsun, replacing legacy tips with modern Upsun workflows.


1. Core Configuration: Single-Runtime vs. Composable Images

When setting up your application in .upsun/config.yaml, you have two primary choices for your environment:

Single-Runtime Image (Standard)

Best for simple Java applications where the OpenJDK runtime is the only requirement.

  • Syntax: type: 'java:21'

  • Benefit: Managed by Upsun; security patches for the OS and OpenJDK are handled automatically.

Composable Image (Advanced)

Best for applications that require multiple runtimes (e.g., Java + Node.js for a frontend) or specific system packages not included in the standard image.

  • Syntax: type: 'composable:25.11' (referencing a Nix channel).

  • Benefit: Offers ultimate flexibility. You can define a stack of runtimes and packages from the Nix ecosystem.

Important Note on Composable Images: While more flexible, Composable images require your team to manage the Nix channel version. You should redeploy frequently to apply updates, as Nix packages are built in isolation and do not receive automatic "background" OS patches like single-runtime images.


2. Java Migration Checklist

When moving a Java application to Upsun, follow these steps to ensure a smooth transition:

  1. Select Your Version: Upsun supports OpenJDK 8, 11, 17, and 21. Use java:21 (or the latest LTS) for new projects.

  2. Port Binding: Your application must listen on the port provided by the $PORT environment variable.

    • Spring Boot example: java -jar app.jar --server.port=$PORT

    • Quarkus example: -Dquarkus.http.port=$PORT

  3. Build Hooks: Use the build hook to compile your application (e.g., ./mvnw clean package). Since the file system is read-only after the build, ensure your executable (Uber-JAR or WAR) is generated here.

  4. Relationships: Service credentials (like PostgreSQL or Redis) are not hardcoded. Access them via the PLATFORM_RELATIONSHIPS environment variable or use the Upsun Java Configuration Reader.


3. Performance Tuning & Memory Management

Java's memory management in containers requires specific flags to prevent the kernel from killing the process (OOM Killer).

Setting Memory Limits

Always set -Xmx (Maximum Heap Size) based on the container's available memory. On Upsun, you can dynamically calculate this using jq:

Bash

 
java -Xmx$(jq .info.limits.memory /run/config.json)m -jar app.jar

Recommended JVM Flags

In your web.commands.start, include these flags for better container resilience:

  • -XX:+ExitOnOutOfMemoryError: Forces the JVM to exit if it hits an OOM, allowing Upsun to automatically restart the container.

  • -XX:+UseG1GC: The recommended Garbage Collector for Java 9+.

  • -XX:+PrintGCDetails: Sends GC logs to STDOUT, which is captured in your Upsun app logs (upsun log app).


4. Handling Dependencies (Maven/Gradle)

  • Use Wrappers: Always include ./mvnw or ./gradlew in your repository. This ensures the exact version of the build tool is used, regardless of what is pre-installed on the image.

  • Caching: Upsun automatically caches the .m2 and .gradle directories between builds to speed up deployment.

  • Specific Versions: If you need a specific Maven version not provided by default, you can install it manually in the build hook:

    YAML

     
    hooks:
      build: |
        # Download and set up a specific Maven version if needed
        curl -sfLO "https://archive.apache.org/dist/maven/maven-3/3.9.0/binaries/apache-maven-3.9.0-bin.tar.gz"
        tar -zxf apache-maven-3.9.0-bin.tar.gz
        export PATH="$PWD/apache-maven-3.9.0/bin:$PATH"
        mvn clean package
    

5. Monitoring & Debugging

  • Logs: All output to STDOUT and STDERR is aggregated in /var/log/app.log. Use upsun log app to view live deployment logs.

  • Mounts: If your application needs to write logs to a file or handle file uploads, you must define a mount in your config, as the rest of the application directory is read-only at runtime.


Additional Resources

Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Please sign in to leave a comment.