Skip to content

Commit

Permalink
Implemented CRUD operations for Product Module (#45)
Browse files Browse the repository at this point in the history
* Implemented CRUD operations for Product Module

* Security Hotspot issue fixed

* Merge Conflicts resolved for "add security and swagger in product (#60)"

* Made requested changes
  • Loading branch information
PALASH2201 authored Oct 19, 2024
1 parent 6871db2 commit 5051dbf
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 22 deletions.
2 changes: 2 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ services:
KC_PROXY: passthrough
KC_DB: postgres
KC_DB_URL: jdbc:postgresql://postgres:5432/keycloak
# KC_DB_USERNAME: ${POSTGRES_USER}
# KC_DB_PASSWORD: ${POSTGRES_PASSWORD}
KC_DB_USERNAME: admin
KC_DB_PASSWORD: admin
KC_HTTP_PORT: 80
Expand Down
12 changes: 6 additions & 6 deletions docker/postgres/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
FROM debezium/postgres:15-alpine
ENV WAL2JSON_TAG=wal2json_2_5
RUN apk add --no-cache --virtual .debezium-build-deps gcc clang15 llvm15 git make musl-dev pkgconf \
&& git clone https://github.com/eulerto/wal2json -b master --single-branch \
&& (cd /wal2json && git checkout tags/$WAL2JSON_TAG -b $WAL2JSON_TAG && make && make install) \
&& rm -rf wal2json \
&& apk del .debezium-build-deps
ENV WAL2JSON_TAG="wal2json_2_5"
RUN apk add --no-cache --virtual .debezium-build-deps clang15 gcc git llvm15 make musl-dev pkgconf \
&& git clone https://github.com/eulerto/wal2json -b master --single-branch \
&& (cd /wal2json && git checkout tags/"$WAL2JSON_TAG" -b "$WAL2JSON_TAG" && make && make install) \
&& rm -rf wal2json \
&& apk del .debezium-build-deps
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ body {
}
.login-content .box .application-name {
width: 270px;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 24px;
font-weight: 600;
font-style: normal;
Expand All @@ -64,7 +64,7 @@ input {
.login-content .box .login-field {
width: 320px;
height: 24px;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
font-weight: normal;
font-style: normal;
Expand All @@ -90,7 +90,7 @@ input {
height: 36px;
border-radius: 2px;
background-color: #00754a;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
font-weight: bold;
font-style: normal;
Expand Down Expand Up @@ -124,7 +124,7 @@ input {
width: 322px;
height: 22px;
opacity: 0.87;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
font-weight: normal;
font-style: normal;
Expand All @@ -142,7 +142,7 @@ input {
}
.identity-providers {
width: 270px;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 16px;
font-weight: 600;
font-style: normal;
Expand All @@ -160,7 +160,7 @@ input {
height: 36px;
border-radius: 2px;
background-color: var(--white);
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
font-weight: bold;
font-style: normal;
Expand All @@ -178,7 +178,7 @@ input {
}

.login-content .box .para {
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
margin-left: 30px;
}
Expand All @@ -196,7 +196,7 @@ a {
height: 36px;
border-radius: 2px;
background-color: white;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
font-weight: bold;
text-align: center;
Expand All @@ -217,7 +217,7 @@ a {
height: 36px;
border-radius: 2px;
background-color: #00754a;
font-family: Muli;
font-family: Muli, sans-serif;
font-size: 14px;
font-weight: bold;
font-style: normal;
Expand Down
16 changes: 16 additions & 0 deletions product/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,22 @@
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>me.paulschwarz</groupId>
<artifactId>spring-dotenv</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,18 @@
import com.fjb.product.dto.request.ProductCreateDto;
import com.fjb.product.dto.response.ProductResponseDto;
import com.fjb.product.service.ProductService;
import jakarta.validation.Valid;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

@RestController
Expand All @@ -19,8 +25,33 @@ public class ProductController {
private final ProductService productService;

@PostMapping
@ResponseStatus(HttpStatus.CREATED)
public ProductResponseDto createProduct(@RequestBody ProductCreateDto productCreateDto) {
return productService.createProduct(productCreateDto);
public ResponseEntity<ProductResponseDto> createProduct(@Valid @RequestBody ProductCreateDto productCreateDto) {
ProductResponseDto productResponseDto = productService.createProduct(productCreateDto);
return ResponseEntity.status(HttpStatus.OK).body(productResponseDto);
}

@GetMapping
public ResponseEntity<List<ProductResponseDto>> getAllProducts() {
List<ProductResponseDto> list = productService.getAllProducts();
return ResponseEntity.status(HttpStatus.OK).body(list);
}

@GetMapping("/{id}")
public ResponseEntity<ProductResponseDto> getProductById(@PathVariable Long id) {
ProductResponseDto productResponseDto = productService.getProduct(id);
return ResponseEntity.status(HttpStatus.OK).body(productResponseDto);
}

@PutMapping("/{id}")
public ResponseEntity<ProductResponseDto> updateProduct(
@PathVariable Long id, @Valid @RequestBody ProductCreateDto newProductCreateDto) {
ProductResponseDto updatedProduct = productService.updateProduct(id, newProductCreateDto);
return ResponseEntity.status(HttpStatus.OK).body(updatedProduct);
}

@DeleteMapping("/{id}")
public ResponseEntity.BodyBuilder deleteProduct(@PathVariable Long id) {
productService.deleteProductById(id);
return ResponseEntity.status(HttpStatus.CREATED);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.fjb.product.dto.request;

import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import java.math.BigDecimal;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand All @@ -13,7 +15,10 @@
@NoArgsConstructor
@AllArgsConstructor
public class ProductCreateDto {
@NotEmpty(message = "name cannot be empty")
private String name;
@NotEmpty(message = "description cannot be empty")
private String description;
@NotNull(message = "price cannot be null")
private BigDecimal price;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,13 @@
public class ApiExceptionHandler {
private static final String ERROR_LOG_FORMAT = "Error: URI: {}, ErrorCode: {}, Message: {}";

@ExceptionHandler(ErrorCreatingEntry.class)
public ResponseEntity<ErrorVm> handleErrorCreatingEntry(ErrorCreatingEntry ex, WebRequest request) {
HttpStatus status = HttpStatus.BAD_REQUEST;
String message = ex.getMessage();
return buildErrorResponse(status, message, null, ex, request, status.value());
}

@ExceptionHandler(NotFoundException.class)
public ResponseEntity<ErrorVm> handleNotFoundException(NotFoundException ex, WebRequest request) {
HttpStatus status = HttpStatus.NOT_FOUND;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.fjb.product.exception;

import com.fjb.product.utils.MessagesUtils;

public class ErrorCreatingEntry extends RuntimeException {
private final String message;

public ErrorCreatingEntry(String errorCode, Object... var2) {
this.message = MessagesUtils.getMessage(errorCode, var2);
}

@Override
public String getMessage() {
return message;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import com.fjb.product.dto.response.ProductResponseDto;
import com.fjb.product.entity.Product;
import org.mapstruct.Mapper;
import org.mapstruct.MappingTarget;

@Mapper(componentModel = "spring")
public interface ProductMapper {
Product toProduct(ProductCreateDto productCreateDto);

ProductResponseDto toProductResponseDto(Product product);

Product updateProduct(@MappingTarget Product product, ProductCreateDto productCreateDto);
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.fjb.product.repository;

import com.fjb.product.entity.Product;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ProductRepository extends JpaRepository<Product, Long> {

List<Product> findAllByOrderByIdAsc();
}
41 changes: 39 additions & 2 deletions product/src/main/java/com/fjb/product/service/ProductService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
import com.fjb.product.dto.request.ProductCreateDto;
import com.fjb.product.dto.response.ProductResponseDto;
import com.fjb.product.entity.Product;
import com.fjb.product.exception.ErrorCreatingEntry;
import com.fjb.product.exception.NotFoundException;
import com.fjb.product.mapper.ProductMapper;
import com.fjb.product.repository.ProductRepository;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
@Transactional(readOnly = true)
public class ProductService {

private final ProductMapper productMapper;
Expand All @@ -20,6 +23,40 @@ public class ProductService {
@Transactional
public ProductResponseDto createProduct(ProductCreateDto productCreateDto) {
Product product = productMapper.toProduct(productCreateDto);
return productMapper.toProductResponseDto(productRepository.save(product));
product = productRepository.save(product);
if (product == null) {
throw new ErrorCreatingEntry("Could not create product");
}
return productMapper.toProductResponseDto(product);
}

public List<ProductResponseDto> getAllProducts() {
List<Product> list = productRepository.findAllByOrderByIdAsc();
if (list.isEmpty()) {
return new ArrayList<>();
}
List<ProductResponseDto> responseList = new ArrayList<>();
list.forEach(product -> responseList.add(productMapper.toProductResponseDto(product)));
return responseList;
}

public ProductResponseDto getProduct(Long id) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Product not found with id: " + id));
return productMapper.toProductResponseDto(product);
}

public ProductResponseDto updateProduct(Long id, ProductCreateDto productCreateDto) {
Product product = productRepository.findById(id)
.orElseThrow(() -> new NotFoundException("Product not found"));
product = productMapper.updateProduct(product, productCreateDto);
return productMapper.toProductResponseDto(product);
}

public void deleteProductById(Long id) {
if (!productRepository.existsById(id)) {
throw new NotFoundException("Product not found with id: " + id);
}
productRepository.deleteById(id);
}
}
3 changes: 3 additions & 0 deletions product/src/main/resources/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
PRODUCT_DATA_USERNAME=
PRODUCT_DATA_PASSWORD=
PRODUCT_DATASOURCE_URL=jdbc:postgresql://localhost:5432/product
Empty file modified sell-bff/mvnw
100755 → 100644
Empty file.

0 comments on commit 5051dbf

Please sign in to comment.