Search code examples
propertiesapache-camelquarkus

Problem with @ConfigProperty in null when using a process in Apache Camel Quarkus


Good morning, I am currently working with Quarkus and Apache Camel and I am using a variable from the application.properties in a processor, I try to bring it in using the @ConfigProperty annotation, but it is giving me a null error, this is how I have it configured:

The variable is called encryptionKey

UserProfileProcessorUserIdParamReq

@ApplicationScoped
@Slf4j
public class UserProfileProcessorUserIdParamReq implements Processor {

    @ConfigProperty(name="aes.encrypt.key")
    String encryptionKey;

    private final IValidationFieldsUserID validationFields;

    public UserProfileProcessorUserIdParamReq() {
        validationFields = new ValidationFieldsUserID();
    }
    
    @Override
    public void process(Exchange exchange) throws Exception {

        String documentType;
        String documentNumber;
        String userId;
        String correlatorId;
        String tokenInfo;
        String userIdDecodedBase64;
        String userIdDecrypt;

        try {
            correlatorId= Optional.ofNullable(exchange.getIn().getHeader("x-correlator")).map(Object::toString).orElse("");
            exchange.setProperty("correlatorId",correlatorId);
            userId = exchange.getIn().getHeader("user_id").toString();
            tokenInfo= Optional.ofNullable(exchange.getIn().getHeader("x-token-info")).map(Object::toString).orElse("");
            validationFields.validateUserId(exchange);
            userId=validateUserIdValue(userId, tokenInfo);
            exchange.setProperty("userIdEncrypt", userId);
            userIdDecodedBase64= EncodeBase64.decrypt(userId);
            log.info("userIdDecodedBase64" + userIdDecodedBase64);
            userIdDecrypt= EncryptUtil.decrypt(userIdDecodedBase64,encryptionKey);
            exchange.setProperty("userId", userIdDecrypt);
            validateTokenInfo(exchange,userId, tokenInfo);
            validateUserIdDecrypt(userIdDecrypt);
            documentType = userIdDecrypt.split("-")[0];
            documentNumber = userIdDecrypt.split("-")[1];
            exchange.setProperty("documentType", documentType);
            exchange.setProperty("documentNumber", documentNumber);
            exchange.setProperty("isSearchByQueryParam","false");

        } catch (RequiredValueException | NullPointerException e) {
            throw new RequiredValueException(e.getMessage());
        }
        catch (NotFoundDataException e) {
            throw new NotFoundDataException(e.getMessage());
        }
        catch (PermissionDeniedException e) {
            throw new PermissionDeniedException(e.getMessage());
        }
        catch (Exception e){
            if( e.getMessage().contains("Input byte array"))
                throw new NotFoundDataException(e.getMessage());
            throw new Exception(e.getMessage());
        }
    }

    private static void validateTokenInfo(Exchange exchange, String userId, String tokenInfoValidated) {
        if (!tokenInfoValidated.isEmpty()) {
            log.info("Valor del x-token-info: {}", tokenInfoValidated);
            /* Se obtiene el Objeto JSON con el valor del campo x-token-info */
            JSONObject jsonObject = new JSONObject(tokenInfoValidated);
            /*String subValue=jsonObject.get("sub").toString(); */
            /* Mediante el optString obtenemos el valor sub si viene (token 3 patas) o no viene (token 2 patas), para este ultimo caso el valor es vacio */
            String subValue = jsonObject.optString("sub");
            log.info("Valor sub que esta llegando en el valor x-token-info: {}", subValue);
            if (!subValue.isEmpty()) {
                if(!subValue.equals(userId)) {
                    throw new PermissionDeniedException("Error validando el campo sub de la autenticacion en el campo x-token-info, no hace match con userId enviado");
                }
            }
        }
    }

