📦 Spring Boot: Packaging and Deployment
The Lunchbox Story 🍱
Imagine you made the most delicious lunch ever. Now you need to:
- Pack it in a lunchbox (Packaging)
- Take it to school or work (Deployment)
- Leave a note about what’s inside (Logging)
That’s exactly what Spring Boot does with your application!
🎯 What You’ll Learn
- Packaging Options - Different lunchboxes for different needs
- Executable JAR - The magic all-in-one lunchbox
- Container Deployment - Shipping your lunch in a truck
- Logging Configuration - Writing notes about your lunch
📦 Packaging Options
What is Packaging?
When you build a Spring Boot app, you need to bundle everything together. Just like packing a suitcase for a trip!
Two Main Lunchbox Types
graph TD A[Your App] --> B{Choose Package} B --> C[JAR File] B --> D[WAR File] C --> E[Runs Anywhere] D --> F[Needs App Server]
| Type | What It Is | When To Use |
|---|---|---|
| JAR | All-in-one package | Most projects ✅ |
| WAR | Needs a server | Legacy systems |
Simple Example
In your pom.xml:
<packaging>jar</packaging>
That’s it! Maven knows to make a JAR.
🚀 Executable JAR (Fat JAR)
The Magic Lunchbox
An executable JAR is special. It contains:
- Your code ✅
- All libraries ✅
- A web server ✅
- Everything to run ✅
One file. That’s all you need.
Why “Fat” JAR?
Regular JAR: Your code only (small)
Fat JAR: Your code + ALL dependencies (big)
Think of it like:
- Regular JAR = Empty lunchbox
- Fat JAR = Lunchbox with food, napkin, fork, and drink!
How Spring Boot Does It
Spring Boot uses a special plugin to create fat JARs:
<build>
<plugins>
<plugin>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-maven-plugin
</artifactId>
</plugin>
</plugins>
</build>
Building Your JAR
Run this command:
mvn clean package
You’ll find your JAR in the target/ folder:
target/
└── myapp-0.0.1.jar ← Your app!
Running Your JAR
Just one command:
java -jar myapp-0.0.1.jar
🎉 That’s it! Your app is running!
Inside the Fat JAR
graph TD A[myapp.jar] --> B[Your Classes] A --> C[BOOT-INF/lib] A --> D[Embedded Tomcat] C --> E[spring-core.jar] C --> F[jackson.jar] C --> G[other libs...]
🐳 Container Deployment
What’s a Container?
Imagine shipping your lunchbox in a protective box that has:
- Perfect temperature
- Right humidity
- Same conditions everywhere
That’s a Docker container!
Why Use Containers?
| Problem | Container Solution |
|---|---|
| “Works on my machine” | Same everywhere |
| Different Java versions | Built-in Java |
| Complex setup | One command to run |
Creating a Dockerfile
A Dockerfile is like a recipe for your container:
FROM eclipse-temurin:17-jre
COPY target/myapp.jar app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
Line by line:
- Start with Java 17
- Copy your JAR file
- Tell it how to run
Building the Container
docker build -t myapp .
Running the Container
docker run -p 8080:8080 myapp
Your app runs inside its own little world!
Better Dockerfile (Layered)
Spring Boot 2.3+ supports layered JARs:
FROM eclipse-temurin:17-jre
WORKDIR /app
COPY target/myapp.jar app.jar
RUN java -Djarmode=layertools \
-jar app.jar extract
FROM eclipse-temurin:17-jre
COPY --from=0 /app/dependencies/ ./
COPY --from=0 /app/application/ ./
ENTRYPOINT ["java", "org...."]
Why layers? Faster rebuilds! Only changed layers update.
graph TD A[Layered JAR] --> B[dependencies] A --> C[spring-boot-loader] A --> D[snapshot-deps] A --> E[application] B --> F[Changes rarely] E --> G[Changes often]
📝 Logging Configuration
Why Logs Matter
Logs are like a diary for your app. They tell you:
- What happened ✅
- When it happened ✅
- What went wrong ❌
Default Logging
Spring Boot uses Logback by default. No setup needed!
2024-01-15 10:30:45 INFO Starting MyApp
2024-01-15 10:30:46 INFO Tomcat started on port 8080
Log Levels
graph TD A[TRACE] --> B[DEBUG] B --> C[INFO] C --> D[WARN] D --> E[ERROR] style A fill:#e8f5e9 style B fill:#e3f2fd style C fill:#fff3e0 style D fill:#ffecb3 style E fill:#ffcdd2
| Level | What It Means |
|---|---|
| TRACE | Super detailed (rarely used) |
| DEBUG | Developer info |
| INFO | Normal events |
| WARN | Something odd happened |
| ERROR | Something broke! |
Setting Log Levels
In application.properties:
# Root level (all logs)
logging.level.root=INFO
# Your package (more detailed)
logging.level.com.myapp=DEBUG
# Spring (less noise)
logging.level.org.springframework=WARN
Logging to a File
# Log file location
logging.file.name=app.log
# Or use a path
logging.file.path=/var/logs
Log Format
Customize how logs look:
logging.pattern.console=\
%d{HH:mm:ss} %-5level %msg%n
Output:
10:30:45 INFO Starting MyApp
10:30:46 INFO Tomcat started
Using Logs in Code
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class MyService {
private static final Logger log =
LoggerFactory.getLogger(MyService.class);
public void doSomething() {
log.info("Starting task");
log.debug("Details: {}", data);
log.error("Oops!", exception);
}
}
Environment-Specific Logging
Use profiles for different settings:
application-dev.properties:
logging.level.root=DEBUG
application-prod.properties:
logging.level.root=WARN
logging.file.name=/var/log/app.log
Run with profile:
java -jar app.jar --spring.profiles.active=prod
🎯 Quick Summary
| Topic | Key Point |
|---|---|
| Packaging | JAR (default) or WAR |
| Executable JAR | Everything in one file |
| Container | Docker for consistency |
| Logging | Logback, levels, files |
🚀 Real-World Flow
graph LR A[Write Code] --> B[mvn package] B --> C[JAR Created] C --> D{Deploy Where?} D --> E[java -jar] D --> F[Docker Container] D --> G[Cloud Platform]
💡 Remember
- JAR = Your whole app in one file
- Docker = Ship your app safely anywhere
- Logs = Your app’s diary
You’re now ready to package and deploy like a pro! 🎉