micronaut-projects / micronaut-projects/micronaut-openapi

JavaMicronautServerCodegen does not enforce required nullable request-body fields

Open
#2,761 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
114
Forks
121
Avg merge
2d 17h
Merged PRs (30d)
25

Description

### Expected Behavior

For an OpenAPI request-body schema field that is both `required` and `nullable`, the generated Micronaut server endpoint should preserve or enforce the OpenAPI presence semantics:

- `{ "field": null }` is valid because the field is present and nullable.
- `{}` is invalid because the required field is absent.

This matters for full-replacement APIs where explicit `null` means "clear/reset this setting", while omission means the request is incomplete.

### Actual Behavior

With `JavaMicronautServerCodegen`, the generated request DTO uses a nullable Java property:

```java
@Nullable(inherited = true)
@JsonProperty(JSON_PROPERTY_FILE_SIZE_LIMIT)
private Long fileSizeLimit;
```

After request binding, both of these payloads produce `getFileSizeLimit() == null`:

```json
{ "fileSizeLimit": null }
```

```json
{}
```

At that point application code cannot tell whether the JSON property was explicitly present with `null` or omitted entirely. As a result, a server cannot implement the OpenAPI contract for `required + nullable` request fields without a pre-binding raw-body validator/filter.

### Steps To Reproduce

Use an OpenAPI schema like this for a server request body:

```yaml
UpdateThingDetails:
type: object
description: Full-replacement request payload.
required:
- enabled
- limit
- allowedValues
properties:
enabled:
type: boolean
limit:
type: integer
format: int64
nullable: true
minimum: 1
allowedValues:
type: array
nullable: true
minItems: 1
items:
type: string
```

Generate Micronaut server models with `JavaMicronautServerCodegen`.

Send a request body that omits `limit`:

```json
{
"enabled": true,
"allowedValues": null
}
```

The generated DTO sees `limit == null`, the same as if the client had sent:

```json
{
"enabled": true,
"limit": null,
"allowedValues": null
}
```

### Environment Information

- Micronaut OpenAPI Gradle plugin: `5.0.0`
- Generated class marker: `@Generated("io.micronaut.openapi.generator.JavaMicronautServerCodegen")`
- Server-side generated DTOs with Micronaut serde annotations

### Possible Solutions

Any of these would make the generated server contract enforceable:

- Validate request-body required field presence before DTO binding for generated server endpoints.
- Generate presence-aware DTO fields for nullable required properties.
- Generate a documented wrapper type for nullable required properties, similar to `JsonNullable`-style semantics.
- Document the expected Micronaut server pattern for enforcing OpenAPI `required + nullable` request fields if this is intentionally left to application code.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by reproducing the issue with the UpdateThingDetails schema and generated JavaMicronautServerCodegen DTO, comparing an omitted nullable field with an explicit null. Determine whether the generated server contract can preserve required-field presence semantics; done means enforcing or clearly documenting the distinction for required nullable request fields.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, openapi
Domain
api, backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.