Encodera

Thanks for reading!

Donate to the site — we work hard for you.

Contents

Building a JAR and running it on a server

Nobody copies sources to a server or runs ./mvnw spring-boot:run there. The application is built into a single executable JAR file: your code, all libraries and the embedded Tomcat inside. The server needs only Java 25 — and one command to start.

Building

./mvnw clean package

Maven compiles the code, runs the tests and builds the file in the target folder:

target/blog-0.0.1-SNAPSHOT.jar           64 MB — for running
target/blog-0.0.1-SNAPSHOT.jar.original  40 KB — only your classes

The big file was built by spring-boot-maven-plugin: it packed all dependencies inside. The .original file is a plain JAR without libraries; it is not used on the server. If tests fail, the JAR is not built; -DskipTests skips them, but fixing them is better.

Running

java -jar target/blog-0.0.1-SNAPSHOT.jar

The log shows the same lines as when starting through Maven. Ctrl+C stops the application; on a server it usually runs as a systemd service or in a container so that it comes back up by itself after a reboot.

Settings for the server

For the server we create a prod profile. It holds no passwords — only what differs from development:

# src/main/resources/application-prod.yaml
spring:
  jpa:
    show-sql: false
  h2:
    console:
      enabled: false
 
logging:
  file:
    name: logs/blog.log

The database address and password are passed as environment variables at startup:

SPRING_PROFILES_ACTIVE=prod \
SPRING_DATASOURCE_URL=jdbc:postgresql://localhost:5432/blog \
SPRING_DATASOURCE_USERNAME=blog \
SPRING_DATASOURCE_PASSWORD=changeme \
java -jar target/blog-0.0.1-SNAPSHOT.jar

Spring Boot turns SPRING_DATASOURCE_URL into the spring.datasource.url setting itself — no files need rewriting on the server. For PostgreSQL, pom.xml must contain the org.postgresql:postgresql driver and the flyway-database-postgresql module.

What you see at startup

INFO ... The following 1 profile is active: "prod"
INFO ... Database: jdbc:postgresql://localhost:5432/blog (PostgreSQL 18.3)
INFO ... Migrating schema "public" to version "1 - create tables"
INFO ... Migrating schema "public" to version "2 - add password and role"
INFO ... Successfully applied 2 migrations to schema "public", now at version v2

On an empty PostgreSQL database Flyway applied both migrations — the same files that worked with H2. After that curl http://localhost:8080/actuator/health answers with the UP status, and the log is copied to logs/blog.log.

A pre-deployment checklist

What to checkHow
The prod profile is onThe line The following 1 profile is active: "prod"
No passwords in GitEnvironment variables only
The H2 console is offspring.h2.console.enabled: false
The schema is managed by migrationsddl-auto: validate and Flyway
There is a health check/actuator/health answers UP

Common mistake

If you start the wrong file, Java answers:

no main manifest attribute, in target\blog-0.0.1-SNAPSHOT.jar.original

This is the .original file without libraries and without an entry point. Run the JAR without that suffix. The same error appears when pom.xml lacks spring-boot-maven-plugin: then the big executable file is never built at all.

Thanks for reading!

Donate to the site — we work hard for you.