    /* Se valida que el UserId sea un valor valido para venezuela, sea enviado cifrado o no*/
    private static void validateUserIdDecrypt (String userId) {
        if(!Pattern.matches("^(CI|RIF|P|CD|NIT)(-).*",userId)){
            throw  new NotFoundDataException("UserId enviado esta en formato incorrecto");
        }
    }
    /*Se valida el valor del campo UserId, si el mismo pudiera contener el valor de me, en este caso se debe extraer el valor de UserId del json token-info, en especifico del campo sub */
    private String validateUserIdValue(String userId,String tokenInfo) {
        if(userId.equals("me")){
            if(!tokenInfo.isEmpty()){
                JSONObject jsonObject = new JSONObject(tokenInfo);
                userId = jsonObject.optString("sub");
            }
            else {
                throw new RequiredValueException("Se requiere parametro x-token-info (autenticacion 3 patas) para campo userId=me");
            }
        }
        return userId;
    }
}

And this is the error it gives:

14:52:44 INFO  traceId=2a0a8e8cd93ddb947e2ab7206ef4f25d, parentId=, spanId=394c6d08dec8d551, sampled=true [route23] (vert.x-worker-thread-0) [2024-07-01 14:52:44.0] Descripcion de la Exception: Cannot invoke "String.getBytes()" because "key" is null

This is how it is in my application.properties:

aes.encrypt.key=${AES_ENCRYPT_KEY:xxxxxxxxxxxx}

Like from ResRoute call to processor without constructor:

from("direct:usersQueryParam")
                /*.removeHeaders("CamelHttp*") */
                .doTry()
                .process(new UserProfileProcessorQueryParamReq())
                .choice()
                /* code */

How can I do here so that it takes the value of the @ConfigProperty?


