Skip to main content

Starter Projects

Apache Juneau provides three minimal, clone-and-go "Hello World" starter projects — one per deployment type. They are deliberately simpler than the petstore showcase: entry-point templates you can build and run in under five minutes, then graduate from.

Pre-release

Juneau 10 is a pre-release (10.0.0-SNAPSHOT). Each starter's pom.xml already points at the Apache snapshots repository, so a normal Maven build resolves it with no extra setup, but it needs network access and the snapshot can change between builds. Maven Central has only 9.2.0 today (see Downloads), and the starters need 10.0, so they cannot build without that repository. See Set the version.

New to Juneau? The Getting Started walkthrough builds a small REST app from an empty directory and does not need a starter.

Each starter is a true-orphan branch of apache/juneau. Clone one branch into a my-app directory (single-branch; not a full Java checkout):

git clone -b microservice-jetty-starter --single-branch https://github.com/apache/juneau.git my-app
git clone -b microservice-springboot-starter --single-branch https://github.com/apache/juneau.git my-app
git clone -b microservice-tomcat-starter --single-branch https://github.com/apache/juneau.git my-app
StarterDeploymentBranch
JettyEmbedded Jetty, runnable jarmicroservice-jetty-starter
Spring BootSpring Boot, runnable jarmicroservice-springboot-starter
TomcatWAR on Tomcat 10.1+microservice-tomcat-starter

Each starter demonstrates a lean, Juneau-native feature set: a POJO-returning resource (JSON/XML/HTML content negotiation), the built-in HtmlDoc view, an auto-generated Swagger/OPTIONS page, @Path/@Query binding, a YAML config file, and a MockRestClient example test exercising an @Remote typed client.

Docs for the starters live on this page and at juneau.apache.org — not on per-starter GitHub Pages.

Quick start​

Prerequisites: JDK 17+. Docker is optional.

Jetty​

git clone -b microservice-jetty-starter --single-branch https://github.com/apache/juneau.git my-app
cd my-app
./mvnw clean package && java -jar target/my-app.jar

Open http://localhost:10000/helloWorld. The port comes from juneau.cfg ([Jetty] port). See Ports used in these docs.

# Docker
./mvnw -q clean package
docker build -t my-app .
docker run --rm -p 10000:10000 my-app

The image is eclipse-temurin:17-jre running the shaded uber-jar.

Spring Boot​

git clone -b microservice-springboot-starter --single-branch https://github.com/apache/juneau.git my-app
cd my-app
./mvnw spring-boot:run
# or: ./mvnw clean package && java -jar target/my-app-1.0.0-SNAPSHOT.jar

Open http://localhost:10000/helloWorld. The port comes from server.port in src/main/resources/application.yaml.

# Docker
./mvnw -q clean package
docker build -t my-app .
docker run --rm -p 10000:10000 my-app

The image is eclipse-temurin:17-jre running the Spring Boot jar.

Tomcat (WAR)​

git clone -b microservice-tomcat-starter --single-branch https://github.com/apache/juneau.git my-app
cd my-app
./mvnw -q clean package
docker build -t my-app .
docker run --rm -p 8080:8080 my-app

Open http://localhost:8080/helloWorld. The image is tomcat:10.1-jdk17-temurin with the WAR copied in as ROOT.war.

To an existing Tomcat 10.1+:

./mvnw -q clean package
cp target/my-app.war "$CATALINA_HOME/webapps/ROOT.war"
cp my-app.yaml "$CATALINA_HOME/bin/"

Try content negotiation​

Jetty / Spring Boot (port 10000):

curl -H "Accept: application/json" http://localhost:10000/helloWorld
curl -H "Accept: text/xml" http://localhost:10000/helloWorld
curl -H "Accept: text/html" http://localhost:10000/helloWorld
curl "http://localhost:10000/helloWorld/greet/Juneau?loud=true"

Tomcat (port 8080): same paths on http://localhost:8080.

Project layout​

Rename com.example / my-app / com.example.myapp to your own coordinates. These are rename-me templates, not Apache GAVs.

Jetty — standalone shaded uber-jar (maven-shade); no Apache reactor:

pom.xml, mvnw, my-app.yaml, juneau.cfg, Dockerfile
src/main/java/com/example/myapp/{App,RootResources,HelloWorldResource,Greeting,GreetingApi}.java
src/test/java/com/example/myapp/HelloWorldResourceTest.java

App calls JettyMicroservice.run(...).

Spring Boot — Spring Boot parent; no Apache reactor:

pom.xml, mvnw, my-app.yaml, Dockerfile
src/main/java/com/example/myapp/{App,RootResources,HelloWorldResource,Greeting,GreetingApi}.java
src/main/resources/application.yaml
src/test/java/com/example/myapp/HelloWorldResourceTest.java

Tomcat — standalone WAR; servlet registered in web.xml; no App.java:

pom.xml, mvnw, my-app.yaml, Dockerfile
src/main/java/com/example/myapp/{RootResources,HelloWorldResource,Greeting,GreetingApi}.java
src/main/webapp/WEB-INF/web.xml
src/test/java/com/example/myapp/HelloWorldResourceTest.java

Configuration​

HelloWorldResource declares @Rest(config="my-app.yaml") and reads:

var message = req.getConfig().getString("HelloWorld/message");
HelloWorld:
message: Hello from my-app.yaml!

The .yaml extension selects Juneau's YAML config format (org.apache.juneau.config.format.YamlConfigFormat, id yaml). Nested keys map to section/key paths.

StarterSecond config filePurpose
Jettyjuneau.cfg (INI)Jetty runtime ([Jetty] port, console, logging).
Spring Bootsrc/main/resources/application.yamlSpring (server.port).
Tomcatnone in-tree besides my-app.yamlAt runtime the Dockerfile copies my-app.yaml to /usr/local/tomcat/bin/. If the file is not found, the resource falls back to "Hello world!".

These starters currently depend on 10.0.0-SNAPSHOT and declare the Apache snapshots repository. After 10.0 GA the version pin and snapshots stanza will be removed (a follow-up, not required to clone).

Adding a view (optional)​

The starters ship only Juneau's built-in HtmlDoc view. To render a custom HTML page, add one of:

  • juneau-rest-server-view-freemarker
  • juneau-rest-server-view-thymeleaf

Attach the view to a @RestGet method. See FreeMarker view support and Thymeleaf view support. Left out of the starters on purpose to stay dependency-light.

Next steps​