Skip to content

fix: Refactor code#40

Merged
thced merged 53 commits into
masterfrom
refactor/openapi-3.1-readiness
May 8, 2026
Merged

fix: Refactor code#40
thced merged 53 commits into
masterfrom
refactor/openapi-3.1-readiness

Conversation

@thced

@thced thced commented May 8, 2026

Copy link
Copy Markdown
Contributor

No description provided.

thced and others added 30 commits May 8, 2026 08:23
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Captures the locked decisions from brainstorming: sealed Schema hierarchy,
consumer-supplied Map<String,Object> spec parsing, RFC 7807 problem-detail
validation errors, single DefaultValidator with pattern-match dispatch, Java
25 target. Includes a prioritized 30-item gap inventory for follow-up specs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
37 tasks across 12 phases (A-L), TDD-style with bite-sized steps.
Each task: failing test, run-and-verify, minimal implementation, verify
green, commit. Builds new packages alongside old, cuts over OpenApiServer
in one task, then deletes legacy code.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a coding-conventions note at the top of the plan and rewrites every
Java sample to import its types explicitly. Removes inline java.util/
java.time/java.util.regex FQDNs and the wildcard schema imports in tests.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…) and arrays

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
thced and others added 23 commits May 8, 2026 09:47
Splits render() into per-field appenders, names magic strings/status as
constants (PROBLEM_TYPE/TITLE/STATUS), pulls control-char threshold to
FIRST_PRINTABLE_ASCII, adds Javadoc on the unicode-escape path.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ng, validation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…by operationId

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er types

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…s to new API

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sses

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Lets IDEs apply JSON syntax highlighting and validation to the inline
request bodies in OpenApiServerIT.
SonarQube flagged the previous (n / multipleOf) % 1 != 0 check for
floating-point equality. Switches to BigDecimal.remainder so e.g. 0.3
divided by 0.1 reports cleanly instead of falling foul of double rounding.
Cleans up two leftovers from the SonarQube pass: an unused Boolean
binding in SchemaParser.parseAdditionalProperties (the false branch
doesn't need the value) and a no-longer-needed @SuppressWarnings on
Spec.resolveParameterOrParse.
…ent empty arm

Addresses the remaining DefaultValidator SonarQube findings: deduplicates
the "format" keyword string into a constant, switches RefSchema and
AdditionalProperties.SchemaConstraint matches to record-pattern
destructuring, and adds a no-op comment to the Allowed switch arm.
- ParamHandler now uses sendResponseHeaders(HTTP_OK, -1) so empty 200
  responses go out as Content-Length: 0 instead of chunked-with-zero-chunks.
- script.js drops the spurious body argument on http.get calls (k6's
  signature is http.get(url, params), not http.get(url, body, params))
  and removes pointless Content-Type headers from GETs.
- JSON.parse calls in checks are wrapped so a malformed/empty body returns
  a clean false instead of throwing JS exceptions that abort the iteration.
- Stages reduced to a steady 30 VUs (curl-equivalent concurrency); higher
  VU counts surface JDK HttpServer + keep-alive reuse anomalies that are
  not server-side defects.
Captures the curl/k6 measurements (20k–35k rps on a dev laptop, 0%
HTTP failures) and flags the known JDK HttpServer keep-alive edge case
that causes some clients to see empty response bodies under aggressive
connection reuse. Also notes the -1 vs 0 sendResponseHeaders gotcha.
…tributes

HttpExchange.setAttribute writes to a context-shared map; concurrent
requests overwrote each other's body bytes/operation-id/path-parameters,
which manifested in k6 as ~30% empty 200 response bodies under modest
keep-alive load. The original master code avoided this via a private
attribute map on its BodyHandler.RequestBodyWrapper, which the refactor
inadvertently dropped.

Replaces the four exchange attributes with a single immutable
RequestContext bound to ScopedValue.CONTEXT for the duration of the
request. Request.bytes/parsed/operationId/pathParams are now no-arg
accessors on the bound value; they throw NoSuchElementException if read
outside a request scope.

Verified with the curl-equivalent k6 profile: 30 sustained VUs / 45 s /
1,436,394 requests / 2,393,990 checks → 100% pass, 0% HTTP failures.

README updated to retract the keep-alive caveat (it was a misdiagnosis)
and document the ScopedValue ⇒ off-thread capture rule for handlers.
The record carries a byte[] body, so the auto-generated record methods
fall back to reference equality / identity hash for that component
(SonarQube java:S6218). Override all three to compare bytes structurally
via Arrays.equals/Arrays.hashCode, and have toString print the body
length instead of the raw byte[]@hex.
Replaces the named pattern variable with full record-pattern
destructuring per Sonar's java21 hint, so the components are pulled
out by name instead of dereferenced via other.body etc.
11 tests exercising structural equality on the byte[] component, the
record-pattern destructure, null tolerance, hashCode stability, and the
custom toString that prints body length instead of the raw array reference.
Documents the seven actionable items (W1–W7) found in a 30-VU / 45 s JFR
recording: cache Spec.basePath, cache compiled Pattern in the validator,
memoise ref resolution, skip parseQuery when not needed, precompute
parameter pointer strings, plus a deferred stream-body change and a
read-context-once mitigation for ScopedValue.get traversal cost.
- Use Request::bytes method reference instead of () -> Request.bytes()
  in assertThrows.
- Chain assertj assertions: isEqualTo(b).hasSameHashCodeAs(b),
  isNotEqualTo(null).isNotEqualTo("not a context").
@sonarqubecloud

sonarqubecloud Bot commented May 8, 2026

Copy link
Copy Markdown

@thced thced merged commit aff17a0 into master May 8, 2026
4 checks passed
@thced thced deleted the refactor/openapi-3.1-readiness branch May 8, 2026 09:56
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