From 3032580fd4e2335d594c100cce4bda6fea2dbe70 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Wed, 15 Apr 2020 17:57:28 +0200 Subject: [PATCH] [jOOQ/jOOQ#10072] Out of the box support mapping between XML and POJOs using JAXB --- .../jooq/impl/DefaultConverterProvider.java | 16 ++++++-- .../src/main/java/org/jooq/tools/Convert.java | 39 ++++++++++++++++++- 2 files changed, 50 insertions(+), 5 deletions(-) diff --git a/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java b/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java index f751fcc374..de6fea438c 100644 --- a/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java +++ b/jOOQ/src/main/java/org/jooq/impl/DefaultConverterProvider.java @@ -58,6 +58,7 @@ import org.jooq.JSON; import org.jooq.JSONB; import org.jooq.Record; import org.jooq.UDTRecord; +import org.jooq.XML; import org.jooq.tools.Convert; /** @@ -95,7 +96,13 @@ public final class DefaultConverterProvider implements ConverterProvider { || isDate(tWrapper) && isDate(uWrapper) || isEnum(tWrapper) && isEnum(uWrapper) || isUUID(tWrapper) && isUUID(uWrapper) - || isJSON(tWrapper) // && isJSON(uWrapper) + + // [#10072] out of the box JSON binding is supported via Jackson or Gson + || isJSON(tWrapper) + + // [#10072] out of the box XML binding is supported via JAXB + || isXML(tWrapper) + || Record.class.isAssignableFrom(tWrapper) || Struct.class.isAssignableFrom(tWrapper) && UDTRecord.class.isAssignableFrom(uWrapper) ) { @@ -133,8 +140,11 @@ public final class DefaultConverterProvider implements ConverterProvider { private final boolean isJSON(Class type) { return type == JSON.class - || type == JSONB.class - || type == String.class; + || type == JSONB.class; + } + + private final boolean isXML(Class type) { + return type == XML.class; } private final boolean isUUID(Class type) { diff --git a/jOOQ/src/main/java/org/jooq/tools/Convert.java b/jOOQ/src/main/java/org/jooq/tools/Convert.java index 19453d5a2e..15b60652d8 100644 --- a/jOOQ/src/main/java/org/jooq/tools/Convert.java +++ b/jOOQ/src/main/java/org/jooq/tools/Convert.java @@ -47,6 +47,8 @@ import static org.jooq.types.Unsigned.ulong; import static org.jooq.types.Unsigned.ushort; import java.io.File; +import java.io.StringReader; +import java.io.StringWriter; import java.lang.reflect.Array; import java.lang.reflect.Method; import java.math.BigDecimal; @@ -80,6 +82,8 @@ import java.util.Set; import java.util.UUID; import java.util.regex.Pattern; +import javax.xml.bind.JAXB; + // ... import org.jooq.Converter; import org.jooq.EnumType; @@ -89,6 +93,7 @@ import org.jooq.JSONB; import org.jooq.Record; import org.jooq.SQLDialect; import org.jooq.UDTRecord; +import org.jooq.XML; import org.jooq.exception.DataTypeException; import org.jooq.tools.jdbc.MockArray; import org.jooq.tools.reflect.Reflect; @@ -96,6 +101,7 @@ import org.jooq.types.UByte; import org.jooq.types.UInteger; import org.jooq.types.ULong; import org.jooq.types.UShort; +import org.jooq.util.xml.jaxb.InformationSchema; /** * Utility methods for type conversions @@ -137,6 +143,11 @@ public final class Convert { */ private static final Method JSON_READ_METHOD; + /** + * Whether a JAXB implementation is available. + */ + private static final boolean JAXB_AVAILABLE; + static { Set trueValues = new HashSet<>(); Set falseValues = new HashSet<>(); @@ -176,29 +187,43 @@ public final class Convert { Object jsonMapper = null; Method jsonReadMethod = null; + boolean jaxbAvailable = false; try { Class klass = Class.forName("com.fasterxml.jackson.databind.ObjectMapper"); jsonMapper = klass.getConstructor().newInstance(); jsonReadMethod = klass.getMethod("readValue", String.class, Class.class); + log.debug("Jackson is available"); } catch (Exception e1) { - log.debug("Jackson not found on the classpath"); + log.debug("Jackson not available", e1.getMessage()); try { Class klass = Class.forName("com.google.gson.Gson"); jsonMapper = klass.getConstructor().newInstance(); jsonReadMethod = klass.getMethod("fromJson", String.class, Class.class); + log.debug("Gson is available"); } catch (Exception e2) { - log.debug("Gson not found on the classpath"); + log.debug("Gson not available", e2.getMessage()); } } JSON_MAPPER = jsonMapper; JSON_READ_METHOD = jsonReadMethod; + + try { + JAXB.marshal(new InformationSchema(), new StringWriter()); + jaxbAvailable = true; + log.debug("JAXB is available"); + } + catch (Exception e) { + log.debug("JAXB not available", e.getMessage()); + } + + JAXB_AVAILABLE = jaxbAvailable; } /** @@ -1078,6 +1103,16 @@ public final class Convert { } } + // [#10072] Out of the box JAXB mapping support + else if (fromClass == XML.class && JAXB_AVAILABLE) { + try { + return JAXB.unmarshal(new StringReader(((XML) from).data()), toClass); + } + catch (Exception e) { + throw new DataTypeException("Error while mapping XML to POJO using JAXB", e); + } + } + // [#3023] Record types can be converted using the supplied Configuration's // RecordMapperProvider else if (Record.class.isAssignableFrom(fromClass)) {