From b6f3f6a587771d0fab329f4ff5fd03bed760fde8 Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Thu, 16 Jul 2015 23:17:16 -0700 Subject: [PATCH 1/2] Test for lost annotations --- .../introspect/POJOPropertyBuilder.java | 2 +- .../TestPOJOPropertiesCollector.java | 58 ++++++++++++++++++- 2 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java index 4c4bbd549a..13a1be203c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java @@ -1056,7 +1056,7 @@ public void remove() { * Node used for creating simple linked lists to efficiently store small sets * of things. */ - private final static class Linked + protected final static class Linked { public final T value; public final Linked next; diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPOJOPropertiesCollector.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPOJOPropertiesCollector.java index 8b59a9bf71..cf961c9e52 100644 --- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestPOJOPropertiesCollector.java +++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestPOJOPropertiesCollector.java @@ -1,5 +1,9 @@ package com.fasterxml.jackson.databind.introspect; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; import java.math.BigDecimal; import java.util.*; @@ -198,7 +202,35 @@ static class PropDescBean @JsonProperty(required=true, index=B_INDEX, defaultValue="13") public int getB() { return b; } } - + + @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + @JacksonAnnotation + @interface A {} + + @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER}) + @Retention(RetentionPolicy.RUNTIME) + @JacksonAnnotation + @interface B {} + + static class DuplicateGetterBean + { + @A + public boolean isBloop() { return true; } + + @B + public boolean getBloop() { return true; } + } + + static class DuplicateGetterCreatorBean + { + public DuplicateGetterCreatorBean(@JsonProperty("bloop") @A boolean bloop) {} + + public boolean isBloop() { return true; } + + public boolean getBloop() { return true; } + } + /* /********************************************************** /* Unit tests @@ -433,6 +465,30 @@ public void testPropertyIndex() throws Exception _verifyProperty(beanDesc, false, true, "13"); } + public void testDuplicateGetters() throws Exception + { + POJOPropertiesCollector coll = collector(MAPPER, DuplicateGetterBean.class, true); + List props = coll.getProperties(); + assertEquals(1, props.size()); + BeanPropertyDefinition prop = props.get(0); + assertEquals("bloop", prop.getName()); + assertTrue(prop.getGetter().hasAnnotation(A.class)); + assertTrue(prop.getGetter().hasAnnotation(B.class)); + } + + public void testDuplicateGettersCreator() throws Exception + { + POJOPropertiesCollector coll = collector(MAPPER, DuplicateGetterCreatorBean.class, true); + List props = coll.getProperties(); + assertEquals(1, props.size()); + POJOPropertyBuilder prop = (POJOPropertyBuilder) props.get(0); + assertEquals("bloop", prop.getName()); + // Can't call getGetter or the duplicate will be removed + assertTrue(prop._getters.value.hasAnnotation(A.class)); + assertNotNull(prop._getters.next); + assertTrue(prop._getters.next.value.hasAnnotation(A.class)); + } + private void _verifyProperty(BeanDescription beanDesc, boolean verifyDesc, boolean verifyIndex, String expDefaultValue) { From 6cf2bb5f44b31dcef1341eec6a3968b4436b225f Mon Sep 17 00:00:00 2001 From: Christopher Currie Date: Thu, 16 Jul 2015 23:48:05 -0700 Subject: [PATCH 2/2] Fix for lost annotations --- .../introspect/POJOPropertyBuilder.java | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java index 13a1be203c..bc975c18f3 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertyBuilder.java @@ -683,28 +683,28 @@ public void mergeAnnotations(boolean forSerialization) if (forSerialization) { if (_getters != null) { AnnotationMap ann = _mergeAnnotations(0, _getters, _fields, _ctorParameters, _setters); - _getters = _getters.withValue(_getters.value.withAnnotations(ann)); + _getters = _applyAnnotations(_getters, ann); } else if (_fields != null) { AnnotationMap ann = _mergeAnnotations(0, _fields, _ctorParameters, _setters); - _fields = _fields.withValue(_fields.value.withAnnotations(ann)); + _fields = _applyAnnotations(_fields, ann); } } else { // for deserialization if (_ctorParameters != null) { AnnotationMap ann = _mergeAnnotations(0, _ctorParameters, _setters, _fields, _getters); - _ctorParameters = _ctorParameters.withValue(_ctorParameters.value.withAnnotations(ann)); + _ctorParameters = _applyAnnotations(_ctorParameters, ann); } else if (_setters != null) { AnnotationMap ann = _mergeAnnotations(0, _setters, _fields, _getters); - _setters = _setters.withValue(_setters.value.withAnnotations(ann)); + _setters = _applyAnnotations(_setters, ann); } else if (_fields != null) { AnnotationMap ann = _mergeAnnotations(0, _fields, _getters); - _fields = _fields.withValue(_fields.value.withAnnotations(ann)); + _fields = _applyAnnotations(_fields, ann); } } } private AnnotationMap _mergeAnnotations(int index, Linked... nodes) { - AnnotationMap ann = nodes[index].value.getAllAnnotations(); + AnnotationMap ann = _getAllAnnotations(nodes[index]); ++index; for (; index < nodes.length; ++index) { if (nodes[index] != null) { @@ -713,7 +713,23 @@ private AnnotationMap _mergeAnnotations(int index, Linked AnnotationMap _getAllAnnotations(Linked node) { + AnnotationMap ann = node.value.getAllAnnotations(); + if (node.next != null) { + ann = AnnotationMap.merge(ann, _getAllAnnotations(node.next)); + } + return ann; + } + + private Linked _applyAnnotations(Linked node, AnnotationMap ann) { + T value = (T) node.value.withAnnotations(ann); + if (node.next != null) { + node = node.withNext(_applyAnnotations(node.next, ann)); + } + return node.withValue(value); + } + private Linked _removeIgnored(Linked node) { if (node == null) {