This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push:
new 47c2b010a2d9 CAMEL-22857: REST binding keeps rejecting unknown
properties on Jackson 3 (#29559)
47c2b010a2d9 is described below
commit 47c2b010a2d9c709322b5bfa950315337956bde8
Author: James Netherton <[email protected]>
AuthorDate: Tue Nov 10 13:28:37 2026 +0000
CAMEL-22857: REST binding keeps rejecting unknown properties on Jackson 3
(#29559)
Jackson 3 turns FAIL_ON_UNKNOWN_PROPERTIES off by default, so with
camel-jackson3 the REST DSL binding accepted a request body with properties
its type does not have. Request bodies come from external callers, so the
binding enables the feature again when it reads them:
RestBindingAdviceFactory
for json.in and the camel-jackson3xml factory for xml.in. It is not added
when
enableFeatures/disableFeatures already names it, or when the data format has
a mapper of the user's own. Responses and the REST producer keep the
Jackson 3
default. The upgrade guide describes the behaviour and the opt-out.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
...nXMLRestBindingJacksonXmlDataFormatFactory.java | 21 ++++
...nXMLRestBindingFailOnUnknownPropertiesTest.java | 108 +++++++++++++++++++++
.../RestJettyPostJsonPojoOwnObjectMapperTest.java | 65 +++++++++++++
...ostJsonPojoUnknownPropertyOtherFeatureTest.java | 30 ++++++
.../RestJettyPostJsonPojoUnknownPropertyTest.java | 88 +++++++++++++++++
.../rest/RestUndertowHttpPojoTypeTest.java | 4 +-
.../processor/RestBindingAdviceFactory.java | 30 ++++++
.../ROOT/pages/camel-4x-upgrade-guide-4_24.adoc | 14 ++-
8 files changed, 352 insertions(+), 8 deletions(-)
diff --git
a/components/camel-jackson3xml/src/main/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingJacksonXmlDataFormatFactory.java
b/components/camel-jackson3xml/src/main/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingJacksonXmlDataFormatFactory.java
index 66723538c4b0..2830239ccb47 100644
---
a/components/camel-jackson3xml/src/main/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingJacksonXmlDataFormatFactory.java
+++
b/components/camel-jackson3xml/src/main/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingJacksonXmlDataFormatFactory.java
@@ -34,6 +34,8 @@ import org.apache.camel.support.PropertyBindingSupport;
@JdkService(RestBindingJacksonXmlDataFormatFactory.FACTORY)
public class JacksonXMLRestBindingJacksonXmlDataFormatFactory implements
RestBindingJacksonXmlDataFormatFactory {
+ private static final String FAIL_ON_UNKNOWN_PROPERTIES =
"FAIL_ON_UNKNOWN_PROPERTIES";
+
@Override
public void setupJacksonXml(
CamelContext camelContext, RestConfiguration config,
@@ -63,6 +65,7 @@ public class JacksonXMLRestBindingJacksonXmlDataFormatFactory
implements RestBin
setAdditionalConfiguration(config, "xml.in.", builder);
builder.bind();
+ failOnUnknownProperties(xml);
//
// OUT
@@ -83,6 +86,24 @@ public class
JacksonXMLRestBindingJacksonXmlDataFormatFactory implements RestBin
outBuilder.bind();
}
+ /**
+ * Jackson 3 accepts unknown properties by default, where Jackson 2
rejects them. REST binding keeps rejecting them
+ * in request bodies, as they come from external callers, unless the
feature or a mapper of your own is configured.
+ */
+ private static void failOnUnknownProperties(DataFormat dataFormat) {
+ if (dataFormat instanceof JacksonXMLDataFormat xml
+ && xml.getXmlMapper() == null
+ && !namesFailOnUnknownProperties(xml.getEnableFeatures())
+ && !namesFailOnUnknownProperties(xml.getDisableFeatures())) {
+ xml.setEnableFeatures(xml.getEnableFeatures() != null
+ ? xml.getEnableFeatures() + "," +
FAIL_ON_UNKNOWN_PROPERTIES : FAIL_ON_UNKNOWN_PROPERTIES);
+ }
+ }
+
+ private static boolean namesFailOnUnknownProperties(String features) {
+ return features != null &&
features.contains(FAIL_ON_UNKNOWN_PROPERTIES);
+ }
+
private static String getOutTypeName(String outType, Class<?>
outTypeClass, String typeName) {
String outTypeName = null;
if (outTypeClass != null) {
diff --git
a/components/camel-jackson3xml/src/test/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingFailOnUnknownPropertiesTest.java
b/components/camel-jackson3xml/src/test/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingFailOnUnknownPropertiesTest.java
new file mode 100644
index 000000000000..8915c4172335
--- /dev/null
+++
b/components/camel-jackson3xml/src/test/java/org/apache/camel/component/jackson3xml/JacksonXMLRestBindingFailOnUnknownPropertiesTest.java
@@ -0,0 +1,108 @@
+/*
+ * 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.jackson3xml;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.RestConfiguration;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import tools.jackson.databind.exc.UnrecognizedPropertyException;
+import tools.jackson.dataformat.xml.XmlMapper;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+/**
+ * REST binding rejects unknown properties with Jackson 3 too, whose default
is to accept them.
+ */
+public class JacksonXMLRestBindingFailOnUnknownPropertiesTest {
+
+ private static final String UNKNOWN =
"<TestPojo><name>Camel</name><donotexists>foo</donotexists></TestPojo>";
+
+ private CamelContext context;
+
+ @BeforeEach
+ public void createContext() {
+ context = new DefaultCamelContext();
+ context.start();
+ }
+
+ @AfterEach
+ public void stopContext() {
+ context.stop();
+ }
+
+ @Test
+ public void testUnknownPropertyIsRejected() throws Exception {
+ JacksonXMLDataFormat xml = setup(Map.of());
+
+ assertEquals("FAIL_ON_UNKNOWN_PROPERTIES", xml.getEnableFeatures());
+ assertThrows(UnrecognizedPropertyException.class, () -> unmarshal(xml,
UNKNOWN));
+ }
+
+ @Test
+ public void testOtherFeaturesKeepTheRejection() throws Exception {
+ JacksonXMLDataFormat xml = setup(Map.of("xml.in.enableFeatures",
"ACCEPT_SINGLE_VALUE_AS_ARRAY"));
+
+
assertEquals("ACCEPT_SINGLE_VALUE_AS_ARRAY,FAIL_ON_UNKNOWN_PROPERTIES",
xml.getEnableFeatures());
+ assertThrows(UnrecognizedPropertyException.class, () -> unmarshal(xml,
UNKNOWN));
+ }
+
+ @Test
+ public void testDisablingTheFeatureAcceptsUnknownProperties() throws
Exception {
+ JacksonXMLDataFormat xml = setup(Map.of("xml.in.disableFeatures",
"FAIL_ON_UNKNOWN_PROPERTIES"));
+
+ TestPojo pojo = (TestPojo) unmarshal(xml, UNKNOWN);
+ assertEquals("Camel", pojo.getName());
+ }
+
+ @Test
+ public void testOwnMapperKeepsItsSettings() throws Exception {
+ JacksonXMLDataFormat xml = setup(Map.of("xml.in.xmlMapper", new
XmlMapper()));
+
+ assertNull(xml.getEnableFeatures());
+ TestPojo pojo = (TestPojo) unmarshal(xml, UNKNOWN);
+ assertEquals("Camel", pojo.getName());
+ }
+
+ private JacksonXMLDataFormat setup(Map<String, Object> properties) throws
Exception {
+ RestConfiguration config = new RestConfiguration();
+ config.setDataFormatProperties(properties);
+
+ JacksonXMLDataFormat xml = new JacksonXMLDataFormat();
+ JacksonXMLDataFormat outXml = new JacksonXMLDataFormat();
+ new JacksonXMLRestBindingJacksonXmlDataFormatFactory()
+ .setupJacksonXml(context, config, null, TestPojo.class, null,
null, xml, outXml);
+ xml.setCamelContext(context);
+ xml.start();
+ return xml;
+ }
+
+ private static Object unmarshal(JacksonXMLDataFormat xml, String body)
throws Exception {
+ Exchange exchange = new DefaultExchange(xml.getCamelContext());
+ return xml.unmarshal(exchange, new
ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8)));
+ }
+}
diff --git
a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoOwnObjectMapperTest.java
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoOwnObjectMapperTest.java
new file mode 100644
index 000000000000..4ca1b5c8eda9
--- /dev/null
+++
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoOwnObjectMapperTest.java
@@ -0,0 +1,65 @@
+/*
+ * 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.jetty.rest;
+
+import org.apache.camel.BindToRegistry;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.jetty.BaseJettyTest;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.junit.jupiter.api.Test;
+import tools.jackson.databind.json.JsonMapper;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * REST binding keeps the settings of a mapper of your own, here one that
accepts unknown properties.
+ */
+public class RestJettyPostJsonPojoOwnObjectMapperTest extends BaseJettyTest {
+
+ @BindToRegistry("myMapper")
+ public JsonMapper myMapper() {
+ return JsonMapper.builder().build();
+ }
+
+ @Test
+ public void testUnknownPropertyIsAccepted() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:input");
+ mock.expectedMessageCount(1);
+ mock.message(0).body().isInstanceOf(UserPojo.class);
+
+ String body = "{\"id\": 123, \"name\": \"Donald Duck\",
\"donotexists\": \"foo\"}";
+ template.sendBody("http://localhost:" + getPort() + "/users/new",
body);
+
+ MockEndpoint.assertIsSatisfied(context);
+ UserPojo user =
mock.getReceivedExchanges().get(0).getIn().getBody(UserPojo.class);
+ assertEquals("Donald Duck", user.getName());
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+
restConfiguration().component("jetty").host("localhost").port(getPort()).bindingMode(RestBindingMode.json)
+ .dataFormatProperty("json.in.objectMapper",
"#myMapper");
+
+
rest("/users/").post("new").type(UserPojo.class).to("mock:input");
+ }
+ };
+ }
+}
diff --git
a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoUnknownPropertyOtherFeatureTest.java
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoUnknownPropertyOtherFeatureTest.java
new file mode 100644
index 000000000000..e4ba411615ab
--- /dev/null
+++
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoUnknownPropertyOtherFeatureTest.java
@@ -0,0 +1,30 @@
+/*
+ * 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.jetty.rest;
+
+import org.apache.camel.model.rest.RestConfigurationDefinition;
+
+/**
+ * Enabling other features keeps the rejection of unknown properties.
+ */
+public class RestJettyPostJsonPojoUnknownPropertyOtherFeatureTest extends
RestJettyPostJsonPojoUnknownPropertyTest {
+
+ @Override
+ protected void configureDataFormat(RestConfigurationDefinition rest) {
+ rest.dataFormatProperty("json.in.enableFeatures",
"ACCEPT_SINGLE_VALUE_AS_ARRAY");
+ }
+}
diff --git
a/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoUnknownPropertyTest.java
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoUnknownPropertyTest.java
new file mode 100644
index 000000000000..c5aa6fab12f1
--- /dev/null
+++
b/components/camel-jetty/src/test/java/org/apache/camel/component/jetty/rest/RestJettyPostJsonPojoUnknownPropertyTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.jetty.rest;
+
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.jetty.BaseJettyTest;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.http.base.HttpOperationFailedException;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.apache.camel.model.rest.RestConfigurationDefinition;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.test.junit6.TestSupport.assertIsInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * REST binding rejects unknown properties with Jackson 3 too, whose default
is to accept them.
+ */
+public class RestJettyPostJsonPojoUnknownPropertyTest extends BaseJettyTest {
+
+ @Test
+ public void testUnknownPropertyIsRejected() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:input");
+ mock.expectedMessageCount(0);
+
+ String body = "{\"id\": 123, \"name\": \"Donald Duck\",
\"donotexists\": \"foo\"}";
+ Exception ex = assertThrows(CamelExecutionException.class,
+ () -> template.sendBody("http://localhost:" + getPort() +
"/users/new", body));
+
+ HttpOperationFailedException cause =
assertIsInstanceOf(HttpOperationFailedException.class, ex.getCause());
+ assertEquals(400, cause.getStatusCode());
+ assertTrue(cause.getResponseBody().contains("donotexists"),
cause.getResponseBody());
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testKnownPropertiesAreAccepted() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:input");
+ mock.expectedMessageCount(1);
+ mock.message(0).body().isInstanceOf(UserPojo.class);
+
+ template.sendBody("http://localhost:" + getPort() + "/users/new",
"{\"id\": 123, \"name\": \"Donald Duck\"}");
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ // answer the binding failure with its message
+ onException(Exception.class)
+ .handled(true)
+ .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(400))
+ .setBody().simple("${exception.message}");
+
+ configureDataFormat(
+
restConfiguration().component("jetty").host("localhost").port(getPort())
+ .bindingMode(RestBindingMode.json));
+
+
rest("/users/").post("new").type(UserPojo.class).to("mock:input");
+ }
+ };
+ }
+
+ protected void configureDataFormat(RestConfigurationDefinition rest) {
+ // the defaults of REST binding
+ }
+}
diff --git
a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
index b9a164e051ae..b67ea806c101 100644
---
a/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
+++
b/components/camel-undertow/src/test/java/org/apache/camel/component/undertow/rest/RestUndertowHttpPojoTypeTest.java
@@ -255,9 +255,7 @@ public class RestUndertowHttpPojoTypeTest extends
BaseUndertowTest {
// configure to use undertow on localhost with the given port
restConfiguration().component("undertow").host("localhost").port(getPort())
- .bindingMode(RestBindingMode.json)
- // Jackson 3 ignores unknown properties by default
- .dataFormatProperty("json.in.enableFeatures",
"FAIL_ON_UNKNOWN_PROPERTIES");
+ .bindingMode(RestBindingMode.json);
// use the rest DSL to define the rest services
rest()
diff --git
a/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdviceFactory.java
b/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdviceFactory.java
index cd6d58c6fe21..6425372c3b3e 100644
---
a/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdviceFactory.java
+++
b/core/camel-support/src/main/java/org/apache/camel/support/processor/RestBindingAdviceFactory.java
@@ -37,6 +37,10 @@ import org.apache.camel.support.ResolverHelper;
*/
public class RestBindingAdviceFactory {
+ // matched by name: camel-support cannot depend on camel-jackson3, and
JSON has no binding factory SPI
+ private static final String JACKSON3_PACKAGE =
"org.apache.camel.component.jackson3.";
+ private static final String FAIL_ON_UNKNOWN_PROPERTIES =
"FAIL_ON_UNKNOWN_PROPERTIES";
+
/**
* Builds the {@link RestBindingAdvice} from the given configuration
*
@@ -169,6 +173,7 @@ public class RestBindingAdviceFactory {
useList);
}
setAdditionalConfiguration(camelContext, config, json, "json.in.");
+ failOnUnknownProperties(camelContext, json);
if (outJson != null) {
Class<?> outClazz = null;
@@ -252,6 +257,31 @@ public class RestBindingAdviceFactory {
}
}
+ /**
+ * Jackson 3 accepts unknown properties by default, where Jackson 2
rejects them. REST binding keeps rejecting them
+ * in request bodies, as they come from external callers, unless the
feature or a mapper of your own is configured.
+ */
+ private static void failOnUnknownProperties(CamelContext camelContext,
DataFormat dataFormat) throws Exception {
+ if (!dataFormat.getClass().getName().startsWith(JACKSON3_PACKAGE)) {
+ return;
+ }
+ BeanIntrospection beanIntrospection =
PluginHelper.getBeanIntrospection(camelContext);
+ if (beanIntrospection.getOrElseProperty(dataFormat, "objectMapper",
null, false) != null) {
+ return;
+ }
+ Object enable = beanIntrospection.getOrElseProperty(dataFormat,
"enableFeatures", null, false);
+ Object disable = beanIntrospection.getOrElseProperty(dataFormat,
"disableFeatures", null, false);
+ if (namesFailOnUnknownProperties(enable) ||
namesFailOnUnknownProperties(disable)) {
+ return;
+ }
+ String features = enable != null ? enable + "," +
FAIL_ON_UNKNOWN_PROPERTIES : FAIL_ON_UNKNOWN_PROPERTIES;
+ beanIntrospection.setProperty(camelContext, dataFormat,
"enableFeatures", features);
+ }
+
+ private static boolean namesFailOnUnknownProperties(Object features) {
+ return features != null &&
features.toString().contains(FAIL_ON_UNKNOWN_PROPERTIES);
+ }
+
private static boolean isKeyKnownPrefix(String key) {
return key.startsWith("json.in.") || key.startsWith("json.out.") ||
key.startsWith("xml.in.")
|| key.startsWith("xml.out.");
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
index f96092f0c261..b74611bbcb8a 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_24.adoc
@@ -7588,7 +7588,7 @@ which differ from Jackson 2. Most visibly:
|===
| Feature | Jackson 2 | Jackson 3 | Effect of the Jackson 3 default
-| `FAIL_ON_UNKNOWN_PROPERTIES` | on | off | Unknown properties are ignored.
See the warning below.
+| `FAIL_ON_UNKNOWN_PROPERTIES` | on | off | Unknown properties are ignored,
except by REST binding (see below).
| `SORT_PROPERTIES_ALPHABETICALLY` | off | on | Properties are written in
alphabetical order.
| `WRITE_DATES_AS_TIMESTAMPS` | on | off | Dates are written as ISO-8601 text,
not as numbers.
| `WRITE_DURATIONS_AS_TIMESTAMPS` | on | off | Durations are written as
ISO-8601 text.
@@ -7605,12 +7605,16 @@ Set a feature back with the `enableFeatures` and
`disableFeatures` options of th
[source,java]
----
restConfiguration().bindingMode(RestBindingMode.json)
- .dataFormatProperty("json.in.enableFeatures",
"FAIL_ON_UNKNOWN_PROPERTIES");
+ .dataFormatProperty("json.out.enableFeatures",
"WRITE_DATES_AS_TIMESTAMPS");
----
-WARNING: With `FAIL_ON_UNKNOWN_PROPERTIES` off, a route using REST binding no
longer rejects a JSON body that does not
-match its type. The body is accepted, the request gets no `400` response, and
the route receives a POJO with empty fields.
-Enable the feature as shown above if your routes rely on that validation.
+NOTE: The REST DSL binding of a service enables `FAIL_ON_UNKNOWN_PROPERTIES`
on its Jackson 3 data formats (`json`, and
+`jacksonXml` from `camel-jackson3xml`), so a request body with properties that
its type does not have is still rejected,
+as with Jackson 2. To accept such bodies, set `json.in.disableFeatures` (or
`xml.in.disableFeatures`) to
+`FAIL_ON_UNKNOWN_PROPERTIES`. A feature you enable with `enableFeatures` is
added to it. A data format with a mapper of
+your own keeps the settings of that mapper: the `objectMapper` option or a
mapper found with `autoDiscoverObjectMapper`
+for JSON, the `xmlMapper` option for XML. The REST producer, which reads the
responses of the services it calls, uses
+the Jackson 3 default.
*Limits.* Jackson 3 reads and writes with other limits: nesting up to 500
levels (it was 1000), for reading and writing, and
strings up to 100 million characters (it was 20 million). They apply to every
component on Jackson 3, including those whose