ECE366 - Lesson 5
Docker Compose, Spring Boot
Instructor: Professor Hong
## What is Maven?
- A Yiddish word meaning accumulator of knowledge
- Standard way to build projects
- Clear definition of what the project consisted of
- An easy way to publish project information
- A way to share JARs (Java ARchive file) across several projects
## Set up Postgres in Docker again
Local Postgres
```
$ docker run --rm --name lil-postgres -e POSTGRES_PASSWORD=password -d -v $HOME/srv/postgres:/var/lib/postgresql/data -p 5432:5432 postgres
```
## Building Projects with Maven
- Create a pom.xml file
```
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.chrishong.lil.jdbc</groupId>
<artifactId>learning-jdbc</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<properties>
<java.version>19</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
com.chrishong.lil.jdbc.JDBCExecutor
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
```
- Note that we specified the main class in this file
## Build JDBC Using Maven w/ Plugin
```
$ mvn package
```
- The Spring Boot plugin creates an executable JAR file with all dependencies built in
- If you don't create an executable JAR, you will need to use the ```-cp``` class path flag when running Java
## Running the JAR File
```
$ java -jar target/learning-jdbc-1.0-SNAPSHOT-spring-boot.jar
```
- This JAR file will run the main in the specified class in the pom.xml file
- It includes all dependencies
## Docker Compose Workflow
- Automated Container Orchestration
- Configuration File: docker-compose.yaml
- Startup: ```$ docker-compose up```
- Monitoring: Provided by Docker, Compose Daemon
- Teardown: ```$ docker-compose down```
Docker Compose Workflow
## Docker Compose with JDBC
Dockerfile
```
FROM maven:3.8.7-eclipse-temurin-19 AS build
ADD . /project
WORKDIR /project
RUN mvn -e package
FROM eclipse-temurin:latest
COPY --from=build /project/target/learning-jdbc-1.0-SNAPSHOT-spring-boot.jar /app/JDBCExecutor.jar
ENTRYPOINT ["java","-jar","/app/JDBCExecutor.jar"]
```
## docker-compose.yaml
```
services:
db:
image: postgres
volumes:
- $HOME/srv/postgres:/var/lib/postgresql/data
environment:
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=password
expose:
- 5432
restart: always
app:
build: .
environment:
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=password
depends_on:
- db
```
- Note that this creates a network in which the dockers can communicate
- You can have multiple networks if desired
## Update to DCM
Update localhost to db in DatabaseConnectionManager
```
DatabaseConnectionManager dcm = new DatabaseConnectionManager("db",
"rps", "postgres", "password");
```
This will make the docker use the proper db docker
## Running Docker Compose
```
$ docker compose build
$ docker compose up
```
## What is the Spring Framework?
- Framework for providing comprehensive infrastructural support for developing Java Apps
- OOP (Object Oriented Programming) Best practices built in
- DRY (Don't Repeat Yourself) Principles
## What is Spring Boot?
- A tool that supports rapid development of web APIs
- Auto-configuration of Application Context
- Automatic Servlet Mappings
- Database support
- Automatic Controller Mappings
## Spring Initializr
- [start.spring.io](start.spring.io)
- Maven
- Java
- 3.0.2
- Group: com.chrishong.rps
Download the zip file and put it in your workspace
## Update the pom.xml file
```
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.chrishong</groupId>
<artifactId>rps</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rps</name>
<description>RPS Game</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>postgresql</groupId>
<artifactId>postgresql</artifactId>
<version>9.1-901-1.jdbc4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
<configuration>
<classifier>spring-boot</classifier>
<mainClass>
com.chrishong.rps.RpsApplication
</mainClass>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
```
- Add postgresql dependency
## Copy over JDBC libraries
- util - DataAccessObject, DataTransferObject
- DatabaseConnectionManager
- Player
- PlayerDAO
## Main
```
package com.chrishong.rps;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
@SpringBootApplication
@RestController
public class RpsApplication {
/**
* Get all Players entities in the database.
*
* @return List of Blog Entities.
*/
@PostMapping("/getPlayerById")
public Player create(@RequestBody String message) {
DatabaseConnectionManager dcm = new DatabaseConnectionManager("db",
"tictactoe", "postgres", "password");
Player player = new Player();
try {
Connection connection = dcm.getConnection();
PlayerDAO playerDAO = new PlayerDAO(connection);
player = playerDAO.findById(Integer.parseInt(message));
System.out.println(player.getPlayerId() + " " + player.getUserName() + " " + player.getPassword());
}
catch(SQLException e) {
e.printStackTrace();
}
return player;
}
public static void main(String[] args) {
System.out.println("Hello World");
SpringApplication.run(RpsApplication.class, args);
}
}
```
- Note we added ```RestController``` and ```PostMapping```
- ```PostMapping``` specifies what the API url maps to
## Docker Compose
```
services:
db:
image: postgres
volumes:
- $HOME/srv/postgres:/var/lib/postgresql/data
environment:
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=password
expose:
- 5432
restart: always
app:
build: .
environment:
- POSTGRES_DB=postgres
- POSTGRES_PASSWORD=password
depends_on:
- db
```
## Dockerfile for Spring Boot
```
FROM maven:3.8.7-eclipse-temurin-19 AS build
ADD . /project
WORKDIR /project
RUN mvn -e package
FROM eclipse-temurin:latest
COPY --from=build /project/target/rps-0.0.1-SNAPSHOT-spring-boot.jar /app/rps.jar
ENTRYPOINT ["java","-jar","/app/rps.jar"]
```
## Common Traps
- Make sure you don't have another spring boot application running on the same port
- Rebuild your docker compose if you edited docker-compose.yaml or any Dockerfiles
- Make sure you use your docker compose services name for your database