[Bug]: ctx.map returns MapResult items as LinkedHashMap instead of the declared result type

Cerrado
#870 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@pcbeingused333 ya está trabajando en esto.

Desde el 3/11/2026.

  • #874 de @pcbeingused333 — abierto

Evaluación

Dificultad
3/5
Tiempo estimado
1-2 días
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Estancado
Stack tecnológico
aws, java
Área
backend

Línea de trabajo

Read sdk/src/main/java/software/amazon/lambda/durable/operation/MapOperation.java and trace how itemResultType reaches the serialized MapResult. Start with the existing MapIntegrationTest cases and add coverage for a POJO item on first execution and replay. Done means both paths return items as the declared type; an open pull request is already linked to this issue.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug pkg:sdk
Expected Behavior

DurableContext.map(name, items, Class<O>, fn, config) returns a MapResult<O> whose items are instances of O. This holds on the first execution and on replay.

Actual Behavior

When O is a POJO or record, each item in the returned MapResult is a java.util.LinkedHashMap. Reading an item as O throws ClassCastException.

This happens on the first execution, not only on replay. On completion, MapOperation replaces its result with a serialize-then-deserialize copy, so the first execution returns the same value that replay returns.

Steps to Reproduce
public record Payload(String value) {}

@Test
void itemIsDeclaredType() {
    var runner = LocalDurableTestRunner.create(String.class, (input, context) -> {
        var result = context.map(
                "m",
                List.of("a", "b"),
                Payload.class,
                (item, index, ctx) -> new Payload(item),
                MapConfig.builder().build());
        Object first = result.getResult(0);
        return first.getClass().getName();
    });
    var result = runner.runUntilComplete("x");
    assertEquals(ExecutionStatus.SUCCEEDED, result.getStatus());
    assertEquals(Payload.class.getName(), result.getResult(String.class));
}

The test fails:

expected: <...$Payload> but was: <java.util.LinkedHashMap>
SDK Version

main at 3.0.1-SNAPSHOT. Also reported on 2.x. On 1.2.1 the first execution returns Payload, and replay of a completed map returns LinkedHashMap.

Java Version

17

Is this a regression?

Yes

Last Working Version

None fully. 1.2.1 is correct on the first execution and wrong on replay.

Additional Context

The cause is in MapOperation. The constructor passes new TypeToken<>() {} to its superclass as the result type (sdk/src/main/java/software/amazon/lambda/durable/operation/MapOperation.java, line 83).

  1. That anonymous class is created inside the generic class MapOperation<I, O>.
  2. So the captured type is MapResult<O>, with O still a type variable.
  3. So Jackson has no item type and deserializes each item as a LinkedHashMap.
  4. The constructor receives the caller's TypeToken<O> as itemResultType. It stores it but does not use it to build the result type.

The existing MapIntegrationTest cases use String and Integer items. Jackson deserializes those correctly without type information, so the tests do not catch the bug.

The JavaScript SDK also returns the serdes round-trip of the batch result on both paths. Its items are plain JSON objects, which already match the declared TypeScript type. So keeping the round-trip and fixing the item type keeps Java consistent with JavaScript.

Suggested fix: build a parameterized MapResult<O> type from itemResultType, for example by letting TypeToken be created from a java.lang.reflect.Type. Add integration tests with a POJO item type for the first execution and for replay.

Lenguaje dominante
Java
Estrellas
28
Forks
18
Merge medio
18 h 16 min
PR fusionados (30 d)
62

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de aws/aws-durable-execution-sdk-java

Todos los issues de aws/aws-durable-execution-sdk-java

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.