QoddiDocumentation
Browse documentation

QODDI DOCUMENTATION

Java

Last updated

Qoddi automatically builds your Java app from your code.
To do that, Qoddi uses buildpacks to detect and build your app automatically.

The Java buildpack offers several ways to build your code from source or a compiled artifact.

For Gradle support, check this article.

Before Building your app

For Maven builds, commit pom.xml, the Maven Wrapper files when used, system.properties, and a Procfile. Use the Gradle guide for Gradle projects.

Your build determines the artifact name. Configure an executable JAR, build locally, and use its actual path in the launch command. The examples below assume target/my-app.jar.

Create your app on Qoddi

Create a new app and link it with your repository using SSH keys.

Read this article for a detailed procedure or check this video :

Procfile

For an executable JAR:

web: java -jar target/my-app.jar

For Spring Boot, bind its HTTP listener to Qoddi’s port:

web: java -Dserver.port=$PORT -jar target/my-app.jar

Replace the filename with the actual packaged artifact. A plain library JAR cannot be started with java -jar unless it contains a suitable main manifest and runtime dependencies.

Specify a Java Version

Set the JDK major in system.properties at the repository root. For an application tested on Java 25 LTS:

java.runtime.version=25

Align the compiler release/target in Maven or Gradle with your chosen runtime. Selecting a major lets the buildpack apply available patch updates when you rebuild.

Supported versions

JDK lineSelection guidance
8, 11, 17, 21, 25LTS lines listed across current Heroku stacks; choose one compatible with your app
27Current feature line listed in the upstream inventory
26 and older non-LTS linesListed binaries may remain available after maintenance ends; prefer a maintained line

The Heroku JDK matrix is stack-specific. Its default is Java 8 on stack 22 and Java 25 on stacks 24/26. Declare a runtime instead of assuming a shared default across builders.

Runtime references checked November 2, 2026. Available binaries and defaults depend on the selected Qoddi builder and stack; confirm the resolved version in the build log.

pom.xml

Maven reads dependencies, plugins, compiler settings, and packaging from pom.xml. Start with your framework’s current project generator or a maintained Maven archetype; commit its configuration and wrapper. Run your tests and package the app locally before deployment.

./mvnw verify

Check the output under target/ and ensure the launch command points to the executable artifact. See Maven’s getting-started guide.

Using the Zulu JDK

Current Heroku Java buildpacks use Azul Zulu builds of OpenJDK. Use the numeric java.runtime.version selector, such as 25; the old heroku- distribution is discontinued. See JDK distribution support.

Maven Version

Commit mvnw and its .mvn/wrapper/ configuration to choose a tested Maven version. The current Heroku buildpack prefers the Maven Wrapper. Ensure the wrapper script is executable and its configured distribution matches the version tested locally.

The classic buildpack also accepts maven.version in system.properties; consult its current Maven support before using that alternative.

Framework launch commands

Framework detection varies by builder. Use an explicit executable-JAR Procfile and the framework’s current packaging plugin. For Spring Boot, pass -Dserver.port=$PORT as shown above.

Using a custom Maven Settings file

A settings.xml file determines the Maven configuration. Read more on this page.

When a file settings.xml is present inside the root directory of your code, Qoddi will use it to configure Maven.

Alternatively, the emplacement of the settings.xml file can be set as an environment variable (before build) with the key MAVEN_SETTINGS_PATH (local file) or MAVEN_SETTINGS_URL (hosted on a URL)

Using password protected repositories

You can use any environment variable of your app (to be set before the app build is required) to use inside the settings.xml file : ${env.ENV_VAR} where ENV_VAR is the name of your variable. Never store passwords inside your code repository but use the environment variables to do that.

Here’s an example with settings.xml file using a private repository like Jfrog Artifactory hosted version :

<servers>
  <server>
    <id>my-private-repo</id>
    <username>deployment</username>
    <password>${env.MY_JFROG_PASSWORD}</password>
  </server>
</servers>

Launch a Console Command

Please check this article on how to launch a command directly to your running app. This can be used to perform database migrations, launch local scripts, or perform database backups.

Ephemeral Disk

