In this blog using the Spring WebFlux module, we are going to leverage the functional programming style to define web endpoints using functional endpoints and routing functions.
Here’s an example demonstrating the usage of functional endpoints in Spring WebFlux:
@Controller
public class UploadController {
@Autowired
UploadService service;
@Bean
@RouterOperations({
@RouterOperation(path = "/upload", produces = {
MediaType.APPLICATION_JSON_VALUE }, consumes = "multipart/form-data", method = RequestMethod.POST, operation = @Operation(operationId = "Upload", responses = {
@ApiResponse(responseCode = Constants.responseCodes.SUCCESS, description = "File Upload Success", content = @Content(schema = @Schema(implementation = Employee.class))),
@ApiResponse(responseCode = Constants.responseCodes.INTERNAL_SERVER_ERROR, description = "File Upload Failed") }, requestBody = @RequestBody(required = true, content = @Content(mediaType = MediaType.MULTIPART_FORM_DATA_VALUE, schemaProperties = {
@SchemaProperty(name = "file", schema = @Schema(type = "string", format = "binary", contentMediaType = MediaType.MULTIPART_FORM_DATA_VALUE)) }))
)) })
RouterFunction<ServerResponse> routeUpload() {
return RouterFunctions.route(
RequestPredicates.POST("/upload").and(RequestPredicates.contentType(MediaType.MULTIPART_FORM_DATA)),
req -> req.body(BodyExtractors.toMultipartData()).flatMap(file -> service.upload(file).collectList())
.flatMap(data -> ServerResponse.ok().contentType(MediaType.APPLICATION_JSON).bodyValue(data)));
}
}
In this example, the functional endpoint “/upload” is defined using RouterFunction. The @RouterOperations and @RouterOperation annotations are used to display REST API’s on the swagger-ui. Additional properties like API responses, request body schemas etc are documented using the @Operation annotation.
The defined route uploads the file contents to DB when accessed via a POST request to “/upload”.
@Service
@Slf4j
public class UploadService {
@Autowired
UploadRepository repo;
public Flux<Employee> upload(MultiValueMap<String, Part> file){
log.info("file upload started...");
Map<String, Part> part = file.toSingleValueMap();
FilePart filePart = (FilePart) part.get("file");
return DataBufferUtils.join(filePart.content()).map(data ->extracted(data)).
map(this::processFile).
flatMapMany(row -> {
List<Employee> employees = new ArrayList<>();
for(int i=0;i<row.size();i++) {
String[] nextLine = row.get(i).split(",");
Employee emp = Employee.builder().name(nextLine[0]).department(nextLine[1]).build();
employees.add(emp);
}
return repo.saveAll(employees);
});
}
private String extracted(DataBuffer data) {
byte[] bytes = data.asByteBuffer().array();
data.read(bytes);
DataBufferUtils.release(data);
return new String(bytes,StandardCharsets.UTF_8);
}
private List<String> processFile(String line){
Supplier<Stream<String>> lines = line::lines;
return lines.get().collect(Collectors.toList());
}
}
Couchbase DB configuration are defined in application.properties:
spring.couchbase.connection-string=localhost
spring.couchbase.password=${PASSWORD}
spring.couchbase.username=${USERNAME}
spring.data.couchbase.auto-index=true
spring.data.couchbase.bucket-name=employees
We can test the API using Swagger which will be available at http://server:port/context-path/swagger-ui.html
Response:
For complete source code: https://github.com/MMahendravarman/Springboot_Examples
Spring Cloud Function is a project within the Spring ecosystem that allows developers to build…
RabbitMQ is an open-source message broker software that implements the Advanced Message Queuing Protocol (AMQP).…
Spring Integration is a powerful extension of the Spring Framework designed to support the implementation…
The Spring Cloud Config Client is a component of the Spring Cloud framework that enables…
In Python, handling CSV (Comma Separated Values) files is easy using the built-in csv module.…
Spring Cloud Config Server provides a centralized location for managing and serving configuration information to…