> ## Documentation Index
> Fetch the complete documentation index at: https://docs.flowwarden.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Handler Signatures

> Supported method signatures for FlowWarden event handlers, with mode exclusivity rules

This page is the focused reference for **all supported handler method signatures**. For dispatch semantics, multi-annotation combinations, and validation errors, see [Event Handlers](/reference/event-handlers).

## Parameter Styles

Typed handlers (`@OnInsert`, `@OnUpdate`, `@OnDelete`, `@OnReplace`) support three parameter styles. `@OnChange` supports only `CONTEXT_ONLY`.

| Style                  | Parameters                            | Notes                                                                               |
| ---------------------- | ------------------------------------- | ----------------------------------------------------------------------------------- |
| `CONTEXT_ONLY`         | `(ChangeStreamContext<T> ctx)`        | Access metadata + document via `ctx.getFullDocument()`.                             |
| `DOCUMENT_ONLY`        | `(T doc)`                             | Receive the deserialized document directly. **Requires a concrete `documentType`.** |
| `DOCUMENT_AND_CONTEXT` | `(T doc, ChangeStreamContext<T> ctx)` | Both the document and the context. **Requires a concrete `documentType`.**          |

<Warning>
  `DOCUMENT_ONLY` and `DOCUMENT_AND_CONTEXT` signatures fail at startup with `BeanCreationException` if `@ChangeStream.documentType` is `Document.class` (the default). Set a concrete class:

  ```java theme={null}
  @ChangeStream(documentType = Order.class)
  ```
</Warning>

## Return Types — Mode Exclusivity

The return type is **bound to the configured execution mode** (`flowwarden.default-mode`):

| Mode                   | Required return type | Other return types                  |
| ---------------------- | -------------------- | ----------------------------------- |
| `IMPERATIVE` (default) | `void`               | `Mono<Void>` is rejected at startup |
| `REACTIVE`             | `Mono<Void>`         | `void` is rejected at startup       |

<Warning>
  Mixing return types across handlers in the same application is **not allowed**. All handler methods must consistently return `void` or `Mono<Void>` matching the configured mode. A mismatch triggers a `BeanCreationException`.
</Warning>

Other return types — `CompletableFuture`, `Flux`, `String`, etc. — are rejected at startup with `unsupported return type`.

## Full Signature Matrix

<Tabs>
  <Tab title="Imperative (void)">
    | Style                  | Signature                                        |
    | ---------------------- | ------------------------------------------------ |
    | `CONTEXT_ONLY`         | `void handle(ChangeStreamContext<T> ctx)`        |
    | `DOCUMENT_ONLY`        | `void handle(T doc)`                             |
    | `DOCUMENT_AND_CONTEXT` | `void handle(T doc, ChangeStreamContext<T> ctx)` |

    For `@OnChange`: only `void handle(ChangeStreamContext<T> ctx)` is allowed.
  </Tab>

  <Tab title="Reactive (Mono)">
    | Style                  | Signature                                              |
    | ---------------------- | ------------------------------------------------------ |
    | `CONTEXT_ONLY`         | `Mono<Void> handle(ChangeStreamContext<T> ctx)`        |
    | `DOCUMENT_ONLY`        | `Mono<Void> handle(T doc)`                             |
    | `DOCUMENT_AND_CONTEXT` | `Mono<Void> handle(T doc, ChangeStreamContext<T> ctx)` |

    For `@OnChange`: only `Mono<Void> handle(ChangeStreamContext<T> ctx)` is allowed.
  </Tab>
</Tabs>

## Examples

### CONTEXT\_ONLY

```java theme={null}
@OnUpdate
void onUpdate(ChangeStreamContext<Order> ctx) {
    Optional<Order> order = ctx.getFullDocument(Order.class);
    log.info("Order updated: {}", ctx.getDocumentKey());
}
```

### DOCUMENT\_ONLY

```java theme={null}
@OnInsert
void onInsert(Order doc) {
    log.info("New order: {}", doc.getId());
}
```

### DOCUMENT\_AND\_CONTEXT

```java theme={null}
@OnInsert
void onInsert(Order doc, ChangeStreamContext<Order> ctx) {
    log.info("Order {} created, attempt #{}", doc.getId(), ctx.getAttemptNumber());
}
```

### Reactive variants

```java theme={null}
@OnInsert
Mono<Void> onInsertReactive(Order doc, ChangeStreamContext<Order> ctx) {
    return orderService.processReactive(doc);
}
```

## Injecting Other Beans

Need a `MongoTemplate`, a custom service, or any other Spring bean? **Inject it through the handler class** (constructor or `@Autowired` field), not via the handler method signature:

```java theme={null}
@ChangeStream(documentType = Order.class)
public class OrderHandler {

    private final MongoTemplate mongoTemplate;
    private final BillingService billing;

    public OrderHandler(MongoTemplate mongoTemplate, BillingService billing) {
        this.mongoTemplate = mongoTemplate;
        this.billing = billing;
    }

    @OnInsert
    void onInsert(Order doc, ChangeStreamContext<Order> ctx) {
        billing.charge(doc);
        mongoTemplate.save(doc, "processed_orders");
    }
}
```

The handler class is a regular Spring `@Component` (via `@ChangeStream`'s meta-annotation), so all standard Spring injection patterns apply.

## DELETE handler caveat

For `DELETE` events, MongoDB does **not** provide a `fullDocument`. If you use `DOCUMENT_ONLY` or `DOCUMENT_AND_CONTEXT` on `@OnDelete`, the `doc` parameter will be `null` at runtime:

```java theme={null}
@OnDelete
void onDelete(Order doc, ChangeStreamContext<Order> ctx) {
    // doc is ALWAYS null here
}
```

Prefer `CONTEXT_ONLY` for `@OnDelete` and use `ctx.getDocumentKey()` to identify the affected document:

```java theme={null}
@OnDelete
void onDelete(ChangeStreamContext<Order> ctx) {
    log.info("Order deleted: {}", ctx.getDocumentKey());
}
```

## See Also

<CardGroup cols={2}>
  <Card title="Event Handlers" icon="bolt" href="/reference/event-handlers">
    Dispatch priority, multi-annotation combinations, validation errors.
  </Card>

  <Card title="@ChangeStream" icon="satellite-dish" href="/reference/change-stream">
    Parent class annotation — `documentType`, modes, behavior flags.
  </Card>

  <Card title="ChangeStreamContext" icon="circle-info" href="/reference/change-stream-context">
    The context object passed to every handler.
  </Card>

  <Card title="@Filter" icon="filter" href="/reference/filter">
    Application-side filtering and signature constraints with `@OnDelete`.
  </Card>
</CardGroup>
