Allow multiple @JacksonInject targets for same id (#5217)#5609
Allow multiple @JacksonInject targets for same id (#5217)#5609dlwldnjs1009 wants to merge 13 commits intoFasterXML:3.xfrom
Conversation
Switch injectables map value to List<AnnotatedMember> to support multiple @JacksonInject targets for same id. Keep existing masking rules (creator param masks same-property members, setter masks field) and add explicit failure for setter-setter conflicts on same property/id. Add memoized member->property lookup + tests.
Verify field-field and param-param don't fail with "Duplicate injectable value" error when InjectableValues is not configured. This directly tests the original issue's expected behavior: consistent error across all cases.
Verify field-field and param-param both throw MissingInjectableValueExcepion (same exception type), proving error path convergence per issue's expected behavior: "The same error should be made in all cases."
- testRecordWithRenamedInjectableProperty: record with renamed injectable - testRecordRenamedPlusDifferentFieldBothInjected: renamed creator + different property field with same ID should both be injected
| } | ||
|
|
||
| public Map<Object, AnnotatedMember> getInjectables() { | ||
| public Map<Object, List<AnnotatedMember>> getInjectables() { |
There was a problem hiding this comment.
This is, technically speaking, incompatible API change.
For compatibility we probably need to add new method (with different name since cannot overload) (getAllInjectables()?) with simple implementation but then re-implement old "old" version which needs to take and return first value of List members. Old version should be deprecated.
There was a problem hiding this comment.
Agreed, this can't work due to compatibility issue At least AS-IS.
| return; | ||
| } | ||
| for (POJOPropertyBuilder creatorProp : _creatorProperties) { | ||
| if (creatorProp == null) { |
src/main/java/tools/jackson/databind/introspect/POJOPropertyBuilder.java
Outdated
Show resolved
Hide resolved
| */ | ||
|
|
||
| public abstract Map<Object, AnnotatedMember> findInjectables(); | ||
| public abstract Map<Object, List<AnnotatedMember>> findInjectables(); |
There was a problem hiding this comment.
Ouch. And even here we have API change... same approach.
|
Hmmh. Good job figuring out how to make this work. My main concern is the whole addition of complexity and additional significant extra-processing. Almost to the degree I wonder if it's all worth it, or if different re-factoring/rethinking was needed. I'll have to think about this; probably should want after 3.1 at this point. |
|
@cowtowncoder I noticed the exception class name I didn’t change it here since renaming would be a public API change. |
…asterXML#4218) - Restore findInjectables() signature to Map<Object, AnnotatedMember> with @deprecated; add findAllInjectables() as concrete default method - Remove _deduplicateSamePropertyInjectables (setter-masks-field policy) and _isMethod helper to reduce complexity per review feedback - Keep only _removeCreatorPropertyInjectables for FasterXML#4218 fix - Add getAllInjectables() / getInjectables() pair on POJOPropertiesCollector with defensive copy and freeze of value lists - Switch BeanDeserializerFactory to findAllInjectables() - Add default-id field-field regression, behavior, and API shape tests - Remove Rule 2 tests (testFieldAndSetterSameProperty etc.)
Ah. I think I must have noticed it at some point but not before 3.0 release. Yes, a separate PR would be make sense, targeting 3.x (for 3.1), creating correctly named sub-class (I think?) exception, deprecating misspelled one and so on. |
This PR changes injectable collection to allow multiple injection targets for the same id (#5217).
Behavioral goal (#5217)
Implementation
Map<Object, List<AnnotatedMember>>to support multiple targets per id.@JacksonInjectis specified for field and deserialized by the Creator, the inject process will be executed twice #4218 fix: creator parameter masks same-property field/setter injectables.getAllInjectables()returns an unmodifiable copy of the map; value lists are frozen duringcollectAll().API compatibility (revised per review feedback)
BeanDescription#findInjectables()signature restored toMap<Object, AnnotatedMember>and deprecated.BeanDescription#findAllInjectables()added as a concrete default method returningMap<Object, List<AnnotatedMember>>.This avoids breaking custom
BeanDescriptionimplementations that only override the legacy method.POJOPropertiesCollector#getInjectables()deprecated; newgetAllInjectables()added.BeanDeserializerFactory) switched tofindAllInjectables().Complexity reduction (revised per review feedback)
_deduplicateSamePropertyInjectables()(setter-masks-field + reportProblem policy) as it was beyond the scope of ADuplicate injectable value ...error occurs only when the same IDJacksonInjectis specified for a field multiple times #5217._isMethod()helper (only used by the above)._removeCreatorPropertyInjectables()for the If@JacksonInjectis specified for field and deserialized by the Creator, the inject process will be executed twice #4218 duplicate-injection bug fix.Duplicate injectable value ...error occurs only when the same IDJacksonInjectis specified for a field multiple times #5217 consistency + If@JacksonInjectis specified for field and deserialized by the Creator, the inject process will be executed twice #4218.Tests
@JacksonInjectis specified for field and deserialized by the Creator, the inject process will be executed twice #4218) / record tests retained.testFieldAndSetterSameProperty,testFieldSetterWithJsonProperty,testTwoInjectableSettersSamePropertyFails) since the policy was removed.Duplicate injectable value ...error occurs only when the same IDJacksonInjectis specified for a field multiple times #5217 reproduction with default IDs (type-based):testDefaultIdFieldFieldNoDuplicateError(regression: no "Duplicate injectable value" error)testDefaultIdFieldFieldBothInjected(behavior: both fields receive injected value)testFindAllInjectablesMultipleMembersForDefaultId(API shape:findAllInjectables()exposes 2+ members per ID)Revised per review feedback from @cowtowncoder.