Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"editor.detectIndentation": false,
"editor.formatOnSave": true,
"[java]": {
"editor.defaultFormatter": "redhat.java"
"editor.defaultFormatter": "redhat.java",
"editor.inlayHints.enabled": "off"
},
"java.configuration.updateBuildConfiguration": "automatic",
"java.compile.nullAnalysis.mode": "automatic",
Expand Down
2 changes: 1 addition & 1 deletion assets/images/structure.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package ar.com.nanotaboada.java.samples.spring.boot.controllers;

import static org.springframework.http.HttpHeaders.LOCATION;

import java.net.URI;
import java.util.List;

import org.springframework.http.HttpHeaders;
import jakarta.validation.Valid;

import org.hibernate.validator.constraints.ISBN;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
Expand All @@ -25,6 +29,7 @@
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;

import ar.com.nanotaboada.java.samples.spring.boot.models.BookDTO;
import ar.com.nanotaboada.java.samples.spring.boot.services.BooksService;

Expand Down Expand Up @@ -52,22 +57,18 @@ public BooksController(BooksService booksService) {
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content),
@ApiResponse(responseCode = "409", description = "Conflict", content = @Content)
})
public ResponseEntity<String> post(@RequestBody BookDTO bookDTO) {
if (booksService.retrieveByIsbn(bookDTO.getIsbn()) != null) {
return new ResponseEntity<>(HttpStatus.CONFLICT);
} else {
if (booksService.create(bookDTO)) {
URI location = MvcUriComponentsBuilder
.fromMethodName(BooksController.class, "getByIsbn", bookDTO.getIsbn())
.build()
.toUri();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setLocation(location);
return new ResponseEntity<>(httpHeaders, HttpStatus.CREATED);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
public ResponseEntity<Void> post(@RequestBody @Valid BookDTO bookDTO) {
boolean created = booksService.create(bookDTO);
if (!created) {
return ResponseEntity.status(HttpStatus.CONFLICT).build();
}
URI location = MvcUriComponentsBuilder
.fromMethodCall(MvcUriComponentsBuilder.on(BooksController.class).getByIsbn(bookDTO.getIsbn()))
.build()
.toUri();
return ResponseEntity.status(HttpStatus.CREATED)
.header(LOCATION, location.toString())
.build();
}

/*
Expand All @@ -77,18 +78,16 @@ public ResponseEntity<String> post(@RequestBody BookDTO bookDTO) {
*/

@GetMapping("/books/{isbn}")
@Operation(summary = "Retrieves a book by its ID")
@Operation(summary = "Retrieves a book by its ISBN")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "OK", content = @Content(mediaType = "application/json", schema = @Schema(implementation = BookDTO.class))),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content)
})
public ResponseEntity<BookDTO> getByIsbn(@PathVariable String isbn) {
BookDTO bookDTO = booksService.retrieveByIsbn(isbn);
if (bookDTO != null) {
return new ResponseEntity<>(bookDTO, HttpStatus.OK);
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
return (bookDTO != null)
? ResponseEntity.status(HttpStatus.OK).body(bookDTO)
: ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}

@GetMapping("/books")
Expand All @@ -98,7 +97,7 @@ public ResponseEntity<BookDTO> getByIsbn(@PathVariable String isbn) {
})
public ResponseEntity<List<BookDTO>> getAll() {
List<BookDTO> books = booksService.retrieveAll();
return new ResponseEntity<>(books, HttpStatus.OK);
return ResponseEntity.status(HttpStatus.OK).body(books);
}

/*
Expand All @@ -108,22 +107,17 @@ public ResponseEntity<List<BookDTO>> getAll() {
*/

