diff --git a/clients/java/JavaClientDesign.md b/clients/java/JavaClientDesign.md index 31896d1..b21ba41 100644 --- a/clients/java/JavaClientDesign.md +++ b/clients/java/JavaClientDesign.md @@ -20,11 +20,11 @@ clients/java/ src/main/generated/ zb-mom-ww-mxgateway-client/ build.gradle - src/main/java/com/dohertylan/mxgateway/client/ - src/test/java/com/dohertylan/mxgateway/client/ + 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/dohertylan/mxgateway/cli/ + src/main/java/com/zb/mom/ww/mxgateway/cli/ ``` Alternative Maven layout is acceptable if the repo standardizes on Maven. @@ -192,8 +192,8 @@ stream for bounded time, and close. Publish library and CLI separately: -- `mxgateway-client` jar, -- `mxgateway-cli` runnable distribution. +- `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. @@ -206,10 +206,10 @@ Run the Java scaffold checks from `clients/java`: gradle test ``` -The `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 `mxgateway-cli` project builds a Picocli-based `mxgw-java` -entry point for later command implementation. +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 diff --git a/clients/java/README.md b/clients/java/README.md index 98aba24..c12b0c8 100644 --- a/clients/java/README.md +++ b/clients/java/README.md @@ -14,18 +14,19 @@ clients/java/ zb-mom-ww-mxgateway-cli/ ``` -`mxgateway-client` generates Java protobuf and gRPC sources from +`zb-mom-ww-mxgateway-client` generates Java protobuf and gRPC sources from `../../src/ZB.MOM.WW.MxGateway.Contracts/Protos`. The Gradle protobuf plugin writes those generated sources under `src/main/generated`, which matches the client proto manifest in `../proto/proto-inputs.json`. Do not edit generated files by hand. -`mxgateway-client` exposes `MxGatewayClientOptions`, `MxGatewayClient`, +`zb-mom-ww-mxgateway-client` exposes `MxGatewayClientOptions`, `MxGatewayClient`, `MxGatewaySession`, value/status helpers, typed gateway exceptions, raw generated stubs, and generated protobuf messages for parity tests. -`mxgateway-cli` depends on `mxgateway-client` and provides the `mxgw-java` -application entry point. The CLI supports version, session, command, event -streaming, write, and smoke-test commands with deterministic JSON output. +`zb-mom-ww-mxgateway-cli` depends on `zb-mom-ww-mxgateway-client` and provides +the `mxgw-java` application entry point. The CLI supports version, session, +command, event streaming, write, and smoke-test commands with deterministic +JSON output. ## Regenerating Protobuf Bindings @@ -33,7 +34,7 @@ Run generation from `clients/java` after the shared `.proto` files or Java output path changes: ```powershell -gradle :mxgateway-client:generateProto +gradle :zb-mom-ww-mxgateway-client:generateProto ``` ## Client Usage @@ -104,9 +105,9 @@ The CLI exposes matching subcommands: `galaxy-test`, `galaxy-deploy-time`, `--timeout`, and `--json` options as the gateway commands. ```powershell -gradle :mxgateway-cli:run --args="galaxy-test --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" -gradle :mxgateway-cli:run --args="galaxy-deploy-time --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" -gradle :mxgateway-cli:run --args="galaxy-discover --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="galaxy-test --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="galaxy-deploy-time --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="galaxy-discover --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" ``` ### Watching deploy events @@ -156,8 +157,8 @@ The matching CLI subcommand streams events until cancelled (Ctrl+C) and prints one line per event in text mode or one JSON object per event with `--json`: ```powershell -gradle :mxgateway-cli:run --args="galaxy-watch --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" -gradle :mxgateway-cli:run --args="galaxy-watch --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --last-seen-deploy-time 2026-04-28T18:30:00Z --limit 5" +gradle :zb-mom-ww-mxgateway-cli:run --args="galaxy-watch --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="galaxy-watch --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --last-seen-deploy-time 2026-04-28T18:30:00Z --limit 5" ``` ## CLI Usage @@ -165,14 +166,14 @@ gradle :mxgateway-cli:run --args="galaxy-watch --endpoint localhost:5000 --api-k Run the CLI through Gradle: ```powershell -gradle :mxgateway-cli:run --args="version --json" -gradle :mxgateway-cli:run --args="open-session --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --client-session-name java-cli --json" -gradle :mxgateway-cli:run --args="register --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --client-name java-cli --json" -gradle :mxgateway-cli:run --args="add-item --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --server-handle 1 --item TestObject.TestInt --json" -gradle :mxgateway-cli:run --args="advise --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --server-handle 1 --item-handle 1 --json" -gradle :mxgateway-cli:run --args="write --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --server-handle 1 --item-handle 1 --type int32 --value 123 --json" -gradle :mxgateway-cli:run --args="stream-events --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --limit 1 --json" -gradle :mxgateway-cli:run --args="smoke --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --item TestObject.TestInt --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="version --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="open-session --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --client-session-name java-cli --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="register --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --client-name java-cli --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="add-item --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --server-handle 1 --item TestObject.TestInt --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="advise --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --server-handle 1 --item-handle 1 --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="write --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --server-handle 1 --item-handle 1 --type int32 --value 123 --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="stream-events --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --session-id --limit 1 --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="smoke --endpoint localhost:5000 --api-key-env MXGATEWAY_API_KEY --plaintext --item TestObject.TestInt --json" ``` The CLI accepts `--api-key`, `--api-key-env`, `--plaintext`, `--ca-file`, @@ -182,7 +183,7 @@ output redacts API keys. Use TLS options for a secured gateway: ```powershell -gradle :mxgateway-cli:run --args="smoke --endpoint mxgateway.example.local:5001 --ca-file C:\certs\mxgateway-ca.pem --server-name-override mxgateway.example.local --api-key-env MXGATEWAY_API_KEY --item TestObject.TestInt --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="smoke --endpoint mxgateway.example.local:5001 --ca-file C:\certs\mxgateway-ca.pem --server-name-override mxgateway.example.local --api-key-env MXGATEWAY_API_KEY --item TestObject.TestInt --json" ``` ## Build And Test @@ -202,11 +203,11 @@ in-process gRPC behavior, stream cancellation, and CLI parser/output behavior. Create local library and CLI artifacts from `clients/java`: ```powershell -gradle :mxgateway-client:jar :mxgateway-cli:installDist +gradle :zb-mom-ww-mxgateway-client:jar :zb-mom-ww-mxgateway-cli:installDist ``` The library jar is under `zb-mom-ww-mxgateway-client/build/libs`. The installed CLI -distribution is under `zb-mom-ww-mxgateway-cli/build/install/mxgateway-cli`. +distribution is under `zb-mom-ww-mxgateway-cli/build/install/zb-mom-ww-mxgateway-cli`. ## Integration Checks @@ -217,7 +218,7 @@ $env:MXGATEWAY_INTEGRATION = '1' $env:MXGATEWAY_ENDPOINT = 'localhost:5000' $env:MXGATEWAY_API_KEY = '' $env:MXGATEWAY_TEST_ITEM = 'TestObject.TestInt' -gradle :mxgateway-cli:run --args="smoke --endpoint $env:MXGATEWAY_ENDPOINT --plaintext --api-key-env MXGATEWAY_API_KEY --item $env:MXGATEWAY_TEST_ITEM --json" +gradle :zb-mom-ww-mxgateway-cli:run --args="smoke --endpoint $env:MXGATEWAY_ENDPOINT --plaintext --api-key-env MXGATEWAY_API_KEY --item $env:MXGATEWAY_TEST_ITEM --json" ``` ## Related Documentation diff --git a/clients/java/src/main/generated/main/grpc/mxaccess_gateway/v1/MxAccessGatewayGrpc.java b/clients/java/src/main/generated/main/grpc/mxaccess_gateway/v1/MxAccessGatewayGrpc.java index b8b8f66..2f307e8 100644 --- a/clients/java/src/main/generated/main/grpc/mxaccess_gateway/v1/MxAccessGatewayGrpc.java +++ b/clients/java/src/main/generated/main/grpc/mxaccess_gateway/v1/MxAccessGatewayGrpc.java @@ -354,6 +354,9 @@ public final class MxAccessGatewayGrpc { * reconnect to seed Part 9 client state, or to reconcile alarms that may * have been missed during a transport blip. Streamed so callers can * begin processing without buffering the full set. + * `QueryActiveAlarmsRequest.alarm_filter_prefix` optionally narrows the + * snapshot to alarms whose `alarm_full_reference` starts with the given + * prefix; an empty prefix returns the full set. * */ default void queryActiveAlarms(mxaccess_gateway.v1.MxaccessGateway.QueryActiveAlarmsRequest request, @@ -457,6 +460,9 @@ public final class MxAccessGatewayGrpc { * reconnect to seed Part 9 client state, or to reconcile alarms that may * have been missed during a transport blip. Streamed so callers can * begin processing without buffering the full set. + * `QueryActiveAlarmsRequest.alarm_filter_prefix` optionally narrows the + * snapshot to alarms whose `alarm_full_reference` starts with the given + * prefix; an empty prefix returns the full set. * */ public void queryActiveAlarms(mxaccess_gateway.v1.MxaccessGateway.QueryActiveAlarmsRequest request, @@ -545,6 +551,9 @@ public final class MxAccessGatewayGrpc { * reconnect to seed Part 9 client state, or to reconcile alarms that may * have been missed during a transport blip. Streamed so callers can * begin processing without buffering the full set. + * `QueryActiveAlarmsRequest.alarm_filter_prefix` optionally narrows the + * snapshot to alarms whose `alarm_full_reference` starts with the given + * prefix; an empty prefix returns the full set. * */ @io.grpc.ExperimentalApi("https://github.com/grpc/grpc-java/issues/10918") @@ -632,6 +641,9 @@ public final class MxAccessGatewayGrpc { * reconnect to seed Part 9 client state, or to reconcile alarms that may * have been missed during a transport blip. Streamed so callers can * begin processing without buffering the full set. + * `QueryActiveAlarmsRequest.alarm_filter_prefix` optionally narrows the + * snapshot to alarms whose `alarm_full_reference` starts with the given + * prefix; an empty prefix returns the full set. * */ public java.util.Iterator queryActiveAlarms( diff --git a/clients/java/src/main/generated/main/java/mxaccess_gateway/v1/MxaccessGateway.java b/clients/java/src/main/generated/main/java/mxaccess_gateway/v1/MxaccessGateway.java index 0b3d0b8..93bb2d4 100644 --- a/clients/java/src/main/generated/main/java/mxaccess_gateway/v1/MxaccessGateway.java +++ b/clients/java/src/main/generated/main/java/mxaccess_gateway/v1/MxaccessGateway.java @@ -1995,9 +1995,10 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile { } /** *
-   * Public request shape for QueryActiveAlarms. session_id is currently unused
-   * (the snapshot is session-less) but reserved so a future per-session view
-   * can be added without a wire break.
+   * Public request shape for QueryActiveAlarms.
+   * Clients may leave `session_id` empty; the gateway currently ignores it and
+   * serves the session-less central-monitor cache. A future version may use it
+   * to scope the snapshot to one session.
    * 
