apache / camel-quarkus

Apache Camel Quarkus
https://camel.apache.org
Apache License 2.0
249 stars 185 forks source link

How to use cache in Apache Camel Quarkus #6224

Open cesarjv opened 5 days ago

cesarjv commented 5 days ago

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

jamesnetherton commented 5 days ago

It may be related how you set the cache key header. Instead of:

.setHeader(CaffeineConstants.KEY, header("$exchangeProperty[userId]"))

Try:

.setHeader("CaffeineConstants.KEY").exchangeProperty("userId")
cesarjv commented 5 days ago

@jamesnetherton Ready I managed to solve, now I am enabling the elimination of the cache after a certain time, but I cannot eliminate it, that is, use the properties camel.component.caffeine-cache.expire-after-access-time and camel.component.caffeine-cache .expire-after-write-time, however, I am testing and after setting a time to 60 seconds, the query is still being done in the cache:

#cache
camel.component.caffeine-cache.expire-after-write-time=60
camel.component.caffeine-cache.expire-after-access-time=60

Test number 1 at 2:00 PM

Screenshot 2024-06-25 140040

Query the cache:

CamelCaffeineActionHasResult =true

Screenshot 2024-06-25 140143

Test number 2 at 2:04 PM, in this chaos 240 seconds have already passed since it was cached:

prueba 4 minutos despues

Keep consulting the cache:

CamelCaffeineActionHasResult =true

Screenshot 2024-06-25 140535

What could be the cause of this behavior? Shouldn't it be possible to consult the service again outside the cache after the expiration time (60sec)?

