Skip to content

Commit 9795b95

Browse files
committed
Rest of 3.x changes to 2.19 backported.
1 parent 17e6d67 commit 9795b95

File tree

6 files changed

+246
-120
lines changed

6 files changed

+246
-120
lines changed

release-notes/VERSION-2.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,11 @@ NOTE: Annotations module will never contain changes in patch versions,
1111
=== Releases ===
1212
------------------------------------------------------------------------
1313

14+
2.19.2 (not yet released)
15+
16+
- Minor forwards-compatibility changes (to support upcoming Jackson 3.0)
17+
(only mentioned wrt binary-compability checking tools)
18+
1419
2.19.1 (13-Jun-2025)
1520

1621
- No functional changes, but released via Sonatype Central Portal

src/main/java/com/fasterxml/jackson/annotation/JacksonInject.java

Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -31,39 +31,47 @@
3131
* if disabled (`OptBoolean.FALSE`), input value (if any) will be ignored;
3232
* otherwise it will override injected value.
3333
*<p>
34-
* Default is `OptBoolean.DEFAULT`, which translates to `OptBoolean.TRUE`: this is
35-
* for backwards compatibility (2.8 and earlier always allow binding input value).
34+
* Default is `OptBoolean.DEFAULT`, which translates to `OptBoolean.TRUE`.
3635
*
3736
* @return {@link OptBoolean#TRUE} to enable use of value from input instead of
3837
* injected value, if available; {@link OptBoolean#FALSE} if injected value will
3938
* always be used regardless of input.
40-
*
41-
* @since 2.9
4239
*/
4340
public OptBoolean useInput() default OptBoolean.DEFAULT;
4441

42+
/**
43+
* Whether to throw an exception when the {@code ObjectMapper} does not find
44+
* the value to inject.
45+
*<p>
46+
* Default is {@code OptBoolean.DEFAULT} for backwards-compatibility: in this
47+
* case {@code ObjectMapper} defaults are used (which in turn are same
48+
* as {code OptBoolean.FALSE}).
49+
*
50+
* @return {@link OptBoolean#FALSE} to throw an exception; {@link OptBoolean#TRUE}
51+
* to avoid throwing it; or {@link OptBoolean#DEFAULT} to use configure defaults
52+
* (which are same as {@link OptBoolean#FALSE} for Jackson 2.x)
53+
*/
54+
public OptBoolean optional() default OptBoolean.DEFAULT;
55+
4556
/*
46-
/**********************************************************
47-
/* Value class used to enclose information, allow for
48-
/* merging of layered configuration settings, and eventually
49-
/* decouple higher level handling from Annotation types
50-
/* (which can not be implemented etc.)
51-
/**********************************************************
57+
/**********************************************************************
58+
/* Value class used to enclose information, allow for merging of layered
59+
/* configuration settings, and eventually decouple higher level handling
60+
/* from Annotation types (which can not be implemented etc.)
61+
/**********************************************************************
5262
*/
5363

5464
/**
5565
* Helper class used to contain information from a single {@link JacksonInject}
5666
* annotation, as well as to provide possible overrides from non-annotation sources.
57-
*
58-
* @since 2.9
5967
*/
6068
public static class Value
6169
implements JacksonAnnotationValue<JacksonInject>,
6270
java.io.Serializable
6371
{
6472
private static final long serialVersionUID = 1L;
6573

66-
protected final static Value EMPTY = new Value(null, null);
74+
protected final static Value EMPTY = new Value(null, null, null);
6775

6876
/**
6977
* Id to use to access injected value; if `null`, "default" name, derived
@@ -73,9 +81,12 @@ public static class Value
7381

7482
protected final Boolean _useInput;
7583

76-
protected Value(Object id, Boolean useInput) {
84+
protected final Boolean _optional;
85+
86+
protected Value(Object id, Boolean useInput, Boolean optional) {
7787
_id = id;
7888
_useInput = useInput;
89+
_optional = optional;
7990
}
8091

8192
@Override
@@ -84,40 +95,40 @@ public Class<JacksonInject> valueFor() {
8495
}
8596

8697
/*
87-
/**********************************************************
98+
/******************************************************************
8899
/* Factory methods
89-
/**********************************************************
100+
/******************************************************************
90101
*/
91102

92103
public static Value empty() {
93104
return EMPTY;
94105
}
95106

96-
public static Value construct(Object id, Boolean useInput) {
107+
public static Value construct(Object id, Boolean useInput, Boolean optional) {
97108
if ("".equals(id)) {
98109
id = null;
99110
}
100-
if (_empty(id, useInput)) {
111+
if (_empty(id, useInput, optional)) {
101112
return EMPTY;
102113
}
103-
return new Value(id, useInput);
114+
return new Value(id, useInput, optional);
104115
}
105116

106117
public static Value from(JacksonInject src) {
107118
if (src == null) {
108119
return EMPTY;
109120
}
110-
return construct(src.value(), src.useInput().asBoolean());
121+
return construct(src.value(), src.useInput().asBoolean(), src.optional().asBoolean());
111122
}
112123

113124
public static Value forId(Object id) {
114-
return construct(id, null);
125+
return construct(id, null, null);
115126
}
116127

117128
/*
118-
/**********************************************************
129+
/******************************************************************
119130
/* Mutant factory methods
120-
/**********************************************************
131+
/******************************************************************
121132
*/
122133

123134
public Value withId(Object id) {
@@ -128,7 +139,7 @@ public Value withId(Object id) {
128139
} else if (id.equals(_id)) {
129140
return this;
130141
}
131-
return new Value(id, _useInput);
142+
return new Value(id, _useInput, _optional);
132143
}
133144

134145
public Value withUseInput(Boolean useInput) {
@@ -139,17 +150,29 @@ public Value withUseInput(Boolean useInput) {
139150
} else if (useInput.equals(_useInput)) {
140151
return this;
141152
}
142-
return new Value(_id, useInput);
153+
return new Value(_id, useInput, _optional);
154+
}
155+
156+
public Value withOptional(Boolean optional) {
157+
if (optional == null) {
158+
if (_optional == null) {
159+
return this;
160+
}
161+
} else if (optional.equals(_optional)) {
162+
return this;
163+
}
164+
return new Value(_id, _useInput, optional);
143165
}
144166

145167
/*
146-
/**********************************************************
168+
/******************************************************************
147169
/* Accessors
148-
/**********************************************************
170+
/******************************************************************
149171
*/
150172

151173
public Object getId() { return _id; }
152174
public Boolean getUseInput() { return _useInput; }
175+
public Boolean getOptional() { return _optional; }
153176

154177
public boolean hasId() {
155178
return _id != null;
@@ -160,15 +183,15 @@ public boolean willUseInput(boolean defaultSetting) {
160183
}
161184

162185
/*
163-
/**********************************************************
164-
/* Std method overrides
165-
/**********************************************************
186+
/******************************************************************
187+
/* Standard method overrides
188+
/******************************************************************
166189
*/
167190

168191
@Override
169192
public String toString() {
170-
return String.format("JacksonInject.Value(id=%s,useInput=%s)",
171-
_id, _useInput);
193+
return String.format("JacksonInject.Value(id=%s,useInput=%s,optional=%s)",
194+
_id, _useInput, _optional);
172195
}
173196

174197
@Override
@@ -180,6 +203,9 @@ public int hashCode() {
180203
if (_useInput != null) {
181204
h += _useInput.hashCode();
182205
}
206+
if (_optional != null) {
207+
h += _optional.hashCode();
208+
}
183209
return h;
184210
}
185211

@@ -189,24 +215,25 @@ public boolean equals(Object o) {
189215
if (o == null) return false;
190216
if (o.getClass() == getClass()) {
191217
Value other = (Value) o;
192-
if (OptBoolean.equals(_useInput, other._useInput)) {
193-
if (_id == null) {
194-
return other._id == null;
195-
}
196-
return _id.equals(other._id);
197-
}
218+
219+
return (_id == null && other._id == null
220+
|| _id != null && _id.equals(other._id))
221+
&& (_useInput == null && other._useInput == null
222+
|| _useInput != null && _useInput.equals(other._useInput))
223+
&& (_optional == null && other._optional == null
224+
|| _optional != null && _optional.equals(other._optional));
198225
}
199226
return false;
200227
}
201228

202229
/*
203-
/**********************************************************
230+
/******************************************************************
204231
/* Other
205-
/**********************************************************
232+
/******************************************************************
206233
*/
207234

208-
private static boolean _empty(Object id, Boolean useInput) {
209-
return (id == null) && (useInput == null);
235+
private static boolean _empty(Object id, Boolean useInput, Boolean optional) {
236+
return (id == null) && (useInput == null) && optional == null;
210237
}
211238
}
212239
}

0 commit comments

Comments
 (0)