BrighterCommand / BrighterCommand/Brighter
Docs defect: 13 XML doc-comment lines say the default message mapper is CloudEventJsonMessageMapper; it is JsonMessageMapper<>
- Dominant language
- C#
- Stars
- 2.5k
- Forks
- 296
- Avg merge
- 1d 11h
- Merged PRs (30d)
- 21
Description
Two independent findings from building `samples/Tutorials/02-FirstMessage` (#4275). They are filed together because both concern what the default message mapper does to a payload, but they have separate fixes and can be split.
---
## 1. The XML doc comments contradict the code
`ServiceCollectionMessageMapperRegistryBuilder.cs:49-51` is the authority:
```csharp
public Type DefaultMessageMapper { get; private set; } = typeof(JsonMessageMapper<>);
public Type DefaultMessageMapperAsync { get; private set; } = typeof(JsonMessageMapper<>);
```
**Confirmed by the wire format on a real run** against `rabbitmq:management`, with no mapper registered: the body is `{"greeting":…,"correlationId":null,"id":…}` with `contentType: application/json` — plain JSON, **not** a CloudEvents envelope.
The doc comments say otherwise in **13 places across 3 files**:
| File | Lines | Claim |
|---|---|---|
| `Extensions.DependencyInjection/IBrighterBuilder.cs` | 43, 44, 82, 83, 91, 92 | ``: "We use `CloudEventJsonMessageMapper` as the default if no mapper is specified" |
| `Extensions.DependencyInjection/ServiceCollectionBrighterBuilder.cs` | 113, 114, 140, 141, 164, 165 | same `` text |
| `Extensions.DependencyInjection/ServiceCollectionMessageMapperRegistryBuilder.cs` | 40 (``, running to 43) | "This builder registers the open generic type `CloudEventJsonMessageMapper` as the default mapper… This ensures that messages are serialized and deserialized according to the CloudEvents JSON format." |
Reproduce:
```bash
git grep -c "as the default if no mapper is specified" -- src # 6 + 6
git grep -n "registers the open generic type" -- src # 1
```
Two knock-on notes:
- The `` block is the most misleading of the thirteen, because it states a *behavioural guarantee* ("serialized … according to the CloudEvents JSON format") that does not hold.
- The `` sites write `` and `` without type arguments; both types are generic, so those crefs do not resolve either.
Either the comments are wrong, or the default was changed and the comments were not — worth deciding which, since the fix differs.
### The gap that let this survive
There is **no test pinning a round trip through the default mapper**. Today the default could be "corrected" to `CloudEventJsonMessageMapper<>` — matching the comments — with every test still green, silently changing the wire format for every application that has not registered a mapper. A test asserting the default produces plain JSON would fix the comments in place.
---
## 2. `RMQTaskQueue`s `GreetingEvent` has been delivering an empty greeting
`samples/TaskQueue/RMQTaskQueue/Greetings/Ports/Commands/GreetingEvent.cs`:
```csharp
public GreetingEvent() : base(Id.Random()) { }
public GreetingEvent(string greeting) : base(Id.Random()) { Greeting = greeting; }
public string? Greeting { get; } // <-- no setter
```
With two public constructors and no `[JsonConstructor]`, `System.Text.Json` selects the parameterless one, and then cannot populate a get-only property. **Measured** on exactly this shape:
```
get-only serialized: {"Greeting":"Hello"}
get-only round-tripped: Greeting=
w/ setter round-tripped: Greeting=Hello
```
So the payload leaves the sender correctly and arrives with `Greeting` null — the receiver prints an empty greeting. Scoping the claim honestly: the mechanism is measured and the shape is identical, but I have not run `RMQTaskQueue` itself against a broker, so the observable end-to-end symptom is inferred from the round trip rather than witnessed in that sample.
Fix: `public string? Greeting { get; set; }`. The same defect was hit and fixed in `samples/Tutorials/02-FirstMessage` while writing #4275.
Contributor guide
Assessment
This issue has not been assessed yet.