Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6b8be4f
feat(core): add JSON-RPC envelope classifier
limehee Mar 3, 2026
12ef5c3
feat(core): add incoming JSON-RPC response parser model
limehee Mar 3, 2026
28c8a7f
feat(core): add configurable JSON-RPC response validator
limehee Mar 3, 2026
1efa658
docs: add response-side protocol utility guides
limehee Mar 3, 2026
a9ed14b
docs: align extension docs with response validation APIs
limehee Mar 3, 2026
96dff9e
docs: clarify response extension wiring and option defaults
limehee Mar 3, 2026
3d1fccb
fix(core): prioritize response classification when result or error ex…
limehee Mar 3, 2026
6f21c6c
refactor(core): migrate deprecated Jackson 3 JsonNode APIs
limehee Mar 3, 2026
43e5aa6
test: replace deprecated JsonNode text accessors
limehee Mar 3, 2026
588e6fb
test(core): expand response parsing and validation branch coverage
limehee Mar 3, 2026
2b207f9
docs: align guides with response utilities and current baselines
limehee Mar 3, 2026
9c07144
docs(core): refine response validation Javadocs
limehee Mar 3, 2026
25a677f
fix(core): propagate JVM Error instead of mapping as JSON-RPC error
limehee Mar 3, 2026
5506510
feat(core): add configurable params type violation error policy
limehee Mar 3, 2026
f72e4ba
fix(core): add fail-fast null guards for pure Java wiring
limehee Mar 3, 2026
f9c0260
docs: document params type violation policy across guides
limehee Mar 3, 2026
e862b40
feat(samples): add pure-java and spring scenario-driven demo coverage
limehee Mar 3, 2026
70cdc0b
feat(samples): add response-side utility scenario in pure-java demo
limehee Mar 3, 2026
2986c2f
feat(samples): add interceptor lifecycle scenario in pure-java demo
limehee Mar 3, 2026
763c129
feat(samples): add notification executor scenarios for spring demo
limehee Mar 3, 2026
1fe4807
feat(samples): add conflict policy scenarios for spring registrations
limehee Mar 3, 2026
eb3cda8
feat(samples): add exception resolver and error-data scenarios
limehee Mar 3, 2026
6b20717
feat(autoconfigure): structure validation config into request/response
limehee Mar 3, 2026
45041b8
fix(core): guard response validator options against null
limehee Mar 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Production-oriented JSON-RPC 2.0 server library for Java, with optional Spring W
- Spring WebMVC transport adapter and Spring Boot auto-configuration
- Multiple registration styles (annotation/manual/typed)
- Explicit extension points (parser/validator/invoker/exception mapping/interceptors/metrics)
- Response-side protocol utilities for bidirectional transports (classifier/parser/validator)
- Focused dependency surface (no direct Guava, Commons Lang3, or Jakarta Validation dependency)

## Specification
Expand All @@ -20,7 +21,7 @@ Production-oriented JSON-RPC 2.0 server library for Java, with optional Spring W

- Java: 17+
- Spring Boot baseline: 4.0.3
- Jackson baseline: 3.0.x
- Jackson baseline: 3.1.x
- Build: Gradle with Version Catalog
- CI matrix: Java 17, 21, 25

Expand Down Expand Up @@ -174,6 +175,24 @@ Response:
{"jsonrpc":"2.0","id":1,"result":"hello developer"}
```

## Spring Configuration Example

Use `jsonrpc.validation.request.*` and `jsonrpc.validation.response.*` for fine-grained validation control:

```yaml
jsonrpc:
validation:
request:
params-type-violation-code-policy: INVALID_REQUEST
response:
require-response-id-member: true
allow-fractional-response-id: false
allow-request-fields-in-response: false
```

For the full list of validation keys and defaults, see
[`docs/configuration-reference.md`](docs/configuration-reference.md).

## Quick Start (Pure Java)

```java
Expand Down Expand Up @@ -256,11 +275,13 @@ Detailed docs are under [`docs/`](docs/):
## Sample

- Spring Boot sample app: [`samples/spring-boot-demo`](samples/spring-boot-demo)
- Pure Java sample app: [`samples/pure-java-demo`](samples/pure-java-demo)

Run:

```bash
./gradlew -p samples/spring-boot-demo bootRun
./gradlew -p samples/pure-java-demo run
```

## Project Docs
Expand Down
9 changes: 8 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,13 @@ flowchart LR

Design goal: each concern is replaceable without rewriting the dispatcher.

Response-side transport integrations can use these additional protocol components:

- `JsonRpcEnvelopeClassifier`
- `JsonRpcResponseParser`
- `JsonRpcResponseValidator`
- `JsonRpcResponseValidationOptions`

## 4. Registration Lifecycle in Auto-Configuration

Method registration order in Spring Boot:
Expand All @@ -59,7 +66,7 @@ Protocol-level normalization:
- parse error -> `-32700`
- invalid request -> `-32600`
- method not found -> `-32601`
- invalid params -> `-32602`
- invalid params -> default `-32602` (`params` type-violation code is configurable in `DefaultJsonRpcRequestValidator`)
- unhandled exceptions -> `-32603`

