kestra-io / kestra-io/plugin-debezium
mysql: `serverId` is `@NotNull` but documented as optional, and the Trigger example omits it
- Dominant language
- Java
- Stars
- 5
- Forks
- 11
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 9
Description
## Summary
The MySQL `serverId` property is internally inconsistent across three places: `Capture` marks it `@NotNull` while `MysqlInterface` documents it as having a generated default, the `@PluginProperty(group = ...)` disagrees between the field and the interface getter, and the batch `Trigger`'s published `@Example` omits it entirely — which makes that copy-pasteable example fail at runtime with an opaque `NullPointerException`.
Surfaced during the documentation review in #199, which deliberately left code changes out of scope.
## Actual Behaviour
**1. `@NotNull` contradicts the documented default.**
`plugin-debezium-mysql/src/main/java/io/kestra/plugin/debezium/mysql/MysqlInterface.java:32-41` documents:
> "By default, a random number between 5400 and 6400 is generated, though the recommendation is to explicitly set a value."
But `mysql/Capture.java:64-66` declares:
```java
@NotNull
@PluginProperty(group = "main")
private Property serverId;
```
`@NotNull` makes the property mandatory, so the documented default can never apply. Either the annotation or the description is wrong.
**2. Group mismatch between field and interface getter.**
- `mysql/Capture.java:65` — `@PluginProperty(group = "main")`
- `MysqlInterface.java:39` — `@PluginProperty(dynamic = true, group = "advanced")`
Field annotations do not inherit from interface getters, so the two declarations drift and the UI grouping depends on which one the schema generator reads.
**3. The batch `Trigger` example omits the required property → runtime NPE.**
`mysql/Trigger.java:35-53` publishes a full runnable example with no `serverId`. `mysql/Trigger.java:97` builds a `Capture` from the trigger's own fields:
```java
Capture task = Capture.builder()
...
.serverId(this.serverId)
```
`mysql.Trigger.serverId` (line 61) carries **no** `@NotNull`, so a flow without it validates fine. `Capture.properties()` then does:
```java
props.setProperty("database.server.id", runContext.render(this.serverId).as(String.class).orElse(null));
```
`Properties.setProperty` is `Hashtable.put`, which throws `NullPointerException` on a null value. The published example therefore fails at runtime rather than at validation time, with a stack trace that names neither `serverId` nor the flow property that caused it.
`mysql/RealtimeTrigger.java:45` already includes `serverId` in its example — only the batch `Trigger` is missing it. PR #199 added it to the `Capture` example for exactly this reason.
## Expected Behaviour
- The `@NotNull` on `Capture.serverId` and the "a random number is generated by default" wording agree with each other.
- The `@PluginProperty` group is declared identically on the field and the interface getter.
- The batch `Trigger` example is runnable as published.
- If `serverId` is genuinely required for the trigger path, `mysql.Trigger` and `mysql.RealtimeTrigger` declare `@NotNull` too, so a missing value fails at flow-validation time with a clear message instead of surfacing as a `NullPointerException` from `Hashtable`.
- Regardless of the above, `Capture.properties()` should not call `setProperty` with a possibly-null value — guard it, or `.orElseThrow()` with a message naming the property and the fix.
## Reproducer
```yaml
id: mysql_trigger_no_serverid
namespace: company.team
tasks:
- id: send_data
type: io.kestra.plugin.core.log.Log
message: "{{ trigger.uris }}"
triggers:
- id: trigger
type: io.kestra.plugin.debezium.mysql.Trigger
snapshotMode: NEVER
hostname: 127.0.0.1
port: "3306"
username: "{{ secret('MYSQL_USERNAME') }}"
password: "{{ secret('MYSQL_PASSWORD') }}"
```
This is the example currently published on the `mysql.Trigger` documentation page (modulo the `type` fix in #199). It passes validation and fails when the trigger first evaluates.
## Logs / Stack Trace
Not captured; the expected failure originates from `java.util.Hashtable.put` via `Properties.setProperty` in `Capture.properties()` (`mysql/Capture.java:78`). Worth attaching a real trace when confirming the reproducer.
## Environment
- **Kestra version**: 1.3.16 (`kestraVersion` in `gradle.properties`)
- **Plugin version**: 1.4.7
- **Deployment**: n/a — source-level defect, reproducible on any deployment
## Acceptance Criteria
- [ ] `Capture.serverId`'s nullability and its `@Schema` description agree
- [ ] `@PluginProperty(group = ...)` matches between `mysql/Capture.java` and `MysqlInterface`
- [ ] `mysql/Trigger.java`'s `@Example` includes `serverId` and is runnable as published
- [ ] A missing `serverId` on a trigger fails with an actionable message, not a bare `NullPointerException`
- [ ] `Capture.properties()` no longer passes a possibly-null value to `Properties.setProperty`
- [ ] A test covers the missing-`serverId` trigger path and asserts the error message
## Additional Context
Flagged in the review of #199 (documentation-only PR). The SQL Server module has a separate, unrelated `serverId` problem tracked in its own issue: there the property exists but does nothing.
---
*[View as Artifact](https://claude.ai/code/artifact/66907e1c-200f-466d-9901-26a9e7de6d51)*
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.