UF02-1845
Subject
- Create a Spring MVC Thyemeleaf with all CRUD.
- Connect to a H2 JPA DB.
- REST Controller (Optional).
- Composition/Inherence0 (Optional).
Project
This Project has been developed during the Webb App Developement course. We are building an app that allows Board Game players to track their games collection, open game sessions where other players can join and save all the plays.
Model
On this section i’m only covering the part that i’ve developed, the class Boardgame, all the crud operations for the MVC model an the Rest controller.
BoardGame.java
@Data
@AllArgsConstructor
@Entity(name="BoardGame")
@Table(name="BOARDGAME_TABLE")
public class BoardGame {
@Id
@GenericGenerator(name="system-uuid", strategy="uuid")
@Column(name="gameID", updatable=false)
private String gameID;
@Column(name="gameTitle")
private String gameTitle;
@Column(name="minPlayers")
private int minPlayers;
@Column(name="maxPlayers")
private int maxPlayers;
@Column(name="minPlayTime")
private int minPlayTime;
@Column(name="maxPlayTime")
private int maxPlayTime;
public BoardGame(String gameTitle){
this.gameID = Helpers.generateUUID();
this.gameTitle = gameTitle;
this.minPlayers = 0;
this.maxPlayers = 0;
this.minPlayTime = 0;
this.maxPlayTime = 0;
}
public BoardGame(String gameTitle, int minPlayers, int maxPlayers, int minPlayTime, int maxPlayTime){
this.gameID = Helpers.generateUUID();
this.gameTitle = gameTitle;
this.minPlayers = minPlayers;
this.maxPlayers = maxPlayers;
this.minPlayTime = minPlayTime;
this.maxPlayTime = maxPlayTime;
}
public BoardGame(){
this.gameID = Helpers.generateUUID();
}
}
Service
Service class with all the busines logic needed for CRUD operations.
BoardGameService.java
@@Service
public class BoardGameService {
@Autowired
;
BoardGameRepository boardGameRepository
public Iterable<BoardGame> getAllBoardGames() {
return boardGameRepository.findAll();
}
public BoardGame createGame(BoardGame game){
= boardGameRepository.save(game);
BoardGame newGame return newGame;
}
public boolean addBoardGameToDB(BoardGame game){
if (boardGameRepository.findById(game.getGameID()).isPresent()){
return false;
}
.save(game);
boardGameRepositoryreturn true;
}
public BoardGame getGameByID(String gameID) {
<BoardGame> gameFromDB = boardGameRepository.findByGameID(gameID);
Optionalif (gameFromDB.isPresent()) {
return gameFromDB.get();
}
return null;
}
public BoardGame getGameByGameTitle(String gameTitle){
<BoardGame> gameFromDB = boardGameRepository.findByGameTitle(gameTitle);
Optionalif (gameFromDB.isPresent()){
return gameFromDB.get();
}
return null;
}
public boolean deleteGameFromDB(BoardGame game){
if (boardGameRepository.findById(game.getGameID()).isPresent()){
.delete(game);
boardGameRepositoryreturn true;
}
return false;
}
public boolean updateGameFromDB(BoardGame game){
if(boardGameRepository.existsById(game.getGameID())){
= boardGameRepository.findById(game.getGameID()).get();
BoardGame gameFromDB
if (gameFromDB.getGameTitle() != game.getGameTitle()){
.setGameTitle(game.getGameTitle());
gameFromDB}
if (gameFromDB.getMinPlayers()!= game.getMinPlayers()){
.setMinPlayers(game.getMinPlayers());
gameFromDB}
if (gameFromDB.getMaxPlayers()!= game.getMaxPlayers()){
.setMaxPlayers(game.getMaxPlayers());
gameFromDB}
if (gameFromDB.getMinPlayTime()!= game.getMinPlayTime()){
.setMinPlayTime(game.getMinPlayTime());
gameFromDB}
if (gameFromDB.getMaxPlayTime()!= game.getMaxPlayTime()){
.setMaxPlayTime(game.getMaxPlayTime());
gameFromDB}
.save(gameFromDB);
boardGameRepositoryreturn true;
}
return false;
}
}
Controller
Here is the controllers and all the end-points needed to perform CRUD operations with thymeleaf.
BoardGameController.java
@Controller
@RequestMapping("/boardgames")
public class BoardGameController {
@Autowired
;
BoardGameService boardGameService
@RequestMapping({"/", ""})
public String index(Model containerToView) {
// Retrieve all available users
.addAttribute("boardGamesFromController", boardGameService.getAllBoardGames());
containerToViewreturn "boardgames/index";
}
@GetMapping(value = {"/creategame", "/creategame/"})
public String createBoardGame(Model containerToView) {
.addAttribute("boardgame", new BoardGame());
containerToView.addAttribute("operation", "creategame");
containerToViewreturn "boardgames/creategame.html";
}
@PostMapping(value = "/creategame/{id}")
public String createBoardGame(@PathVariable("id") String gameTitle, Optional<BoardGame> game){
if(boardGameService.getGameByGameTitle(gameTitle) != null){
return "Already on DB";
}
if(game.isPresent()) {
.addBoardGameToDB(game.get());
boardGameService//TODO: add a confirmation message with redirection
}
return "redirect:/boardgames/creategame";
}
@GetMapping(value = "/id/{id}")
public String getGameByID(@PathVariable("id") String id, Model containerToView) {
= boardGameService.getGameByID(id);
BoardGame gameFromDB .addAttribute("boardgame", gameFromDB);
containerToViewreturn "boardgames/gameDetails";
}
@GetMapping(value = "game/{gameTitle}")
public String getByGameTitle(@PathVariable("gameTitle") String gameTitle, Model containerToView) {
= boardGameService.getGameByGameTitle(gameTitle);
BoardGame gameFromDB .addAttribute("boardgame", gameFromDB);
containerToViewreturn "boardgames/gameDetails";
}
@GetMapping("/deleteGame/{id}")
public String deleteGame(@PathVariable("id") String id) {
= boardGameService.getGameByID(id);
BoardGame toDelete .deleteGameFromDB(toDelete);
boardGameServicereturn "redirect:/boardgames/";
}
@GetMapping(value = "/updategame/{id}")
public String updateBoardGame(@PathVariable("id") String id, Model containerToView) {
// Retrieve the user based on the provided ID
= boardGameService.getGameByID(id);
BoardGame gameFromDB .addAttribute("boardgame", gameFromDB);
containerToViewreturn "boardgames/updategame";
}
@PostMapping(value = "/updategame/{id}")
public String updateBoardGame(@PathVariable("id") String id, Optional<BoardGame> updatedGame) {
= boardGameService.getGameByID(id);
BoardGame gameToUpdate
if (updatedGame.isPresent()) {
if (gameToUpdate != null && updatedGame.get().getGameID().equals(gameToUpdate.getGameID())) {
.updateGameFromDB(updatedGame.get());
boardGameService}
}
// Redirect to the GET method
return "redirect:/boardgames/updategame/" + id;
}
}
Reposiory class
Code for the repository Interface. Implemented with the CrudRepository framework by Spring Boot.
BoardGameRepository.java
public interface BoardGameRepository extends CrudRepository<BoardGame, String> {
<BoardGame> findByGameTitle(String gameTitle);
Optional<BoardGame> findByGameID(String gameID);
Optional}
HTML templates
Here’s the templates used to implement the CRUD operations with TH implementation.
Create Board Game
Board Game Details
Update Board Game
API REST implementation
Here’s the class that implements the REST controller to acces DB and obtaining JSON files.
BoardGameRestController.java
@RestController
@RequestMapping("/api")
public class BoardGameRestController {
@Autowired
;
BoardGameService gameService
@GetMapping("")
public String index(){
return "Welcome to Meeple Match API!";
}
@GetMapping("/boardgames/")
public Iterable<BoardGame> getAllGames(){
return gameService.getAllBoardGames();
}
@GetMapping("/title/{gameTitle}")
public BoardGame getGameByTitle(@PathVariable String gameTitle){
<BoardGame> game = Optional.ofNullable(gameService.getGameByGameTitle(gameTitle));
Optionalif (game.isPresent()){
return game.get();
}
return null;
}
@GetMapping("/id/{gameID}")
public BoardGame getGameByID(@PathVariable String gameID){
<BoardGame> game = Optional.ofNullable(gameService.getGameByID(gameID));
Optionalif (game.isPresent()){
return game.get();
}
return null;
}
@PostMapping(path="createGame", consumes = "application/JSON")
public BoardGame createGame(@RequestBody BoardGame game){
= gameService.createGame(game);
BoardGame newGame return newGame;
}
@DeleteMapping("/deleteGame")
public ResponseEntity<BoardGame> deleteGame(@RequestParam("gameID") String gameID){
= new HttpHeaders();
HttpHeaders headers .add("operation", "deleteGame");
headers.add("version", "api 1.0");
headers
<BoardGame> gameFound = Optional.ofNullable(gameService.getGameByID(gameID));
Optionalboolean game = gameFound.isPresent();
if (game){
.deleteGameFromDB(gameFound.get());
gameService.add("operationStatus", "deleted");
headersreturn ResponseEntity.accepted().headers(headers).body(gameFound.get());
}
return ResponseEntity.accepted().body(null);
}
@PutMapping("/updateGame/")
public ResponseEntity<BoardGame> updateGame(@RequestBody BoardGame game){
= new HttpHeaders();
HttpHeaders headers .add("operation", "updateGame");
headers.add("version", "api 1.0");
headers<BoardGame> gameFromDB= Optional.ofNullable(gameService.getGameByID(game.getGameID()));
Optional
if (gameFromDB.isPresent()){
.updateGameFromDB(game);
gameService.add("operationStatus", "updated");
headersreturn ResponseEntity.accepted().headers(headers).body(gameService.getGameByID(game.getGameID()));
}
return ResponseEntity.accepted().headers(headers).body(null);
}
}
GitHub
Source code to the project’s source code GitHub