Transport-level status is handled separately by `JsonRpcHttpStatusStrategy`.
Expand Down
68 changes: 50 additions & 18 deletions docs/configuration-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,35 @@ All properties are under `jsonrpc.*` and are bound to `JsonRpcProperties`.

## 1. Property Table

| Key | Type | Default | Description |
|-----------------------------------------------|-----------------------|------------|-----------------------------------------------------------------|
| `jsonrpc.enabled` | `boolean` | `true` | Enable/disable WebMVC endpoint auto-configuration |
| `jsonrpc.path` | `String` | `/jsonrpc` | JSON-RPC HTTP endpoint path |
| `jsonrpc.max-batch-size` | `int` | `100` | Maximum number of entries allowed in one batch request |
| `jsonrpc.max-request-bytes` | `int` | `1048576` | Raw HTTP request payload size limit in bytes |
| `jsonrpc.scan-annotated-methods` | `boolean` | `true` | Scan Spring beans for `@JsonRpcMethod` |
| `jsonrpc.include-error-data` | `boolean` | `false` | Include `JsonRpcException.data` in error responses |
| `jsonrpc.method-registration-conflict-policy` | `REJECT` or `REPLACE` | `REJECT` | Duplicate method name registration policy |
| `jsonrpc.method-allowlist` | `List<String>` | `[]` | Allowlist for method access filtering |
| `jsonrpc.method-denylist` | `List<String>` | `[]` | Denylist for method access filtering (higher priority) |
| `jsonrpc.metrics-enabled` | `boolean` | `true` | Enable Micrometer interceptor/observer when registry is present |
| `jsonrpc.metrics-latency-histogram-enabled` | `boolean` | `false` | Publish latency histogram buckets |
| `jsonrpc.metrics-latency-percentiles` | `List<Double>` | `[]` | Optional latency percentiles (`0.0 < p < 1.0`) |
| `jsonrpc.metrics-max-method-tag-values` | `int` | `100` | Max distinct method tag values before fallback to `other` |
| `jsonrpc.notification-executor-enabled` | `boolean` | `false` | Enable executor-backed notification dispatch |
| `jsonrpc.notification-executor-bean-name` | `String` | `""` | Preferred executor bean name for notifications |
| Key | Type | Default | Description |
|--------------------------------------------------------|---------------------------------------|------------------|----------------------------------------------------------------------|
| `jsonrpc.enabled` | `boolean` | `true` | Enable/disable WebMVC endpoint auto-configuration |
| `jsonrpc.path` | `String` | `/jsonrpc` | JSON-RPC HTTP endpoint path |
| `jsonrpc.max-batch-size` | `int` | `100` | Maximum number of entries allowed in one batch request |
| `jsonrpc.max-request-bytes` | `int` | `1048576` | Raw HTTP request payload size limit in bytes |
| `jsonrpc.scan-annotated-methods` | `boolean` | `true` | Scan Spring beans for `@JsonRpcMethod` |
| `jsonrpc.include-error-data` | `boolean` | `false` | Include `JsonRpcException.data` in error responses |
| `jsonrpc.validation.request.params-type-violation-code-policy` | `INVALID_PARAMS` or `INVALID_REQUEST` | `INVALID_PARAMS` | Error code used when `params` exists but is neither object nor array |
| `jsonrpc.validation.response.require-json-rpc-version-20` | `boolean` | `true` | Require incoming response `jsonrpc` to equal `"2.0"` |
| `jsonrpc.validation.response.require-response-id-member` | `boolean` | `true` | Require incoming responses to include an `id` member |
| `jsonrpc.validation.response.allow-null-response-id` | `boolean` | `true` | Allow `id: null` in incoming responses |
| `jsonrpc.validation.response.allow-string-response-id` | `boolean` | `true` | Allow string IDs in incoming responses |
| `jsonrpc.validation.response.allow-numeric-response-id` | `boolean` | `true` | Allow numeric IDs in incoming responses |
| `jsonrpc.validation.response.allow-fractional-response-id` | `boolean` | `true` | Allow fractional numeric IDs in incoming responses |
| `jsonrpc.validation.response.require-exclusive-result-or-error` | `boolean` | `true` | Require exactly one of `result` or `error` |
| `jsonrpc.validation.response.require-error-object-when-present` | `boolean` | `true` | Require `error` to be an object when present |
| `jsonrpc.validation.response.require-integer-error-code` | `boolean` | `true` | Require `error.code` to be an integer |
| `jsonrpc.validation.response.require-string-error-message` | `boolean` | `true` | Require `error.message` to be a string |
| `jsonrpc.validation.response.allow-request-fields-in-response` | `boolean` | `true` | Allow request-only fields (`method`/`params`) on responses |
| `jsonrpc.method-registration-conflict-policy` | `REJECT` or `REPLACE` | `REJECT` | Duplicate method name registration policy |
| `jsonrpc.method-allowlist` | `List<String>` | `[]` | Allowlist for method access filtering |
| `jsonrpc.method-denylist` | `List<String>` | `[]` | Denylist for method access filtering (higher priority) |
| `jsonrpc.metrics-enabled` | `boolean` | `true` | Enable Micrometer interceptor/observer when registry is present |
| `jsonrpc.metrics-latency-histogram-enabled` | `boolean` | `false` | Publish latency histogram buckets |
| `jsonrpc.metrics-latency-percentiles` | `List<Double>` | `[]` | Optional latency percentiles (`0.0 < p < 1.0`) |
| `jsonrpc.metrics-max-method-tag-values` | `int` | `100` | Max distinct method tag values before fallback to `other` |
| `jsonrpc.notification-executor-enabled` | `boolean` | `false` | Enable executor-backed notification dispatch |
| `jsonrpc.notification-executor-bean-name` | `String` | `""` | Preferred executor bean name for notifications |

