6.4 KiB
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 for handwritten code and the Protobuf Style Guide for generated contract inputs.
Build Layout
Recommended Gradle multi-project layout:
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 21 recommended.
- The Gradle scaffold uses the Java 21 toolchain for compilation and tests.
Expected dependencies:
grpc-netty-shadedgrpc-protobufgrpc-stubprotobuf-javapicoclijunit-jupitermockitoif needed
Library API
Suggested API:
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
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:
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
caCertificatePathto pin a CA (full verification against that root), or - set
requireCertificateValidationtotrueto 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
StreamObserverfor services.
Do not reorder events. Stream cancellation should call ClientCall.cancel.
Error Handling
Recommended exceptions:
MxGatewayException
MxGatewayAuthenticationException
MxGatewayAuthorizationException
MxGatewaySessionException
MxGatewayWorkerException
MxGatewayCommandException
MxAccessException
MxGatewayCommandException should carry the raw command reply when available.
Test CLI
Binary wrapper name:
mxgw-java
Use picocli.
Commands:
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:
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-clientjar,zb-mom-ww-mxgateway-clirunnable 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:
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.