From 613e1641644ec597f888b17eb0fba1df148fd5aa Mon Sep 17 00:00:00 2001 From: Phillip Kruger Date: Fri, 1 Sep 2023 21:53:53 +1000 Subject: [PATCH] Fix DevUI fix serialization error on Throwable Signed-off-by: Phillip Kruger --- .../ByteArrayInputStreamDeserializer.java | 27 +++++++++++++++++++ .../ByteArrayInputStreamSerializer.java | 21 +++++++++++++++ .../jsonrpc/DevUIDatabindCodec.java | 3 +++ .../menu/ContinuousTestingProcessor.java | 9 +------ .../testrunner/TestRunnerSmokeTestCase.java | 27 +++++++++---------- .../ContinuousTestingJsonRPCService.java | 10 +++---- 6 files changed, 70 insertions(+), 27 deletions(-) create mode 100644 extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamDeserializer.java create mode 100644 extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamSerializer.java diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamDeserializer.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamDeserializer.java new file mode 100644 index 0000000000000..49c8509bdde59 --- /dev/null +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamDeserializer.java @@ -0,0 +1,27 @@ +package io.quarkus.devui.deployment.jsonrpc; + +import static io.quarkus.vertx.runtime.jackson.JsonUtil.BASE64_DECODER; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; + +public class ByteArrayInputStreamDeserializer extends JsonDeserializer { + + @Override + public ByteArrayInputStream deserialize(JsonParser p, DeserializationContext ctxt) + throws IOException, JsonProcessingException { + String text = p.getText(); + try { + byte[] decode = BASE64_DECODER.decode(text); + return new ByteArrayInputStream(decode); + } catch (IllegalArgumentException e) { + throw new InvalidFormatException(p, "Expected a base64 encoded byte array", text, ByteArrayInputStream.class); + } + } +} diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamSerializer.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamSerializer.java new file mode 100644 index 0000000000000..c9321eb745455 --- /dev/null +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/ByteArrayInputStreamSerializer.java @@ -0,0 +1,21 @@ +package io.quarkus.devui.deployment.jsonrpc; + +import static io.quarkus.vertx.runtime.jackson.JsonUtil.BASE64_ENCODER; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import io.quarkus.deployment.util.IoUtil; + +public class ByteArrayInputStreamSerializer extends JsonSerializer { + + @Override + public void serialize(ByteArrayInputStream value, JsonGenerator jgen, SerializerProvider provider) throws IOException { + byte[] readBytes = IoUtil.readBytes(value); + jgen.writeString(BASE64_ENCODER.encodeToString(readBytes)); + } +} diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/DevUIDatabindCodec.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/DevUIDatabindCodec.java index b9b8af66a9d74..877c25a895a90 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/DevUIDatabindCodec.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/jsonrpc/DevUIDatabindCodec.java @@ -1,5 +1,6 @@ package io.quarkus.devui.deployment.jsonrpc; +import java.io.ByteArrayInputStream; import java.io.Closeable; import java.io.IOException; import java.time.Instant; @@ -137,6 +138,8 @@ public JsonMapper create(JsonTypeAdapter> jsonObjectAdapt module.addDeserializer(Instant.class, new InstantDeserializer()); module.addSerializer(byte[].class, new ByteArraySerializer()); module.addDeserializer(byte[].class, new ByteArrayDeserializer()); + module.addSerializer(ByteArrayInputStream.class, new ByteArrayInputStreamSerializer()); + module.addDeserializer(ByteArrayInputStream.class, new ByteArrayInputStreamDeserializer()); mapper.registerModule(module); SimpleModule runtimeModule = new SimpleModule("vertx-module-runtime"); diff --git a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ContinuousTestingProcessor.java b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ContinuousTestingProcessor.java index 48a8fa798fd12..d9c4fd83d582a 100644 --- a/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ContinuousTestingProcessor.java +++ b/extensions/vertx-http/deployment/src/main/java/io/quarkus/devui/deployment/menu/ContinuousTestingProcessor.java @@ -1,13 +1,10 @@ package io.quarkus.devui.deployment.menu; import java.io.IOException; -import java.io.StringWriter; import java.util.HashMap; import java.util.Map; import java.util.Optional; -import com.fasterxml.jackson.databind.ObjectMapper; - import io.quarkus.arc.deployment.BeanContainerBuildItem; import io.quarkus.deployment.IsDevelopment; import io.quarkus.deployment.annotations.BuildStep; @@ -233,7 +230,6 @@ private void registerGetStatusMethod(LaunchModeBuildItem launchModeBuildItem) { private void registerGetResultsMethod(LaunchModeBuildItem launchModeBuildItem) { DevConsoleManager.register(NAMESPACE + DASH + "getResults", ignored -> { - ObjectMapper objectMapper = new ObjectMapper(); // Remove in favior of build in. try { Optional ts = TestSupport.instance(); if (testsDisabled(launchModeBuildItem, ts)) { @@ -246,10 +242,7 @@ private void registerGetResultsMethod(LaunchModeBuildItem launchModeBuildItem) { return null; } - try (StringWriter sw = new StringWriter()) { - objectMapper.writeValue(sw, testRunResults); - return sw.toString(); - } + return testRunResults; } catch (Exception e) { throw new RuntimeException(e); diff --git a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/TestRunnerSmokeTestCase.java b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/TestRunnerSmokeTestCase.java index 2a248f7ecea50..42ce03667c735 100644 --- a/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/TestRunnerSmokeTestCase.java +++ b/extensions/vertx-http/deployment/src/test/java/io/quarkus/vertx/http/testrunner/TestRunnerSmokeTestCase.java @@ -1,6 +1,6 @@ package io.quarkus.vertx.http.testrunner; -import java.util.List; +import java.util.Iterator; import java.util.Map; import java.util.function.Function; import java.util.function.Supplier; @@ -56,22 +56,21 @@ public void checkTestsAreRun() throws InterruptedException, Exception { Assertions.assertEquals(1L, ts.getTotalTestsPassed()); Assertions.assertEquals(0L, ts.getTotalTestsSkipped()); - JsonNode jsonRPCResultString = super.executeJsonRPCMethod("getResults"); - Assertions.assertNotNull(jsonRPCResultString); + JsonNode jsonRPCResult = super.executeJsonRPCMethod("getResults"); + Assertions.assertNotNull(jsonRPCResult); + Assertions.assertTrue(jsonRPCResult.has("results")); - @SuppressWarnings("unchecked") - Map> jsonRPCResult = mapper.readValue(jsonRPCResultString.textValue(), Map.class); + JsonNode results = jsonRPCResult.get("results"); + Assertions.assertNotNull(results); - Assertions.assertTrue(jsonRPCResult.containsKey("results")); + Iterator> fields = results.fields(); - Map results = jsonRPCResult.get("results"); - Assertions.assertNotNull(results); - for (Map.Entry result : results.entrySet()) { - @SuppressWarnings("unchecked") - Map testResult = result.getValue(); - String className = (String) testResult.get("className"); - List passing = (List) testResult.get("passing"); - List failing = (List) testResult.get("failing"); + while (fields.hasNext()) { + JsonNode testResult = fields.next().getValue(); + String className = testResult.get("className").asText(); + + JsonNode passing = testResult.get("passing"); + JsonNode failing = testResult.get("failing"); if (className.equals(SimpleET.class.getName())) { Assertions.assertEquals(1, failing.size(), className); diff --git a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/continuoustesting/ContinuousTestingJsonRPCService.java b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/continuoustesting/ContinuousTestingJsonRPCService.java index 932c71ba61226..1700e58105032 100644 --- a/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/continuoustesting/ContinuousTestingJsonRPCService.java +++ b/extensions/vertx-http/runtime/src/main/java/io/quarkus/devui/runtime/continuoustesting/ContinuousTestingJsonRPCService.java @@ -16,10 +16,10 @@ public class ContinuousTestingJsonRPCService implements Consumer { private final BroadcastProcessor stateBroadcaster = BroadcastProcessor.create(); - private final BroadcastProcessor resultBroadcaster = BroadcastProcessor.create(); + private final BroadcastProcessor resultBroadcaster = BroadcastProcessor.create(); private String lastKnownState = ""; - private String lastKnownResults = ""; + private Object lastKnownResults = ""; @Override public void accept(ContinuousTestingSharedStateManager.State state) { @@ -46,7 +46,7 @@ public Multi streamTestState() { return stateBroadcaster; } - public Multi streamTestResults() { + public Multi streamTestResults() { return resultBroadcaster; } @@ -56,7 +56,7 @@ public String lastKnownState() { } @NonBlocking - public String lastKnownResults() { + public Object lastKnownResults() { return this.lastKnownResults; } @@ -89,7 +89,7 @@ public boolean toggleInstrumentation() { return invokeAction("toggleInstrumentation"); } - public String getResults() { + public Object getResults() { return invokeAction("getResults"); }