This is how I ended up configuring my 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())
                .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET))
                .setHeader(CaffeineConstants.KEY).exchangeProperty("documentNumber")
                .toF("caffeine-cache://%s", "IndividualCache")
                .log("Hay Resultado en Cache de la consulta asociado al siguiente documento: ${exchangeProperty[userId]} ${header.CamelCaffeineActionHasResult}}")
                .log("CamelCaffeineActionSucceeded: ${header.CamelCaffeineActionSucceeded}")
                .choice().when(header(CaffeineConstants.ACTION_HAS_RESULT).isEqualTo(Boolean.FALSE))
                    .to(configureSsl.setupSSLContext(getCamelContext(), findIndividualCustomerByDocId))
                    .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT))
                    .setHeader(CaffeineConstants.KEY).exchangeProperty("documentNumber")
                    .toF("caffeine-cache://%s", "IndividualCache")
                    .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]}")
                .otherwise()
                    .log("Cache is working")
                    .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())
                .to(configureSsl.setupSSLContext(getCamelContext(), findOrganizacionCustomerByDocId))
                .process(new FindOrganizationCustomerByDocIdProcessorRes())
                /*.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);
    }
}
jamesnetherton commented 5 days ago

You need to set:

camel.component.caffeine-cache.eviction-type = TIME_BASED

Otherwise expire-after-access-time& expire-after-write-time has no effect since the default eviction-type is based on the cache size.

Also:

https://stackoverflow.com/questions/78669211/configuring-cache-expiration-time-in-apache-camel-quarkus

cesarjv commented 4 days ago

Thank you so much @jamesnetherton

Everything works great for me locally, but I have the following problem once I do the native compilation, what could be happening?

12:04:05 ERROR traceId=, parentId=, spanId=, sampled= [or.ap.ca.im.en.AbstractCamelContext] (main) Error starting CamelContext (camel-1) due to exception thrown: Failed to start route route2 because of null: org.apache.camel.FailedToStartRouteException: Failed to start route route2 because of null
    at org.apache.camel.impl.engine.RouteService.warmUp(RouteService.java:123)
    at org.apache.camel.impl.engine.InternalRouteStartupManager.doWarmUpRoutes(InternalRouteStartupManager.java:306)
    at org.apache.camel.impl.engine.InternalRouteStartupManager.safelyStartRouteServices(InternalRouteStartupManager.java:189)
    at org.apache.camel.impl.engine.InternalRouteStartupManager.doStartOrResumeRoutes(InternalRouteStartupManager.java:147)
    at org.apache.camel.impl.engine.AbstractCamelContext.doStartCamel(AbstractCamelContext.java:3425)
    at org.apache.camel.impl.engine.AbstractCamelContext.doStartContext(AbstractCamelContext.java:3094)
    at org.apache.camel.impl.engine.AbstractCamelContext.doStart(AbstractCamelContext.java:3049)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.impl.engine.AbstractCamelContext.start(AbstractCamelContext.java:2698)
    at org.apache.camel.impl.DefaultCamelContext.start(DefaultCamelContext.java:262)
    at org.apache.camel.quarkus.main.CamelMain.doStart(CamelMain.java:94)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.quarkus.main.CamelMain.startEngine(CamelMain.java:140)
    at org.apache.camel.quarkus.main.CamelMainRuntime.start(CamelMainRuntime.java:49)
    at org.apache.camel.quarkus.core.CamelBootstrapRecorder.start(CamelBootstrapRecorder.java:45)
    at io.quarkus.deployment.steps.CamelBootstrapProcessor$boot173480958.deploy_0(Unknown Source)
    at io.quarkus.deployment.steps.CamelBootstrapProcessor$boot173480958.deploy(Unknown Source)
    at io.quarkus.runner.ApplicationImpl.doStart(Unknown Source)
    at io.quarkus.runtime.Application.start(Application.java:101)
    at io.quarkus.runtime.ApplicationLifecycleManager.run(ApplicationLifecycleManager.java:108)
    at io.quarkus.runtime.Quarkus.run(Quarkus.java:71)
    at io.quarkus.runtime.Quarkus.run(Quarkus.java:44)
    at io.quarkus.runtime.Quarkus.run(Quarkus.java:124)
    at io.quarkus.runner.GeneratedMain.main(Unknown Source)
Caused by: java.lang.IllegalStateException: com.github.benmanes.caffeine.cache.SSAW
    at com.github.benmanes.caffeine.cache.LocalCacheFactory.loadFactory(LocalCacheFactory.java:90)
    at com.github.benmanes.caffeine.cache.LocalCacheFactory.newBoundedLocalCache(LocalCacheFactory.java:40)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache.<init>(BoundedLocalCache.java:3687)
    at com.github.benmanes.caffeine.cache.BoundedLocalCache$BoundedLocalManualCache.<init>(BoundedLocalCache.java:3683)
    at com.github.benmanes.caffeine.cache.Caffeine.build(Caffeine.java:1035)
    at org.apache.camel.component.caffeine.cache.CaffeineCacheComponent.lambda$getOrCreateCache$0(CaffeineCacheComponent.java:68)
    at java.base@17.0.10/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
    at org.apache.camel.component.caffeine.cache.CaffeineCacheComponent.getOrCreateCache(CaffeineCacheComponent.java:65)
    at org.apache.camel.component.caffeine.cache.CaffeineCacheEndpoint.doStart(CaffeineCacheEndpoint.java:72)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.processor.SendProcessor.doStart(SendProcessor.java:242)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.impl.engine.DefaultChannel.doStart(DefaultChannel.java:126)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:116)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.processor.Pipeline.doStart(Pipeline.java:207)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.processor.DelegateAsyncProcessor.doStart(DelegateAsyncProcessor.java:89)
    at org.apache.camel.processor.FilterProcessor.doStart(FilterProcessor.java:150)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:116)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.processor.ChoiceProcessor.doStart(ChoiceProcessor.java:185)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.impl.engine.DefaultChannel.doStart(DefaultChannel.java:126)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:116)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.processor.Pipeline.doStart(Pipeline.java:207)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.processor.TryProcessor.doStart(TryProcessor.java:139)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.impl.engine.DefaultChannel.doStart(DefaultChannel.java:126)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:116)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:130)
    at org.apache.camel.processor.Pipeline.doStart(Pipeline.java:207)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.support.processor.DelegateAsyncProcessor.doStart(DelegateAsyncProcessor.java:89)
    at org.apache.camel.support.service.BaseService.start(BaseService.java:119)
    at org.apache.camel.support.service.ServiceHelper.startService(ServiceHelper.java:113)
    at org.apache.camel.impl.engine.RouteService.startChildServices(RouteService.java:396)
    at org.apache.camel.impl.engine.RouteService.doWarmUp(RouteService.java:193)
    at org.apache.camel.impl.engine.RouteService.warmUp(RouteService.java:121)
    ... 23 more
Caused by: java.lang.ClassNotFoundException: com.github.benmanes.caffeine.cache.SSAW
    at java.base@17.0.10/java.lang.Class.forName(DynamicHub.java:1132)
    at java.base@17.0.10/java.lang.Class.forName(DynamicHub.java:1105)
    at com.github.benmanes.caffeine.cache.LocalCacheFactory.loadFactory(LocalCacheFactory.java:84)
    ... 82 more

I attach my pom.xml

<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <modelVersion>4.0.0</modelVersion>
  <groupId>org.tmve.customer</groupId>
  <artifactId>find-customer-by-doc-id</artifactId>
  <version>1.0.2-DEV</version>
  <properties>
    <compiler-plugin.version>3.10.1</compiler-plugin.version>
    <maven.compiler.release>17</maven.compiler.release>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
    <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
    <quarkus.platform.version>2.16.7.Final</quarkus.platform.version>
    <skipITs>true</skipITs>
    <surefire-plugin.version>3.0.0-M7</surefire-plugin.version>
    <jacoco.version>0.8.7</jacoco.version>
    <sonar.coverage.jacoco.xmlReportPaths>${project.build.directory}/jacoco-report/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
  </properties>
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>${quarkus.platform.artifact-id}</artifactId>
        <version>${quarkus.platform.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>quarkus-camel-bom</artifactId>
        <version>${quarkus.platform.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-rest-openapi</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-bean</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-direct</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-http</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-jackson</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-jaxb</artifactId>
    </dependency>

    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-log</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-rest</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-resteasy-jsonb</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-arc</artifactId>
    </dependency>
    <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.22</version>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-openapi-java</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-smallrye-openapi</artifactId>
    </dependency>
    <dependency>
      <groupId>org.webjars</groupId>
      <artifactId>swagger-ui</artifactId>
      <version>4.11.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.camel.quarkus</groupId>
      <artifactId>camel-quarkus-opentelemetry</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-opentelemetry-exporter-otlp</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-jacoco</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
    </dependency>
    <dependency>
      <groupId>org.apache.camel</groupId>
      <artifactId>camel-caffeine</artifactId>
    </dependency>
  </dependencies>
  <build>
    <plugins>
      <plugin>
        <groupId>${quarkus.platform.group-id}</groupId>
        <artifactId>quarkus-maven-plugin</artifactId>
        <version>${quarkus.platform.version}</version>
        <extensions>true</extensions>
        <executions>
          <execution>
            <goals>
              <goal>build</goal>
              <goal>generate-code</goal>
              <goal>generate-code-tests</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${compiler-plugin.version}</version>
        <configuration>
          <compilerArgs>
            <arg>-parameters</arg>
          </compilerArgs>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>${surefire-plugin.version}</version>
        <configuration>
          <systemPropertyVariables>
            <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
            <maven.home>${maven.home}</maven.home>
          </systemPropertyVariables>
        </configuration>
      </plugin>
      <plugin>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${surefire-plugin.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>verify</goal>
            </goals>
            <configuration>
              <systemPropertyVariables>
                <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
                <maven.home>${maven.home}</maven.home>
              </systemPropertyVariables>
            </configuration>
          </execution>
          <execution>
            <id>integration-tests</id>
            <phase>integration-test</phase>
            <configuration>
              <excludedGroups>!integration</excludedGroups>
              <groups>integration</groups>
              <systemPropertyVariables>
                <jacoco-agent.destfile>${project.build.directory}/jacoco-quarkus.exec</jacoco-agent.destfile>
              </systemPropertyVariables>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <groupId>org.jacoco</groupId>
        <artifactId>jacoco-maven-plugin</artifactId>
        <version>${jacoco.version}</version>
        <executions>
          <execution>
            <id>default-prepare-agent</id>
            <goals>
              <goal>prepare-agent</goal>
            </goals>
            <configuration>
              <exclClassLoaders>*QuarkusClassLoader</exclClassLoaders>
              <destFile>${project.build.directory}/jacoco-quarkus.exec</destFile>
              <append>true</append>
              <excludes>
              </excludes>
            </configuration>
          </execution>
          <execution>
            <id>report</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>report</goal>
            </goals>
            <configuration>
              <dataFile>${project.build.directory}/jacoco-quarkus.exec</dataFile>
              <outputDirectory>${project.build.directory}/jacoco-report</outputDirectory>
            </configuration>
          </execution>
          <execution>
            <id>jacoco-check</id>
            <goals>
              <goal>check</goal>
            </goals>
            <phase>post-integration-test</phase>
            <configuration>
              <dataFile>${project.build.directory}/jacoco-quarkus.exec</dataFile>
              <rules>
                <rule>
                  <element>BUNDLE</element>
                  <limits>
                    <limit>
                      <counter>LINE</counter>
                      <value>COVEREDRATIO</value>
                      <minimum>0.5</minimum>
                    </limit>
                    <limit>
                      <counter>BRANCH</counter>
                      <value>COVEREDRATIO</value>
                      <minimum>0.5</minimum>
                    </limit>
                  </limits>
                </rule>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>
  <profiles>
    <profile>
      <id>native</id>
      <activation>
        <property>
          <name>native</name>
        </property>
      </activation>
      <properties>
        <skipITs>false</skipITs>
        <quarkus.package.type>native</quarkus.package.type>
      </properties>
    </profile>
  </profiles>
</project>

ResRoute

package org.tmve.customer.ms.route;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.caffeine.CaffeineConstants;
import org.apache.camel.model.rest.RestBindingMode;
import org.apache.http.NoHttpResponseException;
import org.apache.http.conn.HttpHostConnectException;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.tmve.customer.ms.beans.Customer;
import org.tmve.customer.ms.exceptions.RequiredValueException;
import org.tmve.customer.ms.exceptions.NotFoundDataException;
import org.tmve.customer.ms.processor.*;
import org.tmve.customer.ms.utilities.BeanDate;

import javax.enterprise.context.ApplicationScoped;
import java.net.UnknownHostException;

import static org.apache.camel.model.rest.RestParamType.body;

@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())
                    .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET))
                    .setHeader(CaffeineConstants.KEY).exchangeProperty("documentNumber")
                    .toF("caffeine-cache://%s", "IndividualCache")
                    .log("Hay Resultado en Cache de la consulta asociado al siguiente documento: ${exchangeProperty[userId]} ${header.CamelCaffeineActionHasResult}}")
                    .log("CamelCaffeineActionSucceeded: ${header.CamelCaffeineActionSucceeded}")
                    .choice().when(header(CaffeineConstants.ACTION_HAS_RESULT).isEqualTo(Boolean.FALSE))
                        .to(configureSsl.setupSSLContext(getCamelContext(), findIndividualCustomerByDocId))
                        .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT))
                        .setHeader(CaffeineConstants.KEY).exchangeProperty("documentNumber")
                        .toF("caffeine-cache://%s", "IndividualCache")
                        .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]}")
                    .otherwise()
                        .log("Cache is working")
                        .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]}")
                    .endChoice()
                .when(simple("${exchangeProperty[customerType]} == 'JURIDICO'"))
                    .process(new FindOrganizationCustomerByDocIdProcessorReq())
                    .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET))
                    .setHeader(CaffeineConstants.KEY).exchangeProperty("documentNumber")
                    .toF("caffeine-cache://%s", "OrganizationCache")
                    .log("Hay Resultado en Cache de la consulta asociado al siguiente documento: ${exchangeProperty[userId]} ${header.CamelCaffeineActionHasResult}}")
                    .log("CamelCaffeineActionSucceeded: ${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).exchangeProperty("documentNumber")
                        .toF("caffeine-cache://%s", "OrganizationCache")
                        .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]}")
                    .otherwise()
                        .log("Cache is working")
                        .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()
                .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);
    }
}

application.properties

#https
quarkus.ssl.native=true
quarkus.http.ssl-port=${PORT-SSl:8080}
quarkus.http.read-timeout=${SERVICE_READ_TIMEOUT:30s}
quarkus.http.connect-timeout=${SERVICE_CONNECT_TIMEOUT:30s}
quarkus.http.timeout=${SERVICE_TIMEOUT:30s}
quarkus.http.insecure-requests=disabled
quarkus.http.ssl.certificate.key-store-file=${UBICATION_CERTIFICATE_SSL:META-INF/resources/srvdevrma1.jks}
quarkus.http.ssl.certificate.key-store-file-type=JKS
quarkus.http.ssl.certificate.key-store-password=${PASSWORD_CERTIFICATE_SSL:service123}
quarkus.http.ssl.certificate.key-store-key-alias=${ALIAS_CERTIFICATE_SSL:srvdevrma1}
quarkus.http.cors=true
path=/customerInformation/v1.4.0/users/.*/customers

