Files
mxaccessgw/clients/java/JavaClientDesign.md
Joseph Doherty 06e1046317 docs(archreview): P2 doc-drift sweep (IPC-06/07/17/21, SEC-09/22, CLI-12/16, TST-13)
Reconcile load-bearing docs with shipped behavior:
- IPC-06: gateway.md Worker Envelope sketch -> points to mxaccess_worker.proto
  as source of truth (string correlation_id, real oneof arms incl.
  worker_shutdown_ack/worker_ready).
- IPC-07: docs/Grpc.md six RPCs -> seven; document QueryActiveAlarms handler
  + validation row.
- IPC-21: gateway.md Session RPC moved from live API into a 'Future work: not
  implemented' subsection.
- TST-13: drop stale design-era sketches from gateway.md; correct the
  single-subscriber-default (config-gated fan-out) note.
- SEC-09: dashboard GroupToRole sample GwAdmin:Admin -> Administrator so it
  passes GatewayOptionsValidator; clarify Administrator is the canonical role.
- SEC-22: rewrite docs/Authentication.md to the pipeline that actually ships
  (ZB.MOM.WW.Auth.ApiKeys package + gateway-owned CachingApiKeyVerifier,
  CoalescingMarkApiKeyStore, CanonicalForwardingApiKeyAuditStore, etc.);
  remove 18 stale type names (grep-verified absent).
- IPC-17: correct wrong Python generated dir (mxgateway -> zb_mom_ww_mxgateway)
  in CLAUDE.md + 3 docs.
- CLI-12: Java docs Java 21 -> Java 17 (JDK17 retarget for Ignition 8.3).
- CLI-16: docs/ClientPackaging.md reconciled with real .slnx, Python package
  name, and gradle project names; fix stale generateProto task name.

Docs-only; type/path/version claims verified against source.

Claude-Session: https://claude.ai/code/session_01DMXXvNuPekkkrTEyPNxEkW
2026-07-09 14:46:15 -04:00

237 lines
6.4 KiB
Markdown

