From 0d6b588dba5b92ee0feaa07113c52eb8953bbbab Mon Sep 17 00:00:00 2001 From: Tatu Saloranta Date: Fri, 10 Jan 2025 20:25:03 -0800 Subject: [PATCH] Improve dynamic handling of java.sql type handlers --- .../ext/sql/JavaSqlBlobSerializer.java | 2 + .../ext/sql/JavaSqlDateDeserializer.java | 2 + .../ext/sql/JavaSqlDateSerializer.java | 2 + .../ext/sql/JavaSqlTimeSerializer.java | 2 + .../ext/sql/JavaSqlTimestampDeserializer.java | 2 + .../ext/sql/JavaSqlTypeHandlerFactory.java | 105 +++++------------- 6 files changed, 36 insertions(+), 79 deletions(-) diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlBlobSerializer.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlBlobSerializer.java index db39394369..9add7dd47e 100644 --- a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlBlobSerializer.java +++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlBlobSerializer.java @@ -27,6 +27,8 @@ public class JavaSqlBlobSerializer extends StdScalarSerializer { + public final static JavaSqlBlobSerializer instance = new JavaSqlBlobSerializer(); + public JavaSqlBlobSerializer() { super(Blob.class); } diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateDeserializer.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateDeserializer.java index 53ad6c538b..6ffd5dc0a1 100644 --- a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateDeserializer.java +++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateDeserializer.java @@ -15,6 +15,8 @@ public class JavaSqlDateDeserializer extends DateBasedDeserializer { + public final static JavaSqlDateDeserializer instance = new JavaSqlDateDeserializer(); + public JavaSqlDateDeserializer() { super(java.sql.Date.class); } public JavaSqlDateDeserializer(JavaSqlDateDeserializer src, DateFormat df, String formatString) { super(src, df, formatString); diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateSerializer.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateSerializer.java index 7fcede569d..c6d1175552 100644 --- a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateSerializer.java +++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlDateSerializer.java @@ -19,6 +19,8 @@ public class JavaSqlDateSerializer extends DateTimeSerializerBase { + public static final JavaSqlDateSerializer instance = new JavaSqlDateSerializer(); + public JavaSqlDateSerializer() { // 11-Oct-2016, tatu: As per [databind#219] fixed for 2.9; was passing `false` prior this(null, null); diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimeSerializer.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimeSerializer.java index dceb9ec8a0..c514c023bb 100644 --- a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimeSerializer.java +++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimeSerializer.java @@ -16,6 +16,8 @@ public class JavaSqlTimeSerializer extends StdScalarSerializer { + public final static JavaSqlTimeSerializer instance = new JavaSqlTimeSerializer(); + public JavaSqlTimeSerializer() { super(java.sql.Time.class); } @Override diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimestampDeserializer.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimestampDeserializer.java index c80bf106cf..f5fca71998 100644 --- a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimestampDeserializer.java +++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTimestampDeserializer.java @@ -17,6 +17,8 @@ */ public class JavaSqlTimestampDeserializer extends DateBasedDeserializer { + public final static JavaSqlTimestampDeserializer instance = new JavaSqlTimestampDeserializer(); + public JavaSqlTimestampDeserializer() { super(java.sql.Timestamp.class); } public JavaSqlTimestampDeserializer(JavaSqlTimestampDeserializer src, DateFormat df, String formatString) { super(src, df, formatString); diff --git a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java index 0796ba6a19..0ff00bf091 100644 --- a/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java +++ b/src/main/java/tools/jackson/databind/ext/sql/JavaSqlTypeHandlerFactory.java @@ -1,11 +1,7 @@ package tools.jackson.databind.ext.sql; -import java.util.HashMap; -import java.util.Map; - import tools.jackson.databind.*; import tools.jackson.databind.ser.jdk.JavaUtilDateSerializer; -import tools.jackson.databind.util.ClassUtil; /** * Helper class used for isolating details of handling optional+external types @@ -15,42 +11,13 @@ public class JavaSqlTypeHandlerFactory { public final static JavaSqlTypeHandlerFactory instance = new JavaSqlTypeHandlerFactory(); - // classes from java.sql module, this module may or may not be present at runtime - // (is included on Java 8, but not part of JDK core for Java 9 and beyond) - private final Map _sqlDeserializers; - private final Map _sqlSerializers; - private final static String CLS_NAME_JAVA_SQL_TIMESTAMP = "java.sql.Timestamp"; private final static String CLS_NAME_JAVA_SQL_DATE = "java.sql.Date"; private final static String CLS_NAME_JAVA_SQL_TIME = "java.sql.Time"; private final static String CLS_NAME_JAVA_SQL_BLOB = "java.sql.Blob"; private final static String CLS_NAME_JAVA_SQL_SERIALBLOB = "javax.sql.rowset.serial.SerialBlob"; - protected JavaSqlTypeHandlerFactory() { - _sqlDeserializers = new HashMap<>(); - _sqlDeserializers.put(CLS_NAME_JAVA_SQL_DATE, - "tools.jackson.databind.ext.sql.JavaSqlDateDeserializer"); - _sqlDeserializers.put(CLS_NAME_JAVA_SQL_TIMESTAMP, - "tools.jackson.databind.ext.sql.JavaSqlTimestampDeserializer"); - // 09-Nov-2020, tatu: No deserializer for `java.sql.Blob` yet; would require additional - // dependency and not yet requested by anyone. Add if requested - - _sqlSerializers = new HashMap<>(); - // 09-Jan-2015, tatu: As per [databind#1073], let's try to guard against possibility - // of some environments missing `java.sql.` types - - // note: timestamps are very similar to java.util.Date, thus serialized as such - _sqlSerializers.put(CLS_NAME_JAVA_SQL_TIMESTAMP, JavaUtilDateSerializer.instance); - _sqlSerializers.put(CLS_NAME_JAVA_SQL_DATE, "tools.jackson.databind.ext.sql.JavaSqlDateSerializer"); - _sqlSerializers.put(CLS_NAME_JAVA_SQL_TIME, "tools.jackson.databind.ext.sql.JavaSqlTimeSerializer"); - - // 09-Nov-2020, tatu: Not really optimal way to deal with these, problem being that - // Blob is interface and actual instance we get is usually different. So may - // need to improve if we reported bugs. But for now, do this - - _sqlSerializers.put(CLS_NAME_JAVA_SQL_BLOB, "tools.jackson.databind.ext.sql.JavaSqlBlobSerializer"); - _sqlSerializers.put(CLS_NAME_JAVA_SQL_SERIALBLOB, "tools.jackson.databind.ext.sql.JavaSqlBlobSerializer"); - } + protected JavaSqlTypeHandlerFactory() { } /* /********************************************************************** @@ -60,64 +27,44 @@ protected JavaSqlTypeHandlerFactory() { public ValueSerializer findSerializer(SerializationConfig config, JavaType type) { - final Class rawType = type.getRawClass(); + switch (type.getRawClass().getName()) { + case CLS_NAME_JAVA_SQL_TIMESTAMP: + return JavaUtilDateSerializer.instance; + case CLS_NAME_JAVA_SQL_DATE: + return JavaSqlDateSerializer.instance; + case CLS_NAME_JAVA_SQL_TIME: + return JavaSqlTimeSerializer.instance; - String className = rawType.getName(); - Object sqlHandler = _sqlSerializers.get(className); + // 09-Nov-2020, tatu: Not really optimal way to deal with these, problem being that + // Blob is interface and actual instance we get is usually different. So may + // need to improve if we reported bugs. But for now, do this - if (sqlHandler != null) { - if (sqlHandler instanceof ValueSerializer) { - return (ValueSerializer) sqlHandler; - } - // must be class name otherwise - return (ValueSerializer) instantiate((String) sqlHandler, type); + case CLS_NAME_JAVA_SQL_BLOB: + return JavaSqlBlobSerializer.instance; + case CLS_NAME_JAVA_SQL_SERIALBLOB: + return JavaSqlBlobSerializer.instance; } + return null; } public ValueDeserializer findDeserializer(DeserializationConfig config, JavaType type) { - final Class rawType = type.getRawClass(); - String className = rawType.getName(); - final String deserName = _sqlDeserializers.get(className); - if (deserName != null) { - return (ValueDeserializer) instantiate(deserName, type); + switch (type.getRawClass().getName()) { + case CLS_NAME_JAVA_SQL_DATE: + return JavaSqlDateDeserializer.instance; + case CLS_NAME_JAVA_SQL_TIMESTAMP: + return JavaSqlTimestampDeserializer.instance; } return null; } public boolean hasDeserializerFor(Class valueType) { - String className = valueType.getName(); - - // 06-Nov-2020, tatu: One of "java.sql" types? - return _sqlDeserializers.containsKey(className); - } - - /* - /********************************************************************** - /* Internal helper methods - /********************************************************************** - */ - - private Object instantiate(String className, JavaType valueType) - { - try { - return instantiate(Class.forName(className), valueType); - } catch (Exception e) { - throw new IllegalStateException("Failed to find class `" -+className+"` for handling values of type "+ClassUtil.getTypeDescription(valueType) -+", problem: ("+e.getClass().getName()+") "+e.getMessage()); - } - } - - private Object instantiate(Class handlerClass, JavaType valueType) - { - try { - return ClassUtil.createInstance(handlerClass, false); - } catch (Exception e) { - throw new IllegalStateException("Failed to create instance of `" -+handlerClass.getName()+"` for handling values of type "+ClassUtil.getTypeDescription(valueType) -+", problem: ("+e.getClass().getName()+") "+e.getMessage()); + switch (valueType.getName()) { + case CLS_NAME_JAVA_SQL_DATE: + case CLS_NAME_JAVA_SQL_TIMESTAMP: + return true; } + return false; } }