Skip to content

Commit 4adcbff

Browse files
committed
Fix #3068
1 parent 21dad11 commit 4adcbff

File tree

6 files changed

+111
-23
lines changed

6 files changed

+111
-23
lines changed

release-notes/VERSION-2.x

+3
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ Project: jackson-databind
3030
#3060: Missing override for `hasAsKey()` in `AnnotationIntrospectorPair`
3131
#3062: Creator lookup fails with `InvalidDefinitionException` for conflict
3232
between single-double/single-Double arg constructor
33+
#3068: `MapDeserializer` forcing `JsonMappingException` wrapping even if
34+
WRAP_EXCEPTIONS set to false
35+
(reported by perkss@github)
3336

3437
2.12.1 (08-Jan-2021)
3538

src/main/java/com/fasterxml/jackson/databind/deser/std/ContainerDeserializerBase.java

+19-2
Original file line numberDiff line numberDiff line change
@@ -155,16 +155,33 @@ public Object getEmptyValue(DeserializationContext ctxt) throws JsonMappingExcep
155155
*/
156156

157157
/**
158-
* Helper method called by various Map(-like) deserializers.
158+
* @deprecated Since 2.12.2 (since it does not get context for accessing config)
159159
*/
160+
@Deprecated
160161
protected <BOGUS> BOGUS wrapAndThrow(Throwable t, Object ref, String key) throws IOException
162+
{
163+
return wrapAndThrow(null, t, ref, key);
164+
}
165+
166+
/**
167+
* Helper method called by various Map(-like) deserializers when encountering
168+
* a processing problem (whether from underlying parser, i/o, or something else).
169+
*
170+
* @since 2.12.2
171+
*/
172+
protected <BOGUS> BOGUS wrapAndThrow(DeserializationContext ctxt,
173+
Throwable t, Object ref, String key) throws IOException
161174
{
162175
// to handle StackOverflow:
163176
while (t instanceof InvocationTargetException && t.getCause() != null) {
164177
t = t.getCause();
165178
}
166-
// Errors and "plain" IOExceptions to be passed as is
179+
// Errors and "plain" IOExceptions to be passed as-is
167180
ClassUtil.throwIfError(t);
181+
// 25-Feb-2021, tatu: as per [databind#3068] need to obey WRAP_EXCEPTIONS setting
182+
if ((ctxt != null) && !ctxt.isEnabled(DeserializationFeature.WRAP_EXCEPTIONS)) {
183+
ClassUtil.throwIfRTE(t);
184+
}
168185
// ... except for mapping exceptions
169186
if (t instanceof IOException && !(t instanceof JsonMappingException)) {
170187
throw (IOException) t;

src/main/java/com/fasterxml/jackson/databind/deser/std/EnumMapDeserializer.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,7 @@ public EnumMap<?,?> deserialize(JsonParser p, DeserializationContext ctxt,
318318
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
319319
}
320320
} catch (Exception e) {
321-
return wrapAndThrow(e, result, keyStr);
321+
return wrapAndThrow(ctxt, e, result, keyStr);
322322
}
323323
result.put(key, value);
324324
}
@@ -377,7 +377,7 @@ public EnumMap<?,?> _deserializeUsingProperties(JsonParser p, DeserializationCon
377377
try {
378378
result = (EnumMap<?,?>)creator.build(ctxt, buffer);
379379
} catch (Exception e) {
380-
return wrapAndThrow(e, _containerType.getRawClass(), keyName);
380+
return wrapAndThrow(ctxt, e, _containerType.getRawClass(), keyName);
381381
}
382382
return deserialize(p, ctxt, result);
383383
}
@@ -412,7 +412,7 @@ public EnumMap<?,?> _deserializeUsingProperties(JsonParser p, DeserializationCon
412412
value = _valueDeserializer.deserializeWithType(p, ctxt, _valueTypeDeserializer);
413413
}
414414
} catch (Exception e) {
415-
wrapAndThrow(e, _containerType.getRawClass(), keyName);
415+
wrapAndThrow(ctxt, e, _containerType.getRawClass(), keyName);
416416
return null;
417417
}
418418
buffer.bufferMapProperty(key, value);
@@ -422,7 +422,7 @@ public EnumMap<?,?> _deserializeUsingProperties(JsonParser p, DeserializationCon
422422
try {
423423
return (EnumMap<?,?>)creator.build(ctxt, buffer);
424424
} catch (Exception e) {
425-
wrapAndThrow(e, _containerType.getRawClass(), keyName);
425+
wrapAndThrow(ctxt, e, _containerType.getRawClass(), keyName);
426426
return null;
427427
}
428428
}