Contrary to Marketplace apps that can use Qoddi’s virtual disk features to store and retrieve persistent data, apps that are created from code use an immutable file system.

You can write data locally, for instance, to process files temporarily during your application life, but the data written into your app’s disk is not persistent and gets wiped out after your app restart.

All apps restart at least once every 24 hours, to apply a new setting or to deploy a new build.

To store data and keep it persistent you can use external services like Amazon S3 or Wasabi, an S3 compatible storage service with very affordable pricing.

Add a domain name

Please check this article for a detailed method on how to use your domain name with Qoddi apps.

Define environment variables

Note: Environment variables set in your app settings are injected during the build process. If the build of your app needs to use an env variable, make sure to set it before requesting the build.

Qoddi lets you externalize the configuration of your app: the Qoddi cluster will automatically inject the data when the app starts or restart.

Environment variables can include any external data your app needs to run like external resources, database addresses, encryption keys, etc…

To add an environment variable, access your app settings and click “Add ENV Variable” :

Enter the key (like DATABASE_USER) and the value and click “Add”. Qoddi will automatically add your environment variable and restart your app after a one-minute delay (to let you add more env variables if necessary without restarting the app each time a new variable is added).

Provision a database

Qoddi Marketplace includes all popular datastore engines, including Mysql, Postgres, MongoDB, and Redis.
To add a database to your app, click on Marketplace and select the database you want to run, then create the new app database inside the same stack as your Python app.

Once the app is running, visit the database app’s settings and retrieve the “internal name” :

Use this internal name as you would use a server address, for instance for MySQL this name replaces the usual “localhost”. Some scripts require you to add the database port at the end of the server address. Qoddi uses a common port for each database software, for MySQL it will be 3306 and you can write it like that inside your scripts: internal-name:3306
Postgres usually uses credentials sent inside the login URL, like that : postgres://<user>:<password>@<internalname>:5432/<database>

The login and password information is available inside the Environment Variables of the database app.

Note: Qoddi’s datastores run on a private and encrypted network. Therefore SSL support is deactivated for all datastores available on Qoddi. Ensure that your code doesn’t require using SSL before deploying your app.

Java and Postgres databases

If you deploy a Postgres database on Qoddi with Java you need to use the JDBC driver with the SSL mode disabled. Qoddi automatically creates a JDBC_DATABASE_URL with the sslmode set to disable if you deploy your database at the same time as your app.

You can connect directly using this environment variable, for instance, with Spring:

spring.datasource.username=<username>
spring.datasource.password=<passw>
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url= ${JDBC_DATABASE_URL}

If you use the JDBC_DATABASE_URL make sure the DATABASE_URL environment variable is removed from your app to avoid conflicts (the builder should remove it automatically).

Other databases (like MySQL) uses other environment variable like DATABASE_HOST. For MySQL you can use:

spring.datasource.username=${DATABASE_USERNAME} 
spring.datasource.password=${DATABASE_PASSWORD} 
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.url= ${DATABASE_HOST}

Make sure that those variables are created on your app settings page (Qoddi creates those variables automatically when you deploy your database at the same time as your app).

Reach your app from another app

Inside your app stack, you can reach any other Qoddi app member of this stack on any port. Qoddi automatically routes the traffic internally and opens the appropriate port. By opposition, your app is only reachable on ports 80/443 outside Qoddi.

To reach your app internally, retrieve the internal name from your app settings page :

This name can be used to reach your app from another app inside the same stack. Use it in any form that works with your script :

http://<internalname>
<internalname>
http://<internalname>:port

Note: https:// is not available, all the traffic inside apps is already encrypted by the cluster.

Encryption

Qoddi uses at rest encryption for the app virtual disks, build images, and encrypted transport from inside the cluster. To make sure the traffic is encrypted between your app and the browser of your users you can set up SSL certificates for any domain name connected to the app (including Qoddi’s default domain name).

Scale your App

From your app settings you can scale your app vertically and horizontally: by upgrading the app size (refer to our pricing for app sizes details) or by adding more nodes.

Additional nodes will run another copy of your app inside another Qoddi server located inside the same cluster (same geographical location). Traffic is automatically sent to the least occupied node by Qoddi’ss load balancer.