diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBean.java b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBean.java new file mode 100644 index 0000000000..19582f4171 --- /dev/null +++ b/spring-web/src/main/java/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBean.java @@ -0,0 +1,327 @@ +/* + * Copyright 2002-2012 the original author or authors. + * + * Licensed 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.springframework.http.converter.json; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.springframework.beans.FatalBeanException; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.databind.AnnotationIntrospector; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * A FactoryBean for creating a Jackson {@link ObjectMapper} with setters to + * enable or disable Jackson features from within XML configuration. + * + *

Example usage with + * {@link org.springframework.http.converter.json.MappingJackson2HttpMessageConverter}: + * + *

+ * <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
+ *   <property name="objectMapper">
+ *     <bean class="org.springframework.web.context.support.Jackson2ObjectMapperFactoryBean"
+ *       p:autoDetectFields="false"
+ *       p:autoDetectGettersSetters="false"
+ *       p:annotationIntrospector-ref="jaxbAnnotationIntrospector" />
+ *   </property>
+ * </bean>
+ * 
+ * + *

Example usage with {@link org.springframework.web.servlet.view.json.MappingJackson2JsonView}: + * + *

+ * <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView">
+ *   <property name="objectMapper">
+ *     <bean class="org.springframework.web.context.support.Jackson2ObjectMapperFactoryBean"
+ *       p:failOnEmptyBeans="false"
+ *       p:indentOutput="true">
+ *       <property name="serializers">
+ *         <array>
+ *           <bean class="org.mycompany.MyCustomSerializer" />
+ *         </array>
+ *       </property>
+ *     </bean>
+ *   </property>
+ * </bean>
+ * 
+ * + *

In case there are no specific setters provided (for some rarely used + * options), you can still use the more general methods + * {@link #setFeaturesToEnable(Object[])} and {@link #setFeaturesToDisable(Object[])}. + * + *

+ * <bean class="org.springframework.web.context.support.Jackson2ObjectMapperFactoryBean">
+ *   <property name="featuresToEnable">
+ *     <array>
+ *       <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature$WRAP_ROOT_VALUE"/>
+ *       <util:constant static-field="com.fasterxml.jackson.databind.SerializationFeature$CLOSE_CLOSEABLE"/>
+ *     </array>
+ *   </property>
+ *   <property name="featuresToDisable">
+ *     <array>
+ *       <util:constant static-field="com.fasterxml.jackson.databind.MapperFeature$USE_ANNOTATIONS"/>
+ *     </array>
+ *   </property>
+ * </bean>
+ * 
+ * + *

Note: This BeanFctory is singleton, so if you need more than one you'll need + * to configure multiple instances. + * + * @author Dmitry Katsubo + * @author Rossen Stoyanchev + * + * @since 3.2 + */ +public class Jackson2ObjectMapperFactoryBean implements FactoryBean, InitializingBean { + + private ObjectMapper objectMapper; + + private Map features = new HashMap(); + + private DateFormat dateFormat; + + private AnnotationIntrospector annotationIntrospector; + + private final Map, JsonSerializer> serializers = new LinkedHashMap, JsonSerializer>(); + + private final Map, JsonDeserializer> deserializers = new LinkedHashMap, JsonDeserializer>(); + + + /** + * Set the ObjectMapper instance to use. If not set, the ObjectMapper will + * be created using its default constructor. + */ + public void setObjectMapper(ObjectMapper objectMapper) { + this.objectMapper = objectMapper; + } + + /** + * Define the format for date/time with the given {@link DateFormat}. + * @see #setSimpleDateFormat(String) + */ + public void setDateFormat(DateFormat dateFormat) { + this.dateFormat = dateFormat; + } + + /** + * Define the date/time format with a {@link SimpleDateFormat}. + * @see #setDateFormat(DateFormat) + */ + public void setSimpleDateFormat(String format) { + this.dateFormat = new SimpleDateFormat(format); + } + + /** + * Set the {@link AnnotationIntrospector} for both serialization and + * deserialization. + */ + public void setAnnotationIntrospector(AnnotationIntrospector annotationIntrospector) { + this.annotationIntrospector = annotationIntrospector; + } + + /** + * Configure custom serializers. Each serializer is registered for the type + * returned by {@link JsonSerializer#handledType()}, which must not be + * {@code null}. + * @see #setSerializersByType(Map) + */ + public void setSerializers(JsonSerializer... serializers) { + if (serializers != null) { + for (JsonSerializer serializer : serializers) { + Class handledType = serializer.handledType(); + Assert.isTrue(handledType != null && handledType != Object.class, + "Unknown handled type in " + serializer.getClass().getName()); + this.serializers.put(serializer.handledType(), serializer); + } + } + } + + /** + * Configure custom serializers for the given types. + * @see #setSerializers(JsonSerializer...) + */ + public void setSerializersByType(Map, JsonSerializer> serializers) { + if (serializers != null) { + this.serializers.putAll(serializers); + } + } + + /** + * Configure custom deserializers for the given types. + */ + public void setDeserializersByType(Map, JsonDeserializer> deserializers) { + if (deserializers != null) { + this.deserializers.putAll(deserializers); + } + } + + /** + * Shortcut for {@link MapperFeature#AUTO_DETECT_FIELDS} option. + */ + public void setAutoDetectFields(boolean autoDetectFields) { + this.features.put(MapperFeature.AUTO_DETECT_FIELDS, autoDetectFields); + } + + /** + * Shortcut for {@link MapperFeature#AUTO_DETECT_SETTERS}/ + * {@link MapperFeature#AUTO_DETECT_GETTERS} option. + */ + public void setAutoDetectGettersSetters(boolean autoDetectGettersSetters) { + this.features.put(MapperFeature.AUTO_DETECT_SETTERS, autoDetectGettersSetters); + this.features.put(MapperFeature.AUTO_DETECT_GETTERS, autoDetectGettersSetters); + } + + /** + * Shortcut for {@link SerializationFeature#FAIL_ON_EMPTY_BEANS} option. + */ + public void setFailOnEmptyBeans(boolean failOnEmptyBeans) { + this.features.put(SerializationFeature.FAIL_ON_EMPTY_BEANS, failOnEmptyBeans); + } + + /** + * Shortcut for {@link SerializationFeature#INDENT_OUTPUT} option. + */ + public void setIndentOutput(boolean indentOutput) { + this.features.put(SerializationFeature.INDENT_OUTPUT, indentOutput); + } + + /** + * Specify features to enable. + * + * @see MapperFeature + * @see SerializationFeature + * @see DeserializationFeature + * @see JsonParser.Feature + * @see JsonGenerator.Feature + */ + public void setFeaturesToEnable(Object... featuresToEnable) { + if (featuresToEnable != null) { + for (Object feature : featuresToEnable) { + this.features.put(feature, Boolean.TRUE); + } + } + } + + /** + * Specify features to disable. + * + * @see MapperFeature + * @see SerializationFeature + * @see DeserializationFeature + * @see JsonParser.Feature + * @see JsonGenerator.Feature + */ + public void setFeaturesToDisable(Object... featuresToDisable) { + if (featuresToDisable != null) { + for (Object feature : featuresToDisable) { + this.features.put(feature, Boolean.FALSE); + } + } + } + + public void afterPropertiesSet() throws FatalBeanException { + if (this.objectMapper == null) { + this.objectMapper = new ObjectMapper(); + } + + if (this.dateFormat != null) { + this.objectMapper.setDateFormat(this.dateFormat); + } + + if (this.serializers != null || this.deserializers != null) { + SimpleModule module = new SimpleModule(); + addSerializers(module); + addDeserializers(module); + this.objectMapper.registerModule(module); + } + + if (this.annotationIntrospector != null) { + this.objectMapper.setAnnotationIntrospector(this.annotationIntrospector); + } + + for (Object feature : this.features.keySet()) { + configureFeature(feature, this.features.get(feature)); + } + } + + @SuppressWarnings("unchecked") + private void addSerializers(SimpleModule module) { + for (Class type : this.serializers.keySet()) { + module.addSerializer((Class) type, (JsonSerializer) this.serializers.get(type)); + } + } + + @SuppressWarnings("unchecked") + private void addDeserializers(SimpleModule module) { + for (Class type : this.deserializers.keySet()) { + module.addDeserializer((Class) type, (JsonDeserializer) this.deserializers.get(type)); + } + } + + private void configureFeature(Object feature, boolean enabled) { + if (feature instanceof MapperFeature) { + this.objectMapper.configure((MapperFeature) feature, enabled); + } + else if (feature instanceof DeserializationFeature) { + this.objectMapper.configure((DeserializationFeature) feature, enabled); + } + else if (feature instanceof SerializationFeature) { + this.objectMapper.configure((SerializationFeature) feature, enabled); + } + else if (feature instanceof JsonParser.Feature) { + this.objectMapper.configure((JsonParser.Feature) feature, enabled); + } + else if (feature instanceof JsonGenerator.Feature) { + this.objectMapper.configure((JsonGenerator.Feature) feature, enabled); + } + else { + throw new FatalBeanException("Unknown feature class " + feature.getClass().getName()); + } + } + + /** + * Return the singleton ObjectMapper. + */ + public ObjectMapper getObject() { + return this.objectMapper; + } + + public Class getObjectType() { + return ObjectMapper.class; + } + + public boolean isSingleton() { + return true; + } + +} diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBean.java b/spring-web/src/main/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBean.java index 765e174255..db8a459a6a 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBean.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBean.java @@ -35,7 +35,7 @@ import org.springframework.beans.factory.InitializingBean; * A FactoryBean for creating a Jackson {@link ObjectMapper} with setters to * enable or disable Jackson features from within XML configuration. * - *