client.file=${CLIENT-FILE:META-INF/resources/srvdevrma1.jks}
client.password=${CLIENT-PASSWORD:service123}
quarkus.native.additional-build-args=-H:IncludeResources=.*\\.jks
quarkus.native.resources.includes=*.jks
#GlobalVariables
server.variables.msgType=RESPONSE
server.variables.msgTypeError=ERROR

error.400.code=INVALID_ARGUMENT
error.400.message=Client specified an invalid argument, request body or query param

error.403.code=PERMISSION_DENIED
error.403.message=Authenticated user has no permission to access the requested resource

error.404.code=NOT_FOUND
error.404.message=A specified resource is not found

error.500.code=INTERNAL
error.500.message=Server error

error.503.code=UNAVAILABLE
error.503.message=Service unavailable

error.504.code=TIMEOUT
error.504.message=Request timeout exceeded. Try it later

descripcion.servicio=MicroServicio que permite orquestar la busqueda de informacion asociados a clientes Naturales y Juridicos

#endpoints_ms- local
client.findIndividualCustomerByDocId=${UBICATION-URL-FIND-INDIVIDUAL-CUSTOMER-BY-DOC-ID:https://10.162.128.94:30000/api/FindIndividualCustomerByDocId}
client.findOrganizacionCustomerByDocId=${UBICATION-URL-FIND-ORGANIZATION-CUSTOMER-BY-DOC-ID:https://10.162.128.94:30000/api/FindOrganizationCustomerByDocId}
#timeZone
quarkus.jackson.timezone=${TIME_ZONE:GMT-4}

#Ruta OpenApi
path.openapi=customerInformation/v1.4.0/users/.*/customers/openapi/swagger-ui/
quarkus.camel.openapi.expose.enabled=true
#camel.rest.api-context-path = /openapi.yaml
#quarkus.swagger-ui.urls.camel = /openapi.yaml
#openapi
quarkus.smallrye-openapi.path=/api/FindCustomerByDocId/swagger
#quarkus.swagger-ui.path= /api/FindCustomerByDocId/swagger-ui/
quarkus.swagger-ui.always-include=true

#cache
camel.component.caffeine-cache.expire-after-write-time=${CACHE_EXPIRE_WRITE_ACCESS_TIME:60}
camel.component.caffeine-cache.expire-after-access-time=${CACHE_EXPIRE_AFTER_ACCESS_TIME:60}
camel.component.caffeine-cache.eviction-type=${CACHE_EVICTION_TIME:TIME_BASED}
#opentelemetry
quarkus.application.name=FindCustomerByDocId
quarkus.opentelemetry.enabled=true
quarkus.opentelemetry.tracer.exporter.otlp.endpoint=${URL_JAEGER:http://172.28.2.107:4317}
quarkus.log.console.format=%d{HH:mm:ss} %-5p traceId=%X{traceId}, parentId=%X{parentId}, spanId=%X{spanId}, sampled=%X{sampled} [%c{2.}] (%t) %s%e%n
quarkus.http.header."X-Content-Type-Options".value=nosniff
quarkus.http.header."X-Frame-Options".value=DENY
quarkus.http.header."Content-Security-Policy".value=default-src
quarkus.http.header."X-XSS-Protection".value=1; mode=block
quarkus.http.header."Expect-CT".value=report-only
quarkus.http.header."Permissions-Policy".value=geolocation=*, fullscreen=*
quarkus.http.header."Cache-Control".value=no-cache
#jacoco report
#quarkus.jacoco.excludes=com/tmve/findaccountinvoicedetail/beans/*, com/tmve/findaccountinvoicedetail/ms/processor/exceptions/*,

That could be happening?

jamesnetherton commented 4 days ago

To work around the problem, try adding a configuration property like:

quarkus.camel.native.reflection.include-patterns = com.github.benmanes.caffeine.cache.SSAW

jamesnetherton commented 4 days ago

To work around the problem, try adding a configuration property like:

quarkus.camel.native.reflection.include-patterns = com.github.benmanes.caffeine.cache.SSAW

This will get fixed permanently in Quarkus 3.13.0 (maybe 3.12.1).

cesarjv commented 3 days ago

@jamesnetherton Thank you very much, in the end I had to add the annotation with 2 values:

quarkus.camel.native.reflection.include-patterns = com.github.benmanes.caffeine.cache.SSAW, com.github.benmanes.caffeine.cache.PSAW