You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/08/04 14:53:24 UTC
[camel] branch camel-3.18.x updated: CAMEL-18345: camel-jacksonxml - Allow to enable/disable more features via FromXmlParser.Feature enum. Thanks to Jose Bustamante for reporting.
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch camel-3.18.x
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/camel-3.18.x by this push:
new 427acea1104 CAMEL-18345: camel-jacksonxml - Allow to enable/disable more features via FromXmlParser.Feature enum. Thanks to Jose Bustamante for reporting.
427acea1104 is described below
commit 427acea11048ef112fe4959956eecbc165744254
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Aug 4 16:52:23 2022 +0200
CAMEL-18345: camel-jacksonxml - Allow to enable/disable more features via FromXmlParser.Feature enum. Thanks to Jose Bustamante for reporting.
---
.../src/main/docs/jacksonXml-dataformat.adoc | 9 ++-
.../component/jacksonxml/JacksonXMLDataFormat.java | 33 +++++++-
.../jacksonxml/JacksonEmptyElementsAsNullTest.java | 87 ++++++++++++++++++++++
3 files changed, 123 insertions(+), 6 deletions(-)
diff --git a/components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc b/components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc
index f44f8ca5d8a..69ffa156dba 100644
--- a/components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc
+++ b/components/camel-jacksonxml/src/main/docs/jacksonXml-dataformat.adoc
@@ -255,8 +255,8 @@ Multiple modules can be specified separated by comma, such as `moduleRefs="myJac
== Enabling or disable features using Jackson
-Jackson has a number of features you can enable or disable, which its
-ObjectMapper uses. For example to disable failing on unknown properties
+Jackson XML has a number of features you can enable or disable, which its
+XmlMapper uses. For example to disable failing on unknown properties
when marshalling, you can configure this using the disableFeatures:
[source,xml]
@@ -273,6 +273,7 @@ from the following enum classes:
* `com.fasterxml.jackson.databind.SerializationFeature`
* `com.fasterxml.jackson.databind.DeserializationFeature`
* `com.fasterxml.jackson.databind.MapperFeature`
+* `com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser.Feature`
To enable a feature use the enableFeatures options instead.
@@ -288,7 +289,7 @@ df.disableFeature(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
== Converting Maps to POJO using Jackson
-Jackson `ObjectMapper` can be used to convert maps to POJO objects.
+Jackson `XmlMapper` can be used to convert maps to POJO objects.
Jackson component comes with the data converter that can be used to
convert `java.util.Map` instance to non-String, non-primitive and
non-Number objects.
@@ -303,7 +304,7 @@ producerTemplate.sendBody("direct:mapToInvoice", invoiceData);
Invoice invoice = exchange.getIn().getBody(Invoice.class);
----------------------------------------------------------------
-If there is a single `ObjectMapper` instance available in the Camel
+If there is a single `XmlMapper` instance available in the Camel
registry, it will used by the converter to perform the conversion.
Otherwise the default mapper will be used.
diff --git a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java
index 683cdad5b7c..21f3e1629f5 100644
--- a/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java
+++ b/components/camel-jacksonxml/src/main/java/org/apache/camel/component/jacksonxml/JacksonXMLDataFormat.java
@@ -33,6 +33,7 @@ import com.fasterxml.jackson.databind.Module;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.CollectionType;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
+import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
import com.fasterxml.jackson.module.jaxb.JaxbAnnotationModule;
import org.apache.camel.CamelContext;
import org.apache.camel.CamelContextAware;
@@ -456,6 +457,14 @@ public class JacksonXMLDataFormat extends ServiceSupport
}
}
+ public void enableFeature(FromXmlParser.Feature feature) {
+ if (enableFeatures == null) {
+ enableFeatures = feature.name();
+ } else {
+ enableFeatures += "," + feature.name();
+ }
+ }
+
public void disableFeature(SerializationFeature feature) {
if (disableFeatures == null) {
disableFeatures = feature.name();
@@ -480,6 +489,14 @@ public class JacksonXMLDataFormat extends ServiceSupport
}
}
+ public void disableFeature(FromXmlParser.Feature feature) {
+ if (disableFeatures == null) {
+ disableFeatures = feature.name();
+ } else {
+ disableFeatures += "," + feature.name();
+ }
+ }
+
@Override
protected void doInit() throws Exception {
if (unmarshalTypeName != null && (unmarshalType == null || unmarshalType == HashMap.class)) {
@@ -540,9 +557,15 @@ public class JacksonXMLDataFormat extends ServiceSupport
xmlMapper.enable(mf);
continue;
}
+ FromXmlParser.Feature pf
+ = getCamelContext().getTypeConverter().tryConvertTo(FromXmlParser.Feature.class, enable);
+ if (pf != null) {
+ xmlMapper.enable(pf);
+ continue;
+ }
throw new IllegalArgumentException(
"Enable feature: " + enable
- + " cannot be converted to an accepted enum of types [SerializationFeature,DeserializationFeature,MapperFeature]");
+ + " cannot be converted to an accepted enum of types [SerializationFeature,DeserializationFeature,MapperFeature,FromXmlParser.Feature]");
}
}
if (disableFeatures != null) {
@@ -567,9 +590,15 @@ public class JacksonXMLDataFormat extends ServiceSupport
xmlMapper.disable(mf);
continue;
}
+ FromXmlParser.Feature pf
+ = getCamelContext().getTypeConverter().tryConvertTo(FromXmlParser.Feature.class, disable);
+ if (pf != null) {
+ xmlMapper.disable(pf);
+ continue;
+ }
throw new IllegalArgumentException(
"Disable feature: " + disable
- + " cannot be converted to an accepted enum of types [SerializationFeature,DeserializationFeature,MapperFeature]");
+ + " cannot be converted to an accepted enum of types [SerializationFeature,DeserializationFeature,MapperFeature,FromXmlParser.Feature]");
}
}
diff --git a/components/camel-jacksonxml/src/test/java/org/apache/camel/component/jacksonxml/JacksonEmptyElementsAsNullTest.java b/components/camel-jacksonxml/src/test/java/org/apache/camel/component/jacksonxml/JacksonEmptyElementsAsNullTest.java
new file mode 100644
index 00000000000..3d782f3e5d6
--- /dev/null
+++ b/components/camel-jacksonxml/src/test/java/org/apache/camel/component/jacksonxml/JacksonEmptyElementsAsNullTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.camel.component.jacksonxml;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.dataformat.xml.deser.FromXmlParser;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit5.CamelTestSupport;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class JacksonEmptyElementsAsNullTest extends CamelTestSupport {
+
+ @Test
+ public void testEmptyAsNull() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result");
+ mock.expectedMessageCount(4);
+
+ template.sendBody("direct:start", "<pojo><name>Jack</name></pojo>");
+ template.sendBody("direct:start", "<pojo><name></name></pojo>");
+ template.sendBody("direct:start", "<pojo><name/></pojo>");
+ template.sendBody("direct:start", "<pojo></pojo>");
+
+ assertMockEndpointsSatisfied();
+
+ Assertions.assertEquals("Jack", mock.getReceivedExchanges().get(0).getMessage().getBody(TestPojo.class).getName());
+ // <name></name> and <name/> are NOT the same as empty string vs null
+ Assertions.assertEquals("", mock.getReceivedExchanges().get(1).getMessage().getBody(TestPojo.class).getName());
+ Assertions.assertNull(mock.getReceivedExchanges().get(2).getMessage().getBody(TestPojo.class).getName());
+ Assertions.assertNull(mock.getReceivedExchanges().get(3).getMessage().getBody(TestPojo.class).getName());
+ }
+
+ @Test
+ public void testDefault() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:result2");
+ mock.expectedMessageCount(4);
+
+ template.sendBody("direct:start2", "<pojo><name>Jack</name></pojo>");
+ template.sendBody("direct:start2", "<pojo><name></name></pojo>");
+ template.sendBody("direct:start2", "<pojo><name/></pojo>");
+ template.sendBody("direct:start2", "<pojo></pojo>");
+
+ assertMockEndpointsSatisfied();
+
+ Assertions.assertEquals("Jack", mock.getReceivedExchanges().get(0).getMessage().getBody(TestPojo.class).getName());
+ // <name></name> and <name/> are both the same as an empty string
+ Assertions.assertEquals("", mock.getReceivedExchanges().get(1).getMessage().getBody(TestPojo.class).getName());
+ Assertions.assertEquals("", mock.getReceivedExchanges().get(2).getMessage().getBody(TestPojo.class).getName());
+ Assertions.assertNull(mock.getReceivedExchanges().get(3).getMessage().getBody(TestPojo.class).getName());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+
+ @Override
+ public void configure() {
+ context.setStreamCaching(false);
+
+ JacksonXMLDataFormat format = new JacksonXMLDataFormat(TestPojo.class);
+ format.enableFeature(FromXmlParser.Feature.EMPTY_ELEMENT_AS_NULL);
+ format.disableFeature(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ from("direct:start").unmarshal(format).to("mock:result");
+
+ JacksonXMLDataFormat format2 = new JacksonXMLDataFormat(TestPojo.class);
+ format.disableFeature(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ from("direct:start2").unmarshal(format2).to("mock:result2");
+ }
+ };
+ }
+
+}