I'm building a very simple application where multiple services are interacting with eachs others (simulating ATM).
A card service calls a fraud service to check whether or not the card is fraudulent.
I have a problem where I'm retrieving a property from application.properties but it's always returning null and can't figure out why. Here is the code for my Card service.
The Controller
package com.grafana.atm.cardservice.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException;
import com.grafana.atm.cardservice.client.FraudServiceClient;
import com.grafana.atm.cardservice.model.Card;
import reactor.core.publisher.Mono;
@RestController
public class CardController {
Logger logger = LoggerFactory.getLogger(CardController.class);
FraudServiceClient fraudServiceClient = new FraudServiceClient();
@PostMapping("/card:check")
public String checkCardValidity(@RequestBody Card card) {
logger.info("Checking if the credit card with number "+card.getCardNumber()+" is valid.");
if (isValidCreditCardNumber(card.getCardNumber())) {
logger.info("The credit card with number '"+card.getCardNumber()+"' is valid.");
fraudServiceClient.getFraudServiceClient().post()
.uri("/fraud:check")
.body(Mono.just(card), Card.class)
.retrieve()
.onStatus(HttpStatus.INTERNAL_SERVER_ERROR::equals,
response -> response.bodyToMono(String.class).map(Exception::new))
.bodyToMono(String.class)
.block();
} else {
logger.error("The credit card with number '"+card.getCardNumber()+"' is invalid or cannot be verified.");
throw new ResponseStatusException(
HttpStatus.INTERNAL_SERVER_ERROR, "The card number is invalid or cannot be verified.");
}
return "all good";
}
}
The class for the WebClient
package com.grafana.atm.cardservice.client;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class FraudServiceClient {
@Value("${atm.application.service.fraud.endpoint}")
private String fraudServiceEndpoint;
private final WebClient fraudServiceClient;
Logger logger = LoggerFactory.getLogger(FraudServiceClient.class);
public FraudServiceClient() {
logger.info("Creating WebClient for calling the Fraud service at "+fraudServiceEndpoint);
this.fraudServiceClient = WebClient.builder()
.baseUrl(fraudServiceEndpoint)
.defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.build();
}
public WebClient getFraudServiceClient() {
return fraudServiceClient;
}
}
The Card model
package com.grafana.atm.cardservice.model;
public class Card {
private String cardNumber;
private Integer cardExpiryDate;
private Integer cardCvc;
public Card() {
}
public Card(String cardNumber, Integer cardExpiryDate, Integer cardCvc) {
this.cardNumber = cardNumber;
this.cardExpiryDate = cardExpiryDate;
this.cardCvc = cardCvc;
}
public String getCardNumber() {
return this.cardNumber;
}
public Integer getCardExpiryDate() {
return this.cardExpiryDate;
}
public Integer getCardCvc() {
return this.cardCvc;
}
}
I confirm the env variable called in my application.properties files is correctly set
Disclamer: I'm very new with Spring Boot - have read a lot but still learning a lot too so pardon me if it sounds obvious :).
application.propertie
spring.application.name=card-service
server.port=${ATM_CARD_SVC_PORT}
atm.application.service.fraud.endpoint=${ATM_FRAUD_SVC_ENDPOINT}
management.endpoint.chaosmonkey.enabled=true
management.endpoint.chaosmonkeyjmx.enabled=true
management.endpoints.web.exposure.include=health,info,prometheus,chaosmonkey
server.error.include-stacktrace=never
server.error.include-message=always
logging.pattern.console=Timestamp=%d{yyyy-MM-dd HH:mm:ss} Level=%p Logger=%logger{36} Message=%msg TraceId=%mdc{trace_id} SpanId=%mdc{span_id} TraceFlags=%mdc{trace_flags} %n