## 2. Validation Rules (Fail Fast)

Expand All @@ -36,6 +48,10 @@ Startup fails with `IllegalArgumentException` when any of these conditions occur
- `jsonrpc.metrics-latency-percentiles` is null
- any percentile is null, `<= 0.0`, or `>= 1.0`
- `jsonrpc.notification-executor-bean-name` is null
- `jsonrpc.validation` is null
- `jsonrpc.validation.request` is null
- `jsonrpc.validation.request.params-type-violation-code-policy` is null
- `jsonrpc.validation.response` is null
- allowlist/denylist list itself is null
- allowlist/denylist contains null or blank values

Expand Down Expand Up @@ -86,6 +102,7 @@ Example environment variable mapping:

- `jsonrpc.max-request-bytes` -> `JSONRPC_MAX_REQUEST_BYTES`
- `jsonrpc.method-registration-conflict-policy` -> `JSONRPC_METHOD_REGISTRATION_CONFLICT_POLICY`
- `jsonrpc.validation.request.params-type-violation-code-policy` -> `JSONRPC_VALIDATION_REQUEST_PARAMS_TYPE_VIOLATION_CODE_POLICY`

## 5. Example Configurations

Expand All @@ -99,6 +116,21 @@ jsonrpc:
method-registration-conflict-policy: REJECT
scan-annotated-methods: true
include-error-data: false
validation:
request:
params-type-violation-code-policy: INVALID_PARAMS
response:
require-json-rpc-version-20: true
require-response-id-member: true
allow-null-response-id: true
allow-string-response-id: true
allow-numeric-response-id: true
allow-fractional-response-id: true
require-exclusive-result-or-error: true
require-error-object-when-present: true
require-integer-error-code: true
require-string-error-message: true
allow-request-fields-in-response: true
method-allowlist: []
method-denylist: []
```
Expand Down Expand Up @@ -139,7 +171,7 @@ The project ships Spring Boot configuration metadata via:
This enables:

- property key completion
- enum value suggestions (`REJECT`, `REPLACE`)
- enum value suggestions (`REJECT`, `REPLACE`, `INVALID_PARAMS`, `INVALID_REQUEST`)
- metadata hints in IntelliJ and Spring-aware tooling

## 7. Related References
Expand Down
20 changes: 20 additions & 0 deletions docs/extension-points.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,26 @@ You can override any of these with custom Spring beans:
- `JsonRpcResponseComposer`
- `JsonRpcNotificationExecutor`

Response-side interfaces are available in `jsonrpc-core` for transport integrations:

- `JsonRpcEnvelopeClassifier`
- `JsonRpcResponseParser`
- `JsonRpcResponseValidator`
- `JsonRpcResponseValidationOptions`

Spring Boot auto-configuration currently wires request-dispatch components by default. For response-side
processing, create and use these components explicitly in your transport adapter.

Request validator customization example:

- Spring Boot property `jsonrpc.validation.request.params-type-violation-code-policy=INVALID_PARAMS`
keeps default `-32602` for `params` type violations.
- Spring Boot property `jsonrpc.validation.request.params-type-violation-code-policy=INVALID_REQUEST`
maps the same violation to `-32600`.
- For non-Spring or fully custom logic, you can still construct
`DefaultJsonRpcRequestValidator(JsonRpcParamsTypeViolationCodePolicy.INVALID_PARAMS)` or
`DefaultJsonRpcRequestValidator(JsonRpcParamsTypeViolationCodePolicy.INVALID_REQUEST)` directly.

## 2. Interceptor Chain

`JsonRpcInterceptor` hooks:
Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
## 2. Core Reference

- Protocol behavior and JSON-RPC compliance: [`protocol-and-compliance.md`](protocol-and-compliance.md)
- Incoming response classification/parsing/validation guidance: [`protocol-and-compliance.md`](protocol-and-compliance.md), [`pure-java-guide.md`](pure-java-guide.md)
- Registration styles and parameter binding rules: [`registration-and-binding.md`](registration-and-binding.md)
- Configuration keys, defaults, constraints, and precedence: [`configuration-reference.md`](configuration-reference.md)
- Extension interfaces and override points: [`extension-points.md`](extension-points.md)
Expand Down
Loading