Example usage with MappingJacksonHttpMessageConverter:

+ *

Example usage with MappingJacksonHttpMessageConverter: *

  * <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
  * 	<property name="objectMapper">
@@ -47,7 +47,7 @@ import org.springframework.beans.factory.InitializingBean;
  * </bean>
  * 
* - *

Example usage with MappingJacksonJsonView:

+ *

Example usage with MappingJacksonJsonView: *

  * <bean class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
  * 	<property name="objectMapper">
@@ -89,10 +89,10 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 
 	private Map features = new HashMap();
 
-	private AnnotationIntrospector annotationIntrospector;
-
 	private DateFormat dateFormat;
 
+	private AnnotationIntrospector annotationIntrospector;
+
 
 	/**
 	 * Set the ObjectMapper instance to use.
@@ -103,16 +103,15 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 	}
 
 	/**
-	 * Define annotationIntrospector for
-	 * {@link SerializationConfig#setAnnotationIntrospector(AnnotationIntrospector)}.
+	 * Define the format for date/time with the given {@link DateFormat}.
+	 * @see #setSimpleDateFormat(String)
 	 */
-	public void setAnnotationIntrospector(AnnotationIntrospector annotationIntrospector) {
-		this.annotationIntrospector = annotationIntrospector;
+	public void setDateFormat(DateFormat dateFormat) {
+		this.dateFormat = dateFormat;
 	}
 
 	/**
-	 * Define the date/time format with the given string, which is in turn used
-	 * to create a {@link SimpleDateFormat}.
+	 * Define the date/time format with a {@link SimpleDateFormat}.
 	 * @see #setDateFormat(DateFormat)
 	 */
 	public void setSimpleDateFormat(String format) {
@@ -120,11 +119,12 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 	}
 
 	/**
-	 * Define the format for date/time with the given {@link DateFormat} instance.
-	 * @see #setSimpleDateFormat(String)
+	 * Set the {@link AnnotationIntrospector} for serialization and deserialization.
+	 * @see SerializationConfig#setAnnotationIntrospector(AnnotationIntrospector)
+	 * @see DeserializationConfig#setAnnotationIntrospector(AnnotationIntrospector)
 	 */
-	public void setDateFormat(DateFormat dateFormat) {
-		this.dateFormat = dateFormat;
+	public void setAnnotationIntrospector(AnnotationIntrospector annotationIntrospector) {
+		this.annotationIntrospector = annotationIntrospector;
 	}
 
 	/**
@@ -161,6 +161,7 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 
 	/**
 	 * Specify features to enable.
+	 *
 	 * @see SerializationConfig.Feature
 	 * @see DeserializationConfig.Feature
 	 * @see JsonParser.Feature
@@ -176,6 +177,7 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 
 	/**
 	 * Specify features to disable.
+	 *
 	 * @see SerializationConfig.Feature
 	 * @see DeserializationConfig.Feature
 	 * @see JsonParser.Feature
@@ -189,7 +191,6 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 		}
 	}
 
-
 	public void afterPropertiesSet() {
 		if (this.objectMapper == null) {
 			this.objectMapper = new ObjectMapper();
@@ -203,11 +204,11 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 			this.objectMapper.getSerializationConfig().setDateFormat(this.dateFormat);
 		}
 		for (Map.Entry entry : this.features.entrySet()) {
-			setFeatureEnabled(entry.getKey(), entry.getValue());
+			configureFeature(entry.getKey(), entry.getValue().booleanValue());
 		}
 	}
 
-	private void setFeatureEnabled(Object feature, boolean enabled) {
+	private void configureFeature(Object feature, boolean enabled) {
 		if (feature instanceof DeserializationConfig.Feature) {
 			this.objectMapper.configure((DeserializationConfig.Feature) feature, enabled);
 		}
@@ -225,7 +226,9 @@ public class JacksonObjectMapperFactoryBean implements FactoryBean
 		}
 	}
 
-
+	/**
+	 * Return the singleton ObjectMapper.
+	 */
 	public ObjectMapper getObject() {
 		return this.objectMapper;
 	}
diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBeanTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBeanTests.java
new file mode 100644
index 0000000000..bc52e4c402
--- /dev/null
+++ b/spring-web/src/test/java/org/springframework/http/converter/json/Jackson2ObjectMapperFactoryBeanTests.java
@@ -0,0 +1,191 @@
+/*
+ * Copyright 2002-2012 the original author or authors.
+ *
+ * Licensed 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.springframework.http.converter.json;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.beans.DirectFieldAccessor;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.cfg.DeserializerFactoryConfig;
+import com.fasterxml.jackson.databind.cfg.SerializerFactoryConfig;
+import com.fasterxml.jackson.databind.deser.std.DateDeserializers.DateDeserializer;
+import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector;
+import com.fasterxml.jackson.databind.ser.std.StdJdkSerializers.ClassSerializer;
+
+/**
+ * Test cases for {@link Jackson2ObjectMapperFactoryBean} class.
+ *
+ * @author Dmitry Katsubo
+ */
+public class Jackson2ObjectMapperFactoryBeanTests {
+
+	private static final String DATE_FORMAT = "yyyy-MM-dd";
+
+	private Jackson2ObjectMapperFactoryBean factory;
+
+	@Before
+	public void setUp() {
+		factory = new Jackson2ObjectMapperFactoryBean();
+	}
+
+	@Test
+	public void testSetFeaturesToEnableEmpty() {
+		this.factory.setFeaturesToEnable(new Object[0]);
+		this.factory.setFeaturesToDisable(new Object[0]);
+	}
+
+	@Test(expected = FatalBeanException.class)
+	public void testUnknownFeature() {
+		this.factory.setFeaturesToEnable(new Object[] { Boolean.TRUE });
+		this.factory.afterPropertiesSet();
+	}
+
+	@Test
+	public void testBooleanSetters() {
+		this.factory.setAutoDetectFields(false);
+		this.factory.setAutoDetectGettersSetters(false);
+		this.factory.setFailOnEmptyBeans(false);
+		this.factory.setIndentOutput(true);
+		this.factory.afterPropertiesSet();
+
+		ObjectMapper objectMapper = this.factory.getObject();
+
+		assertFalse(objectMapper.getSerializationConfig().isEnabled(MapperFeature.AUTO_DETECT_FIELDS));
+		assertFalse(objectMapper.getDeserializationConfig().isEnabled(MapperFeature.AUTO_DETECT_FIELDS));
+		assertFalse(objectMapper.getSerializationConfig().isEnabled(MapperFeature.AUTO_DETECT_GETTERS));
+		assertFalse(objectMapper.getDeserializationConfig().isEnabled(MapperFeature.AUTO_DETECT_SETTERS));
+		assertFalse(objectMapper.getSerializationConfig().isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS));
+		assertTrue(objectMapper.getSerializationConfig().isEnabled(SerializationFeature.INDENT_OUTPUT));
+	}
+
+	@Test
+	public void testDateTimeFormatSetter() {
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+		this.factory.setDateFormat(dateFormat);
+		this.factory.afterPropertiesSet();
+
+		assertEquals(dateFormat, this.factory.getObject().getSerializationConfig().getDateFormat());
+		assertEquals(dateFormat, this.factory.getObject().getDeserializationConfig().getDateFormat());
+	}
+
+	@Test
+	public void testSimpleDateFormatStringSetter() {
+		SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
+
+		this.factory.setSimpleDateFormat(DATE_FORMAT);
+		this.factory.afterPropertiesSet();
+
+		assertEquals(dateFormat, this.factory.getObject().getSerializationConfig().getDateFormat());
+		assertEquals(dateFormat, this.factory.getObject().getDeserializationConfig().getDateFormat());
+	}
+
+	@Test
+	public void testSimpleSetup() {
+		this.factory.afterPropertiesSet();
+
+		assertNotNull(this.factory.getObject());
+		assertTrue(this.factory.isSingleton());
+		assertEquals(ObjectMapper.class, this.factory.getObjectType());
+	}
+
+	/**
+	 * TODO: Remove use of {@link DirectFieldAccessor} with getters.
+	 * See issue#65.
+	 */
+	private static final SerializerFactoryConfig getSerializerFactoryConfig(ObjectMapper objectMapper) {
+		Object factoryProp = new DirectFieldAccessor(objectMapper).getPropertyValue("_serializerFactory");
+		return (SerializerFactoryConfig) new DirectFieldAccessor(factoryProp).getPropertyValue("_factoryConfig");
+	}
+
+	private static final DeserializerFactoryConfig getDeserializerFactoryConfig(ObjectMapper objectMapper) {
+		Object contextProp = new DirectFieldAccessor(objectMapper).getPropertyValue("_deserializationContext");
+		Object factoryProp = new DirectFieldAccessor(contextProp).getPropertyValue("_factory");
+		return (DeserializerFactoryConfig) new DirectFieldAccessor(factoryProp).getPropertyValue("_factoryConfig");
+	}
+
+	@Test
+	public void testCompleteSetup() {
+		NopAnnotationIntrospector annotationIntrospector = NopAnnotationIntrospector.instance;
+		ObjectMapper objectMapper = new ObjectMapper();
+
+		assertTrue(this.factory.isSingleton());
+		assertEquals(ObjectMapper.class, this.factory.getObjectType());
+
+		Map, JsonDeserializer> deserializers = new HashMap, JsonDeserializer>();
+		deserializers.put(Date.class, new DateDeserializer());
+
+		this.factory.setObjectMapper(objectMapper);
+		this.factory.setSerializers(new ClassSerializer());
+		this.factory.setDeserializersByType(deserializers);
+		this.factory.setAnnotationIntrospector(annotationIntrospector);
+
+		this.factory.setFeaturesToEnable(
+				SerializationFeature.FAIL_ON_EMPTY_BEANS,
+				DeserializationFeature.UNWRAP_ROOT_VALUE,
+				JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER,
+				JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS);
+
+		this.factory.setFeaturesToDisable(
+				MapperFeature.AUTO_DETECT_GETTERS,
+				MapperFeature.AUTO_DETECT_FIELDS,
+				JsonParser.Feature.AUTO_CLOSE_SOURCE,
+				JsonGenerator.Feature.QUOTE_FIELD_NAMES);
+
+		assertFalse(getSerializerFactoryConfig(objectMapper).hasSerializers());
+		assertFalse(getDeserializerFactoryConfig(objectMapper).hasDeserializers());
+
+		this.factory.afterPropertiesSet();
+
+		assertTrue(objectMapper == this.factory.getObject());
+
+		assertTrue(getSerializerFactoryConfig(objectMapper).hasSerializers());
+		assertTrue(getDeserializerFactoryConfig(objectMapper).hasDeserializers());
+
+		assertTrue(annotationIntrospector == objectMapper.getSerializationConfig().getAnnotationIntrospector());
+		assertTrue(annotationIntrospector == objectMapper.getDeserializationConfig().getAnnotationIntrospector());
+
+		assertTrue(objectMapper.getSerializationConfig().isEnabled(SerializationFeature.FAIL_ON_EMPTY_BEANS));
+		assertTrue(objectMapper.getDeserializationConfig().isEnabled(DeserializationFeature.UNWRAP_ROOT_VALUE));
+		assertTrue(objectMapper.getJsonFactory().isEnabled(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER));
+		assertTrue(objectMapper.getJsonFactory().isEnabled(JsonGenerator.Feature.WRITE_NUMBERS_AS_STRINGS));
+
+		assertFalse(objectMapper.getSerializationConfig().isEnabled(MapperFeature.AUTO_DETECT_GETTERS));
+		assertFalse(objectMapper.getDeserializationConfig().isEnabled(MapperFeature.AUTO_DETECT_FIELDS));
+		assertFalse(objectMapper.getJsonFactory().isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE));
+		assertFalse(objectMapper.getJsonFactory().isEnabled(JsonGenerator.Feature.QUOTE_FIELD_NAMES));
+	}
+}
diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBeanTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBeanTests.java
index 3a22dfddf1..a66f4e2fbb 100644
--- a/spring-web/src/test/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBeanTests.java
+++ b/spring-web/src/test/java/org/springframework/http/converter/json/JacksonObjectMapperFactoryBeanTests.java
@@ -32,8 +32,6 @@ import org.codehaus.jackson.map.SerializationConfig;
 import org.codehaus.jackson.map.introspect.NopAnnotationIntrospector;
 import org.junit.Before;
 import org.junit.Test;
-import org.springframework.beans.FatalBeanException;
-import org.springframework.http.converter.json.JacksonObjectMapperFactoryBean;
 
 /**
  * @author Dmitry Katsubo
diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java
index 603b6613ab..3579c5d464 100644
--- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java
+++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java
@@ -52,7 +52,7 @@ public class MappingJackson2HttpMessageConverterTests extends AbstractMappingJac
 
 			@Override
 			protected JavaType getJavaType(Type type) {
-				if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
+				if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
 					return new ObjectMapper().getTypeFactory().constructCollectionType(ArrayList.class, MyBean.class);
 				}
 				else {
diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java
index c3fe567a69..5f70a4d6d4 100644
--- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java
+++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java
@@ -50,7 +50,7 @@ public class MappingJacksonHttpMessageConverterTests extends AbstractMappingJack
 		MappingJacksonHttpMessageConverter converter = new MappingJacksonHttpMessageConverter() {
 			@Override
 			protected JavaType getJavaType(Type type) {
-				if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
+				if (type instanceof Class && List.class.isAssignableFrom((Class)type)) {
 					return TypeFactory.collectionType(ArrayList.class, MyBean.class);
 				}
 				else {