-
Notifications
You must be signed in to change notification settings - Fork 0
Add controllers #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
4f7f1ad
feat: added exception handling
LightInTheFire 8f698af
feat: added duplicate data exception
LightInTheFire d1a3d32
feat: added user dto's and mapper for them
LightInTheFire 57b63e6
feat: added repository layer for user
LightInTheFire 6f177b5
feat: updated user controller for all crud operations and added user …
LightInTheFire 12f961b
fix: changed name fakeuserrepo to inmemory
LightInTheFire b02bd81
fix: changed isEmpty check to isBlank
LightInTheFire 99b44c8
feat: added ForbiddenAccessException and it handler
LightInTheFire 217a560
feat: added item model, dto's and ItemMapper
LightInTheFire da84bc0
feat: added inmemory item repository
LightInTheFire c4444b5
feat: updated controller and added service layer for item
LightInTheFire f742aea
fix: changed line brakes
LightInTheFire c86616d
chore: method line breaks adjustment
LightInTheFire d6ff9cb
chore: moved error dto's and handler in their packages
LightInTheFire 78cf24c
fix: moved logic of empty search query to service
LightInTheFire File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
src/main/java/ru/practicum/shareit/exception/DuplicateDataException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package ru.practicum.shareit.exception; | ||
|
|
||
| public class DuplicateDataException extends RuntimeException { | ||
| public DuplicateDataException(String message) { | ||
| super(message); | ||
| } | ||
| } |
7 changes: 7 additions & 0 deletions
7
src/main/java/ru/practicum/shareit/exception/ForbiddenAccessException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package ru.practicum.shareit.exception; | ||
|
|
||
| public class ForbiddenAccessException extends RuntimeException { | ||
| public ForbiddenAccessException(String message) { | ||
| super(message); | ||
| } | ||
| } |
13 changes: 13 additions & 0 deletions
13
src/main/java/ru/practicum/shareit/exception/NotFoundException.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| package ru.practicum.shareit.exception; | ||
|
|
||
| import java.util.function.Supplier; | ||
|
|
||
| public class NotFoundException extends RuntimeException { | ||
| public NotFoundException(String message) { | ||
| super(message); | ||
| } | ||
|
|
||
| public static Supplier<NotFoundException> supplier(String message, Object... args) { | ||
| return () -> new NotFoundException(message.formatted(args)); | ||
| } | ||
| } |
4 changes: 4 additions & 0 deletions
4
src/main/java/ru/practicum/shareit/exception/dto/ErrorResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| package ru.practicum.shareit.exception.dto; | ||
|
|
||
| public record ErrorResponse(String name, String message) { | ||
| } |
6 changes: 6 additions & 0 deletions
6
src/main/java/ru/practicum/shareit/exception/dto/ValidationErrorResponse.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package ru.practicum.shareit.exception.dto; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| public record ValidationErrorResponse(List<Violation> violations) { | ||
| } |
4 changes: 4 additions & 0 deletions
4
src/main/java/ru/practicum/shareit/exception/dto/Violation.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| package ru.practicum.shareit.exception.dto; | ||
|
|
||
| public record Violation(String fieldName, String message) { | ||
| } |
81 changes: 81 additions & 0 deletions
81
src/main/java/ru/practicum/shareit/exception/handler/GlobalExceptionHandler.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,81 @@ | ||
| package ru.practicum.shareit.exception.handler; | ||
|
|
||
| import jakarta.validation.ConstraintViolationException; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.web.bind.MethodArgumentNotValidException; | ||
| import org.springframework.web.bind.annotation.ExceptionHandler; | ||
| import org.springframework.web.bind.annotation.ResponseStatus; | ||
| import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
| import ru.practicum.shareit.exception.DuplicateDataException; | ||
| import ru.practicum.shareit.exception.ForbiddenAccessException; | ||
| import ru.practicum.shareit.exception.NotFoundException; | ||
| import ru.practicum.shareit.exception.dto.ErrorResponse; | ||
| import ru.practicum.shareit.exception.dto.ValidationErrorResponse; | ||
| import ru.practicum.shareit.exception.dto.Violation; | ||
|
|
||
| import java.util.List; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| @Slf4j | ||
| @RestControllerAdvice | ||
| class GlobalExceptionHandler { | ||
|
|
||
| @ExceptionHandler | ||
| @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) | ||
| public ErrorResponse onException(Exception ex) { | ||
| log.error("Error occurred while processing request {}", ex.getMessage()); | ||
| return new ErrorResponse("internal server error", | ||
| "An error occurred while processing request"); | ||
| } | ||
|
|
||
| @ExceptionHandler(ConstraintViolationException.class) | ||
| @ResponseStatus(HttpStatus.BAD_REQUEST) | ||
| public ValidationErrorResponse onConstraintValidationException( | ||
| ConstraintViolationException ex | ||
| ) { | ||
| final List<Violation> violations = ex.getConstraintViolations().stream() | ||
| .map( | ||
| violation -> new Violation( | ||
| violation.getPropertyPath().toString(), | ||
| violation.getMessage() | ||
| ) | ||
| ) | ||
| .collect(Collectors.toList()); | ||
| log.warn(violations.toString()); | ||
| return new ValidationErrorResponse(violations); | ||
| } | ||
|
|
||
| @ExceptionHandler(MethodArgumentNotValidException.class) | ||
| @ResponseStatus(HttpStatus.BAD_REQUEST) | ||
| public ValidationErrorResponse onMethodArgumentNotValidException( | ||
| MethodArgumentNotValidException ex | ||
| ) { | ||
| final List<Violation> violations = ex.getBindingResult().getFieldErrors().stream() | ||
| .map(error -> new Violation(error.getField(), error.getDefaultMessage())) | ||
| .collect(Collectors.toList()); | ||
| log.warn(violations.toString()); | ||
| return new ValidationErrorResponse(violations); | ||
| } | ||
|
|
||
| @ExceptionHandler(NotFoundException.class) | ||
| @ResponseStatus(HttpStatus.NOT_FOUND) | ||
| public ErrorResponse onNotFoundException(NotFoundException ex) { | ||
| log.warn("Not found exception occurred while processing request {}", ex.getMessage()); | ||
| return new ErrorResponse("not found", ex.getMessage()); | ||
| } | ||
|
|
||
| @ExceptionHandler(DuplicateDataException.class) | ||
| @ResponseStatus(HttpStatus.CONFLICT) | ||
| public ErrorResponse onDuplicateDataException(DuplicateDataException ex) { | ||
| log.warn("Duplicate data exception occurred while processing request {}", ex.getMessage()); | ||
| return new ErrorResponse("duplicate data", ex.getMessage()); | ||
| } | ||
|
|
||
| @ExceptionHandler(ForbiddenAccessException.class) | ||
| @ResponseStatus(HttpStatus.FORBIDDEN) | ||
| public ErrorResponse onForbiddenAccessException(ForbiddenAccessException ex) { | ||
| log.warn("Forbidden access exception occurred while processing request {}", ex.getMessage()); | ||
| return new ErrorResponse("forbidden", ex.getMessage()); | ||
| } | ||
| } |
59 changes: 54 additions & 5 deletions
59
src/main/java/ru/practicum/shareit/item/ItemController.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,61 @@ | ||
| package ru.practicum.shareit.item; | ||
|
|
||
| import org.springframework.web.bind.annotation.RequestMapping; | ||
| import org.springframework.web.bind.annotation.RestController; | ||
| import jakarta.validation.Valid; | ||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.validation.annotation.Validated; | ||
| import org.springframework.web.bind.annotation.*; | ||
| import ru.practicum.shareit.item.dto.ItemDto; | ||
| import ru.practicum.shareit.item.dto.NewItemDto; | ||
| import ru.practicum.shareit.item.dto.UpdateItemDto; | ||
|
|
||
| /** | ||
| * TODO Sprint add-controllers. | ||
| */ | ||
| import java.util.Collection; | ||
|
|
||
| @Slf4j | ||
| @Validated | ||
| @RestController | ||
| @RequestMapping("/items") | ||
| @RequiredArgsConstructor | ||
| public class ItemController { | ||
| private static final String SHARER_USER_ID_HEADER = "X-Sharer-User-Id"; | ||
| private final ItemService itemService; | ||
|
|
||
| @GetMapping("/{itemId}") | ||
| public ItemDto getItem( | ||
| @RequestHeader(SHARER_USER_ID_HEADER) long userId, | ||
| @PathVariable long itemId | ||
| ) { | ||
| return itemService.getItemOfUserById(userId, itemId); | ||
| } | ||
|
|
||
| @GetMapping | ||
| public Collection<ItemDto> getItems( | ||
| @RequestHeader(SHARER_USER_ID_HEADER) long userId | ||
| ) { | ||
| return itemService.getAllItemsOfUser(userId); | ||
| } | ||
|
|
||
| @PostMapping | ||
| public ItemDto createItem( | ||
| @RequestHeader(SHARER_USER_ID_HEADER) long userId, | ||
| @RequestBody @Valid NewItemDto newItemDto | ||
| ) { | ||
| return itemService.saveItem(userId, newItemDto); | ||
| } | ||
|
|
||
| @PatchMapping("/{itemId}") | ||
| public ItemDto updateItem( | ||
| @RequestHeader(SHARER_USER_ID_HEADER) long userId, | ||
| @PathVariable long itemId, | ||
| @RequestBody @Valid UpdateItemDto updatedItem | ||
| ) { | ||
| return itemService.updateItem(userId, itemId, updatedItem); | ||
| } | ||
|
|
||
| @GetMapping("/search") | ||
| public Collection<ItemDto> searchItems( | ||
| @RequestParam(name = "text") String query | ||
| ) { | ||
| return itemService.searchItems(query); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| package ru.practicum.shareit.item; | ||
|
|
||
| import lombok.experimental.UtilityClass; | ||
| import ru.practicum.shareit.item.dto.ItemDto; | ||
| import ru.practicum.shareit.item.dto.NewItemDto; | ||
| import ru.practicum.shareit.item.dto.UpdateItemDto; | ||
| import ru.practicum.shareit.item.model.Item; | ||
|
|
||
| @UtilityClass | ||
| public class ItemMapper { | ||
|
|
||
| public ItemDto toItemDto(Item item) { | ||
| return new ItemDto( | ||
| item.getId(), | ||
| item.getName(), | ||
| item.getDescription(), | ||
| item.isAvailable(), | ||
| item.getRequest() != null ? item.getRequest().getId() : null | ||
| ); | ||
| } | ||
|
|
||
| public Item toItem(NewItemDto newItemDto) { | ||
| Item item = new Item(); | ||
| item.setName(newItemDto.name()); | ||
| item.setDescription(newItemDto.description()); | ||
| item.setAvailable(newItemDto.available()); | ||
| return item; | ||
| } | ||
|
|
||
| public Item updateItem(Item item, UpdateItemDto updateItemDto) { | ||
| if (updateItemDto.hasName()) { | ||
| item.setName(updateItemDto.name()); | ||
| } | ||
|
|
||
| if (updateItemDto.hasDescription()) { | ||
| item.setDescription(updateItemDto.description()); | ||
| } | ||
|
|
||
| if (updateItemDto.hasAvailable()) { | ||
| item.setAvailable(updateItemDto.available()); | ||
| } | ||
|
|
||
| return item; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| package ru.practicum.shareit.item; | ||
|
|
||
| import ru.practicum.shareit.item.dto.ItemDto; | ||
| import ru.practicum.shareit.item.dto.NewItemDto; | ||
| import ru.practicum.shareit.item.dto.UpdateItemDto; | ||
|
|
||
| import java.util.Collection; | ||
|
|
||
| public interface ItemService { | ||
| ItemDto getItemOfUserById(long userId, long itemId); | ||
|
|
||
| Collection<ItemDto> getAllItemsOfUser(long userId); | ||
|
|
||
| ItemDto saveItem(long userId, NewItemDto newItem); | ||
|
|
||
| ItemDto updateItem(long userId, long itemId, UpdateItemDto updatedItem); | ||
|
|
||
| Collection<ItemDto> searchItems(String query); | ||
| } |
90 changes: 90 additions & 0 deletions
90
src/main/java/ru/practicum/shareit/item/ItemServiceImpl.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package ru.practicum.shareit.item; | ||
|
|
||
| import lombok.RequiredArgsConstructor; | ||
| import lombok.extern.slf4j.Slf4j; | ||
| import org.springframework.stereotype.Service; | ||
| import ru.practicum.shareit.exception.ForbiddenAccessException; | ||
| import ru.practicum.shareit.exception.NotFoundException; | ||
| import ru.practicum.shareit.item.dto.ItemDto; | ||
| import ru.practicum.shareit.item.dto.NewItemDto; | ||
| import ru.practicum.shareit.item.dto.UpdateItemDto; | ||
| import ru.practicum.shareit.item.model.Item; | ||
| import ru.practicum.shareit.item.repository.ItemRepository; | ||
| import ru.practicum.shareit.user.model.User; | ||
| import ru.practicum.shareit.user.repository.UserRepository; | ||
|
|
||
| import java.util.Collection; | ||
| import java.util.Collections; | ||
|
|
||
| @Slf4j | ||
| @Service | ||
| @RequiredArgsConstructor | ||
| public class ItemServiceImpl implements ItemService { | ||
| private final ItemRepository itemRepository; | ||
| private final UserRepository userRepository; | ||
|
|
||
| @Override | ||
| public ItemDto getItemOfUserById(long userId, long itemId) { | ||
| getUserOrThrow(userId); | ||
|
|
||
| return itemRepository.findById(itemId) | ||
| .map(ItemMapper::toItemDto) | ||
| .orElseThrow(NotFoundException.supplier("item with id %d not found", itemId)); | ||
| } | ||
|
|
||
| @Override | ||
| public Collection<ItemDto> getAllItemsOfUser(long userId) { | ||
| getUserOrThrow(userId); | ||
|
|
||
| return itemRepository.findAllByUserId(userId) | ||
| .stream() | ||
| .map(ItemMapper::toItemDto) | ||
| .toList(); | ||
| } | ||
|
|
||
| @Override | ||
| public ItemDto saveItem(long userId, NewItemDto newItem) { | ||
| User owner = getUserOrThrow(userId); | ||
| Item item = ItemMapper.toItem(newItem); | ||
| item.setOwner(owner); | ||
| item = itemRepository.save(item); | ||
| return ItemMapper.toItemDto(item); | ||
| } | ||
|
|
||
| @Override | ||
| public ItemDto updateItem(long userId, long itemId, UpdateItemDto newItem) { | ||
| getUserOrThrow(userId); | ||
| Item item = getItemOrThrow(itemId); | ||
| if (item.getOwner().getId() != userId) { | ||
| throw new ForbiddenAccessException("Only owner of item can update it"); | ||
| } | ||
| Item updatedItem = ItemMapper.updateItem(item, newItem); | ||
| itemRepository.save(updatedItem); | ||
| return ItemMapper.toItemDto(updatedItem); | ||
| } | ||
|
|
||
|
|
||
| @Override | ||
| public Collection<ItemDto> searchItems(String query) { | ||
| if (query.isBlank()) { | ||
| return Collections.emptyList(); | ||
| } | ||
|
|
||
| return itemRepository.searchItems(query) | ||
| .stream() | ||
| .map(ItemMapper::toItemDto) | ||
| .toList(); | ||
| } | ||
|
|
||
| private Item getItemOrThrow(long itemId) { | ||
| return itemRepository.findById(itemId).orElseThrow( | ||
| NotFoundException.supplier("Item with id %d not found", itemId) | ||
| ); | ||
| } | ||
|
|
||
| private User getUserOrThrow(long userId) { | ||
| return userRepository.findById(userId).orElseThrow( | ||
| NotFoundException.supplier("User with id %d not found", userId) | ||
| ); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,7 +1,10 @@ | ||
| package ru.practicum.shareit.item.dto; | ||
|
|
||
| /** | ||
| * TODO Sprint add-controllers. | ||
| */ | ||
| public class ItemDto { | ||
| public record ItemDto( | ||
| Long id, | ||
| String name, | ||
| String description, | ||
| boolean available, | ||
| Long requestId | ||
| ) { | ||
| } |
11 changes: 11 additions & 0 deletions
11
src/main/java/ru/practicum/shareit/item/dto/NewItemDto.java
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| package ru.practicum.shareit.item.dto; | ||
|
|
||
| import jakarta.validation.constraints.NotBlank; | ||
| import jakarta.validation.constraints.NotNull; | ||
|
|
||
| public record NewItemDto( | ||
| @NotBlank String name, | ||
| @NotBlank String description, | ||
| @NotNull Boolean available | ||
| ) { | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.