diff --git a/composites/ebean/pom.xml b/composites/ebean/pom.xml
index d6ef2cb13..57f45f13b 100644
--- a/composites/ebean/pom.xml
+++ b/composites/ebean/pom.xml
@@ -37,6 +37,12 @@
13.9.3-SNAPSHOT
+
+ io.ebean
+ ebean-jackson-mapper
+ 13.9.3-SNAPSHOT
+
+
io.ebean
ebean-datasource
diff --git a/ebean-bom/pom.xml b/ebean-bom/pom.xml
index eb1e958e3..46e47c2c7 100644
--- a/ebean-bom/pom.xml
+++ b/ebean-bom/pom.xml
@@ -122,6 +122,12 @@
13.9.3-SNAPSHOT
+
+ io.ebean
+ ebean-jackson-mapper
+ 13.9.3-SNAPSHOT
+
+
io.ebean
ebean-ddl-generator
diff --git a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarJsonMapper.java b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarJsonMapper.java
index de38bd942..2cbd964a4 100644
--- a/ebean-core-type/src/main/java/io/ebean/core/type/ScalarJsonMapper.java
+++ b/ebean-core-type/src/main/java/io/ebean/core/type/ScalarJsonMapper.java
@@ -1,4 +1,13 @@
package io.ebean.core.type;
+/**
+ * Supports JSON bean properties that use something like Jackson ObjectMapper to convert between
+ * JSON content and the logical bean property value.
+ */
public interface ScalarJsonMapper {
+
+ /**
+ * Return a ScalarType for the given JSON property.
+ */
+ ScalarType> createType(ScalarJsonRequest request);
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
index e4df81962..be3a25609 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/type/DefaultTypeManager.java
@@ -72,6 +72,7 @@ public final class DefaultTypeManager implements TypeManager {
private final PlatformArrayTypeFactory arrayTypeListFactory;
private final PlatformArrayTypeFactory arrayTypeSetFactory;
+ private final ScalarJsonMapper jsonMapper;
private GeoTypeBinder geoTypeBinder;
/**
@@ -94,6 +95,9 @@ public final class DefaultTypeManager implements TypeManager {
this.offlineMigrationGeneration = DbOffline.isGenerateMigration();
this.defaultEnumType = config.getDefaultEnumType();
+ ServiceLoader mappers = ServiceLoader.load(ScalarJsonMapper.class);
+ jsonMapper = mappers.findFirst().orElse(null);
+
initialiseStandard(config);
initialiseJavaTimeTypes(config);
loadTypesFromProviders(config, objectMapper);
@@ -377,14 +381,14 @@ public final class DefaultTypeManager implements TypeManager {
}
private ScalarType> createJsonObjectMapperType(DeployBeanProperty prop, int dbType, DocPropertyType docType) {
- if (objectMapper == null) {
+ if (jsonMapper == null) {
throw new IllegalArgumentException("Unsupported @DbJson mapping - Jackson ObjectMapper not present for " + prop);
}
if (MutationDetection.DEFAULT == prop.getMutationDetection()) {
prop.setMutationDetection(jsonManager.mutationDetection());
}
var req = new ScalarJsonRequest(jsonManager, dbType, docType, prop.getDesc().getBeanType(), prop.getMutationDetection(), prop.getName());
- return ScalarTypeJsonObjectMapper.createTypeFor(req);
+ return jsonMapper.createType(req);
}
/**
diff --git a/ebean-core/src/main/java/module-info.java b/ebean-core/src/main/java/module-info.java
index 58a3438c9..d09920dd5 100644
--- a/ebean-core/src/main/java/module-info.java
+++ b/ebean-core/src/main/java/module-info.java
@@ -9,6 +9,7 @@ module io.ebean.core {
uses io.ebean.datasource.DataSourceAlertFactory;
uses io.ebean.core.type.ExtraTypeFactory;
uses io.ebean.core.type.ScalarTypeSetFactory;
+ uses io.ebean.core.type.ScalarJsonMapper;
uses io.ebeanservice.docstore.api.DocStoreFactory;
uses io.ebean.migration.auto.AutoMigrationRunner;
uses io.avaje.classpath.scanner.ClassPathScannerFactory;
diff --git a/ebean-jackson-mapper/pom.xml b/ebean-jackson-mapper/pom.xml
new file mode 100644
index 000000000..9371f4a86
--- /dev/null
+++ b/ebean-jackson-mapper/pom.xml
@@ -0,0 +1,46 @@
+
+
+
+ ebean-parent
+ io.ebean
+ 13.9.3-SNAPSHOT
+
+ 4.0.0
+
+ ebean-jackson-mapper
+
+
+
+
+ io.ebean
+ ebean-core-type
+ 13.9.3-SNAPSHOT
+ provided
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+ ${jackson.version}
+ provided
+
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+ provided
+
+
+
+ io.avaje
+ junit
+ 1.1
+ test
+
+
+
+
+
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/DeployBeanObtainJackson.java b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/DeployBeanObtainJackson.java
similarity index 96%
rename from ebean-core/src/main/java/io/ebeaninternal/server/type/DeployBeanObtainJackson.java
rename to ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/DeployBeanObtainJackson.java
index 943422aa3..747d66394 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/DeployBeanObtainJackson.java
+++ b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/DeployBeanObtainJackson.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.type;
+package io.ebean.jackson.mapper;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/JacksonTypeHelper.java b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/JacksonTypeHelper.java
similarity index 97%
rename from ebean-core/src/main/java/io/ebeaninternal/server/type/JacksonTypeHelper.java
rename to ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/JacksonTypeHelper.java
index 7d2d5b3e1..11f8cc0a8 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/JacksonTypeHelper.java
+++ b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/JacksonTypeHelper.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.type;
+package io.ebean.jackson.mapper;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.introspect.AnnotatedField;
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/JsonTrim.java b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/JsonTrim.java
similarity index 95%
rename from ebean-core/src/main/java/io/ebeaninternal/server/type/JsonTrim.java
rename to ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/JsonTrim.java
index ec0808f14..855978681 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/JsonTrim.java
+++ b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/JsonTrim.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.type;
+package io.ebean.jackson.mapper;
/**
* Helper that removes whitespace from JSON. Used to normalise Postgres JSONB content.
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java
similarity index 94%
rename from ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java
rename to ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java
index 86f5d9c82..9193d86d2 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/type/ScalarTypeJsonObjectMapper.java
+++ b/ebean-jackson-mapper/src/main/java/io/ebean/jackson/mapper/ScalarJsonJacksonMapper.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.type;
+package io.ebean.jackson.mapper;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
@@ -24,14 +24,15 @@ import java.util.concurrent.ConcurrentHashMap;
/**
* Supports @DbJson properties using Jackson ObjectMapper.
*/
-final class ScalarTypeJsonObjectMapper {
+public final class ScalarJsonJacksonMapper implements ScalarJsonMapper {
- static final Map, AnnotatedClass> jacksonClasses = new ConcurrentHashMap<>();
+ private final Map, AnnotatedClass> jacksonClasses = new ConcurrentHashMap<>();
/**
* Create and return the appropriate ScalarType.
*/
- static ScalarType> createTypeFor(ScalarJsonRequest req) {
+ @Override
+ public ScalarType> createType(ScalarJsonRequest req) {
AnnotatedClass annotatedClass = annotatedClass(req);
AnnotatedField field = annotatedField(annotatedClass, req);
if (req.mode() == MutationDetection.NONE) {
@@ -41,7 +42,7 @@ final class ScalarTypeJsonObjectMapper {
}
}
- private static AnnotatedField annotatedField(AnnotatedClass annotatedClass, ScalarJsonRequest req) {
+ private AnnotatedField annotatedField(AnnotatedClass annotatedClass, ScalarJsonRequest req) {
for (AnnotatedField field : annotatedClass.fields()) {
if (field.getName().equals(req.name())) {
return field;
@@ -50,7 +51,7 @@ final class ScalarTypeJsonObjectMapper {
throw new IllegalStateException("AnnotatedField not found to match " + req.name());
}
- private static AnnotatedClass annotatedClass(ScalarJsonRequest req) {
+ private AnnotatedClass annotatedClass(ScalarJsonRequest req) {
return jacksonClasses.computeIfAbsent(req.beanType(), key -> {
ObjectMapper mapper = (ObjectMapper) req.manager().mapper();
return new DeployBeanObtainJackson(mapper, req.beanType()).obtain();
diff --git a/ebean-jackson-mapper/src/main/java/module-info.java b/ebean-jackson-mapper/src/main/java/module-info.java
new file mode 100644
index 000000000..f43b84144
--- /dev/null
+++ b/ebean-jackson-mapper/src/main/java/module-info.java
@@ -0,0 +1,9 @@
+import io.ebean.jackson.mapper.ScalarJsonJacksonMapper;
+
+module io.ebean.jackson.mapper {
+ requires io.ebean.core.type;
+ requires com.fasterxml.jackson.core;
+ requires com.fasterxml.jackson.databind;
+
+ provides io.ebean.core.type.ScalarJsonMapper with ScalarJsonJacksonMapper;
+}
diff --git a/ebean-jackson-mapper/src/main/resources/META-INF/services/io.ebean.core.type.ScalarJsonMapper b/ebean-jackson-mapper/src/main/resources/META-INF/services/io.ebean.core.type.ScalarJsonMapper
new file mode 100644
index 000000000..e85a66aaa
--- /dev/null
+++ b/ebean-jackson-mapper/src/main/resources/META-INF/services/io.ebean.core.type.ScalarJsonMapper
@@ -0,0 +1 @@
+io.ebean.jackson.mapper.ScalarJsonJacksonMapper
diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/type/JsonTrimTest.java b/ebean-jackson-mapper/src/test/java/io/ebean/jackson/mapper/JsonTrimTest.java
similarity index 98%
rename from ebean-core/src/test/java/io/ebeaninternal/server/type/JsonTrimTest.java
rename to ebean-jackson-mapper/src/test/java/io/ebean/jackson/mapper/JsonTrimTest.java
index 27d1ad8f9..f5b78b147 100644
--- a/ebean-core/src/test/java/io/ebeaninternal/server/type/JsonTrimTest.java
+++ b/ebean-jackson-mapper/src/test/java/io/ebean/jackson/mapper/JsonTrimTest.java
@@ -1,4 +1,4 @@
-package io.ebeaninternal.server.type;
+package io.ebean.jackson.mapper;
import org.junit.jupiter.api.Test;
diff --git a/ebean-test/pom.xml b/ebean-test/pom.xml
index 4a71e45cf..ea8996a56 100644
--- a/ebean-test/pom.xml
+++ b/ebean-test/pom.xml
@@ -116,6 +116,13 @@
test
+
+ io.ebean
+ ebean-jackson-mapper
+ 13.9.3-SNAPSHOT
+ test
+
+
io.ebean
ebean-platform-all
diff --git a/pom.xml b/pom.xml
index de0c4f3b7..d1217fb8d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -92,6 +92,7 @@
ebean-joda-time
ebean-csv-reader
ebean-jackson-jsonnode
+ ebean-jackson-mapper