1 package com.fasterxml.jackson.failing; 2 3 import java.beans.ConstructorProperties; 4 5 import com.fasterxml.jackson.annotation.*; 6 7 import com.fasterxml.jackson.databind.*; 8 import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 9 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; 10 11 // [databind#2686]: Not sure if this can ever be solved as 12 // setter/builder is on Builder class, but it is called after 13 // building completes, i.e. on wrong class. 14 15 public class BuilderWithBackRef2686Test extends BaseMapTest 16 { 17 // [databind#2686] 18 public static class Container { 19 private Content forward; 20 21 private String containerValue; 22 23 @JsonManagedReference getForward()24 public Content getForward() { 25 return forward; 26 } 27 28 @JsonManagedReference setForward(Content forward)29 public void setForward(Content forward) { 30 this.forward = forward; 31 } 32 getContainerValue()33 public String getContainerValue() { 34 return containerValue; 35 } 36 setContainerValue(String containerValue)37 public void setContainerValue(String containerValue) { 38 this.containerValue = containerValue; 39 } 40 } 41 42 @JsonDeserialize(builder = Content.Builder.class) // Works when removing this, i.e. using the constructor 43 public static class Content { 44 // @JsonBackReference 45 private Container back; 46 47 private String contentValue; 48 49 @ConstructorProperties({ "back", "contentValue" }) Content(Container back, String contentValue)50 public Content(Container back, String contentValue) { 51 this.back = back; 52 this.contentValue = contentValue; 53 } 54 getContentValue()55 public String getContentValue() { 56 return contentValue; 57 } 58 59 @JsonBackReference getBack()60 public Container getBack() { 61 return back; 62 } 63 64 @JsonPOJOBuilder(withPrefix = "") 65 public static class Builder { 66 private Container back; 67 private String contentValue; 68 69 @JsonBackReference back(Container b)70 Builder back(Container b) { 71 this.back = b; 72 return this; 73 } 74 contentValue(String cv)75 Builder contentValue(String cv) { 76 this.contentValue = cv; 77 return this; 78 } 79 build()80 Content build() { 81 return new Content(back, contentValue); 82 } 83 } 84 } 85 86 private final ObjectMapper MAPPER = sharedMapper(); 87 88 testBuildWithBackRefs2686()89 public void testBuildWithBackRefs2686() throws Exception 90 { 91 Container container = new Container(); 92 container.containerValue = "containerValue"; 93 Content content = new Content(container, "contentValue"); 94 container.forward = content; 95 96 String json = MAPPER.writeValueAsString(container); 97 Container result = MAPPER.readValue(json, Container.class); // Exception here 98 99 assertNotNull(result); 100 } 101 } 102