* * Protobuf type {@code mxaccess_gateway.v1.QueryActiveAlarmsRequest} @@ -2344,9 +2345,10 @@ public final class MxaccessGateway extends com.google.protobuf.GeneratedFile { } /** *
-     * Public request shape for QueryActiveAlarms. session_id is currently unused
-     * (the snapshot is session-less) but reserved so a future per-session view
-     * can be added without a wire break.
+     * Public request shape for QueryActiveAlarms.
+     * Clients may leave `session_id` empty; the gateway currently ignores it and
+     * serves the session-less central-monitor cache. A future version may use it
+     * to scope the snapshot to one session.
      * 
* * Protobuf type {@code mxaccess_gateway.v1.QueryActiveAlarmsRequest} diff --git a/clients/java/zb-mom-ww-mxgateway-client/src/test/java/com/zb/mom/ww/mxgateway/client/MxGatewayClientSessionTests.java b/clients/java/zb-mom-ww-mxgateway-client/src/test/java/com/zb/mom/ww/mxgateway/client/MxGatewayClientSessionTests.java index a80426a..6b4273a 100644 --- a/clients/java/zb-mom-ww-mxgateway-client/src/test/java/com/zb/mom/ww/mxgateway/client/MxGatewayClientSessionTests.java +++ b/clients/java/zb-mom-ww-mxgateway-client/src/test/java/com/zb/mom/ww/mxgateway/client/MxGatewayClientSessionTests.java @@ -2,6 +2,7 @@ package com.zb.mom.ww.mxgateway.client; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -23,7 +24,9 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicReference; import mxaccess_gateway.v1.MxAccessGatewayGrpc; +import mxaccess_gateway.v1.MxaccessGateway.ActiveAlarmSnapshot; import mxaccess_gateway.v1.MxaccessGateway.AddItemReply; +import mxaccess_gateway.v1.MxaccessGateway.AlarmConditionState; import mxaccess_gateway.v1.MxaccessGateway.BulkSubscribeReply; import mxaccess_gateway.v1.MxaccessGateway.CloseSessionReply; import mxaccess_gateway.v1.MxaccessGateway.CloseSessionRequest; @@ -35,6 +38,7 @@ import mxaccess_gateway.v1.MxaccessGateway.OpenSessionReply; import mxaccess_gateway.v1.MxaccessGateway.OpenSessionRequest; import mxaccess_gateway.v1.MxaccessGateway.ProtocolStatus; import mxaccess_gateway.v1.MxaccessGateway.ProtocolStatusCode; +import mxaccess_gateway.v1.MxaccessGateway.QueryActiveAlarmsRequest; import mxaccess_gateway.v1.MxaccessGateway.RegisterReply; import mxaccess_gateway.v1.MxaccessGateway.SessionState; import mxaccess_gateway.v1.MxaccessGateway.StreamEventsRequest; @@ -179,6 +183,91 @@ final class MxGatewayClientSessionTests { } } + @Test + void queryActiveAlarmsForwardsRequestAndStreamsSnapshots() throws Exception { + AtomicReference queryRequest = new AtomicReference<>(); + TestGatewayService service = new TestGatewayService() { + @Override + public void queryActiveAlarms( + QueryActiveAlarmsRequest request, StreamObserver responseObserver) { + queryRequest.set(request); + responseObserver.onNext(ActiveAlarmSnapshot.newBuilder() + .setAlarmFullReference("Galaxy!TestArea.TestMachine_001.HiTemp") + .setSourceObjectReference("TestMachine_001") + .setAlarmTypeName("HiAlarm") + .setSeverity(800) + .setCurrentState(AlarmConditionState.ALARM_CONDITION_STATE_ACTIVE) + .setCategory("Process") + .setDescription("High temperature alarm") + .build()); + responseObserver.onNext(ActiveAlarmSnapshot.newBuilder() + .setAlarmFullReference("Galaxy!TestArea.TestMachine_002.LoTemp") + .setSourceObjectReference("TestMachine_002") + .setAlarmTypeName("LoAlarm") + .setSeverity(500) + .setCurrentState(AlarmConditionState.ALARM_CONDITION_STATE_ACTIVE_ACKED) + .setOperatorUser("operator-1") + .setOperatorComment("acknowledged") + .build()); + responseObserver.onCompleted(); + } + }; + + try (InProcessGateway gateway = InProcessGateway.start(service, new AtomicReference<>()); + MxGatewayClient client = gateway.client("", Duration.ofSeconds(5))) { + CountDownLatch completed = new CountDownLatch(1); + java.util.List received = new java.util.ArrayList<>(); + AtomicReference errorRef = new AtomicReference<>(); + + QueryActiveAlarmsRequest request = QueryActiveAlarmsRequest.newBuilder() + .setSessionId("alarm-session") + .setClientCorrelationId("test-corr-1") + .setAlarmFilterPrefix("Galaxy!TestArea") + .build(); + + MxGatewayActiveAlarmsSubscription subscription = client.queryActiveAlarms( + request, + new StreamObserver<>() { + @Override + public void onNext(ActiveAlarmSnapshot value) { + received.add(value); + } + + @Override + public void onError(Throwable t) { + errorRef.set(t); + completed.countDown(); + } + + @Override + public void onCompleted() { + completed.countDown(); + } + }); + + assertTrue(completed.await(5, TimeUnit.SECONDS)); + subscription.close(); + + assertNotNull(queryRequest.get()); + assertEquals("alarm-session", queryRequest.get().getSessionId()); + assertEquals("test-corr-1", queryRequest.get().getClientCorrelationId()); + assertEquals("Galaxy!TestArea", queryRequest.get().getAlarmFilterPrefix()); + + assertEquals(2, received.size()); + assertEquals("Galaxy!TestArea.TestMachine_001.HiTemp", received.get(0).getAlarmFullReference()); + assertEquals( + AlarmConditionState.ALARM_CONDITION_STATE_ACTIVE, + received.get(0).getCurrentState()); + assertEquals(800, received.get(0).getSeverity()); + assertEquals("Galaxy!TestArea.TestMachine_002.LoTemp", received.get(1).getAlarmFullReference()); + assertEquals( + AlarmConditionState.ALARM_CONDITION_STATE_ACTIVE_ACKED, + received.get(1).getCurrentState()); + assertEquals("operator-1", received.get(1).getOperatorUser()); + assertNull(errorRef.get()); + } + } + @Test void commandFailureKeepsRawReply() throws Exception { TestGatewayService service = new TestGatewayService() { diff --git a/code-reviews/Client.Java/findings.md b/code-reviews/Client.Java/findings.md index 612723f..fe55dc4 100644 --- a/code-reviews/Client.Java/findings.md +++ b/code-reviews/Client.Java/findings.md @@ -451,13 +451,13 @@ documentation updates lag — see the doc-side findings below. | Severity | Medium | | Category | Documentation & comments | | Location | `clients/java/README.md:36,107-175,185,205,220`, `clients/java/JavaClientDesign.md:195-211` | -| Status | Open | +| Status | Resolved | **Description:** Commit `397d3c5` renamed the gradle subprojects to `zb-mom-ww-mxgateway-client` and `zb-mom-ww-mxgateway-cli` in `settings.gradle`, but did not propagate that rename into the README's documented gradle commands or into `JavaClientDesign.md`. Every documented gradle invocation still uses the old short names — `gradle :mxgateway-client:generateProto`, `gradle :mxgateway-cli:run --args=...`, `gradle :mxgateway-client:jar :mxgateway-cli:installDist` — and every one fails with `project 'mxgateway-client' not found in root project 'zb-mom-ww-mxaccessgw-java'`. A user copy-pasting from the README or design doc will hit this on the very first command. **Recommendation:** Find-and-replace `:mxgateway-client:` → `:zb-mom-ww-mxgateway-client:` and `:mxgateway-cli:` → `:zb-mom-ww-mxgateway-cli:` across `clients/java/README.md` and `clients/java/JavaClientDesign.md`. (Roughly 17 occurrences in the README, 3 in the design doc.) Test by running one updated command end-to-end. -**Resolution:** _(empty until closed)_ +**Resolution:** 2026-05-24 — Replaced every stale gradle task path in `clients/java/README.md` (line 37 `:mxgateway-client:generateProto`, lines 108–110 `:mxgateway-cli:run` galaxy-* invocations, lines 160–161 `:mxgateway-cli:run` galaxy-watch invocations, lines 169–176 `:mxgateway-cli:run` gateway-command invocations, line 186 `:mxgateway-cli:run` TLS smoke invocation, line 206 `:mxgateway-client:jar :mxgateway-cli:installDist` packaging command, line 221 `:mxgateway-cli:run` integration-check invocation) and in `clients/java/JavaClientDesign.md` (lines 195–196 packaging bullets, lines 209–212 "Current Build" prose) with their prefixed `:zb-mom-ww-mxgateway-client:` / `:zb-mom-ww-mxgateway-cli:` equivalents. Verified by running `gradle :zb-mom-ww-mxgateway-client:test --tests …` (now the updated documented form) end-to-end and `gradle build`, both BUILD SUCCESSFUL. Doc-only change; no production code touched. ### Client.Java-028 @@ -466,13 +466,13 @@ documentation updates lag — see the doc-side findings below. | Severity | Medium | | Category | Documentation & comments | | Location | `clients/java/JavaClientDesign.md:23-27` | -| Status | Open | +| Status | Resolved | **Description:** The build-layout block in `JavaClientDesign.md` still shows the old Java package paths `com/dohertylan/mxgateway/client/` and `com/dohertylan/mxgateway/cli/`. The actual source tree was moved to `com/zb/mom/ww/mxgateway/{client,cli}/` in commit `397d3c5`. Anyone using the design doc to locate or navigate code will look in the wrong place. **Recommendation:** Update the layout block to reflect the new paths: `com/zb/mom/ww/mxgateway/client/` and `com/zb/mom/ww/mxgateway/cli/`. Comment-only change. -**Resolution:** _(empty until closed)_ +**Resolution:** 2026-05-24 — Updated the Build Layout block in `clients/java/JavaClientDesign.md:23-27` to show `com/zb/mom/ww/mxgateway/client/` and `com/zb/mom/ww/mxgateway/cli/` instead of the old `com/dohertylan/mxgateway/{client,cli}/` package paths, matching the actual on-disk source tree under `clients/java/zb-mom-ww-mxgateway-{client,cli}/src/{main,test}/java/`. Doc-only change; no production code touched. ### Client.Java-029 @@ -481,13 +481,13 @@ documentation updates lag — see the doc-side findings below. | Severity | Low | | Category | Documentation & comments | | Location | `clients/java/README.md:208-209` | -| Status | Open | +| Status | Resolved | **Description:** The packaging section states "The library jar is under `zb-mom-ww-mxgateway-client/build/libs`. The installed CLI distribution is under `zb-mom-ww-mxgateway-cli/build/install/mxgateway-cli`." The library-jar path is correct, but the install-distribution path is wrong — gradle's `installDist` produces a directory whose name matches the project name, not the (now-retired) short name, so the actual path is `zb-mom-ww-mxgateway-cli/build/install/zb-mom-ww-mxgateway-cli/`. The e2e script (`scripts/run-client-e2e-tests.ps1`) uses the correct path, so the script works; only the README is wrong. **Recommendation:** Correct the README to `zb-mom-ww-mxgateway-cli/build/install/zb-mom-ww-mxgateway-cli`. Comment-only. -**Resolution:** _(empty until closed)_ +**Resolution:** 2026-05-24 — Corrected the install-distribution path in `clients/java/README.md:210` from `zb-mom-ww-mxgateway-cli/build/install/mxgateway-cli` to `zb-mom-ww-mxgateway-cli/build/install/zb-mom-ww-mxgateway-cli`, matching what gradle's `installDist` actually produces (the directory name matches the subproject name). The library-jar path on the preceding line was already correct and is unchanged. Doc-only change; the e2e script `scripts/run-client-e2e-tests.ps1` was already using the correct path. ### Client.Java-030 @@ -496,13 +496,13 @@ documentation updates lag — see the doc-side findings below. | Severity | Low | | Category | Testing coverage | | Location | `clients/java/zb-mom-ww-mxgateway-client/src/test/java/com/zb/mom/ww/mxgateway/client/` | -| Status | Open | +| Status | Resolved | **Description:** Commit `397d3c5` added the missing `QueryActiveAlarmsRequest` proto message and the corresponding `rpc QueryActiveAlarms` to `mxaccess_gateway.proto`. The Java client now generates the request type and the gRPC stub method, and `MxGatewayClient.queryActiveAlarms` correctly references both. No unit test exercises the new RPC end-to-end on the Java side — the proto compiles, the import resolves, the method is callable, but the absence of a `queryActiveAlarmsForwardsRequestAndStreamsSnapshots` (or similar) fixture means a serialisation regression in `QueryActiveAlarmsRequest` or the streaming reply would not surface in the Java unit tests. **Recommendation:** Add a unit test in `MxGatewayFixtureTests` (or wherever the alarm fixtures live) that pushes a `QueryActiveAlarmsRequest` through a `FakeMxAccessGateway` and asserts the `ActiveAlarmSnapshot` stream is consumed correctly — mirror the existing `acknowledgeAlarm` test shape. -**Resolution:** _(empty until closed)_ +**Resolution:** 2026-05-24 — Re-triaged the recommendation: the suite uses the `InProcessGateway` + `TestGatewayService` fixture in `MxGatewayClientSessionTests` (no separate `FakeMxAccessGateway`), and there is in fact no existing `acknowledgeAlarm` test in the current tree to mirror — the alarm RPC surface has zero coverage. Added `queryActiveAlarmsForwardsRequestAndStreamsSnapshots` to `MxGatewayClientSessionTests` (the same file/fixture style as the other unary/streaming RPC tests): the test overrides `TestGatewayService.queryActiveAlarms` to capture the inbound `QueryActiveAlarmsRequest` and emit two `ActiveAlarmSnapshot` messages (one `ACTIVE`, one `ACTIVE_ACKED` with an operator/comment populated), then calls `MxGatewayClient.queryActiveAlarms` with a request carrying `session_id`, `client_correlation_id`, and `alarm_filter_prefix`. It awaits `onCompleted` via a `CountDownLatch`, closes the subscription, and asserts (a) the server observed all three inbound request fields, (b) both snapshots arrived in order with the expected `alarm_full_reference`/`current_state`/`severity`/`operator_user`, and (c) the observer never received an error. TDD red phase confirmed by temporarily changing the `session_id` assertion to `"WRONG-SESSION-ID"` — `gradle :zb-mom-ww-mxgateway-client:test --tests "…queryActiveAlarmsForwardsRequestAndStreamsSnapshots"` failed with `AssertionFailedError at MxGatewayClientSessionTests.java:252`. Restoring the assertion turned the build green. Full `gradle build` from `clients/java` is BUILD SUCCESSFUL. ### Client.Java-031 @@ -511,10 +511,10 @@ documentation updates lag — see the doc-side findings below. | Severity | Low | | Category | mxaccessgw conventions | | Location | `clients/java/README.md:13,17,26` | -| Status | Open | +| Status | Resolved | **Description:** The README prose at lines 13–26 introduces the subprojects as `mxgateway-client` and `mxgateway-cli` (the old short names) when discussing the layout. Those are no longer the actual subproject names — `settings.gradle` declares `zb-mom-ww-mxgateway-client` / `zb-mom-ww-mxgateway-cli`. The prose works as a naming mnemonic, but it confuses anyone trying to map README descriptions to actual gradle output, IDE project trees, or the e2e script. **Recommendation:** Either (a) update the prose to the full prefixed names, or (b) clarify in a one-line note: "The subprojects are `zb-mom-ww-mxgateway-client` and `zb-mom-ww-mxgateway-cli`; this README refers to them by their short suffixes below for readability." (a) is more honest; (b) preserves readability at the cost of one extra concept. -**Resolution:** _(empty until closed)_ +**Resolution:** 2026-05-24 — Took option (a): updated the README layout-section prose in `clients/java/README.md:17,22,26` (the `mxgateway-client` generates… paragraph, the `mxgateway-client` exposes… paragraph, and the `mxgateway-cli` depends on `mxgateway-client`… paragraph) to use the full prefixed `zb-mom-ww-mxgateway-client` and `zb-mom-ww-mxgateway-cli` names, matching the layout block at lines 13–14 and `settings.gradle`. Reflows the final paragraph slightly because the prefixed names push past the existing 80-column wrap; content is unchanged otherwise. Doc-only change.