Commit 5e67d4ed authored by Tejas Sharma's avatar Tejas Sharma

implemented mapstruct, internalization and parallel/sequential req res...

implemented mapstruct, internalization and parallel/sequential req res mechanism in inventory service
parent 41ab3dda
...@@ -59,5 +59,52 @@ ...@@ -59,5 +59,52 @@
<version>3.8.1</version> <version>3.8.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>3.4.0</version>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<source>17</source> <!-- Set this according to your JDK version -->
<target>17</target>
<compilerArgument>-parameters</compilerArgument>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version> <!-- Ensure this is the same as above -->
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>
package org.nisum.config;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MessageConfig implements WebMvcConfigurer {
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath::messages"); //base name for messages file
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
}
package org.nisum.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
@Bean
public WebClient.Builder webClientBuilder(){
return WebClient.builder();
}
}
package org.nisum.controller; package org.nisum.controller;
import org.nisum.dto.InventoryDTO;
import org.nisum.model.Inventory; import org.nisum.model.Inventory;
import org.nisum.service.InventoryService; import org.nisum.service.InventoryService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.util.List;
import java.util.Locale;
@RestController @RestController
@RequestMapping("/inventory") @RequestMapping("/inventory")
public class InventoryController { public class InventoryController {
@Autowired @Autowired
private InventoryService inventoryService; private InventoryService inventoryService;
@Autowired
private MessageSource messageSource;
@PostMapping("/create") @PostMapping("/create")
public Mono<Inventory> AddProductToInventory(@RequestBody Inventory inventory){ public Mono<ResponseEntity<String>> AddProductToInventory(@RequestBody InventoryDTO inventoryDTO, Locale locale){
return inventoryService.createInventory(inventory); return inventoryService.createInventory(inventoryDTO)
.map(savedInventory -> ResponseEntity.status(HttpStatus.CREATED)
.body(messageSource.getMessage("inventory.created.success",new Object[]{},locale)))
.defaultIfEmpty(ResponseEntity
.status(HttpStatus.BAD_REQUEST)
.body(messageSource.getMessage("inventory.invalid.data",new Object[]{},locale)));
} }
@GetMapping("/check/{productId}/{quantity}") @GetMapping("/check/{productId}/{quantity}")
...@@ -24,5 +39,24 @@ public class InventoryController { ...@@ -24,5 +39,24 @@ public class InventoryController {
return inventoryService.checkProductAvailability(productId,quantity); return inventoryService.checkProductAvailability(productId,quantity);
} }
// http://localhost:8082/inventory/allRecords
@GetMapping("/allRecords")
public Flux<InventoryDTO> getAllInventories(){
return inventoryService.getAllInventories();
}
@GetMapping("/sequential")
public Mono<List<String>> getSequentialInventoryDetails() {
return inventoryService.getSequentialInventoryDetails();
}
@GetMapping("/sequential1")
public Mono<List<String>> getSequentialInventoryDetails1() {
return inventoryService.getSequentialInventoryDetails();
}
@GetMapping("/parallel")
public Mono<List<String>> getParallelInventoryDetails() {
return inventoryService.getParallelInventoryDetails();
}
} }
package org.nisum.dto;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class InventoryDTO {
private String id;
private String productId;
private boolean inStock;
private int quantity;
private LocalDateTime timeStamp;
}
package org.nisum.mapper;
import org.mapstruct.Mapper;
import org.nisum.dto.InventoryDTO;
import org.nisum.model.Inventory;
@Mapper(componentModel = "spring")
public interface InventoryMapper {
Inventory toInventory(InventoryDTO inventoryDTO);
InventoryDTO toInventoryDTO(Inventory inventory);
}
...@@ -3,10 +3,9 @@ package org.nisum.repository; ...@@ -3,10 +3,9 @@ package org.nisum.repository;
import org.nisum.model.Inventory; import org.nisum.model.Inventory;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository; import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import reactor.core.publisher.Flux;
import java.util.Optional;
@Repository @Repository
public interface InventoryRepository extends ReactiveMongoRepository<Inventory,String> { public interface InventoryRepository extends ReactiveMongoRepository<Inventory,String> {
Optional<Inventory> findByProductId(String productId); Flux<Inventory> findByProductId(String productId);
} }
package org.nisum.service; package org.nisum.service;
import org.nisum.dto.InventoryDTO;
import org.nisum.mapper.InventoryMapper;
import org.nisum.model.Inventory; import org.nisum.model.Inventory;
import org.nisum.repository.InventoryRepository; import org.nisum.repository.InventoryRepository;
import org.slf4j.Logger; import org.slf4j.Logger;
...@@ -7,37 +9,118 @@ import org.slf4j.LoggerFactory; ...@@ -7,37 +9,118 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono; import reactor.core.publisher.Mono;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional; import java.util.Optional;
@Service @Service
public class InventoryService { public class InventoryService {
private final InventoryMapper inventoryMapper;
@Autowired @Autowired
private InventoryRepository inventoryRepository; private InventoryRepository inventoryRepository;
@Autowired
private WebClient.Builder webClientBuilder;
Boolean status;
public static final Logger log = LoggerFactory.getLogger(InventoryService.class); public static final Logger log = LoggerFactory.getLogger(InventoryService.class);
public Mono<Inventory> createInventory(Inventory inventory) {
@Autowired
public InventoryService(InventoryMapper inventoryMapper) {
this.inventoryMapper = inventoryMapper;
}
public InventoryDTO getInventoryDTO(Inventory inventory){
return inventoryMapper.toInventoryDTO(inventory);
}
public Inventory getInventory(InventoryDTO inventoryDTO){
return inventoryMapper.toInventory(inventoryDTO);
}
public Mono<InventoryDTO> createInventory(InventoryDTO inventoryDTO) {
Inventory inventory = inventoryMapper.toInventory(inventoryDTO);
inventory.setTimeStamp(LocalDateTime.now()); inventory.setTimeStamp(LocalDateTime.now());
inventory.setInStock(true); inventory.setInStock(true);
return inventoryRepository.save(inventory).doOnSuccess(inventory1 -> { return Mono.just(inventory).flatMap(inventoryRepository::save)
log.info("product with product id: "+inventory1.getProductId() + " added successfully to the inventory"); .map(inventoryMapper::toInventoryDTO).doOnSuccess(inventoryDTO1 -> {
log.info("product with product id: "+inventoryDTO1.getProductId() + " added successfully to the inventory");
}); });
}
public Flux<InventoryDTO> getAllInventories(){
Flux<Inventory> inventoryFlux = inventoryRepository.findAll();
return inventoryFlux.map(inventoryMapper::toInventoryDTO);
} }
public ResponseEntity<Boolean> checkProductAvailability(String productId, int requiredQuantity){ public ResponseEntity<Boolean> checkProductAvailability(String productId, int requiredQuantity){
Inventory inventory = inventoryRepository.findByProductId(productId).orElse(null); Flux<Inventory> inventory = inventoryRepository.findByProductId(productId);
inventory.subscribe(inventory1 -> {
log.info(inventory1.getProductId() + " : " + inventory1.getQuantity());
log.info(String.valueOf(requiredQuantity));
if(inventory1 != null){
log.info("inside not null");
if(inventory != null){ if(inventory1.getQuantity() >= requiredQuantity){
if(inventory.getQuantity() >= requiredQuantity){ log.info("inside true");
return ResponseEntity.ok(true); status = true;
}else{ }else{
return ResponseEntity.ok(false); status = false;
} }
}else { }else {
return ResponseEntity.ok(false); log.info("inside false");
status = false;
}
});
log.info(String.valueOf(status));
return ResponseEntity.ok(status);
}
//sequential request-response model
public Mono<List<String>> getSequentialInventoryDetails(){
return webClientBuilder.baseUrl("https://dummyjson.com")
.build()
.get()
.uri("/products/1")
.retrieve()
.bodyToMono(String.class)
.flatMap(s ->
webClientBuilder.baseUrl("https://dummyjson.com")
.build()
.get()
.uri("/products/2")
.retrieve()
.bodyToMono(String.class)
.map(s1 -> List.of(s,s1)));
} }
//parallel request response model
public Mono<List<String>> getParallelInventoryDetails(){
Mono<String> product1 =webClientBuilder.baseUrl("https://dummyjson.com")
.build()
.get()
.uri("/products/1")
.retrieve()
.bodyToMono(String.class);
Mono<String> product2 =webClientBuilder.baseUrl("https://dummyjson.com")
.build()
.get()
.uri("/products/2")
.retrieve()
.bodyToMono(String.class);
return Mono.zip(product1,product2)
.map(objects -> List.of(objects.getT1(),objects.getT2()));
} }
} }
...@@ -4,3 +4,9 @@ spring: ...@@ -4,3 +4,9 @@ spring:
data: data:
mongodb: mongodb:
uri: mongodb://localhost:27017/inventory_db uri: mongodb://localhost:27017/inventory_db
messages:
basename: messages
cache-duration: 3600
mvc:
locale: en #Points to the base name of the message files. In this case, we use messages.properties, messages_en.properties, etc.
locale-resolver: accept-header #We are using the AcceptHeaderLocaleResolver that will automatically resolve the locale based on the Accept-Language header in the HTTP request.
inventory.created.success=Inventory created successfully!
inventory.all.retrieved=All inventories retrieved successfully!
inventory.invalid.data=Invalid data provided!
\ No newline at end of file
inventory.created.success=¡Inventario creado con éxito!
inventory.all.retrieved=¡Todos los inventarios recuperados con éxito!
inventory.invalid.data=¡Datos proporcionados no válidos!
\ No newline at end of file
...@@ -68,6 +68,28 @@ ...@@ -68,6 +68,28 @@
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
<version>2.0.16</version> <version>2.0.16</version>
</dependency> </dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct-processor -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mapstruct/mapstruct -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-devtools -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>3.4.0</version>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>
...@@ -81,7 +103,16 @@ ...@@ -81,7 +103,16 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> <artifactId>spring-boot-maven-plugin</artifactId>
<configuration> <configuration>
<source>17</source> <!-- Set this according to your JDK version -->
<target>17</target>
<compilerArgument>-parameters</compilerArgument> <compilerArgument>-parameters</compilerArgument>
<annotationProcessorPaths>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.5.5.Final</version> <!-- Ensure this is the same as above -->
</path>
</annotationProcessorPaths>
</configuration> </configuration>
</plugin> </plugin>
</plugins> </plugins>
......
...@@ -38,19 +38,21 @@ public class OrderService { ...@@ -38,19 +38,21 @@ public class OrderService {
} }
public Mono<String> placeOrder(String productId, int quantity){ public Mono<String> placeOrder(String productId, int quantity){
return checkProductAvailability(productId, quantity) log.info(String.valueOf(checkProductAvailability(productId,quantity)));
.flatMap(isAvailable -> { return Mono.just("Something");
if(isAvailable){ // return checkProductAvailability(productId, quantity)
return createOrder(productId,quantity); // .flatMap(isAvailable -> {
} // if(isAvailable){
return Mono.just("Product is out of stock or insufficient quantity."); // return createOrder(productId,quantity);
}); // }
// return Mono.just("Product is out of stock or insufficient quantity.");
// });
} }
private Mono<Boolean> checkProductAvailability(String productId, int quantity){ private Mono<Boolean> checkProductAvailability(String productId, int quantity){
return webClient.get() return webClient.get()
.uri("/check/{productId}/{quantity}") .uri("/check/{'"+productId+"'}/{'"+quantity+"'}")
.retrieve() .retrieve()
.bodyToMono(Boolean.class); .bodyToMono(Boolean.class);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment