Mensajes PascalCase
¿Cómo puedo aceptar mensajes que están entrantes en formato PascalCase?
Definiendo un Custom Jackson ObjectMapper
IPF actualmente tiene una clase de utilidad llamada Serialization Helper que es un envoltorio alrededor de un Jackson ObjectMapper que registra custom serializadores/deserializadores. Esto nos permite tener un enfoque consistente al serializar/deserializar mensajes a través de la infraestructura de IPF.
Por defecto,Jackson soporte CamelCase y el Serialization Helper por lo tanto también solo soporta mensajes en CamelCase por defecto. Esto puede ser fácilmente cambiado para soportar PascalCase.
Para soportar PascalCase, usted debe definir una nueva instancia de ObjectMapper con la siguiente propiedad:
private final ObjectMapper pascalCaseMapper = SerializationHelper.objectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies. UPPER_CAMEL_CASE);
Esto puede ser utilizado cuando mapping mensajes de/para el sistema externo dentro del código del conector.
A continuación se muestra un ejemplo de ReceiveConnector y SendConnector que recibiría o enviaría mensajes en PascalCase respectivamente:
package com.iconsolutions.connector.samples.pascal;
import akka.actor.ActorSystem;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.iconsolutions.common.exception.IconRuntimeException;
import com.iconsolutions.ipf.core.connector.ReceiveConnector;
import com.iconsolutions.ipf.core.connector.ReceiveConnectorBuilderHelper;
import com.iconsolutions.ipf.core.connector.SendConnector;
import com.iconsolutions.ipf.core.connector.SendConnectorBuilderHelper;
import com.iconsolutions.ipf.core.connector.message.MessageHeaders;
import com.iconsolutions.ipf.core.connector.message.TransportMessage;
import com.iconsolutions.ipf.core.connector.transport.ConnectorTransport;
import com.iconsolutions.ipf.core.connector.transport.ReceiveConnectorTransport;
import com.iconsolutions.ipf.core.shared.correlation.CorrelationId;
import com.iconsolutions.ipf.core.shared.domain.context.ProcessingContext;
import com.iconsolutions.ipf.core.shared.domain.context.UnitOfWorkId;
import com.iconsolutions.ipf.payments.domain.clearing_and_settlement.pacs002.FIToFIPaymentStatusReport;
import com.iconsolutions.ipf.payments.domain.clearing_and_settlement.pacs008.FIToFICustomerCreditTransfer;
import com.iconsolutions.ipf.payments.domain.payment_initiation.pain001.CustomerCreditTransferInitiation;
import com.iconsolutions.samplesystems.shared.model.header.CryptoHelper;
import com.iconsolutions.simulator.api.RequestHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
@Slf4j
public class PascalConnectors {
/**
* Here set the UPPER_CASE_CAMEL (PascalCase) naming strategy
* on your ObjectMapper instance
*/
private final ObjectMapper pascalCaseMapper = SerializationHelper.objectMapper()
.setPropertyNamingStrategy(PropertyNamingStrategies.UPPER_CAMEL_CASE);
// tag::receiveConnector[]
@Bean
public ReceiveConnector<CustomerCreditTransferInitiation> executePaymentReceiveConnector(
ReceiveConnectorTransport initPaymentReceiveConnectorTransport,
RequestHandler someRequestHandler,
ActorSystem actorSystem) {
return ReceiveConnector.<CustomerCreditTransferInitiation>builder("InitPaymentReceive", "initpayment.receive-connector", actorSystem)
.withMessageLogger(m -> log.debug("Receive connector has identified message: {}", m.getMessage()))
.withProcessingContextExtractor(tm -> ProcessingContext.builder()
.unitOfWorkId(UnitOfWorkId.createRandom())
.build())
.withConnectorTransport(initPaymentReceiveConnectorTransport)
.withReceiveTransportMessageConverter(message -> this.convertResponse(message.getPayload().toString()))
.withReceiveHandler((context, payload) -> someRequestHandler.process(payload))
.build();
}
// end::receiveConnector[]
/**
* Here you would convert the incoming PAIN001 JSON message in Pascal format into your PAIN001 domain object
*/
public CustomerCreditTransferInitiation convertResponse(String messageText) {
try {
return pascalCaseMapper.readValue(messageText, CustomerCreditTransferInitiation.class);
} catch (JsonProcessingException e) {
throw new IconRuntimeException(e);
}
}
@Bean
public SendConnector<FIToFIPaymentStatusReport, FIToFIPaymentStatusReport> executePaymentSendConnector(
ConnectorTransport<FIToFIPaymentStatusReport> executePaymentReceiveConnectorTransport,
ActorSystem actorSystem) {
return SendConnector
.<FIToFIPaymentStatusReport, FIToFIPaymentStatusReport>builder("ExecutePaymentSend", "executepayment.send-connector", actorSystem)
.withMessageLogger(m -> log.debug("Send connector has identified message: {}", m.getMessage()))
.withCorrelationIdExtractor(it -> CorrelationId.of(it.getTxInfAndSts().get(0).getOrgnlTxId()))
.withConnectorTransport(executePaymentReceiveConnectorTransport)
.withSendTransportMessageConverter(this::convertToTransport)
.build();
}
/**
* Here you would convert the PACS002 domain object into Pascal formatted JSON before sending out
*/
public TransportMessage convertToTransport(FIToFIPaymentStatusReport response) {
try {
return new TransportMessage(new MessageHeaders(CryptoHelper.messageHeaders()), pascalCaseMapper.writeValueAsString(response));
} catch (JsonProcessingException e) {
throw new IllegalStateException(e);
}
}
}