1 package com.fasterxml.jackson.failing; 2 3 import java.util.Objects; 4 5 import com.fasterxml.jackson.annotation.*; 6 7 import com.fasterxml.jackson.databind.*; 8 import com.fasterxml.jackson.databind.exc.ValueInstantiationException; 9 10 // For [databind#1921]: Creator method not used when merging even if there is 11 // no feasible alternative. Unclear whether this can even theoretically be 12 // improved since combination of Creator + Setter(s)/field is legit; but use 13 // of Creator always means that operation is not true merge. 14 // But added test just in case future brings us a good idea of way forward. 15 public class MergeWithCreator1921Test extends BaseMapTest 16 { 17 static class Account { 18 @JsonMerge(value = OptBoolean.TRUE) 19 private final Validity validity; 20 21 @JsonCreator Account(@sonPropertyvalue = "validity", required = true) Validity validity)22 public Account(@JsonProperty(value = "validity", required = true) Validity validity) { 23 this.validity = validity; 24 } 25 getValidity()26 public Validity getValidity() { 27 return validity; 28 } 29 } 30 31 static class Validity { 32 public static final String VALID_FROM_CANT_BE_NULL = "Valid from can't be null"; 33 public static final String VALID_TO_CANT_BE_BEFORE_VALID_FROM = "Valid to can't be before valid from"; 34 35 private final String _validFrom; 36 private final String _validTo; 37 38 @JsonCreator Validity(@sonPropertyvalue = "validFrom", required = true) String validFrom, @JsonProperty("validTo") String validTo)39 public Validity(@JsonProperty(value = "validFrom", required = true) String validFrom, 40 @JsonProperty("validTo") String validTo) { 41 checkValidity(validFrom, validTo); 42 43 this._validFrom = validFrom; 44 this._validTo = validTo; 45 } 46 checkValidity(String from, String to)47 private void checkValidity(String from, String to) { 48 Objects.requireNonNull(from, VALID_FROM_CANT_BE_NULL); 49 if (to != null) { 50 if (from.compareTo(to) > 0) { 51 throw new IllegalStateException(VALID_TO_CANT_BE_BEFORE_VALID_FROM); 52 } 53 } 54 } 55 getValidFrom()56 public String getValidFrom() { 57 return _validFrom; 58 } 59 getValidTo()60 public String getValidTo() { 61 return _validTo; 62 } 63 } 64 testMergeWithCreator()65 public void testMergeWithCreator() throws Exception 66 { 67 final String JSON = "{ \"validity\": { \"validFrom\": \"2018-02-01\", \"validTo\": \"2018-01-31\" } }"; 68 69 final ObjectMapper mapper = newJsonMapper(); 70 71 try { 72 mapper.readValue(JSON, Account.class); 73 fail("Should not pass"); 74 } catch (ValueInstantiationException e) { 75 verifyException(e, "Cannot construct"); 76 verifyException(e, Validity.VALID_TO_CANT_BE_BEFORE_VALID_FROM); 77 } 78 79 try { 80 Account acc = new Account(new Validity("abc", "def")); 81 mapper.readerForUpdating(acc) 82 .readValue(JSON); 83 fail("Should not pass"); 84 } catch (ValueInstantiationException e) { 85 verifyException(e, "Cannot construct"); 86 verifyException(e, Validity.VALID_TO_CANT_BE_BEFORE_VALID_FROM); 87 } 88 } 89 } 90