LAB#SB00-6: Rest & MongoDB
Spring Boot
lab
JPA
REST
MongoDB
Introduction
Getting started
Prepare a MongoDB project
On cloud
In your cluster,
Initialize a Spring Boot project
Dependencies
- Spring Boot DevTools
- Lombok
- Spring Web
- Rest Repositories
- Spring Session
- Spring Data JPA
- Spring Data MongoDB
pom.xml
Add the official MongoDB driver dependency.
application.yml
Define the MongoDB connection parameters.
Implement the REST API that connects to MongoDB
Domain classes
BookImage
BookImage.java
package com.springbootlab0.approach_1.bookimagemongodb;
import jakarta.persistence.Id;
import lombok.*;
import org.bson.types.Binary;
import org.springframework.data.mongodb.core.mapping.Document;
// Lombok annotations
@Getter
@Setter
@ToString
@NoArgsConstructor
@AllArgsConstructor
// MongoDB annotations
@Document(collection = "book_images")
public class BookImage {
@Id
private String id;
private String name;
// Image is stored as a binary file
private Binary image;
private String publication_id;
}
What happens with the document’s
id
?
Here are some insights on how the id
value is handled in the Mapping Layer –> LINK
For more control over the actual id mapping, try to use the @MongoId
annotation.
Repository
BookImageRepository
Service
BookImageService
BookImageService.java
package com.springbootlab0.approach_1.bookimagemongodb;
import org.bson.types.Binary;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Optional;
@Service
public class BookImageService {
@Autowired
BookImageRepository bookImageRepository;
public BookImage uploadBookImage(String name, MultipartFile file) throws IOException {
BookImage bookImage = new BookImage();
// TODO: Assign alternative ID to avoid exposing sensitive data
bookImage.setName(name);
bookImage.setImage(new Binary(file.getBytes()));
// Save the image into the repository
return bookImageRepository.save(bookImage);
}
public Iterable<BookImage> getAllBookImages() {
return bookImageRepository.findAll();
}
public BookImage getBookImageById(String id) {
Optional<BookImage> expectedBook = bookImageRepository.findById(id);
if (expectedBook.isPresent()) {
return expectedBook.get();
}
return null;
}
// TODO: updateBookImage
public BookImage deleteBookImageById(String id) {
Optional<BookImage> bookImageOptional = bookImageRepository.findById(id);
if (bookImageOptional.isPresent()) {
bookImageRepository.deleteById(id);
return bookImageOptional.get();
}
return null;
}
}
Controller
BookImageRestController
BookImageRestController.java
package com.springbootlab0.approach_1.bookimagemongodb;
import com.springbootlab0.approach_1.domain.Publication;
import com.springbootlab0.approach_1.services.PublicationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.util.Base64;
import java.util.Base64.Encoder;
import java.util.Optional;
@Controller
@RequestMapping(value = "/api/bookImages")
public class BookImageRestController {
@Autowired
BookImageService bookImageService;
@Autowired
PublicationService publicationService;
private final String OPERATION = "operation";
private final String VERSION = "version";
private final String API = "api 1.0";
private final String OPERATION_STATUS = "operationStatus";
private final String ID_NOT_FOUND = "ID not found";
// CRUD
// Create --> Upload an image
@PostMapping(value = "upload")
public ResponseEntity<BookImage> uploadBookImage(@RequestParam String publicationId, @RequestParam String name, @RequestParam MultipartFile file) throws IOException {
HttpHeaders headers = new HttpHeaders();
headers.add(OPERATION, "upload");
headers.add(VERSION, API);
BookImage uploadedBookImage = bookImageService.uploadBookImage(name, file);
if (uploadedBookImage != null) {
// Retrieve the publication
Optional<Publication> imagePublication = publicationService.findPublicationById(publicationId);
// Assign the BookImage ID to the publication
if (imagePublication.isPresent()) {
imagePublication.get().addImageId(uploadedBookImage.getId());
publicationService.updatePublication(imagePublication.get());
headers.add(OPERATION_STATUS, "OK");
return ResponseEntity.ok().headers(headers).body(uploadedBookImage);
}
headers.add(OPERATION_STATUS, "Publication not found");
return ResponseEntity.ok().headers(headers).body(uploadedBookImage);
}
// Return an internal server error if the image couldn't be uploaded
headers.add(OPERATION_STATUS, "Not uploaded");
return ResponseEntity.internalServerError().headers(headers).body(null);
}
// Read --> get all images
@GetMapping("")
public ResponseEntity<Iterable<BookImage>> getAllBookImages() {
// TODO: Parametrize the headers attributes
HttpHeaders headers = new HttpHeaders();
headers.add(OPERATION, "getAllImages");
headers.add(VERSION, API);
Iterable<BookImage> availableBookImages = bookImageService.getAllBookImages();
if (availableBookImages != null) {
headers.add(OPERATION_STATUS, "ok");
return ResponseEntity.ok().headers(headers).body(availableBookImages);
}
headers.add(OPERATION_STATUS, "Cannot access book images collection");
return ResponseEntity.internalServerError().headers(headers).build();
}
// Read --> get a single image
@GetMapping("getImage")
public ResponseEntity<byte[]> getBookImage(@RequestParam String id){
// TODO: Parametrize the headers attributes
HttpHeaders headers = new HttpHeaders();
headers.add(OPERATION, "getImage");
headers.add(VERSION, API);
// Don't forget to set the returned content type!!
// TODO: define generic MediaType for images
headers.setContentType(MediaType.IMAGE_JPEG);
// Retrieve the requested bookImage
BookImage requestedBookImage = bookImageService.getBookImageById(id);
if (requestedBookImage != null) {
headers.add(OPERATION_STATUS, "found");
return ResponseEntity.ok().headers(headers).body(requestedBookImage.getImage().getData());
}
headers.add(OPERATION_STATUS, ID_NOT_FOUND);
return ResponseEntity.notFound().headers(headers).build();
}
// Read --> Get the data of a single image
@GetMapping("getData")
public ResponseEntity<String> getDataBookImage(@RequestParam String id) {
// TODO: Parametrize the headers attributes
HttpHeaders headers = new HttpHeaders();
headers.add(OPERATION, "getData");
headers.add(VERSION, API);
BookImage requestedBookImage = bookImageService.getBookImageById(id);
if (requestedBookImage != null) {
headers.add(OPERATION_STATUS, "found");
Encoder encoder = Base64.getEncoder();
return ResponseEntity.ok().headers(headers).body(encoder.encodeToString(requestedBookImage.getImage().getData()));
}
headers.add(OPERATION_STATUS, ID_NOT_FOUND);
return ResponseEntity.notFound().headers(headers).build();
}
// Update --> Update a Book Image information
// TODO
@PutMapping("update")
public ResponseEntity<BookImage> updateBookImage(@RequestParam String id, @RequestParam(required = false) String name, @RequestParam(required = false) MultipartFile file) {
return null;
}
// Delete --> Delete a Book Image
@DeleteMapping("delete")
public ResponseEntity<BookImage> deleteBookImage(@RequestParam String id) {
// TODO: Parametrize the headers attributes
HttpHeaders headers = new HttpHeaders();
headers.add(OPERATION, "getData");
headers.add(VERSION, API);
BookImage deletedBookImage = bookImageService.deleteBookImageById(id);
if (deletedBookImage != null) {
headers.add(OPERATION_STATUS, "deleted");
return ResponseEntity.ok().headers(headers).body(deletedBookImage);
}
headers.add(OPERATION_STATUS, ID_NOT_FOUND);
return ResponseEntity.notFound().headers(headers).build();
}
}