Recuperando datos del padre desde un hijo

Por defecto, cuando un padre flow calls En un flujo secundario, las estructuras de datos relacionadas con el flujo principal no están disponibles en el flujo secundario.

Una de las situaciones en las que podríamos desear recuperar las estructuras de datos parentales es en bulking/debulking El procesamiento se divide en niveles, con muchos niveles C (información del acreedor) requeridos por cada nivel B (información del deudor). Al procesar el nivel C, es necesario acceder a la información del deudor para la reserva/liquidación.

Accediendo al Flujo Principal

En ausencia de otras alternativas, para acceder a estas estructuras (como el MDS y PDS), se requeriría una llamada a través de un dominio externo para ODS para recuperar la información.

Sin embargo, hay maneras mejores y más eficientes de recuperar esta información:

1) Si el padre está desplegado en un servicio de procesamiento separado, entonces necesitamos utilizar API de transactionOperation desplegado en el servicio principal, que contiene un punto final que permite que se recupere el agregado.

2) Si el padre está presente en el mismo servicio de procesamiento. En esta situación, las estructuras de datos pueden ser recuperadas del dominio flo. API.

Utilizando el dominio flo API

Esto asume que el flujo principal está disponible en el mismo servicio de procesamiento.

Una alternativa a una llamada a ODS para recuperar los datos se utiliza una llamada a getAggregate desde el flo-domain API, donde tanto el flujo padre como el flujo hijo están en el mismo servicio de procesamiento.

Esto hace uso del hecho de que una acción secundaria conoce el Id de flujo que la llamó, y como tal, los datos pueden ser recuperados.

La clase Aggregate especificada como un parámetro en la llamada pertenece al flujo padre, aunque, por supuesto, la recuperación está ocurriendo durante el procesamiento dentro de la acción del flujo hijo.

En la situación a continuación, el TransactionFlow se está llamando desde el BatchFlow, por lo que el agregado que se está recuperando es el BatchFlowAggregate.

import debulkexamplemodel.domain. DebulkexamplemodelModelOperations;
[...]
debulkexamplemodelModelOperations.getAggregate(parentId, BatchFlowAggregate.class)

Procesando los valores

MDS y PDS los valores se filtran del agregado padre para su uso:
return debulkexamplemodelModelOperations.getAggregate(parentId, BatchFlowAggregate.class)
                .thenAccept(batchFlowAggregate -> {
                    MdsWrapper<PaymentInstruction30> parentMdsValues = batchFlowAggregate.getPain001Instruction();
                    List<? extends DataElementWrapper<?>> parentPdsValues = batchFlowAggregate.businessData().values()
                            .stream()
                            .filter(dataElementWrapper -> dataElementWrapper.getCategory().equals("PROCESSING_DATA_STRUCTURE"))
                            .toList();
                });

Usando el cache

Además de esto, si se está recuperando el mismo id de padre múltiples veces,caching sería útil.ipf-cache debe utilizarse para esto, para reducir el uso repetido de getAggregate.

Para facilitar esto, se puede añadir la siguiente entrada al pom.xml

<dependency>
    <groupId>com.iconsolutions.ipf.core.platform</groupId>
    <artifactId>ipf-cache-api</artifactId>
</dependency>
<dependency>
    <groupId>com.iconsolutions.ipf.core.platform</groupId>
    <artifactId>ipf-cache-caffeine</artifactId>
</dependency>

Documentación adicional sobre cómo configurar el cache para uso es aquí.

Al hacer esto, se puede utilizar una implementación que evite los inconvenientes asociados con la relectura del agregado. Más detalles aquí.

Implementando el cache

Cuando todo esto se reúne en el ActionAdapter para el flujo secundario, podemos tener algo como lo siguiente:

private final DebulkexamplemodelModelOperations debulkexamplemodelModelOperations;
private final CacheAdapter<String, MdsPdsWrapper> cacheAdapter;

private Optional<MdsPdsWrapper> getFromCache(String parentId) {
    var mdsPdsWrapper = cacheAdapter.get(parentId);
    if (mdsPdsWrapper.isPresent()) {
        log.debug("Existing MdsPdsWrapper retrieved from cache; parentId:{} mdsPdsWrapper:{}", parentId, mdsPdsWrapper);
    }
    return mdsPdsWrapper;
}


CompletionStage<Void> getFromCacheOrLoad(String parentId) {
    return getFromCache(parentId).isPresent()?
            CompletableFuture.completedFuture(null):
            retrieveParentMdsPdsWrapper(parentId);
}

private CompletionStage<Void> retrieveParentMdsPdsWrapper(String parentId) {
    return debulkexamplemodelModelOperations.getAggregate(parentId, BatchFlowAggregate.class)
            .thenAccept(batchFlowAggregate -> {
                MdsWrapper<PaymentInstruction30> parentMdsValues = batchFlowAggregate.getPain001Instruction();
                List<? extends DataElementWrapper<?>> parentPdsValues = batchFlowAggregate.businessData().values()
                        .stream()
                        .filter(dataElementWrapper -> dataElementWrapper.getCategory().equals("PROCESSING_DATA_STRUCTURE"))
                        .toList();
                MdsPdsWrapper mdsPdsWrapper = new MdsPdsWrapper(parentMdsValues, parentPdsValues);
                cacheAdapter.put(parentId, mdsPdsWrapper);
                log.debug("Loaded into cache -- parentId:{} mdsPdsWrapper:{}", parentId, mdsPdsWrapper);
            });
}
El MdsWrapper la clase es un POJO que se añadió para simplificar los valores almacenados en el cache.