# Java Client Detailed Design
## Purpose
Provide a Java client library for MXAccess Gateway, plus a test CLI and unit
tests. The Java client should work for JVM services and operator tooling.
Follow the [Java Style Guide](../../docs/style-guides/JavaStyleGuide.md) for handwritten
code and the [Protobuf Style Guide](../../docs/style-guides/ProtobufStyleGuide.md) for
generated contract inputs.
## Build Layout
Recommended Gradle multi-project layout:
```text
clients/java/
settings.gradle
build.gradle
src/main/generated/
zb-mom-ww-mxgateway-client/
build.gradle
src/main/java/com/zb/mom/ww/mxgateway/client/
src/test/java/com/zb/mom/ww/mxgateway/client/
zb-mom-ww-mxgateway-cli/
build.gradle
src/main/java/com/zb/mom/ww/mxgateway/cli/
```
Alternative Maven layout is acceptable if the repo standardizes on Maven.
Target Java:
- Java 17 required (retargeted from 21 for Ignition 8.3 compatibility).
- The Gradle scaffold uses the Java 17 toolchain for compilation and tests.
Expected dependencies:
- `grpc-netty-shaded`
- `grpc-protobuf`
- `grpc-stub`
- `protobuf-java`
- `picocli`
- `junit-jupiter`
- `mockito` if needed
## Library API
Suggested API:
```java
public final class MxGatewayClient implements AutoCloseable {
public static MxGatewayClient connect(MxGatewayClientOptions options);
public MxGatewaySession openSession(OpenSessionOptions options);
public MxCommandReply invoke(MxCommandRequest request);
public CompletableFuture<MxCommandReply> invokeAsync(MxCommandRequest request);
public void close();
}
public final class MxGatewaySession implements AutoCloseable {
public String sessionId();
public int register(String clientName);
public void unregister(int serverHandle);
public int addItem(int serverHandle, String item);
public int addItem2(int serverHandle, String item, String context);
public void advise(int serverHandle, int itemHandle);
public List<SubscribeResult> addItemBulk(int serverHandle, List<String> tagAddresses);
public List<SubscribeResult> adviseItemBulk(int serverHandle, List<Integer> itemHandles);
public List<SubscribeResult> removeItemBulk(int serverHandle, List<Integer> itemHandles);
public List<SubscribeResult> unAdviseItemBulk(int serverHandle, List<Integer> itemHandles);
public List<SubscribeResult> subscribeBulk(int serverHandle, List<String> tagAddresses);
public List<SubscribeResult> unsubscribeBulk(int serverHandle, List<Integer> itemHandles);
public void write(int serverHandle, int itemHandle, MxValue value, int userId);
public Iterator<MxEvent> streamEvents();
public void streamEventsAsync(StreamObserver<MxEvent> observer);
public void close();
}
```
Expose generated protobuf classes for callers that need raw access.
## Options
```java
public final class MxGatewayClientOptions {
URI endpoint;
String apiKey;
boolean plaintext;
Path caCertificatePath;
String serverNameOverride;
Duration connectTimeout;
Duration callTimeout;
}
```
## Authentication
Use a gRPC `ClientInterceptor` to attach:
```text
authorization: Bearer <api key>
```
Redact API keys in `toString`, logs, and CLI output.
## TLS
Support:
- plaintext for local development,
- TLS with default JVM trust store,
- custom CA certificate file,
- server name override for test environments.
### Trust posture
The gateway can serve a self-signed certificate it generates itself (it has no
PKI). To make that usable, TLS is **lenient by default**: when the channel is not
plaintext and no `caCertificatePath` is set, the client builds
`GrpcSslContexts.forClient().trustManager(InsecureTrustManagerFactory.INSTANCE)`
(grpc-netty-shaded), so the gateway's self-signed certificate is accepted without
verification.
To verify the gateway instead:
- set `caCertificatePath` to pin a CA (full verification against that root), or
- set `requireCertificateValidation` to `true` to verify against the JVM trust
store without pinning.
Pinning a CA always wins over the lenient default.
## Streaming
Support both:
- blocking iterator for simple CLIs,
- async `StreamObserver` for services.
Do not reorder events. Stream cancellation should call `ClientCall.cancel`.
## Error Handling
Recommended exceptions:
```java
MxGatewayException
MxGatewayAuthenticationException
MxGatewayAuthorizationException
MxGatewaySessionException
MxGatewayWorkerException
MxGatewayCommandException
MxAccessException
```
`MxGatewayCommandException` should carry the raw command reply when available.
## Test CLI
Binary wrapper name:
```text
mxgw-java
```
Use `picocli`.
Commands:
```text
mxgw-java version
mxgw-java smoke --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --item TestChildObject.TestInt
mxgw-java stream-events --session-id <id> --json
mxgw-java write --session-id <id> --server-handle 1 --item-handle 1 --type int32 --value 123
```
JSON output can use Jackson or protobuf JSON formatting. Keep it deterministic.
## Unit Tests
Use JUnit 5.
Use `InProcessServerBuilder` and `InProcessChannelBuilder` for fake gRPC tests.
Required tests:
- auth interceptor attaches metadata,
- key redaction,
- plaintext and TLS channel setup,
- request construction helpers,
- value conversion,
- status/error mapping,
- blocking event stream iteration,
- async stream observer cancellation,
- CLI parsing,
- JSON output.
## Integration Tests
Skip unless:
```text
MXGATEWAY_INTEGRATION=1
```
Use JUnit assumptions. Integration flow should open, register, add, advise,
stream for bounded time, and close.
## Packaging
Publish library and CLI separately:
- `zb-mom-ww-mxgateway-client` jar,
- `zb-mom-ww-mxgateway-cli` runnable distribution.
Generated protobuf code should be produced during the build from shared proto
files and should not be hand-edited.
## Current Build
Run the Java scaffold checks from `clients/java`:
```powershell
gradle test
```
The `zb-mom-ww-mxgateway-client` project generates the gateway and worker
protobuf/gRPC bindings into `src/main/generated`, compiles the generated
contracts, and runs JUnit 5 tests. The `zb-mom-ww-mxgateway-cli` project
builds a Picocli-based `mxgw-java` entry point for later command implementation.
## Related Documentation
- [Client Libraries Detailed Design](../../docs/ClientLibrariesDesign.md)
- [Client Proto Generation](../../docs/ClientProtoGeneration.md)
- [Client Packaging](../../docs/ClientPackaging.md)
- [Java Style Guide](../../docs/style-guides/JavaStyleGuide.md)