Spring WebFlux Reactive Controller Pattern
Example
java
@RestController
@RequestMapping("/api/users")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@Operation(summary = "Get user by ID")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "User found"),
@ApiResponse(responseCode = "404", description = "User not found")
})
@GetMapping("/{id}")
public Mono<ResponseEntity<UserDto>> getUser(@PathVariable String id) {
return userService.getUserById(id)
.map(ResponseEntity::ok)
.defaultIfEmpty(ResponseEntity.notFound().build());
}
@Operation(summary = "Get all users")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "List of users")
})
@GetMapping
public Flux<UserDto> getAllUsers() {
return userService.getAllUsers();
}
// ... other endpoints using Mono/Flux ...
}Guidelines
- Annotate with
@RestControllerand use@RequestMappingfor base path. - Inject services via constructor.
- Use
@GetMapping,@PostMapping, etc. for endpoints. - Return
Mono<T>orFlux<T>for all handler methods. - Validate input with
@Validand constraint annotations. - Return DTOs, not entities.
- Use
ResponseEntity<T>insideMonofor flexible responses (status, headers, etc). - Use
defaultIfEmptyfor 404/empty results. - Avoid blocking calls in controller or service methods.
- Use reactive types for request bodies and responses (e.g.,
Mono<UserDto>for POST/PUT). - Document endpoints with Swagger/OpenAPI annotations:
- Use
@Operationto describe the endpoint's purpose. - Use
@ApiResponsesand@ApiResponseto document all possible HTTP responses, including success and error cases. - Include
responseCode,description, and, if possible, content/schema for each response. - Place annotations directly above each controller method.
- Keep descriptions concise and user-focused.
- Use