From 5f4e838f4165f99ac6166a14e8ce6afcc39a5ba0 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 14 Apr 2016 14:13:13 +0200 Subject: [PATCH] Jackson-based message converters do not log warning for serializer not found Issue: SPR-14163 --- .../MappingJackson2MessageConverter.java | 48 +++++++++++-------- .../AbstractJackson2HttpMessageConverter.java | 32 +++++++------ ...pingJackson2HttpMessageConverterTests.java | 12 +++-- 3 files changed, 53 insertions(+), 39 deletions(-) diff --git a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java index 0a34986896..d553fe1edb 100644 --- a/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java +++ b/spring-messaging/src/main/java/org/springframework/messaging/converter/MappingJackson2MessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; +import java.lang.reflect.Type; import java.nio.charset.Charset; import java.util.Arrays; import java.util.concurrent.atomic.AtomicReference; @@ -30,6 +31,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.MapperFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; @@ -136,42 +138,49 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter { @Override protected boolean canConvertFrom(Message message, Class targetClass) { - if (targetClass == null) { + if (targetClass == null || !supportsMimeType(message.getHeaders())) { return false; } JavaType javaType = this.objectMapper.constructType(targetClass); if (!logger.isWarnEnabled()) { - return (this.objectMapper.canDeserialize(javaType) && supportsMimeType(message.getHeaders())); + return this.objectMapper.canDeserialize(javaType); } AtomicReference causeRef = new AtomicReference(); - if (this.objectMapper.canDeserialize(javaType, causeRef) && supportsMimeType(message.getHeaders())) { + if (this.objectMapper.canDeserialize(javaType, causeRef)) { return true; } - Throwable cause = causeRef.get(); - if (cause != null) { - String msg = "Failed to evaluate deserialization for type " + javaType; - if (logger.isDebugEnabled()) { - logger.warn(msg, cause); - } - else { - logger.warn(msg + ": " + cause); - } - } + logWarningIfNecessary(javaType, causeRef.get()); return false; } @Override protected boolean canConvertTo(Object payload, MessageHeaders headers) { + if (payload == null || !supportsMimeType(headers)) { + return false; + } if (!logger.isWarnEnabled()) { - return (this.objectMapper.canSerialize(payload.getClass()) && supportsMimeType(headers)); + return this.objectMapper.canSerialize(payload.getClass()); } AtomicReference causeRef = new AtomicReference(); - if (this.objectMapper.canSerialize(payload.getClass(), causeRef) && supportsMimeType(headers)) { + if (this.objectMapper.canSerialize(payload.getClass(), causeRef)) { return true; } - Throwable cause = causeRef.get(); - if (cause != null) { - String msg = "Failed to evaluate serialization for type [" + payload.getClass() + "]"; + logWarningIfNecessary(payload.getClass(), causeRef.get()); + return false; + } + + /** + * Determine whether to log the given exception coming from a + * {@link ObjectMapper#canDeserialize} / {@link ObjectMapper#canSerialize} check. + * @param type the class that Jackson tested for (de-)serializability + * @param cause the Jackson-thrown exception to evaluate + * (typically a {@link JsonMappingException}) + * @since 4.3 + */ + protected void logWarningIfNecessary(Type type, Throwable cause) { + if (cause != null && !(cause instanceof JsonMappingException && cause.getMessage().startsWith("Can not find"))) { + String msg = "Failed to evaluate Jackson " + (type instanceof JavaType ? "de" : "") + + "serialization for type [" + type + "]"; if (logger.isDebugEnabled()) { logger.warn(msg, cause); } @@ -179,7 +188,6 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter { logger.warn(msg + ": " + cause); } } - return false; } @Override diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java index 739de6200d..44a7535d1a 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java @@ -27,6 +27,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectWriter; import com.fasterxml.jackson.databind.SerializationFeature; @@ -148,16 +149,7 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener if (this.objectMapper.canDeserialize(javaType, causeRef)) { return true; } - Throwable cause = causeRef.get(); - if (cause != null) { - String msg = "Failed to evaluate deserialization for type " + javaType; - if (logger.isDebugEnabled()) { - logger.warn(msg, cause); - } - else { - logger.warn(msg + ": " + cause); - } - } + logWarningIfNecessary(javaType, causeRef.get()); return false; } @@ -173,9 +165,22 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener if (this.objectMapper.canSerialize(clazz, causeRef)) { return true; } - Throwable cause = causeRef.get(); - if (cause != null) { - String msg = "Failed to evaluate serialization for type [" + clazz + "]"; + logWarningIfNecessary(clazz, causeRef.get()); + return false; + } + + /** + * Determine whether to log the given exception coming from a + * {@link ObjectMapper#canDeserialize} / {@link ObjectMapper#canSerialize} check. + * @param type the class that Jackson tested for (de-)serializability + * @param cause the Jackson-thrown exception to evaluate + * (typically a {@link JsonMappingException}) + * @since 4.3 + */ + protected void logWarningIfNecessary(Type type, Throwable cause) { + if (cause != null && !(cause instanceof JsonMappingException && cause.getMessage().startsWith("Can not find"))) { + String msg = "Failed to evaluate Jackson " + (type instanceof JavaType ? "de" : "") + + "serialization for type [" + type + "]"; if (logger.isDebugEnabled()) { logger.warn(msg, cause); } @@ -183,7 +188,6 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener logger.warn(msg + ": " + cause); } } - return false; } @Override 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 51a04ee602..e2b15b0861 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2016 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. @@ -31,7 +31,6 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ser.FilterProvider; import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter; import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider; - import org.junit.Test; import org.springframework.core.ParameterizedTypeReference; @@ -68,9 +67,7 @@ public class MappingJackson2HttpMessageConverterTests { assertTrue(converter.canWrite(Map.class, new MediaType("application", "json"))); } - // SPR-7905 - - @Test + @Test // SPR-7905 public void canReadAndWriteMicroformats() { assertTrue(converter.canRead(MyBean.class, new MediaType("application", "vnd.test-micro-type+json"))); assertTrue(converter.canWrite(MyBean.class, new MediaType("application", "vnd.test-micro-type+json"))); @@ -439,9 +436,12 @@ public class MappingJackson2HttpMessageConverterTests { } } + private interface MyJacksonView1 {}; + private interface MyJacksonView2 {}; + @SuppressWarnings("unused") private static class JacksonViewBean { @@ -478,11 +478,13 @@ public class MappingJackson2HttpMessageConverterTests { } } + @JsonFilter("myJacksonFilter") @SuppressWarnings("unused") private static class JacksonFilteredBean { private String property1; + private String property2; public String getProperty1() {