From 2d8e43c9e153d2ae4e5db4133eecada21da698c0 Mon Sep 17 00:00:00 2001 From: Yash Goel Date: Sun, 15 Feb 2026 04:33:52 +0530 Subject: [PATCH 1/2] refactor: return Optional from state(), KeyEvents.get(), and Config.get() Complete the Optional refactoring started in #57 for the remaining methods that still threw exceptions for not-found conditions: - SignifyClient.state() returns Optional instead of throwing IllegalArgumentException on 404 - SignifyClient.connect() uses orElseThrow() for clear error messaging - Coring.KeyEvents.get() returns Optional with 404 check - Coring.Config.get() returns Optional with 404 check - TestUtils.getOrCreateClient() uses state().isEmpty() instead of try/catch flow control Closes #49 --- .../signify/app/clienting/SignifyClient.java | 16 +++++----- .../signify/app/coring/Coring.java | 29 +++++++++++++++---- .../signify/e2e/RandyTest.java | 4 +-- .../signify/e2e/SaltyTests.java | 2 +- .../signify/e2e/utils/TestUtils.java | 6 ++-- 5 files changed, 36 insertions(+), 21 deletions(-) diff --git a/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java b/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java index ffd22419..2d5edd96 100644 --- a/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java +++ b/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java @@ -150,8 +150,10 @@ public void boot() throws Exception { /** * Get state of the agent and the client + * + * @return Optional containing the State if the agent exists, or empty if not found */ - public State state() throws Exception { + public Optional state() throws Exception { String caid = controller != null ? controller.getPre() : null; if (caid == null) { throw new IllegalArgumentException("Controller not initialized"); @@ -167,7 +169,7 @@ public State state() throws Exception { HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == HttpURLConnection.HTTP_NOT_FOUND) { - throw new IllegalArgumentException("Agent does not exist for controller " + caid); + return Optional.empty(); } if (response.statusCode() != HttpURLConnection.HTTP_OK @@ -177,22 +179,20 @@ public State state() throws Exception { Map data = Utils.fromJson(response.body(), new TypeReference<>() {}); - return State.builder() + return Optional.of(State.builder() .agent(data.getOrDefault(SignifyFields.AGENT.getValue(), null)) .controller(data.getOrDefault(SignifyFields.CONTROLLER.getValue(), null)) .ridx((Integer) data.getOrDefault(SignifyFields.RIDX.getValue(), 0)) .pidx((Integer) data.getOrDefault(SignifyFields.PIDX.getValue(), 0)) - .build(); + .build()); } /** * Connect to a KERIA agent */ public void connect() throws Exception { - State state = state(); - if (state == null) { - throw new RuntimeException("State not initialized"); - } + State state = state() + .orElseThrow(() -> new IllegalArgumentException("Agent not booted — call boot() first")); this.pidx = state.getPidx(); // Create controller representing the local client AID diff --git a/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java b/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java index 65383d86..84b0bf52 100644 --- a/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java +++ b/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java @@ -10,7 +10,9 @@ import org.cardanofoundation.signify.cesr.args.RawArgs; import org.cardanofoundation.signify.cesr.util.Utils; +import java.net.HttpURLConnection; import java.net.http.HttpResponse; +import java.util.Optional; public class Coring { public static String randomPasscode() { @@ -51,16 +53,21 @@ public KeyEvents(SignifyClient client) { } /** - * Retrieve the key state for an identifier + * Retrieve the key events for an identifier * @param pre Identifier prefix - * @return A map representing the key states + * @return Optional containing the key events if found, or empty if not found * @throws Exception if the fetch operation fails */ - public Object get(String pre) throws Exception { + public Optional get(String pre) throws Exception { String path = "/events?pre=" + pre; String method = "GET"; HttpResponse res = this.client.fetch(path, method, null); - return Utils.fromJson(res.body(), Object.class); + + if (res.statusCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return Optional.empty(); + } + + return Optional.of(Utils.fromJson(res.body(), Object.class)); } } @@ -76,11 +83,21 @@ public Config(SignifyClient client) { this.client = client; } - public Object get() throws Exception { + /** + * Retrieve the agent configuration + * @return Optional containing the config if found, or empty if not found + * @throws Exception if the fetch operation fails + */ + public Optional get() throws Exception { String path = "/config"; String method = "GET"; HttpResponse res = this.client.fetch(path, method, null); - return Utils.fromJson(res.body(), Object.class); + + if (res.statusCode() == HttpURLConnection.HTTP_NOT_FOUND) { + return Optional.empty(); + } + + return Optional.of(Utils.fromJson(res.body(), Object.class)); } } } diff --git a/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java b/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java index 3940af39..0c433c31 100644 --- a/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java +++ b/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java @@ -90,7 +90,7 @@ void randyTest() throws Exception { Coring.KeyEvents events = client1.keyEvents(); - List> logList = (List>) events.get(opResponsePrefix); + List> logList = (List>) events.get(opResponsePrefix).orElseThrow(); assertEquals(2, logList.size()); icpResult = client1.identifiers().rotate("aid1"); @@ -111,7 +111,7 @@ void randyTest() throws Exception { rot.getVerfers().getFirst().getQb64b()); assertEquals(dig.getQb64(), icp.getDigers().getFirst().getQb64()); - logList = (List>) events.get(opResponsePrefix); + logList = (List>) events.get(opResponsePrefix).orElseThrow(); assertEquals(3, logList.size()); assertOperations(Collections.singletonList(client1)); } diff --git a/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java b/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java index 7c5ca67f..93b34a2f 100644 --- a/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java +++ b/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java @@ -176,7 +176,7 @@ void saltyTest() throws Exception { // KeyEvents Coring.KeyEvents events = client.keyEvents(); - List> log = (List>) events.get((String) aidLast.get("prefix")); + List> log = (List>) events.get((String) aidLast.get("prefix")).orElseThrow(); assertEquals(3, log.size()); Serder serder = new Serder((Map) log.getFirst().get("ked")); diff --git a/src/test/java/org/cardanofoundation/signify/e2e/utils/TestUtils.java b/src/test/java/org/cardanofoundation/signify/e2e/utils/TestUtils.java index df3178ca..d5759cad 100644 --- a/src/test/java/org/cardanofoundation/signify/e2e/utils/TestUtils.java +++ b/src/test/java/org/cardanofoundation/signify/e2e/utils/TestUtils.java @@ -220,12 +220,10 @@ public static SignifyClient getOrCreateClient(String bran) throws Exception { } SignifyClient client = new SignifyClient(url, bran, Salter.Tier.low, bootUrl, null); - try { - client.connect(); - } catch (Exception e) { + if (client.state().isEmpty()) { client.boot(); - client.connect(); } + client.connect(); System.out.println("Client: " + Map.of("agent", client.getAgent() != null ? client.getAgent().getPre() : null, "controller", client.getController().getPre() From c98d226ce0aea311ab0657506655e54fb150d0a3 Mon Sep 17 00:00:00 2001 From: Yash Goel <162511050+yashhzd@users.noreply.github.com> Date: Wed, 18 Feb 2026 04:47:55 +0530 Subject: [PATCH 2/2] fix: address review feedback from iFergal - Revert KeyEvents.get() and Config.get() to return plain Object since KERIA endpoints return [] instead of 404 for not-found - Include controller identifier (caid) in connect() error message for easier debugging during development - Update test files to match reverted signatures --- .../signify/app/clienting/SignifyClient.java | 4 +++- .../signify/app/coring/Coring.java | 24 +++++-------------- .../signify/e2e/RandyTest.java | 4 ++-- .../signify/e2e/SaltyTests.java | 2 +- 4 files changed, 12 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java b/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java index 2d5edd96..f7b8c251 100644 --- a/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java +++ b/src/main/java/org/cardanofoundation/signify/app/clienting/SignifyClient.java @@ -191,8 +191,10 @@ public Optional state() throws Exception { * Connect to a KERIA agent */ public void connect() throws Exception { + String caid = controller != null ? controller.getPre() : "unknown"; State state = state() - .orElseThrow(() -> new IllegalArgumentException("Agent not booted — call boot() first")); + .orElseThrow(() -> new IllegalArgumentException( + "Agent not booted for controller " + caid + " \u2014 call boot() first")); this.pidx = state.getPidx(); // Create controller representing the local client AID diff --git a/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java b/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java index 84b0bf52..85a0f987 100644 --- a/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java +++ b/src/main/java/org/cardanofoundation/signify/app/coring/Coring.java @@ -10,9 +10,7 @@ import org.cardanofoundation.signify.cesr.args.RawArgs; import org.cardanofoundation.signify.cesr.util.Utils; -import java.net.HttpURLConnection; import java.net.http.HttpResponse; -import java.util.Optional; public class Coring { public static String randomPasscode() { @@ -55,19 +53,14 @@ public KeyEvents(SignifyClient client) { /** * Retrieve the key events for an identifier * @param pre Identifier prefix - * @return Optional containing the key events if found, or empty if not found + * @return A list representing the key events (empty list if none found) * @throws Exception if the fetch operation fails */ - public Optional get(String pre) throws Exception { + public Object get(String pre) throws Exception { String path = "/events?pre=" + pre; String method = "GET"; HttpResponse res = this.client.fetch(path, method, null); - - if (res.statusCode() == HttpURLConnection.HTTP_NOT_FOUND) { - return Optional.empty(); - } - - return Optional.of(Utils.fromJson(res.body(), Object.class)); + return Utils.fromJson(res.body(), Object.class); } } @@ -85,19 +78,14 @@ public Config(SignifyClient client) { /** * Retrieve the agent configuration - * @return Optional containing the config if found, or empty if not found + * @return The agent configuration * @throws Exception if the fetch operation fails */ - public Optional get() throws Exception { + public Object get() throws Exception { String path = "/config"; String method = "GET"; HttpResponse res = this.client.fetch(path, method, null); - - if (res.statusCode() == HttpURLConnection.HTTP_NOT_FOUND) { - return Optional.empty(); - } - - return Optional.of(Utils.fromJson(res.body(), Object.class)); + return Utils.fromJson(res.body(), Object.class); } } } diff --git a/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java b/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java index 0c433c31..3940af39 100644 --- a/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java +++ b/src/test/java/org/cardanofoundation/signify/e2e/RandyTest.java @@ -90,7 +90,7 @@ void randyTest() throws Exception { Coring.KeyEvents events = client1.keyEvents(); - List> logList = (List>) events.get(opResponsePrefix).orElseThrow(); + List> logList = (List>) events.get(opResponsePrefix); assertEquals(2, logList.size()); icpResult = client1.identifiers().rotate("aid1"); @@ -111,7 +111,7 @@ void randyTest() throws Exception { rot.getVerfers().getFirst().getQb64b()); assertEquals(dig.getQb64(), icp.getDigers().getFirst().getQb64()); - logList = (List>) events.get(opResponsePrefix).orElseThrow(); + logList = (List>) events.get(opResponsePrefix); assertEquals(3, logList.size()); assertOperations(Collections.singletonList(client1)); } diff --git a/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java b/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java index 93b34a2f..7c5ca67f 100644 --- a/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java +++ b/src/test/java/org/cardanofoundation/signify/e2e/SaltyTests.java @@ -176,7 +176,7 @@ void saltyTest() throws Exception { // KeyEvents Coring.KeyEvents events = client.keyEvents(); - List> log = (List>) events.get((String) aidLast.get("prefix")).orElseThrow(); + List> log = (List>) events.get((String) aidLast.get("prefix")); assertEquals(3, log.size()); Serder serder = new Serder((Map) log.getFirst().get("ked"));