spring-reactive

Build reactive applications - WebFlux, Mono/Flux, R2DBC, backpressure, reactive streams

16 stars

Best use case

spring-reactive is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Build reactive applications - WebFlux, Mono/Flux, R2DBC, backpressure, reactive streams

Teams using spring-reactive should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/spring-reactive/SKILL.md --create-dirs "https://raw.githubusercontent.com/diegosouzapw/awesome-omni-skill/main/skills/development/spring-reactive/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/spring-reactive/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How spring-reactive Compares

Feature / Agentspring-reactiveStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Build reactive applications - WebFlux, Mono/Flux, R2DBC, backpressure, reactive streams

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

SKILL.md Source

# Spring Reactive Skill

Master reactive programming with Spring WebFlux, Project Reactor, R2DBC, and reactive streams patterns.

## Overview

This skill covers building non-blocking, reactive applications with Spring WebFlux and Project Reactor.

## Parameters

| Name | Type | Required | Default | Validation |
|------|------|----------|---------|------------|
| `reactive_db` | enum | ✗ | r2dbc-postgresql | r2dbc-postgresql \| r2dbc-mysql \| mongodb |
| `streaming` | enum | ✗ | - | sse \| websocket \| rsocket |
| `backpressure` | enum | ✗ | buffer | buffer \| drop \| latest |

## Topics Covered

### Core (Must Know)
- **WebFlux**: `@RestController` with `Mono<T>` and `Flux<T>`
- **Project Reactor**: Core operators (map, flatMap, filter)
- **R2DBC**: Reactive database access

### Intermediate
- **Error Handling**: onErrorResume, onErrorReturn
- **Backpressure**: Handling fast producers
- **SSE**: Server-Sent Events

### Advanced
- **WebSocket**: Reactive WebSocket handlers
- **RSocket**: Bi-directional reactive streams
- **Context Propagation**: MDC in reactive chains

## Code Examples

### Reactive Controller
```java
@RestController
@RequestMapping("/api/users")
@RequiredArgsConstructor
public class UserController {

    private final UserService userService;

    @GetMapping
    public Flux<UserResponse> findAll() {
        return userService.findAll().map(UserResponse::from);
    }

    @GetMapping("/{id}")
    public Mono<ResponseEntity<UserResponse>> findById(@PathVariable Long id) {
        return userService.findById(id)
            .map(UserResponse::from)
            .map(ResponseEntity::ok)
            .defaultIfEmpty(ResponseEntity.notFound().build());
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Mono<UserResponse> create(@Valid @RequestBody Mono<CreateUserRequest> request) {
        return request.flatMap(userService::create).map(UserResponse::from);
    }
}
```

### Reactive Repository (R2DBC)
```java
public interface UserRepository extends ReactiveCrudRepository<User, Long> {

    Mono<User> findByEmail(String email);

    Flux<User> findByActiveTrue();

    @Query("SELECT * FROM users WHERE created_at > :since")
    Flux<User> findRecentUsers(@Param("since") LocalDateTime since);
}
```

### Reactive Service with Error Handling
```java
@Service
@RequiredArgsConstructor
@Transactional
public class UserService {

    private final UserRepository userRepository;

    public Mono<User> create(CreateUserRequest request) {
        return userRepository.findByEmail(request.email())
            .flatMap(existing -> Mono.<User>error(new DuplicateEmailException()))
            .switchIfEmpty(Mono.defer(() -> {
                User user = new User(request.email(), request.name());
                return userRepository.save(user);
            }));
    }

    public Flux<User> findAll() {
        return userRepository.findAll()
            .timeout(Duration.ofSeconds(5))
            .onErrorResume(TimeoutException.class, e -> Flux.empty());
    }
}
```

### Server-Sent Events
```java
@RestController
@RequestMapping("/api/events")
public class EventController {

    private final Sinks.Many<Event> eventSink = Sinks.many()
        .multicast().onBackpressureBuffer();

    @GetMapping(produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<ServerSentEvent<Event>> stream() {
        return eventSink.asFlux()
            .map(e -> ServerSentEvent.<Event>builder()
                .id(e.id())
                .event(e.type())
                .data(e)
                .build());
    }

    @PostMapping
    public Mono<Void> publish(@RequestBody Event event) {
        return Mono.fromRunnable(() -> eventSink.tryEmitNext(event));
    }
}
```

## Operator Quick Reference

```
Transformation: map(), flatMap(), flatMapMany()
Filtering:      filter(), take(), skip(), distinct()
Combination:    merge(), concat(), zip()
Error:          onErrorResume(), onErrorReturn(), retry(), timeout()
Side Effects:   doOnNext(), doOnError(), doFinally(), log()
```

## Troubleshooting

### Failure Modes

