POC using Spring Web Flux and Mongo DB

parents
# Default ignored files
/shelf/
/workspace.xml
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="Spring-WebFlux-MongoDB" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="Spring-WebFlux-MongoDB" options="-parameters" />
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_22" default="true" project-jdk-name="corretto-22" project-jdk-type="JavaSDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>
\ No newline at end of file
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.mongo</groupId>
<artifactId>Spring-WebFlux-MongoDB</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Mongo demo example</name>
<description>Catalogue project for Spring Boot</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb-reactive</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
package com.mongo.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class MongoDemoExampleApplication {
public static void main(String[] args) {
SpringApplication.run(MongoDemoExampleApplication.class, args);
}
}
package com.mongo.demo.controller;
import com.mongo.demo.dto.EmployeeDto;
import com.mongo.demo.entity.Employee;
import com.mongo.demo.service.EmployeeService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Mono;
import java.util.List;
@RestController
public class EmployeeController {
@Autowired
private EmployeeService service;
@GetMapping("/employeesDetails")
public Mono<List<Employee>> getEmployeesDetails(){
return service.getEmployeesDetails();
}
@GetMapping("/employeeDetails/{id}")
public Mono<EmployeeDto> getEmployeeDetails(@PathVariable String id){
return service.getEmployeeDetails(id);
}
@PostMapping("/createEmployee")
public Mono<EmployeeDto> createEmployee(@RequestBody Mono<EmployeeDto> employeeDtoMono){
return service.createEmployee(employeeDtoMono);
}
@DeleteMapping("/deleteEmployee/{id}")
public Mono<String> deleteEmployee(@PathVariable String id){
return service.deleteEmployee(id);
}
}
package com.mongo.demo.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class EmployeeDto {
private String id;
private String name;
private String designation;
private BigDecimal salary;
public String getId() {
return id;
}
}
package com.mongo.demo.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
import java.math.BigDecimal;
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
@Document(collection = "employee")
public class Employee {
@Id
private String id;
private String name;
private String designation;
private BigDecimal salary;
public String getId() {
return this.id;
}
}
package com.mongo.demo.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class EmployeeExceptionController {
@ExceptionHandler(value = EmployeeNotFoundException.class)
public ResponseEntity<String> handleException(EmployeeNotFoundException exception){
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(exception.getMessage());
}
}
package com.mongo.demo.exception;
public class EmployeeNotFoundException extends RuntimeException{
public EmployeeNotFoundException(){
super();
}
public EmployeeNotFoundException(String s) {
super(s);
}
}
package com.mongo.demo.repositery;
import com.mongo.demo.entity.Employee;
import org.springframework.data.mongodb.repository.ReactiveMongoRepository;
public interface EmployeeRepository extends ReactiveMongoRepository<Employee, String> {
}
package com.mongo.demo.service;
import com.mongo.demo.dto.EmployeeDto;
import com.mongo.demo.entity.Employee;
import com.mongo.demo.exception.EmployeeNotFoundException;
import com.mongo.demo.repositery.EmployeeRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.mongo.demo.utils.EmployeeMapper;
import reactor.core.publisher.Mono;
import java.util.List;
@Service
public class EmployeeService {
@Autowired
private EmployeeRepository employeeRepository;
public Mono<List<Employee>> getEmployeesDetails(){
return employeeRepository.findAll().collectList();
}
public Mono<EmployeeDto> getEmployeeDetails(String id){
Mono<Employee> byId = employeeRepository.findById(id).switchIfEmpty(Mono.error(new EmployeeNotFoundException("Employee with ID " + id + " not found")));
return byId.flatMap(employee -> {
return Mono.just(EmployeeMapper.entityToDto(employee));
});
}
public Mono<EmployeeDto> createEmployee(Mono<EmployeeDto> employeeDtoMono){
return employeeDtoMono
.map(EmployeeMapper::dtoToEntity)
.flatMap(employeeRepository :: insert)
.map(EmployeeMapper :: entityToDto);
}
public Mono<String> deleteEmployee(String id){
return employeeRepository.existsById(id)
.flatMap(exists -> {
if (exists) {
return employeeRepository.deleteById(id)
.then(Mono.just("Success"));
} else {
return Mono.just("No record found");
}
});
}
}
package com.mongo.demo.utils;
import com.mongo.demo.dto.EmployeeDto;
import com.mongo.demo.entity.Employee;
import org.springframework.beans.BeanUtils;
public class EmployeeMapper {
public static EmployeeDto entityToDto(Employee employee ){
EmployeeDto dto = new EmployeeDto();
BeanUtils.copyProperties(employee,dto);
return dto;
}
public static Employee dtoToEntity(EmployeeDto dto ){
Employee entity = new Employee();
BeanUtils.copyProperties(dto , entity);
return entity;
}
}
spring.application.name=Mongo demo example
Spring :
data:
mongodb:
database : Employeedb
host : localhost
port : 27017
server :
port: 9292
package com.mongo.demo;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class MongoDemoExampleApplicationTests {
@Test
void contextLoads() {
}
}
package com.mongo.demo.controller;
import com.mongo.demo.dto.EmployeeDto;
import com.mongo.demo.entity.Employee;
import com.mongo.demo.service.EmployeeService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import reactor.core.publisher.Mono;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
class EmployeeControllerTest {
@Mock
EmployeeService service;
@InjectMocks
EmployeeController employeeController;
@BeforeEach
void setUp() {
MockitoAnnotations.openMocks(this);
}
@Test
void testGetEmployeesDetails() {
when(service.getEmployeesDetails()).thenReturn(buildEmployeeList());
Mono<List<Employee>> result = employeeController.getEmployeesDetails();
result.subscribe(employees -> {
Assertions.assertEquals("1", employees.get(0).getId());
});
}
private Mono<List<Employee>> buildEmployeeList() {
List<Employee> employeeList=new ArrayList<>();
Employee employeeDto=new Employee();
employeeDto.setId("1");
employeeDto.setName("Bala");
employeeDto.setDesignation("Module Lead");
employeeDto.setSalary(new BigDecimal(100000));
employeeList.add(employeeDto);
return Mono.just(employeeList);
}
@Test
void testGetEmployeeDetails() {
when(service.getEmployeeDetails(anyString())).thenReturn(buildCreateEmployee());
Mono<EmployeeDto> result = employeeController.getEmployeeDetails("2");
result.subscribe(employeeDto -> {
Assertions.assertEquals("2", employeeDto.getId());
});
}
@Test
void testGetEmployeeDetailsWithNoID() {
when(service.getEmployeeDetails(anyString())).thenThrow(new RuntimeException());
assertThrows(RuntimeException.class, () -> {
Mono<EmployeeDto> result = employeeController.getEmployeeDetails("id");
result.subscribe(); // This line is optional, depending on what you want to do after the exception is thrown
});
}
@Test
void testCreateEmployee() {
when(service.createEmployee(any())).thenReturn(buildCreateEmployee());
Mono<EmployeeDto> result = employeeController.createEmployee(any());
result.subscribe( employeeDto-> {
Assertions.assertEquals("2", employeeDto.getId());
});
}
private Mono<EmployeeDto> buildCreateEmployee() {
EmployeeDto employeeDto=new EmployeeDto();
employeeDto.setId("2");
employeeDto.setName("Mahesh");
employeeDto.setDesignation("Software Engineer");
employeeDto.setSalary(new BigDecimal(5021));
return Mono.just(employeeDto);
}
@Test
void testDeleteEmployee() {
when(service.deleteEmployee(anyString())).thenReturn(Mono.just("SUCCESS"));
Mono<String> result = employeeController.deleteEmployee("id");
Assertions.assertEquals("SUCCESS", result.block());
}
}
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