Repository navigation
fix(map): return items as the declared type from MapOperation - #874
Conversation
zhongkechen
left a comment
There was a problem hiding this comment.
Thank you for your contribution. Left a comment for the new ParameterizedType.
…izedType contract
| public static <U> TypeToken<U> of(Type type) { | ||
| return new TypeToken<>(type) {}; | ||
| } |
There was a problem hiding this comment.
Codex AI review · Finding arf_v1_exti74gecpzis5h27y5gqj3mzd
[P2] Complete the design alternatives for the public API addition. Rules 2.5 and 3.3 require concrete alternatives, including simplification of existing logic, and reasons for rejecting them. The description explains why the existing anonymous capture fails, but citing #870 and stating “none simpler” does not evaluate an alternative or justify exposing a general public factory. This introduces a lasting API contract without the required scope analysis. Please return to the design phase under rule 8, step 6, and document the alternatives and chosen API scope before proceeding.
To suppress repeats, reply /ai verdict deferred, /ai verdict false-positive, or /ai verdict out-of-scope on the first nonblank line. Add rationale on later lines. A new /ai verdict accepted allows future repeats again.
| && getRawType().equals(that.getRawType()) | ||
| && that.getOwnerType() == null |
There was a problem hiding this comment.
Codex AI review · Finding arf_v1_yuqlni6oon2q5cnp3sjkqll4se
[P2] Revisit the equality conditions under rule 4. The new equality tests compare only parameterized MapResult types with null owners; their negative case changes only the item type. Removing either the raw-type comparison or the owner check leaves those assertions unchanged, so these added conditions lack the behavior-distinguishing tests required by “Every branch has a test that fails without it.” The claimed cache-key contract is therefore incompletely guarded. Please return to the design phase under rule 8, step 6, and establish which conditions the contract needs and how each will be demonstrated.
To suppress repeats, reply /ai verdict deferred, /ai verdict false-positive, or /ai verdict out-of-scope on the first nonblank line. Add rationale on later lines. A new /ai verdict accepted allows future repeats again.
Codex AI reviewTwo approach findings: incomplete design alternatives at Reviewed commit |
| * @param <U> the type | ||
| * @return a TypeToken representing the given type | ||
| */ | ||
| public static <U> TypeToken<U> of(Type type) { |
There was a problem hiding this comment.
The type parameter U does not appear in the argument, so TypeToken<String> t = TypeToken.of(Integer.class) compiles, and a null argument is accepted and fails later. Since of is new and unreleased, we can still think about the signature. Could this return TypeToken<?>, call Objects.requireNonNull(type, ...), and keep the unchecked cast inside MapOperation.mapResultType? (Maybe also have a direct test of this case?)
The type parameter did not appear in the argument, so a caller could pick any T, and a null type failed later. Keep the unchecked cast inside MapOperation.mapResultType and add direct tests for of().
|
Done in e567ed3: This comment was drafted with Claude Code. |
yaythomas
left a comment
There was a problem hiding this comment.
Thank you so much for the quick turnaround, @pcbeingused333! 🙇
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
Issue Link, if available
Fixes #870
Description
MapOperationreturned its items asLinkedHashMapinstead of the declared item type. The superclass was givennew TypeToken<>() {}created inside the genericMapOperation<I, O>, so the captured type wasMapResult<O>withOstill a type variable and Jackson had no item type. This also affects the first execution, becauseMapOperationreplaces its result with the serialize-then-deserialize copy. The fix builds theMapResult<O>type from theitemResultTypethe constructor already receives, and addsTypeToken.of(Type)(the approach suggested in the issue).Demo/Screenshots
Not applicable.
Design
TypeToken.of(Type)) is the fix suggested in [Bug]: ctx.map returns MapResult items as LinkedHashMap instead of the declared result type #870.TypeToken<O>, and the anonymous-class capture cannot see it.TypeTokenin the genericMapOperationcaptures an unresolved type variable, so Jackson deserializes items asLinkedHashMap.TypeToken.of).Assumptions
TypeFactory.constructTypeaccepts a customParameterizedTypeimplementation. Evidence:MapIntegrationTestpasses with record items on first execution and replay.JacksonSerDescaches byTypein an unbounded map, so the new type needs value equality or each operation leaks an entry. Evidence:JacksonSerDes.typeCache(computeIfAbsent); the type is a record andMapOperationTypeTestchecks equals/hashCode.Decisions not covered by the issue or the design note
ParameterizedTypeis a private record inMapOperation: records giveequals/hashCodefor free, and nothing else needs it.Checklist
Testing
Unit Tests
Yes.
MapOperationTypeTestchecks that twomapResultType(x)tokens are equal with equal hash codes, and differ for a different item type.Integration Tests
Yes.
MapIntegrationTest.testPojoItemsKeepDeclaredTypeOnFirstExecutionAndReplaymaps to a record type and reads the items as that type on the first execution and on replay. It fails without the change and passes with it; the full class (110 tests) passes.Examples
Not applicable.
This change was prepared with the assistance of an AI coding tool (Claude) and reviewed before submission.