diff --git a/console-framework-client/pom.xml b/console-framework-client/pom.xml
index ad2e573..bcbd53e 100644
--- a/console-framework-client/pom.xml
+++ b/console-framework-client/pom.xml
@@ -38,6 +38,27 @@
com.fasterxml.jackson.dataformat
jackson-dataformat-cbor
+ provided
+ true
+
+
+ com.fasterxml.jackson.module
+ jackson-module-kotlin
+
+
+ tools.jackson.core
+ jackson-databind
+ 3.1.0
+
+
+ tools.jackson.dataformat
+ jackson-dataformat-cbor
+ 3.1.0
+
+
+ tools.jackson.module
+ jackson-module-kotlin
+ 3.1.0
diff --git a/console-framework-client/src/main/java/io/axoniq/console/framework/AxoniqConsoleConfigurerModule.java b/console-framework-client/src/main/java/io/axoniq/console/framework/AxoniqConsoleConfigurerModule.java
index d08a125..716e74d 100644
--- a/console-framework-client/src/main/java/io/axoniq/console/framework/AxoniqConsoleConfigurerModule.java
+++ b/console-framework-client/src/main/java/io/axoniq/console/framework/AxoniqConsoleConfigurerModule.java
@@ -33,7 +33,8 @@
import io.axoniq.console.framework.client.RSocketHandlerRegistrar;
import io.axoniq.console.framework.client.ServerProcessorReporter;
import io.axoniq.console.framework.client.SetupPayloadCreator;
-import io.axoniq.console.framework.client.strategy.CborEncodingStrategy;
+import io.axoniq.console.framework.client.strategy.CborJackson2EncodingStrategy;
+import io.axoniq.console.framework.client.strategy.CborJackson3EncodingStrategy;
import io.axoniq.console.framework.client.strategy.RSocketPayloadEncodingStrategy;
import io.axoniq.console.framework.eventprocessor.DeadLetterManager;
import io.axoniq.console.framework.eventprocessor.EventProcessorManager;
@@ -176,7 +177,7 @@ public void configureModule(@NotNull Configurer configurer) {
)
)
.registerComponent(RSocketPayloadEncodingStrategy.class,
- c -> new CborEncodingStrategy()
+ c -> createJackson2Or3EncodingStrategy()
)
.registerComponent(RSocketHandlerRegistrar.class,
c -> new RSocketHandlerRegistrar(c.getComponent(RSocketPayloadEncodingStrategy.class))
@@ -313,6 +314,54 @@ public void configureModule(@NotNull Configurer configurer) {
new AxoniqConsoleEnhancingConfigurerModule(spanMatcherPredicateMap).configureModule(configurer);
}
+ /**
+ * Checks the classpath for Jackson 2 or Jackson 3 and its requirements for this application.
+ * Will fail to create the component if neither is there, or if one is present and doesn't have the right modules.
+ */
+ private static RSocketPayloadEncodingStrategy createJackson2Or3EncodingStrategy() {
+ try {
+ Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
+ try {
+ Class.forName(
+ "com.fasterxml.jackson.dataformat.cbor.databind.CBORMapper");
+ try {
+ Class.forName(
+ "com.fasterxml.jackson.module.kotlin.KotlinModule");
+ return new CborJackson2EncodingStrategy();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(
+ "Found Jackson 2 on the classpath, but can not find the KotlinModule. Please add the com.fasterxml.jackson.module:jackson-module-kotlin dependency to your project");
+ }
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(
+ "Found Jackson 2 on the classpath, but cannot find the CBOR dataformat. Please add the com.fasterxml.jackson.dataformat:jackson-dataformat-cbor dependency to your project.");
+ }
+ } catch (ClassNotFoundException e) {
+
+ }
+
+ try {
+ Class.forName("tools.jackson.databind.ObjectMapper");
+ try {
+ Class.forName("tools.jackson.dataformat.cbor.CBORMapper");
+ try {
+ Class.forName("tools.jackson.module.kotlin.KotlinModule");
+ return new CborJackson3EncodingStrategy();
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(
+ "Found Jackson 3 on the classpath, but can not find the KotlinModule. Please add the tools.jackson.module:jackson-module-kotlin dependency to your project");
+ }
+ } catch (ClassNotFoundException e) {
+ throw new IllegalArgumentException(
+ "Found Jackson 3 on the classpath, but cannot find the CBOR dataformat. Please add the tools.jackson.dataformat:jackson-dataformat-cbor dependency to your project.");
+ }
+ } catch (ClassNotFoundException e) {
+ // Do nothing, Jackson 3 is not on the classpath. Continue to check for 2
+ throw new IllegalArgumentException(
+ "Neither Jackson 2 nor 3 was found on the classpath. Please add either Jackson 2 or 3 to your project.");
+ }
+ }
+
/**
* Builder class to instantiate a {@link AxoniqConsoleConfigurerModule}.
*/
diff --git a/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborEncodingStrategy.kt b/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborJackson2EncodingStrategy.kt
similarity index 96%
rename from console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborEncodingStrategy.kt
rename to console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborJackson2EncodingStrategy.kt
index a19a47f..3c30225 100644
--- a/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborEncodingStrategy.kt
+++ b/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborJackson2EncodingStrategy.kt
@@ -25,7 +25,7 @@ import io.rsocket.Payload
import io.rsocket.metadata.WellKnownMimeType
import io.rsocket.util.DefaultPayload
-class CborEncodingStrategy : RSocketPayloadEncodingStrategy {
+class CborJackson2EncodingStrategy : RSocketPayloadEncodingStrategy {
private val mapper = CBORMapper.builder().build().findAndRegisterModules()
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
diff --git a/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborJackson3EncodingStrategy.kt b/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborJackson3EncodingStrategy.kt
new file mode 100644
index 0000000..a9950c2
--- /dev/null
+++ b/console-framework-client/src/main/java/io/axoniq/console/framework/client/strategy/CborJackson3EncodingStrategy.kt
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2022-2024. AxonIQ B.V.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package io.axoniq.console.framework.client.strategy
+
+import io.netty.buffer.ByteBuf
+import io.netty.buffer.ByteBufAllocator
+import io.netty.buffer.CompositeByteBuf
+import io.rsocket.Payload
+import io.rsocket.metadata.WellKnownMimeType
+import io.rsocket.util.DefaultPayload
+import tools.jackson.databind.DeserializationFeature
+import tools.jackson.dataformat.cbor.CBORMapper
+
+class CborJackson3EncodingStrategy : RSocketPayloadEncodingStrategy {
+ private val mapper = CBORMapper.builder()
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ .build()
+
+ override fun getMimeType(): WellKnownMimeType {
+ return WellKnownMimeType.APPLICATION_CBOR
+ }
+
+ override fun encode(payload: Any, metadata: ByteBuf?): Payload {
+ val payloadBuffer: CompositeByteBuf = ByteBufAllocator.DEFAULT.compositeBuffer()
+ payloadBuffer.writeBytes(mapper.writeValueAsBytes(payload))
+ return DefaultPayload.create(payloadBuffer, metadata)
+ }
+
+ override fun decode(payload: Payload, expectedType: Class): T {
+ if (expectedType == String::class.java) {
+ return payload.dataUtf8 as T
+ }
+
+ return mapper.readValue(payload.data.array(), expectedType)
+ }
+}
diff --git a/pom.xml b/pom.xml
index 8e945a2..158fc24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -54,8 +54,8 @@
axoniq
https://sonarcloud.io
- 1.9.25
- 1.9.20
+ 2.2.20
+ 2.0.0
4.6.7