| Issue | Diagnosis | Fix |
|-------|-----------|-----|
| Nothing happens | Not subscribed | Return Mono/Flux from controller |
| Blocking error | Blocking in reactive | Use `subscribeOn(Schedulers.boundedElastic())` |
| Memory issues | Unbounded buffer | Add backpressure strategy |

### Debug Checklist

```
□ Verify Mono/Flux is returned (not subscribed manually)
□ Check for blocking calls (JDBC, Thread.sleep)
□ Review backpressure strategy
□ Enable Reactor debug: Hooks.onOperatorDebug()
□ Use .log() operator for debugging
```

## Unit Test Template

```java
@WebFluxTest(UserController.class)
class UserControllerTest {

    @Autowired
    private WebTestClient webTestClient;

    @MockBean
    private UserService userService;

    @Test
    void shouldReturnUsers() {
        when(userService.findAll()).thenReturn(Flux.just(
            new User(1L, "john@test.com", "John")));

        webTestClient.get().uri("/api/users")
            .exchange()
            .expectStatus().isOk()
            .expectBodyList(UserResponse.class)
            .hasSize(1);
    }

    @Test
    void shouldReturn404WhenNotFound() {
        when(userService.findById(1L)).thenReturn(Mono.empty());

        webTestClient.get().uri("/api/users/1")
            .exchange()
            .expectStatus().isNotFound();
    }
}
```

## Usage

```
Skill("spring-reactive")
```

## Version History

| Version | Date | Changes |
|---------|------|---------|
| 2.0.0 | 2024-12-30 | R2DBC, SSE, WebTestClient patterns |
| 1.0.0 | 2024-01-01 | Initial release |

Related Skills

springboot-architecture-analyzer

16
from diegosouzapw/awesome-omni-skill

系統化分析 Spring Boot 專案並生成完整的企業級架構文件,涵蓋系統概述、架構視圖、技術細節、部署策略等所有關鍵面向。

springboot-4-migration

16
from diegosouzapw/awesome-omni-skill

Comprehensive guide for migrating Spring Boot applications from 3.x to 4.0, focusing on Gradle Kotlin DSL and version catalogs Triggers on: **/*.java, **/*.kt, **/build.gradle.kts, **/build.gradle, **/settings.gradle.kts, **/gradle/libs.versions.toml, **/*.properties, **/*.yml, **/*.yaml

spring-rest-api

16
from diegosouzapw/awesome-omni-skill

RESTful API design with Spring Boot including OpenAPI/Swagger documentation, content negotiation, CORS, pagination, HATEOAS, and API versioning patterns.

spring-boot-testing

16
from diegosouzapw/awesome-omni-skill

No description provided.

spring-boot-performance

16
from diegosouzapw/awesome-omni-skill

Guide for optimizing Spring Boot application performance including caching, pagination, async processing, and JPA optimization. Use this when addressing performance issues or implementing high-traffic features.

spring-boot-migrator

16
from diegosouzapw/awesome-omni-skill

Automated migration of Spring Boot 2.x to 3.x with JDK 8 to 21 upgrade using OpenRewrite. Use when asked to migrate, upgrade, or modernize Spring Boot applications, upgrade from JDK 8/11/17 to JDK 21, migrate from javax to jakarta namespace, or when facing Spring Boot 2 EOL migration tasks. Handles Maven projects with standard or custom parent POMs.

spring-boot-engineer

16
from diegosouzapw/awesome-omni-skill

Use when building Spring Boot 3.x applications, microservices, or reactive Java applications. Invoke for Spring Data JPA, Spring Security 6, WebFlux, Spring Cloud integration.

openapi-to-application-java-spring-boot-openapi-to-application-c

16
from diegosouzapw/awesome-omni-skill

Generate a complete, production-ready application from an OpenAPI specification Use when: the task directly matches openapi to application code responsibilities within plugin openapi-to-application-java-spring-boot. Do not use when: a more specific framework or task-focused skill is clearly a better match.

create-spring-boot-kotlin-project

16
from diegosouzapw/awesome-omni-skill

Create Spring Boot Kotlin Project Skeleton

create-spring-boot-java-project

16
from diegosouzapw/awesome-omni-skill

Create Spring Boot Java Project Skeleton

awesome-copilot-root-create-spring-boot-java-project

16
from diegosouzapw/awesome-omni-skill

Create Spring Boot Java Project Skeleton Use when: the task directly matches create spring boot java project responsibilities within plugin awesome-copilot-root. Do not use when: a more specific framework or task-focused skill is clearly a better match.

springfield-max

16
from diegosouzapw/awesome-omni-skill

Simpsons-themed autonomous workflow orchestrator v7.0 for platform building. Powered by Opus 4.6 Agent Teams, 1M context, adaptive thinking, and effort levels. 17 characters, full MCP access, 50 iteration limits, orchestrator promises, and mandatory quality gates. Domain-agnostic - works for any software platform.