ECE366 - Lesson 5

Docker Compose, Spring Boot

Instructor: Professor Hong

Review & Questions

## Maven
## 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
## 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 ```
## Spring Boot
## 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