PreviewDrop for Spring Boot

Deploy previews for Spring Boot apps

Push a branch, get a live preview URL. PreviewDrop builds your fat JAR, boots the embedded server, and posts the link to the pull request in under 60 seconds — no CI scripts, no serverless Java wrappers.

TL;DR
Add a multi-stage Dockerfile, connect your repo, push. PreviewDrop builds the JAR with Maven or Gradle, runs it on the JRE, and posts a TLS-terminated preview URL to the PR. Embedded Tomcat or Netty runs exactly as in production — your @Scheduled jobs, connection pools and a warm JVM are all intact, not folded into a Lambda handler.

Dockerfile

Drop this at the root of your repo. PreviewDrop picks it up on the next push and builds it into a container behind a TLS-terminated subdomain.

Dockerfile
FROM eclipse-temurin:21-jdk AS build WORKDIR /app COPY .mvn/ .mvn COPY mvnw pom.xml ./ RUN ./mvnw dependency:go-offline -B COPY src ./src RUN ./mvnw clean package -DskipTests FROM eclipse-temurin:21-jre WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 # PreviewDrop injects PORT; Spring binds to it via server.port CMD ["sh", "-c", "java ${JAVA_OPTS} -Dserver.port=${PORT:-8080} -jar app.jar"]

Environment variables

Set these in the Variables tab of your PreviewDrop project. They're encrypted at rest and injected into every preview container at start.

VariableExample valueNote
SPRING_PROFILES_ACTIVEpreviewActivates an application-preview.yml so previews can use a lighter config than prod.
JAVA_OPTS-XX:MaxRAMPercentage=75Cap the heap so the JVM fits the preview container instead of grabbing the whole host.
SPRING_DATASOURCE_URLjdbc:postgresql://host:5432/dbPoint at a shared dev DB, or use an in-memory H2 profile for UI-only previews.

Common gotchas

Bind to the injected PORT, not hard-coded 8080

PreviewDrop routes traffic to whatever port your app listens on via the PORT env var. Pass -Dserver.port=${PORT} (as in the Dockerfile CMD) or set SERVER_PORT. A hard-coded port still works as long as it matches what the proxy expects, but reading PORT is the safe default.

Commit the Maven wrapper with the executable bit

The build calls ./mvnw, which must be committed and executable. Windows checkouts often drop the exec bit — restore it once with git update-index --chmod=+x mvnw so the Linux build can run it. (Gradle: swap in ./gradlew bootJar.)

Skip the test suite in the image build

The Dockerfile uses -DskipTests. Preview builds should be fast — your full suite belongs in CI, not on the critical path to a preview URL. Keeping the build lean is what keeps you inside the ~60-second window.

Cap the JVM heap

By default the JVM sizes its heap from total host memory, which can exceed a preview container and trigger an OOM kill. Set JAVA_OPTS=-XX:MaxRAMPercentage=75 (or an explicit -Xmx256m) so the heap stays inside the container limit.

Why not Vercel or Netlify?

Vercel and Netlify have no JVM runtime. “Serverless Java” options wrap a single handler in a Lambda, but you lose the embedded Tomcat/Netty server, @Scheduled jobs, hosted background workers, and a warm JVM with live connection pools. PreviewDrop runs your fat JAR directly — the same container shape as production, used as a per-PR deploy preview.

Preview your Spring Boot app in 5 minutes

Connect a repo, push a branch, get a URL. No credit card, no trial clock.

Start free