src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java

+7-7
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ protected final void _readAndBind(JsonParser p, DeserializationContext ctxt,
556556
} catch (UnresolvedForwardReference reference) {
557557
handleUnresolvedReference(ctxt, referringAccumulator, key, reference);
558558
} catch (Exception e) {
559-
wrapAndThrow(e, result, keyStr);
559+
wrapAndThrow(ctxt, e, result, keyStr);
560560
}
561561
}
562562
}
@@ -618,7 +618,7 @@ protected final void _readAndBindStringKeyMap(JsonParser p, DeserializationConte
618618
} catch (UnresolvedForwardReference reference) {
619619
handleUnresolvedReference(ctxt, referringAccumulator, key, reference);
620620
} catch (Exception e) {
621-
wrapAndThrow(e, result, key);
621+
wrapAndThrow(ctxt, e, result, key);
622622
}
623623
}
624624
// 23-Mar-2015, tatu: TODO: verify we got END_OBJECT?
@@ -659,7 +659,7 @@ public Map<Object,Object> _deserializeUsingCreator(JsonParser p, Deserialization
659659
try {
660660
result = (Map<Object,Object>)creator.build(ctxt, buffer);
661661
} catch (Exception e) {
662-
return wrapAndThrow(e, _containerType.getRawClass(), key);
662+
return wrapAndThrow(ctxt, e, _containerType.getRawClass(), key);
663663
}
664664
_readAndBind(p, ctxt, result);
665665
return result;
@@ -682,7 +682,7 @@ public Map<Object,Object> _deserializeUsingCreator(JsonParser p, Deserialization
682682
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
683683
}
684684
} catch (Exception e) {
685-
wrapAndThrow(e, _containerType.getRawClass(), key);
685+
wrapAndThrow(ctxt, e, _containerType.getRawClass(), key);
686686
return null;
687687
}
688688
buffer.bufferMapProperty(actualKey, value);
@@ -692,7 +692,7 @@ public Map<Object,Object> _deserializeUsingCreator(JsonParser p, Deserialization
692692
try {
693693
return (Map<Object,Object>)creator.build(ctxt, buffer);
694694
} catch (Exception e) {
695-
wrapAndThrow(e, _containerType.getRawClass(), key);
695+
wrapAndThrow(ctxt, e, _containerType.getRawClass(), key);
696696
return null;
697697
}
698698
}
@@ -764,7 +764,7 @@ protected final void _readAndUpdate(JsonParser p, DeserializationContext ctxt,
764764
result.put(key, value);
765765
}
766766
} catch (Exception e) {
767-
wrapAndThrow(e, result, keyStr);
767+
wrapAndThrow(ctxt, e, result, keyStr);
768768
}
769769
}
770770
}
@@ -831,7 +831,7 @@ protected final void _readAndUpdateStringKeyMap(JsonParser p, DeserializationCon
831831
result.put(key, value);
832832
}
833833
} catch (Exception e) {
834-
wrapAndThrow(e, result, key);
834+
wrapAndThrow(ctxt, e, result, key);
835835
}
836836
}
837837
}

src/main/java/com/fasterxml/jackson/databind/deser/std/MapEntryDeserializer.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ public Map.Entry<Object,Object> deserialize(JsonParser p, DeserializationContext
214214
value = valueDes.deserializeWithType(p, ctxt, typeDeser);
215215
}
216216
} catch (Exception e) {
217-
wrapAndThrow(e, Map.Entry.class, keyStr);
217+
wrapAndThrow(ctxt, e, Map.Entry.class, keyStr);
218218
}
219219

220220
// Close, but also verify that we reached the END_OBJECT

src/test/java/com/fasterxml/jackson/databind/deser/jdk/CollectionDeserTest.java

+77-9
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44
import java.util.*;
55
import java.util.concurrent.ArrayBlockingQueue;
66

7+
import com.fasterxml.jackson.annotation.JsonProperty;
8+
79
import com.fasterxml.jackson.core.*;
810
import com.fasterxml.jackson.core.type.TypeReference;
11+
912
import com.fasterxml.jackson.databind.*;
1013
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
1114
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
1215
import com.fasterxml.jackson.databind.exc.MismatchedInputException;
16+
import com.fasterxml.jackson.databind.module.SimpleModule;
1317

1418
@SuppressWarnings("serial")
1519
public class CollectionDeserTest
@@ -65,7 +69,7 @@ static class KeyListBean {
6569
public List<Key> keys;
6670
}
6771

