📦 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! 🎉