@PutMapping("/books")
@Operation(summary = "Updates (entirely) a book by its ID")
@Operation(summary = "Updates (entirely) a book by its ISBN")
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "No Content", content = @Content),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content)
})
public ResponseEntity<String> put(@RequestBody BookDTO bookDTO) {
if (booksService.retrieveByIsbn(bookDTO.getIsbn()) != null) {
if (booksService.update(bookDTO)) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
public ResponseEntity<Void> put(@RequestBody @Valid BookDTO bookDTO) {
boolean updated = booksService.update(bookDTO);
return (updated)
? ResponseEntity.status(HttpStatus.NO_CONTENT).build()
: ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}

/*
Expand All @@ -133,21 +127,16 @@ public ResponseEntity<String> put(@RequestBody BookDTO bookDTO) {
*/

@DeleteMapping("/books/{isbn}")
@Operation(summary = "Deletes a book by its ID")
@Operation(summary = "Deletes a book by its ISBN")
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "No Content", content = @Content),
@ApiResponse(responseCode = "400", description = "Bad Request", content = @Content),
@ApiResponse(responseCode = "404", description = "Not Found", content = @Content)
})
public ResponseEntity<String> delete(@PathVariable String isbn) {
if (booksService.retrieveByIsbn(isbn) != null) {
if (booksService.delete(isbn)) {
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
} else {
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
} else {
return new ResponseEntity<>(HttpStatus.NOT_FOUND);
}
public ResponseEntity<Void> delete(@PathVariable @ISBN String isbn) {
boolean deleted = booksService.delete(isbn);
return (deleted)
? ResponseEntity.status(HttpStatus.NO_CONTENT).build()
: ResponseEntity.status(HttpStatus.NOT_FOUND).build();
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
package ar.com.nanotaboada.java.samples.spring.boot.services;

import jakarta.validation.Validator;
import lombok.RequiredArgsConstructor;

import java.util.List;
import java.util.stream.StreamSupport;

import lombok.RequiredArgsConstructor;

import org.modelmapper.ModelMapper;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
Expand All @@ -21,7 +20,6 @@
public class BooksService {

private final BooksRepository booksRepository;
private final Validator validator;
private final ModelMapper modelMapper;

/*
Expand All @@ -32,14 +30,14 @@ public class BooksService {

@CachePut(value = "books", key = "#bookDTO.isbn")
public boolean create(BookDTO bookDTO) {
boolean notExists = !booksRepository.existsById(bookDTO.getIsbn());
boolean valid = validator.validate(bookDTO).isEmpty();
if (notExists && valid) {
if (booksRepository.existsById(bookDTO.getIsbn())) {
return false;
} else {
Book book = mapFrom(bookDTO);
booksRepository.save(book);
return true;
}
return false;

}

/*
Expand Down Expand Up @@ -70,14 +68,13 @@ public List<BookDTO> retrieveAll() {

@CachePut(value = "books", key = "#bookDTO.isbn")
public boolean update(BookDTO bookDTO) {
boolean exists = booksRepository.existsById(bookDTO.getIsbn());
boolean valid = validator.validate(bookDTO).isEmpty();
if (exists && valid) {
if (booksRepository.existsById(bookDTO.getIsbn())) {
Book book = mapFrom(bookDTO);
booksRepository.save(book);
return true;
} else {
return false;
}
return false;
}

/*
Expand All @@ -91,8 +88,9 @@ public boolean delete(String isbn) {
if (booksRepository.existsById(isbn)) {
booksRepository.deleteById(isbn);
return true;
} else {
return false;
}
return false;
}

private BookDTO mapFrom(Book book) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@

import ar.com.nanotaboada.java.samples.spring.boot.models.BookDTO;

public class BookDTOsBuilder {
public final class BookDTOFakes {

public static BookDTO buildOneValid() {
private BookDTOFakes() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

public static BookDTO createOneValid() {
BookDTO bookDTO = new BookDTO();
bookDTO.setIsbn("978-1484200773");
bookDTO.setTitle("Pro Git");
Expand All @@ -28,7 +32,7 @@ Pro Git (Second Edition) is your fully-updated guide to Git and its \
return bookDTO;
}

public static BookDTO buildOneInvalid() {
public static BookDTO createOneInvalid() {
BookDTO bookDTO = new BookDTO();
bookDTO.setIsbn("978-1234567890"); // Invalid (invalid ISBN)
bookDTO.setTitle("Title");
Expand All @@ -42,7 +46,7 @@ public static BookDTO buildOneInvalid() {
return bookDTO;
}

public static List<BookDTO> buildManyValid() {
public static List<BookDTO> createManyValid() {
ArrayList<BookDTO> bookDTOs = new ArrayList<>();
BookDTO bookDTO9781838986698 = new BookDTO();
bookDTO9781838986698.setIsbn("9781838986698");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@

import ar.com.nanotaboada.java.samples.spring.boot.models.Book;

public class BooksBuilder {
public final class BookFakes {

public static Book buildOneValid() {
private BookFakes() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}

public static Book createOneValid() {
Book book = new Book();
book.setIsbn("9781484200773");
book.setTitle("Pro Git");
Expand All @@ -28,7 +32,7 @@ Pro Git (Second Edition) is your fully-updated guide to Git and its \
return book;
}

public static Book buildOneInvalid() {
public static Book createOneInvalid() {
Book book = new Book();
book.setIsbn("9781234567890"); // Invalid (invalid ISBN)
book.setTitle("Title");
Expand All @@ -42,7 +46,7 @@ public static Book buildOneInvalid() {
return book;
}

public static List<Book> buildManyValid() {
public static List<Book> createManyValid() {
ArrayList<Book> books = new ArrayList<>();
Book book9781838986698 = new Book();
book9781838986698.setIsbn("9781838986698");
Expand Down
Loading