68-
// [Issue#828]
72+
// [databind#828]
6973
@JsonDeserialize(using=SomeObjectDeserializer.class)
7074
static class SomeObject {}
7175

@@ -79,6 +83,26 @@ public SomeObject deserialize(JsonParser p, DeserializationContext ctxt)
7983
}
8084
}
8185

86+
// [databind#3068]: Exception wrapping (or not)
87+
static class MyContainerModel {
88+
@JsonProperty("processor-id")
89+
public String id = "123";
90+
}
91+
92+
static class MyJobModel {
93+
public Map<String, MyContainerModel> containers = Collections.singletonMap("key",
94+
new MyContainerModel());
95+
public int maxChangeLogStreamPartitions = 13;
96+
}
97+
98+
static class CustomException extends RuntimeException {
99+
private static final long serialVersionUID = 1L;
100+
101+
public CustomException(String s) {
102+
super(s);
103+
}
104+
}
105+
82106
/*
83107
/**********************************************************
84108
/* Test methods
@@ -272,24 +296,24 @@ public void testArrayIndexForExceptions() throws Exception
272296
// for [databind#828]
273297
public void testWrapExceptions() throws Exception
274298
{
275-
ObjectMapper mapper = jsonMapperBuilder()
276-
.enable(DeserializationFeature.WRAP_EXCEPTIONS)
277-
.build();
299+
final ObjectReader wrappingReader = MAPPER
300+
.readerFor(new TypeReference<List<SomeObject>>() {})
301+
.with(DeserializationFeature.WRAP_EXCEPTIONS);
278302

279303
try {
280-
mapper.readValue("[{}]", new TypeReference<List<SomeObject>>() {});
304+
wrappingReader.readValue("[{}]");
281305
} catch (JsonMappingException exc) {
282306
assertEquals("I want to catch this exception", exc.getOriginalMessage());
283307
} catch (RuntimeException exc) {
284308
fail("The RuntimeException should have been wrapped with a JsonMappingException.");
285309
}
286310

287-
ObjectMapper mapperNoWrap = jsonMapperBuilder()
288-
.disable(DeserializationFeature.WRAP_EXCEPTIONS)
289-
.build();
311+
final ObjectReader noWrapReader = MAPPER
312+
.readerFor(new TypeReference<List<SomeObject>>() {})
313+
.without(DeserializationFeature.WRAP_EXCEPTIONS);
290314

291315
try {
292-
mapperNoWrap.readValue("[{}]", new TypeReference<List<SomeObject>>() {});
316+
noWrapReader.readValue("[{}]");
293317
} catch (JsonMappingException exc) {
294318
fail("It should not have wrapped the RuntimeException.");
295319
} catch (RuntimeException exc) {
@@ -310,4 +334,48 @@ public void testAbstractListAndSet() throws Exception
310334
assertEquals(2, set.values.size());
311335
assertEquals(HashSet.class, set.values.getClass());
312336
}
337+
338+
// for [databind#3068]
339+
public void testWrapExceptions3068() throws Exception
340+
{
341+
final SimpleModule module = new SimpleModule("SimpleModule", Version.unknownVersion())
342+
.addDeserializer(MyContainerModel.class,
343+
new JsonDeserializer<MyContainerModel>() {
344+
@Override
345+
public MyContainerModel deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
346+
throw new CustomException("Custom message");
347+
}
348+
});
349+
350+
final ObjectMapper mapper = jsonMapperBuilder()
351+
.addModule(module)
352+
.build();
353+
final String json = mapper.writeValueAsString(new MyJobModel());
354+
355+
// First, verify NO wrapping:
356+
try {
357+
mapper.readerFor(MyJobModel.class)
358+
.without(DeserializationFeature.WRAP_EXCEPTIONS)
359+
.readValue(json);
360+
fail("Should not pass");
361+
} catch (CustomException e) {
362+
verifyException(e, "Custom message");
363+
} catch (JacksonException e) {
364+
fail("Should not have wrapped exception, got: "+e);
365+
}
366+
367+
// and then wrapping
368+
try {
369+
mapper.readerFor(MyJobModel.class)
370+
.with(DeserializationFeature.WRAP_EXCEPTIONS)
371+
.readValue(json);
372+
fail("Should not pass");
373+
} catch (JacksonException e) {
374+
verifyException(e, "Custom message");
375+
assertEquals(JsonMappingException.class, e.getClass());
376+
Throwable rootC = e.getCause();
377+
assertNotNull(rootC);
378+
assertEquals(CustomException.class, rootC.getClass());
379+
}
380+
}
313381
}

0 commit comments

Comments
 (0)