Solution

  • I think it's not working because you're creating the Processor manually. Try to pass the encryptionKey as a constructor parameter and move your @ConfigProperty to the route builder:

    UserProfileProcessorUserIdParamReq

    @Slf4j
    public class UserProfileProcessorUserIdParamReq implements Processor {
    
        private String encryptionKey;
    
        private final IValidationFieldsUserID validationFields;
    
        public UserProfileProcessorUserIdParamReq(String encryptionKey) {
            validationFields = new ValidationFieldsUserID();
            this.encryptionKey = encryptionKey;
        }
        
        @Override
        public void process(Exchange exchange) throws Exception {
    
            String documentType;
            String documentNumber;
            String userId;
            String correlatorId;
            String tokenInfo;
            String userIdDecodedBase64;
            String userIdDecrypt;
    
            try {
                correlatorId= Optional.ofNullable(exchange.getIn().getHeader("x-correlator")).map(Object::toString).orElse("");
                exchange.setProperty("correlatorId",correlatorId);
                userId = exchange.getIn().getHeader("user_id").toString();
                tokenInfo= Optional.ofNullable(exchange.getIn().getHeader("x-token-info")).map(Object::toString).orElse("");
                validationFields.validateUserId(exchange);
                userId=validateUserIdValue(userId, tokenInfo);
                exchange.setProperty("userIdEncrypt", userId);
                userIdDecodedBase64= EncodeBase64.decrypt(userId);
                log.info("userIdDecodedBase64" + userIdDecodedBase64);
                userIdDecrypt= EncryptUtil.decrypt(userIdDecodedBase64,encryptionKey);
                exchange.setProperty("userId", userIdDecrypt);
                validateTokenInfo(exchange,userId, tokenInfo);
                validateUserIdDecrypt(userIdDecrypt);
                documentType = userIdDecrypt.split("-")[0];
                documentNumber = userIdDecrypt.split("-")[1];
                exchange.setProperty("documentType", documentType);
                exchange.setProperty("documentNumber", documentNumber);
                exchange.setProperty("isSearchByQueryParam","false");
    
            } catch (RequiredValueException | NullPointerException e) {
                throw new RequiredValueException(e.getMessage());
            }
            catch (NotFoundDataException e) {
                throw new NotFoundDataException(e.getMessage());
            }
            catch (PermissionDeniedException e) {
                throw new PermissionDeniedException(e.getMessage());
            }
            catch (Exception e){
                if( e.getMessage().contains("Input byte array"))
                    throw new NotFoundDataException(e.getMessage());
                throw new Exception(e.getMessage());
            }
        }
    
        private static void validateTokenInfo(Exchange exchange, String userId, String tokenInfoValidated) {
            if (!tokenInfoValidated.isEmpty()) {
                log.info("Valor del x-token-info: {}", tokenInfoValidated);
                /* Se obtiene el Objeto JSON con el valor del campo x-token-info */
                JSONObject jsonObject = new JSONObject(tokenInfoValidated);
                /*String subValue=jsonObject.get("sub").toString(); */
                /* Mediante el optString obtenemos el valor sub si viene (token 3 patas) o no viene (token 2 patas), para este ultimo caso el valor es vacio */
                String subValue = jsonObject.optString("sub");
                log.info("Valor sub que esta llegando en el valor x-token-info: {}", subValue);
                if (!subValue.isEmpty()) {
                    if(!subValue.equals(userId)) {
                        throw new PermissionDeniedException("Error validando el campo sub de la autenticacion en el campo x-token-info, no hace match con userId enviado");
                    }
                }
            }
        }
    
        /* Se valida que el UserId sea un valor valido para venezuela, sea enviado cifrado o no*/
        private static void validateUserIdDecrypt (String userId) {
            if(!Pattern.matches("^(CI|RIF|P|CD|NIT)(-).*",userId)){
                throw  new NotFoundDataException("UserId enviado esta en formato incorrecto");
            }
        }
        /*Se valida el valor del campo UserId, si el mismo pudiera contener el valor de me, en este caso se debe extraer el valor de UserId del json token-info, en especifico del campo sub */
        private String validateUserIdValue(String userId,String tokenInfo) {
            if(userId.equals("me")){
                if(!tokenInfo.isEmpty()){
                    JSONObject jsonObject = new JSONObject(tokenInfo);
                    userId = jsonObject.optString("sub");
                }
                else {
                    throw new RequiredValueException("Se requiere parametro x-token-info (autenticacion 3 patas) para campo userId=me");
                }
            }
            return userId;
        }
    }
    

    ResRoute

        package org.tmve.customer.ms.route;
        
        import org.apache.camel.Exchange;
        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.response.UserProfile;
        import org.tmve.customer.ms.exceptions.NotFoundDataException;
        import org.tmve.customer.ms.exceptions.EmptyDataExceptionQueryParam;
        import org.tmve.customer.ms.exceptions.PermissionDeniedException;
        import org.tmve.customer.ms.exceptions.RequiredValueException;
        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="aes.encrypt.key")
            String encryptionKey;
        
            @ConfigProperty(name="client.findCustomerByDocId")
            String findCustomerByDocId;
        
            @ConfigProperty(name="client.findCustomerAccountListByDocId")
            String findCustomerAccountsListByDocId;
        
            @ConfigProperty(name="client.findPostpaidAccountInfo")
            String findPostpaidAccountInfo;
        
            @ConfigProperty(name="client.findCustomerDocumentBySubscriberId")
            String findCustomerDocumentBySubscriberId;
        
            @ConfigProperty(name="client.findFeatureByAccount")
            String findFeatureByAccount;
            @ConfigProperty(name = "path.openapi")
            String openApiPath;
            @ConfigProperty(name = "descripcion.servicio")
            String serviceDescription;
            private ConfigureSsl configureSsl;
            private static final String SALIDA_BSS_EXCEPTION = "Salida del microservicio BSS UserProfile ${exchangeProperty[bodyRs]}";
            private static final String USER_PROFILE = "UserProfile";
            private static final String MSG_EXCEPTION = "Descripcion de la Exception: ${exception.message}";
        
            private static final String DATE_LOG = "[${bean:BeanDate.getCurrentDateTime()}] ";
        
            private static final String DIRECT_PIPELINE = "direct:pipeline";
        
            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(openApiPath)
                        .apiProperty("api.title", USER_PROFILE)
                        .apiProperty("api.description", serviceDescription)
                        .apiProperty("api.version", "1.0.0")
                        .apiProperty("cors", "true");
        
                rest("userProfile/v3/")
                        .get("/users/{user_id}").to("direct:/{user_id}")
                            .outType(UserProfile.class)
                            .param().name(USER_PROFILE).type(body).description("parametro de salida").required(true)
                            .endParam()
                            .to("direct:userIdParam");
                rest("/userProfile/v3/")
                        .get("/users?").to("direct:/users?")
                        .outType(UserProfile.class)
                        .param().name(USER_PROFILE).type(body).description("parametro de salida").required(true).endParam()
                        .to("direct:usersQueryParam");
        
                onException(RequiredValueException.class)
                        .handled(true)
                        .process(new UserProfileProcessorInvalidFormatException())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
                onException(NotFoundDataException.class)
                        .handled(true)
                        .process(new UserProfileProcessorInformationSubscriber())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
                onException(HttpHostConnectException.class)
                        .handled(true)
                        .process(new UserProfileProcessHttpHostConectionException())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
                onException(PermissionDeniedException.class)
                        .handled(true)
                        .process(new UserProfileProcessorPermissionDenied())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
                onException(Exception.class)
                        .handled(true)
                        .process(new UserProfileProcessorException())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
                from("direct:userIdParam")
                        .doTry()
                                .process(new UserProfileProcessorUserIdParamReq(encryptionKey))
                                .log(DATE_LOG+"User ID: ${exchangeProperty[userId]}")
                                .log(DATE_LOG+"UserId Encrypt: ${exchangeProperty[userIdEncrypt]}")
                                .log(DATE_LOG+"Correlator ID: ${exchangeProperty[correlatorId]}")
                        .endDoTry()
                        .to(DIRECT_PIPELINE);
                from("direct:usersQueryParam")
                        /*.removeHeaders("CamelHttp*") */
                        .doTry()
                        .process(new UserProfileProcessorQueryParamReq())
                        .choice()
                            .when(simple("${exchangeProperty[isSearchByQueryParamIdDocumentValueAndIdDocumentType]} == 'true'"))
                                .to(DIRECT_PIPELINE)
                            .otherwise()
                                .log(DATE_LOG+"Identity: ${exchangeProperty[identityQueryParam]}")
                                .log(DATE_LOG+"IdentityType: ${exchangeProperty[identityTypeQueryParam]}")
                                .process(new FindCustomerDocumentBySubscriberIdReq())
                                .log(DATE_LOG+"Entrada Microservicio FindCustomerDocumentBySubscriberId: ${exchangeProperty[findCustomerDocumentBySubscriberIdRequest]}")
                                .to(configureSsl.setupSSLContext(getCamelContext(), findCustomerDocumentBySubscriberId))
                                .process(new FindCustomerDocumentBySubscriberIdRes())
                                .log(DATE_LOG+"Salida FindCustomerDocumentBySubscriberId: ${exchangeProperty[findCustomerDocumentBySubscriberIdResponseStatus]}")
                                .log(DATE_LOG+"User ID Mediante QueryParam: ${exchangeProperty[userId]}")
                                .to(DIRECT_PIPELINE)
                        .endDoTry()
                        /*.to(DIRECT_PIPELINE) */
                        .doCatch(EmptyDataExceptionQueryParam.class)
                        .process(new UserProfileEmptyDataSubscriberQueryParam())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
        
                from(DIRECT_PIPELINE)
                        .doTry()
                        .log(DATE_LOG+"UserId: ${exchangeProperty[userId]}")
                        .process(new FindCustomerByDocIdProcessorReq())
                        .to(configureSsl.setupSSLContext(getCamelContext(), findCustomerByDocId))
                        .choice()
                        .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(200))
                            .process(new FindCustomerByDocIdProcessorRes())
                            .log(DATE_LOG+"Mensaje Ejecucion MS FindCustomerByDocId: ${exchangeProperty[findCustomerByDocIdResponseMessage]}")
                        .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(404))
                                .process(new FindCustomerByDocIdProcessorResHttp404())
                                .log(DATE_LOG+"Mensaje Ejecucion MS FindCustomerByDocId: ${exchangeProperty[findCustomerByDocIdResponseMessage]}")
                        .otherwise()
                        .log("Error al consultar Microservicio FindCustomerByDocId con codigo de respuesta: ${header.CamelHttpResponseCode}")
                            .process(new UserProfileFaultProcessRes())
                        .end()
                        .log(DATE_LOG+"Document userId: ${exchangeProperty[userDocument]}")
                        .log(DATE_LOG+"Name userId: ${exchangeProperty[userName]}")
                        .process(new FindCustomerAccountListByDocIdReq())
                        .to(configureSsl.setupSSLContext(getCamelContext(), findCustomerAccountsListByDocId))
                        .choice()
                        .when(header(Exchange.HTTP_RESPONSE_CODE).isEqualTo(200))
                            .process(new FindCustomerAccountsListByDocIdRes())
                        .log(DATE_LOG+"Mensaje Ejecucion MS FindCustomerAccountListByDocId: ${exchangeProperty[findCustomerAccountListByDocIdResponseMessage]}")
                        .log(DATE_LOG+"Total Cuentas Prepago: ${exchangeProperty[prepaidAccountCount]}")
                        .log(DATE_LOG+"Total Cuentas Pospago: ${exchangeProperty[postpaidAccountCount]}")
                        .log(DATE_LOG+"Cuentas Prepago: ${exchangeProperty[prepaidAccounts]}")
                        .log(DATE_LOG+"Cuentas Pospago: ${exchangeProperty[postpaidAccounts]}")
                        .otherwise()
                        .log("Error al consultar Microservicio FindCustomerAccountsListByDocId con codigo de respuesta: ${header.CamelHttpResponseCode}")
                            .process(new UserProfileFaultProcessRes())
                        .end()
                        .loop(simple("${exchangeProperty[postpaidAccountCount]}"))
                            .process(new FindPostpaidAccountInfoProcessReq())
                            .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET))
                            .setHeader(CaffeineConstants.KEY).exchangeProperty("postpaidAccount")
                            .toF("caffeine-cache://%s", "SVAPostpaid")
                            .choice().when(header(CaffeineConstants.ACTION_HAS_RESULT).isEqualTo(Boolean.FALSE))
                                .to(configureSsl.setupSSLContext(getCamelContext(), findPostpaidAccountInfo))
                                .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT))
                                .setHeader(CaffeineConstants.KEY).exchangeProperty("postpaidAccount")
                                .toF("caffeine-cache://%s", "SVAPostpaid")
                                .process(new FindPostpaidAccountInfoProcessRes())
                            .otherwise()
                                .process(new FindPostpaidAccountInfoProcessRes())
                            .end()
                        .end()
                        .log(DATE_LOG+"Busqueda SVA para Cuentas Pospago Exitosa....")
                        .loop(simple("${exchangeProperty[prepaidAccountCount]}"))
                            .process(new FindFeaturesByAccountProcessorReq())
                            .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_GET))
                            .setHeader(CaffeineConstants.KEY).exchangeProperty("prepaidAccount")
                            .toF("caffeine-cache://%s", "SVAPrepaid")
                            .choice().when(header(CaffeineConstants.ACTION_HAS_RESULT).isEqualTo(Boolean.FALSE))
                                .to(configureSsl.setupSSLContext(getCamelContext(), findFeatureByAccount))
                                .setHeader(CaffeineConstants.ACTION, constant(CaffeineConstants.ACTION_PUT))
                                .setHeader(CaffeineConstants.KEY).exchangeProperty("prepaidAccount")
                                .toF("caffeine-cache://%s", "SVAPrepaid")
                                .process(new FindFeatureByAccountProcessorRes())
                            .otherwise()
                                .process(new FindFeatureByAccountProcessorRes())
                            .end()
                        .end()
                        .log(DATE_LOG+"Busqueda SVA para Cuentas Prepago Exitosa....")
                        .choice()
                        .when(simple("${exchangeProperty[isSearchByQueryParam]} == 'true'"))
                            .process(new UserProfileProcessorQueryParamRes())
                            .log(DATE_LOG+"Salida MS UserProfile: ${exchangeProperty[userProfileResponse]}")
                        .otherwise()
                            .process(new UserProfileProcessorUserIdRes())
                            .log(DATE_LOG+"Salida MS UserProfile: ${exchangeProperty[userProfileResponse]}")
                        .endDoTry()
                        .doCatch(UnknownHostException.class)
                        .process(new UserProfileProcessHttpHostConectionException())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION)
                        .doCatch(NoHttpResponseException.class)
                        .process(new UserProfileProcessHttpHostConectionException())
                        .log(DATE_LOG+MSG_EXCEPTION)
                        .log(DATE_LOG+SALIDA_BSS_EXCEPTION);
            }
        }