camel-quarkus icon indicating copy to clipboard operation
camel-quarkus copied to clipboard

How to use cache in Apache Camel Quarkus

Open cesarjv opened this issue 8 months ago • 7 comments

Good morning

I am currently working with camel in quarkus and I want to implement cache when making calls to other APIs, however, I have doubts when implementing it in my ResRoute classes:

Class ResRoute

@ApplicationScoped
public class ResRoute extends RouteBuilder {

    @ConfigProperty(name = "client.findIndividualCustomerByDocId")
    String findIndividualCustomerByDocId;
    @ConfigProperty(name = "client.findOrganizacionCustomerByDocId")
    String findOrganizacionCustomerByDocId;
    @ConfigProperty(name = "path.openapi")
    String pathOpenapi;
    @ConfigProperty(name = "descripcion.servicio")
    String descripcionServicio;
    private ConfigureSsl configureSsl;
    private static final String SALIDA_BSS_EXCEPTION = "Salida del microservicio BSS FindCustomerByDocId ${exchangeProperty[bodyRs]}";
    private static final String MSG_EXCEPTION = "Descripcion de la Exception: ${exception.message}";

    public ResRoute() {
        configureSsl = new ConfigureSsl();
    }

    @Override
    public void configure() throws Exception {

        BeanDate beanDate= new BeanDate();
        getContext().getRegistry().bind("BeanDate",beanDate);
        restConfiguration()
                .bindingMode(RestBindingMode.json)
                .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES")
                .apiContextPath(pathOpenapi)
                .apiProperty("api.title", "FindCustomerByDocId")
                .apiProperty("api.description", descripcionServicio)
                .apiProperty("api.version", "1.0.0")
                .apiProperty("cors", "true");

        rest("customerInformation/v1.4.0/users/")
                .get("/{user_id}/customers").to("direct:/{user_id}/customers")
                .outType(Customer.class)
                .param().name("FindCustomerByDocIdResponse").type(body).description("parametro de salida").required(true)
                .endParam()
                .to("direct:pipeline");

        from("direct:pipeline")
                .doTry()
                .process(new FindCustomerByDocIdProcessorReq())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"User ID: ${exchangeProperty[userId]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Correlator ID: ${exchangeProperty[correlatorId]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Tipo de Documento (Num): ${exchangeProperty[documentTypeNum]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Tipo de Cliente: ${exchangeProperty[customerType]}")
                .choice()
                .when(simple("${exchangeProperty[customerType]} == 'NATURAL'"))
                .process(new FindIndividualCustomerByDocIdProcessorReq())
                .to(configureSsl.setupSSLContext(getCamelContext(), findIndividualCustomerByDocId))
                .process(new FindIndividualCustomerByDocIdProcessorRes())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio FindIndividualCustomerByDocId ${exchangeProperty[findIndividualCustomerByDocIdResponse]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio BSS FindCustomerByDocId ${exchangeProperty[findCustomerByDocIdResponse]}")
                .when(simple("${exchangeProperty[customerType]} == 'JURIDICO'"))
                .process(new FindOrganizationCustomerByDocIdProcessorReq())
                /*.log("\n["+getCurrentDate()+"]"+"Entrada del microservicio FindOrganizationCustomerByDocId ${exchangeProperty[findOrganizationCustomerByDocIdRequest]}") */
                .to(configureSsl.setupSSLContext(getCamelContext(), findOrganizacionCustomerByDocId))
                .process(new FindOrganizationCustomerByDocIdProcessorRes())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio FindOrganizationCustomerByDocId ${exchangeProperty[findOrganizationCustomerByDocIdResponse]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio BSS FindCustomerByDocId ${exchangeProperty[findCustomerByDocIdResponse]}")
                .endChoice()
                .endDoTry()
                .doCatch(RequiredValueException.class)
                .process(new FindCustomerByDocIdProcessorInvalidFormatException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(HttpHostConnectException.class)
                .process(new FindCustomerByDocIdProcessorHttpHostConectionException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(NotFoundDataException.class)
                .process(new FindCustomerByDocIdProcessorInformationSubscriber())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(UnknownHostException.class)
                .process(new FindCustomerByDocIdProcessorHttpHostConectionException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(NoHttpResponseException.class)
                .process(new FindCustomerByDocIdProcessorHttpHostConectionException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(Exception.class)
                .process(new FindCustomerByDocIdProcessorException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION);
    }
}

In this part he called one of the microservices:

                .when(simple("${exchangeProperty[customerType]} == 'NATURAL'"))
                .process(new FindIndividualCustomerByDocIdProcessorReq())
                .to(configureSsl.setupSSLContext(getCamelContext(), findIndividualCustomerByDocId))
                .process(new FindIndividualCustomerByDocIdProcessorRes())

In the FindIndividualCustomerByDocIdProcessorReq class I create the Request for the call:


@Slf4j
public class FindIndividualCustomerByDocIdProcessorReq implements Processor {

    private IFindIndividualCustomerByDocIdMapping findIndividualCustomerByDocIdMapping;
    private ObjectMapper objectMapper;

    public FindIndividualCustomerByDocIdProcessorReq() {
        findIndividualCustomerByDocIdMapping = new FindIndividualCustomerByDocumentRequestMappingImpl();
        objectMapper = new ObjectMapper();
    }
    @Override
    public void process(Exchange exchange) throws Exception {

        String documentType = exchange.getProperty("documentTypeNum").toString();
        String documentNumber = exchange.getProperty("documentNumber").toString();
        String userId=exchange.getProperty("userId").toString();
        FindIndividualCustomerByDocIdInput findIndividualCustomerByDocIdInput;
        findIndividualCustomerByDocIdInput = findIndividualCustomerByDocIdMapping.toRequest(documentType,documentNumber,userId);
        String jsonFindIndividualCustomerByDocIdRq = objectMapper.writeValueAsString(findIndividualCustomerByDocIdInput);
        exchange.setProperty("findIndividualCustomerByDocIdRq", findIndividualCustomerByDocIdInput);
        exchange.setProperty("findIndividualCustomerByDocIdRequest", jsonFindIndividualCustomerByDocIdRq);
        exchange.getOut().setHeader(Exchange.CONTENT_TYPE, "application/json");
        exchange.getOut().setHeader(Exchange.HTTP_METHOD, "POST");
        exchange.getOut().setBody(jsonFindIndividualCustomerByDocIdRq);
    }
}

The request that is created is like the following:

{
    "FindIndividualCustomerByDocId": {
        "Header": {
            "country": "VE",
            "lang": "ES",
            "entity": "TMVE",
            "system": "97",
            "subsystem": "APP",
            "origin": "VE:TMVE:97:APP",
            "userId": "4242374781",
            "operation": "FindOrganizationCustomerByDocId",
            "destiny": "VE:TMVE:93:RSB",
            "timestamp": "2021-01-20T10:23:23.233-04:00",
            "msgType": "REQUEST"
        },
        "Body": {
            "findIndividualCustomerByDocIdRequest": {
                "documentType": "1",
                "documentNumber": "2056133",
                "idCountry": "1"
            }
        }
    }
}

If I have 2 fields that must be mandatory (documentType and documentNumber), would it be a key with both fields or can it be just one?

In the FindIndividualCustomerByDocIdProcessorRes class I create the Response for the service response:

@Slf4j
@ApplicationScoped
public class FindIndividualCustomerByDocIdProcessorRes implements Processor {

    public ObjectMapper objectMapper;
    public IContactMediaMapping contactMediaMapping;

    public FindIndividualCustomerByDocIdProcessorRes() {
        objectMapper = new ObjectMapper();
        contactMediaMapping=new ContactMediaMapping();
    }
    @Override
    public void process(Exchange exchange) throws Exception {

        String bodyResponse=exchange.getIn().getBody(String.class);
        FindIndividualCustomerByDocIdOutput findIndividualCustomerByDocIdRs=objectMapper.readValue(bodyResponse,FindIndividualCustomerByDocIdOutput.class);
        String jsonFindIndividualCustomerByDocIdRs = objectMapper.writeValueAsString(findIndividualCustomerByDocIdRs);
        exchange.setProperty("findIndividualCustomerByDocIdResponse", jsonFindIndividualCustomerByDocIdRs);
        String msgType=findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getHeaderResponse().getMsgType();
        String documentType= (String) exchange.getProperty("documentType");
        String documentNumber= (String) exchange.getProperty("documentNumber");
        String userId= (String) exchange.getProperty("userId");

        if(msgType.equals("ERROR")) {
            try {
                String msgError = findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponseFault()
                        .getExceptionCode();
                log.info("Código Error Microservice FindIndividualCustomerByDocId: "+findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponseFault().getExceptionCode());
                log.info("Mensaje Error MicroserviceFindIndividualCustomerByDocId: "+findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponseFault().getExceptionMessage());
                if (msgError.equals("MSG001") || msgError.equals("MSG002") ) {
                    throw new InvalidFormatException("Error al validar parametros de entradas");
                } else if (msgError.equals("MSG062")) {
                    throw new NotFoundDataException("No se encontro informacion asociado al cliente");
                } else if(msgError.equals("MSG019") || msgError.equals("MSG162") || msgError.equals("MSG020")){
                    throw new Exception("Ha ocurrido un error al realizar la operacion");
                }
            } catch (UnknownHostException e) {
                throw new UnknownHostException("Error de comunicacion con Host Receptor");
            }
        }

        Document document=new Document("VE",documentType,documentNumber);
        ArrayList<ContactMedia> contactMedia=new ArrayList<>();
        String contactMediaFavorite=findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponse().getPreferredContactMedium();
        String email=findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponse().getEmailAddress();
        String phoneNumber=findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponse().getTelephoneNumber();
        contactMedia=contactMediaMapping.toRequest(email,phoneNumber,contactMediaFavorite);
        String name=findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponse().getName()+" "+findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponse().getLastName();
        String customerSince= String.valueOf(findIndividualCustomerByDocIdRs.getFindIndividualCustomerByDocIdResponseHB().getFindIndividualCustomerByDocIdBodyResponse().getFindIndividualCustomerByDocIdResponse().getCustomerSince());
        Customer customer=new Customer(userId,name,document,contactMedia, Segment.CONSUMER.getType(), customerSince);
        String jsonFindCustomerByDocIdRs = objectMapper.writeValueAsString(customer);
        exchange.setProperty("findCustomerByDocIdRs", customer);
        exchange.setProperty("findCustomerByDocIdResponse", jsonFindCustomerByDocIdRs);
        exchange.getMessage().setHeader(Exchange.CONTENT_TYPE, "application/json");
        exchange.getMessage().setHeader(Exchange.HTTP_RESPONSE_CODE, "200");
        exchange.getMessage().setBody(customer);
    }
}

My question is how can I edit my code to add cache to my calls?

I tried the following way, but it gives me an error code http 500:

@ApplicationScoped
public class ResRoute extends RouteBuilder {

    @ConfigProperty(name = "client.findIndividualCustomerByDocId")
    String findIndividualCustomerByDocId;
    @ConfigProperty(name = "client.findOrganizacionCustomerByDocId")
    String findOrganizacionCustomerByDocId;
    @ConfigProperty(name = "path.openapi")
    String pathOpenapi;
    @ConfigProperty(name = "descripcion.servicio")
    String descripcionServicio;
    private ConfigureSsl configureSsl;
    private static final String SALIDA_BSS_EXCEPTION = "Salida del microservicio BSS FindCustomerByDocId ${exchangeProperty[bodyRs]}";
    private static final String MSG_EXCEPTION = "Descripcion de la Exception: ${exception.message}";

    public ResRoute() {
        configureSsl = new ConfigureSsl();
    }

    @Override
    public void configure() throws Exception {

        BeanDate beanDate= new BeanDate();
        getContext().getRegistry().bind("BeanDate",beanDate);
        restConfiguration()
                .bindingMode(RestBindingMode.json)
                .dataFormatProperty("json.in.disableFeatures", "FAIL_ON_UNKNOWN_PROPERTIES")
                .apiContextPath(pathOpenapi)
                .apiProperty("api.title", "FindCustomerByDocId")
                .apiProperty("api.description", descripcionServicio)
                .apiProperty("api.version", "1.0.0")
                .apiProperty("cors", "true");

        rest("customerInformation/v1.4.0/users/")
                .get("/{user_id}/customers").to("direct:/{user_id}/customers")
                .outType(Customer.class)
                .param().name("FindCustomerByDocIdResponse").type(body).description("parametro de salida").required(true)
                .endParam()
                .to("direct:pipeline");

        from("direct:pipeline")
                .doTry()
                .process(new FindCustomerByDocIdProcessorReq())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"User ID: ${exchangeProperty[userId]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Correlator ID: ${exchangeProperty[correlatorId]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Tipo de Documento (Num): ${exchangeProperty[documentTypeNum]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Tipo de Cliente: ${exchangeProperty[customerType]}")
                .choice()
                .when(simple("${exchangeProperty[customerType]} == 'NATURAL'"))
                .process(new FindIndividualCustomerByDocIdProcessorReq())
                /* .log("\n["+getCurrentDate()+"]"+"Entrada del microservicio FindIndividualCustomerByDocId ${exchangeProperty[findIndividualCustomerByDocIdRequest]}") */
                .to(configureSsl.setupSSLContext(getCamelContext(), findIndividualCustomerByDocId))
                .process(new FindIndividualCustomerByDocIdProcessorRes())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio FindIndividualCustomerByDocId ${exchangeProperty[findIndividualCustomerByDocIdResponse]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio BSS FindCustomerByDocId ${exchangeProperty[findCustomerByDocIdResponse]}")
                .when(simple("${exchangeProperty[customerType]} == 'JURIDICO'"))
                .process(new FindOrganizationCustomerByDocIdProcessorReq())
                .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET))
                .setHeader(CaffeineConstants.KEY, header("$exchangeProperty[userId]"))
                .toF("caffeine-cache://%s", "OrganizationCache")
                .log("Has Result ${header.CamelCaffeineActionHasResult} ActionSucceeded ${header.CamelCaffeineActionSucceeded}")
                .choice().when(header(CaffeineConstants.ACTION_HAS_RESULT).isEqualTo(Boolean.FALSE))
                    .to(configureSsl.setupSSLContext(getCamelContext(), findOrganizacionCustomerByDocId))
                    .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT))
                    .setHeader(CaffeineConstants.KEY, header("$exchangeProperty[userId]"))
                    .toF("caffeine-cache://%s", "OrganizationCache")
                    .process(new FindOrganizationCustomerByDocIdProcessorRes())
                .otherwise()
                    .log("Cache is working")
                /*.log("\n["+getCurrentDate()+"]"+"Entrada del microservicio FindOrganizationCustomerByDocId ${exchangeProperty[findOrganizationCustomerByDocIdRequest]}") */
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio FindOrganizationCustomerByDocId ${exchangeProperty[findOrganizationCustomerByDocIdResponse]}")
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+"Salida del microservicio BSS FindCustomerByDocId ${exchangeProperty[findCustomerByDocIdResponse]}")
                .endChoice()
                .endDoTry()
                .doCatch(RequiredValueException.class)
                .process(new FindCustomerByDocIdProcessorInvalidFormatException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(HttpHostConnectException.class)
                .process(new FindCustomerByDocIdProcessorHttpHostConectionException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(NotFoundDataException.class)
                .process(new FindCustomerByDocIdProcessorInformationSubscriber())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(UnknownHostException.class)
                .process(new FindCustomerByDocIdProcessorHttpHostConectionException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION)
                .doCatch(NoHttpResponseException.class)
                .process(new FindCustomerByDocIdProcessorHttpHostConectionException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION);
                .doCatch(Exception.class)
                .process(new FindCustomerByDocIdProcessorException())
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+MSG_EXCEPTION)
                .log("\n[${bean:BeanDate.getCurrentDateTime()}] "+SALIDA_BSS_EXCEPTION);
    }
}

The error it gives me is the following, it seems to me that it is not correctly taking the value of the key:

Failed delivery for (MessageId: 1089E8B0FF423A6-0000000000000000 on ExchangeId: 1089E8B0FF423A6-0000000000000000). Exhausted after delivery attempt: 1 caught: org.apache.camel.CamelExchangeException: No value provided in header or as default value (CamelCaffeineKey). Exchange[1089E8B0FF423A6-0000000000000000]

Thanks for the support in advance

cesarjv avatar Jun 25 '24 15:06 cesarjv