0

I'm working with HashiCorp Vault and want to map the key-value from Vault json file to a application.yml placeholder, but catching the NPE when making request to call another service

that's my Vault secrets file

{
  "vault": {
    "region-location": {
      "34": {
        "latitude": 55.76593684245433,
        "longitude": 37.62111491585245
      },
      "2397": {
        "latitude": 53.3499441638952,
        "longitude": 83.7835286298899
      },
      "6609": {
        "latitude": 56.860216399045555,
        "longitude": 53.22638189062013
      },
      "7011": {
        "latitude": 43.02940154439686,
        "longitude": 44.666051850849186
      }
    },
    "security": {
      "user": {
        "name": "user",
        "password": "password"
      }
    }
  }
}

here is my bootstrap.yml

spring:
  cloud:
    vault:
      enabled: true
      fail-fast: true
      uri: ******
      authentication: approle
      namespace: dom
      application-name: atp
      app-role:
        role-id: ${SPRING_ROLE_ID} #from env var
        secret-id: ${SPRING_SECRET_ID} #from env var
        role: approle
      generic:
        enabled: false
      kv:
        enabled: true
        backend: applications
        default-context: common # not used for now
      config:
        lifecycle:
          enabled: false
      session:
        lifecycle:
          enabled: false

here is my application.yml

build.version: @project.version@

server:
  port: ${PORT:8080}
  shutdown: graceful
  forward-headers-strategy: framework
  servlet:
    encoding:
      charset: UTF-8
      force-response: true

spring:
  application:
    name: @project.name@
  security:
    user:
      name: ${vault.security.user.name}
      password: ${vault.security.user.password}

springdoc:
  default-produces-media-type: application/json

region-location: ${vault.region-location}

here is the service class

@Service
@RequiredArgsConstructor
public class AppointmentService {

    private final AppointmentClient appointmentClient;
    private final DataConfigProperties dataProperties;

    public Map<String, OffsetDateTime> getHomeDeliveryStoreToNearestDate(String regionId, OffsetDateTime now,
                                                                         Set<String> homeDeliveryEligibleStoresIds) {
        if (homeDeliveryEligibleStoresIds.size() == 0) {
            return emptyMap();
        }
        var request = makeHomeDeliveryAppointmentsRequest(regionId, homeDeliveryEligibleStoresIds, now);
        var storeIds = request.getActualDates().stream().map(ActualDate::getStoreId).collect(Collectors.toSet());
        var storeToNearestDate = new HashMap<String, OffsetDateTime>();
        var response = appointmentClient.getHomeDeliveryAppointments(request);
        for (String storeId : storeIds) {
            var startDate = response.getAppointments()
                    .stream()
                    .filter(appointment -> appointment != null
                                           && appointment.getStart() != null
                                           && appointment.getAvailableStoreIds().contains(storeId))
                    .min(Comparator.comparing(Appointment::getStart));
            startDate.ifPresent(appointment -> storeToNearestDate.put(storeId, appointment.getStart()));
        }
        return storeToNearestDate;
    }

    private AppointmentHomeDeliveryRequest makeHomeDeliveryAppointmentsRequest(String regionId, Set<String> storesIds,
                                                                               OffsetDateTime now) {
        var actualDates = storesIds
                .stream()
                .map(storeId -> new ActualDate(now.toZonedDateTime(), storeId))
                .toList();
        return new AppointmentHomeDeliveryRequest(
                actualDates, dataProperties.getRegionLocation().get(regionId), regionId, PERSON, ONLINE, STANDARD);
    }
}

When I try to call my endpoint, it creates request to another service and then NPE occurs:

java.lang.NullPointerException: Cannot invoke "java.util.Map.get(Object)" because the return value of "com.msk.someservice.client.config.properties.DataConfigProperties.getRegionLocation()" is null

@Data
@Component
@ConfigurationProperties(prefix = "region-location")
public class DataConfigProperties {

    private Map<String, Location> regionLocation;

}

i tried to use the common configuration annotations and also the `@Value` annotation with `@PropertySource` - but in wont help, did you face the problem?

upd: Authorization credentials mapping works fine from Vault

1 Answers1

-1

There is specific dependency for using Vault in Spring, first create Vault configuration: https://spring.io/projects/spring-vault

then read from using template:

https://www.baeldung.com/spring-vault

notAPPP
  • 188
  • 5