Skip to content

WW-5720 fix(rest): log any-setter dynamic-key rejections once per request - #1948

Merged
lukaszlenart merged 3 commits into
mainfrom
WW-5720
Sep 15, 2026
Merged

lukaszlenart merged 3 commits into
mainfrom
WW-5720

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5720

With struts.rest.anySetter.requireAnnotations enabled, AuthorizingSettableAnyProperty wrote one WARN per rejected dynamic key. An any-setter's key space is the request body, so a body with ten thousand unknown keys wrote ten thousand WARN lines.

Change

  • New request-scoped DynamicKeyRejections tallies rejections per any-setter (Class#member, or Class#creator[n] for a creator parameter) and reason.
  • Per-key detail moves to DEBUG; one WARN per any-setter and reason is written when ParameterAuthorizingModule.clearRequestState() runs — both Jackson handlers already call it in a finally, and ContentTypeInterceptor once more after unbinding, where the second call is a no-op.
  • The four reasons (missing consent, creator-parameter form, depth exceeded, property name unavailable) keep distinct wording, since they point at different fixes on the application side.
  • Rejection itself is unchanged: redactAndSkip still runs on every path.

The tally is its own holder rather than part of DynamicKeyAuthorizationContext, which is the nested-scope depth stack pushed and popped per accepted key; the tally is per request and flushed at a different point. It is keyed by the class model and a four-value enum, so its size does not depend on the body.

Tests

ParameterAuthorizingModuleTest captures the DynamicKeyRejections logger: zero WARNs during the read and exactly one after the clear with the count and sink; a second clear logs nothing; distinct summaries per reason and per sink; the creator-parameter label.

🤖 Generated with Claude Code

lukaszlenart and others added 2 commits September 15, 2026 18:55
…uest

An any-setter's key space is the request body, so a WARN per rejected key
let a single body write an unbounded number of log lines. The per-key
detail now goes to DEBUG and DynamicKeyRejections tallies the rejections
per any-setter and reason, writing one WARN for each when the request
state is cleared after the mapper read. Rejection itself is unchanged.

The tally lives in its own request-scoped holder rather than inside
DynamicKeyAuthorizationContext: that class is the nested-scope depth
stack, pushed and popped per accepted key, while the tally is per request
and flushed at a different point.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n the rejection summary

AnnotatedParameter.getName() is empty, so the sink for a creator-parameter
any-setter read as "Foo#". Label it "Foo#creator[n]" instead, point the
WARN at the DEBUG lines that carry the rejected keys, and pin the wording
of the two reasons the tests did not yet assert on.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@lukaszlenart
lukaszlenart marked this pull request as ready for review September 15, 2026 17:15
Sonar S6204.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@lukaszlenart
lukaszlenart merged commit a9ef39e into main Sep 15, 2026
13 checks passed
@lukaszlenart
lukaszlenart deleted the WW-5720 branch September 15, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant