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?
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);
}
}