diff --git a/backend/HELP.md b/backend/HELP.md index a9596dd..5d85555 100644 --- a/backend/HELP.md +++ b/backend/HELP.md @@ -7,8 +7,8 @@ For further reference, please consider the following sections: * [Spring Boot Maven Plugin Reference Guide](https://docs.spring.io/spring-boot/docs/3.2.2/maven-plugin/reference/html/) * [Create an OCI image](https://docs.spring.io/spring-boot/docs/3.2.2/maven-plugin/reference/html/#build-image) * [Spring Web](https://docs.spring.io/spring-boot/docs/3.2.2/reference/htmlsingle/index.html#web) -* [Spring Boot DevTools](https://docs.spring.io/spring-boot/docs/3.2.2/reference/htmlsingle/index.html#using.devtools) * [Spring Data JPA](https://docs.spring.io/spring-boot/docs/3.2.2/reference/htmlsingle/index.html#data.sql.jpa-and-spring-data) +* [Validation](https://docs.spring.io/spring-boot/docs/3.2.2/reference/htmlsingle/index.html#io.validation) ### Guides The following guides illustrate how to use some features concretely: @@ -16,6 +16,7 @@ The following guides illustrate how to use some features concretely: * [Building a RESTful Web Service](https://spring.io/guides/gs/rest-service/) * [Serving Web Content with Spring MVC](https://spring.io/guides/gs/serving-web-content/) * [Building REST services with Spring](https://spring.io/guides/tutorials/rest/) -* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/) * [Accessing Data with JPA](https://spring.io/guides/gs/accessing-data-jpa/) +* [Accessing data with MySQL](https://spring.io/guides/gs/accessing-data-mysql/) +* [Validation](https://spring.io/guides/gs/validating-form-input/) diff --git a/backend/README.md b/backend/README.md deleted file mode 100644 index c0a4bbb..0000000 --- a/backend/README.md +++ /dev/null @@ -1 +0,0 @@ -# Backend directory \ No newline at end of file diff --git a/backend/pom.xml b/backend/pom.xml index 7da3b2e..83635ba 100644 --- a/backend/pom.xml +++ b/backend/pom.xml @@ -8,7 +8,7 @@ 3.2.2 - com.reactpairdemo + com.pairdemo demo 0.0.1-SNAPSHOT demo @@ -22,34 +22,19 @@ modelmapper 3.1.1 - - org.slf4j - jul-to-slf4j - - - - - - org.springframework.boot - spring-boot-starter-validation + spring-boot-starter-data-jpa org.springframework.boot - spring-boot-starter-data-jpa + spring-boot-starter-validation org.springframework.boot spring-boot-starter-web - - org.springframework.boot - spring-boot-devtools - runtime - true - com.mysql mysql-connector-j diff --git a/backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java b/backend/src/main/java/com/pairdemo/demo/DemoApplication.java similarity index 77% rename from backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java rename to backend/src/main/java/com/pairdemo/demo/DemoApplication.java index b6ead96..ed1b59f 100644 --- a/backend/src/main/java/com/reactpairdemo/demo/DemoApplication.java +++ b/backend/src/main/java/com/pairdemo/demo/DemoApplication.java @@ -1,4 +1,4 @@ -package com.reactpairdemo.demo; +package com.pairdemo.demo; import org.modelmapper.ModelMapper; import org.springframework.boot.SpringApplication; @@ -11,9 +11,10 @@ public class DemoApplication { public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } + @Bean - public ModelMapper modelMapper() { - return new ModelMapper(); - } + public ModelMapper modelMapper(){ + return new ModelMapper(); + } } diff --git a/backend/src/main/java/com/pairdemo/demo/controller/ProductController.java b/backend/src/main/java/com/pairdemo/demo/controller/ProductController.java new file mode 100644 index 0000000..22212e4 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/controller/ProductController.java @@ -0,0 +1,42 @@ +package com.pairdemo.demo.controller; + +import com.pairdemo.demo.dto.ProductDto; +import com.pairdemo.demo.entity.Product; +import com.pairdemo.demo.service.ProductService; +import jakarta.validation.Valid; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +import static com.pairdemo.demo.utils.Constants.BASE_URL; + +@RestController +@RequestMapping(BASE_URL) +public class ProductController { + + private final ProductService productService; + + @Autowired + public ProductController(ProductService productService) { + this.productService = productService; + } + @GetMapping("/search") + public ResponseEntity> searchProductByName(@RequestParam("name") String name) { + return new ResponseEntity<>(productService.searchProductByName(name), HttpStatus.OK) ; + } + + @PostMapping + public ResponseEntity createProduct(@Valid @RequestBody ProductDto productDto) { + + return new ResponseEntity<>(productService.createProduct(productDto), HttpStatus.CREATED); + } + @DeleteMapping("/{id}") + public ResponseEntity createProduct(@PathVariable Long id) { + + return new ResponseEntity<>(productService.deleteProduct(id), HttpStatus.CREATED) ; + } + +} diff --git a/backend/src/main/java/com/pairdemo/demo/dto/ProductDto.java b/backend/src/main/java/com/pairdemo/demo/dto/ProductDto.java new file mode 100644 index 0000000..e238572 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/dto/ProductDto.java @@ -0,0 +1,16 @@ +package com.pairdemo.demo.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +@Data +public class ProductDto { + private Long id; + @NotBlank(message = "Please enter a name") + @Size(min = 3,message = "") + private String name; + @NotNull(message = "Please enter a price") + private Double Price; +} diff --git a/backend/src/main/java/com/pairdemo/demo/entity/Product.java b/backend/src/main/java/com/pairdemo/demo/entity/Product.java new file mode 100644 index 0000000..787119a --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/entity/Product.java @@ -0,0 +1,18 @@ +package com.pairdemo.demo.entity; + +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import lombok.Data; + +@Entity +@Data +public class Product { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + + private Long id; + private String name; + private Double Price; +} diff --git a/backend/src/main/java/com/pairdemo/demo/exceptions/ErrorResponse.java b/backend/src/main/java/com/pairdemo/demo/exceptions/ErrorResponse.java new file mode 100644 index 0000000..c802290 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/exceptions/ErrorResponse.java @@ -0,0 +1,11 @@ +package com.pairdemo.demo.exceptions; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class ErrorResponse { + String message; + String title; +} diff --git a/backend/src/main/java/com/pairdemo/demo/exceptions/GlobalExceptionHandler.java b/backend/src/main/java/com/pairdemo/demo/exceptions/GlobalExceptionHandler.java new file mode 100644 index 0000000..17c4f95 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/exceptions/GlobalExceptionHandler.java @@ -0,0 +1,39 @@ +package com.pairdemo.demo.exceptions; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.HashMap; +import java.util.Map; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(ResourceNotFoundException.class) + public ResponseEntity handleResourceNotFound(Exception e){ + ErrorResponse errorResponse=ErrorResponse.builder().message(e.getMessage()).title(HttpStatus.NOT_FOUND.getReasonPhrase()).build(); + return new ResponseEntity<>(errorResponse,HttpStatus.NOT_FOUND); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleResourceNotFound(MethodArgumentNotValidException e){ + Map resp=new HashMap<>(); + e.getBindingResult().getAllErrors().forEach(objectError -> { + resp.put(((FieldError)objectError).getField(),objectError.getDefaultMessage()); + }); + + + return new ResponseEntity<>(resp,HttpStatus.BAD_REQUEST); + } + + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity handleIllegalArgumentException(IllegalArgumentException e){ + ErrorResponse errorResponse=ErrorResponse.builder().message(e.getMessage()).title(HttpStatus.NOT_ACCEPTABLE.getReasonPhrase()).build(); + return new ResponseEntity<>(errorResponse,HttpStatus.NOT_ACCEPTABLE); + } + +} diff --git a/backend/src/main/java/com/pairdemo/demo/exceptions/ResourceNotFoundException.java b/backend/src/main/java/com/pairdemo/demo/exceptions/ResourceNotFoundException.java new file mode 100644 index 0000000..504aa53 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/exceptions/ResourceNotFoundException.java @@ -0,0 +1,7 @@ +package com.pairdemo.demo.exceptions; + +public class ResourceNotFoundException extends RuntimeException{ + public ResourceNotFoundException(String message) { + super(message); + } +} diff --git a/backend/src/main/java/com/pairdemo/demo/repository/ProductRepository.java b/backend/src/main/java/com/pairdemo/demo/repository/ProductRepository.java new file mode 100644 index 0000000..62bbcf1 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/repository/ProductRepository.java @@ -0,0 +1,10 @@ +package com.pairdemo.demo.repository; + +import com.pairdemo.demo.entity.Product; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface ProductRepository extends JpaRepository { + public List findByName(String name); +} diff --git a/backend/src/main/java/com/pairdemo/demo/service/ProductService.java b/backend/src/main/java/com/pairdemo/demo/service/ProductService.java new file mode 100644 index 0000000..2bbfeed --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/service/ProductService.java @@ -0,0 +1,12 @@ +package com.pairdemo.demo.service; + +import com.pairdemo.demo.dto.ProductDto; + +import java.util.List; + +public interface ProductService { + List searchProductByName(String name); + + ProductDto createProduct(ProductDto productDto); + String deleteProduct(Long id); +} diff --git a/backend/src/main/java/com/pairdemo/demo/service/ProductServiceImpl.java b/backend/src/main/java/com/pairdemo/demo/service/ProductServiceImpl.java new file mode 100644 index 0000000..d84e4be --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/service/ProductServiceImpl.java @@ -0,0 +1,54 @@ +package com.pairdemo.demo.service; + +import com.pairdemo.demo.dto.ProductDto; +import com.pairdemo.demo.entity.Product; +import com.pairdemo.demo.repository.ProductRepository; +import org.modelmapper.ModelMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import static com.pairdemo.demo.utils.Constants.ID_NOT_FOUND; +import static com.pairdemo.demo.utils.Constants.SUCESS_DELETE; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +@Service +public class ProductServiceImpl implements ProductService{ + + private final ProductRepository productRepository; + + private final ModelMapper modelMapper; + + @Autowired + public ProductServiceImpl(ProductRepository productRepository, ModelMapper modelMapper) { + this.productRepository = productRepository; + this.modelMapper = modelMapper; + } + + @Override + public List searchProductByName(String name) { + List productList = productRepository.findByName(name); +// System.out.println(productList); +// return productList.stream().map(product -> modelMapper.map(product,ProductDto.class)).collect(Collectors.toList()); + return productList.stream().map(product -> modelMapper.map(product, ProductDto.class)).filter(productDto -> productDto.getName().equalsIgnoreCase(name)).collect(Collectors.toList()); + } + + @Override + public ProductDto createProduct(ProductDto productDto) { + Product product = modelMapper.map(productDto, Product.class); + Product product1 = productRepository.save(product); + return modelMapper.map(product, ProductDto.class); + } + + @Override + public String deleteProduct(Long id) { + Optional productOptional = productRepository.findById(id); + if (productOptional.isEmpty()) { + throw new ResourceNotFoundException(ID_NOT_FOUND); + } + productRepository.deleteById(id); + return SUCESS_DELETE; + } +} diff --git a/backend/src/main/java/com/pairdemo/demo/utils/Constants.java b/backend/src/main/java/com/pairdemo/demo/utils/Constants.java new file mode 100644 index 0000000..c937904 --- /dev/null +++ b/backend/src/main/java/com/pairdemo/demo/utils/Constants.java @@ -0,0 +1,7 @@ +package com.pairdemo.demo.utils; + +public class Constants { + public static final String BASE_URL = "/api/v1/product"; + public static final String ID_NOT_FOUND= "Given Id Not Found!!"; + public static final String SUCESS_DELETE= "Success to Delete"; +} diff --git a/backend/src/main/resources/application.properties b/backend/src/main/resources/application.properties index 89eef6b..66b7a72 100644 --- a/backend/src/main/resources/application.properties +++ b/backend/src/main/resources/application.properties @@ -1,4 +1,5 @@ + spring.datasource.url=jdbc:mysql://localhost:3306/pairdemo?useSSL=false&ServerTimeZone=UTC spring.datasource.username=root spring.datasource.password=root diff --git a/backend/src/test/java/com/reactpairdemo/demo/DemoApplicationTests.java b/backend/src/test/java/com/pairdemo/demo/DemoApplicationTests.java similarity index 84% rename from backend/src/test/java/com/reactpairdemo/demo/DemoApplicationTests.java rename to backend/src/test/java/com/pairdemo/demo/DemoApplicationTests.java index 823b938..ba7faf6 100644 --- a/backend/src/test/java/com/reactpairdemo/demo/DemoApplicationTests.java +++ b/backend/src/test/java/com/pairdemo/demo/DemoApplicationTests.java @@ -1,4 +1,4 @@ -package com.reactpairdemo.demo; +package com.pairdemo.demo; import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; diff --git a/backend/target/classes/application.properties b/backend/target/classes/application.properties index 89eef6b..66b7a72 100644 --- a/backend/target/classes/application.properties +++ b/backend/target/classes/application.properties @@ -1,4 +1,5 @@ + spring.datasource.url=jdbc:mysql://localhost:3306/pairdemo?useSSL=false&ServerTimeZone=UTC spring.datasource.username=root spring.datasource.password=root diff --git a/backend/target/classes/com/pairdemo/demo/DemoApplication.class b/backend/target/classes/com/pairdemo/demo/DemoApplication.class new file mode 100644 index 0000000..60dab7b Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/DemoApplication.class differ diff --git a/backend/target/classes/com/pairdemo/demo/controller/ProductController.class b/backend/target/classes/com/pairdemo/demo/controller/ProductController.class new file mode 100644 index 0000000..fb27832 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/controller/ProductController.class differ diff --git a/backend/target/classes/com/pairdemo/demo/dto/ProductDto.class b/backend/target/classes/com/pairdemo/demo/dto/ProductDto.class new file mode 100644 index 0000000..d14e08d Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/dto/ProductDto.class differ diff --git a/backend/target/classes/com/pairdemo/demo/entity/Product.class b/backend/target/classes/com/pairdemo/demo/entity/Product.class new file mode 100644 index 0000000..765d787 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/entity/Product.class differ diff --git a/backend/target/classes/com/pairdemo/demo/exceptions/ErrorResponse$ErrorResponseBuilder.class b/backend/target/classes/com/pairdemo/demo/exceptions/ErrorResponse$ErrorResponseBuilder.class new file mode 100644 index 0000000..cc80c14 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/exceptions/ErrorResponse$ErrorResponseBuilder.class differ diff --git a/backend/target/classes/com/pairdemo/demo/exceptions/ErrorResponse.class b/backend/target/classes/com/pairdemo/demo/exceptions/ErrorResponse.class new file mode 100644 index 0000000..6a9e727 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/exceptions/ErrorResponse.class differ diff --git a/backend/target/classes/com/pairdemo/demo/exceptions/GlobalExceptionHandler.class b/backend/target/classes/com/pairdemo/demo/exceptions/GlobalExceptionHandler.class new file mode 100644 index 0000000..620b98d Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/exceptions/GlobalExceptionHandler.class differ diff --git a/backend/target/classes/com/pairdemo/demo/exceptions/ResourceNotFoundException.class b/backend/target/classes/com/pairdemo/demo/exceptions/ResourceNotFoundException.class new file mode 100644 index 0000000..a462123 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/exceptions/ResourceNotFoundException.class differ diff --git a/backend/target/classes/com/pairdemo/demo/repository/ProductRepository.class b/backend/target/classes/com/pairdemo/demo/repository/ProductRepository.class new file mode 100644 index 0000000..32ab222 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/repository/ProductRepository.class differ diff --git a/backend/target/classes/com/pairdemo/demo/service/ProductService.class b/backend/target/classes/com/pairdemo/demo/service/ProductService.class new file mode 100644 index 0000000..54103e8 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/service/ProductService.class differ diff --git a/backend/target/classes/com/pairdemo/demo/service/ProductServiceImpl.class b/backend/target/classes/com/pairdemo/demo/service/ProductServiceImpl.class new file mode 100644 index 0000000..3622835 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/service/ProductServiceImpl.class differ diff --git a/backend/target/classes/com/pairdemo/demo/utils/Constants.class b/backend/target/classes/com/pairdemo/demo/utils/Constants.class new file mode 100644 index 0000000..20e04d5 Binary files /dev/null and b/backend/target/classes/com/pairdemo/demo/utils/Constants.class differ diff --git a/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class b/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class deleted file mode 100644 index 5662ef5..0000000 Binary files a/backend/target/classes/com/reactpairdemo/demo/DemoApplication.class and /dev/null differ diff --git a/backend/target/test-classes/com/reactpairdemo/demo/DemoApplicationTests.class b/backend/target/test-classes/com/reactpairdemo/demo/DemoApplicationTests.class deleted file mode 100644 index fca0906..0000000 Binary files a/backend/target/test-classes/com/reactpairdemo/demo/DemoApplicationTests.class and /dev/null differ