Java Spring cloud config client and config server. custom link to actuator endpoint

79 views Asked by At

I have a Java Spring config client application ("A") that works with my config server ("B"). I also have an application.yaml configuration file in project "A". If the contents of the application.yaml file are:

spring:
 config:
  import: configserver:http://localhost:8080/config
  activate:
   on-profile: useConfigServer
 cloud:
  config:
   enabled: true

Everything works perfectly. However, if I try to set the import property with my custom actuator endpoint in "B" like this:

spring:
 config:
  import: configserver:http://config-server-1-9-int/actuator/getconfigurations/proxy-gw-1-8-c78d88cbf-nfbh4/proxy-gw/useConfigServer,dev

I am getting an exception:

[main] ERROR org.springframework.boot.SpringApplication - Application run failed
java.lang.IllegalStateException: Unable to load config data from 'dev'
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:141)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:126)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.resolve(StandardConfigDataLocationResolver.java:119)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.lambda$resolve$1(ConfigDataLocationResolvers.java:115)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:126)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:115)
    at org.springframework.boot.context.config.ConfigDataLocationResolvers.resolve(ConfigDataLocationResolvers.java:107)
    at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:105)
    at org.springframework.boot.context.config.ConfigDataImporter.resolve(ConfigDataImporter.java:97)
    at org.springframework.boot.context.config.ConfigDataImporter.resolveAndLoad(ConfigDataImporter.java:85)
    at org.springframework.boot.context.config.ConfigDataEnvironmentContributors.withProcessedImports(ConfigDataEnvironmentContributors.java:116)
    at org.springframework.boot.context.config.ConfigDataEnvironment.processWithProfiles(ConfigDataEnvironment.java:311)
    at org.springframework.boot.context.config.ConfigDataEnvironment.processAndApply(ConfigDataEnvironment.java:232)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:102)
    at org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor.postProcessEnvironment(ConfigDataEnvironmentPostProcessor.java:94)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEnvironmentPreparedEvent(EnvironmentPostProcessorApplicationListener.java:102)
    at org.springframework.boot.env.EnvironmentPostProcessorApplicationListener.onApplicationEvent(EnvironmentPostProcessorApplicationListener.java:87)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:176)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:169)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:143)
    at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:131)
    at org.springframework.boot.context.event.EventPublishingRunListener.environmentPrepared(EventPublishingRunListener.java:85)
    at org.springframework.boot.SpringApplicationRunListeners.lambda$environmentPrepared$2(SpringApplicationRunListeners.java:66)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:120)
    at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:114)
    at org.springframework.boot.SpringApplicationRunListeners.environmentPrepared(SpringApplicationRunListeners.java:65)
    at org.springframework.boot.SpringApplication.prepareEnvironment(SpringApplication.java:343)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:301)
    at org.springframework.boot.builder.SpringApplicationBuilder.run(SpringApplicationBuilder.java:164)
    at com.poalim.modernization.infra.Application.main(Application.java:34)
Caused by: java.lang.IllegalStateException: File extension is not known to any PropertySourceLoader. If the location is meant to reference a directory, it must end in '/' or File.separator
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferencesForFile(StandardConfigDataLocationResolver.java:229)
    at org.springframework.boot.context.config.StandardConfigDataLocationResolver.getReferences(StandardConfigDataLocationResolver.java:138)
    ... 30 common frames omitted

Process finished with exit code 1

And in this case, the actuator endpoint in "B" is not accessed (during debugging). Please pay attention to the fact that if I perform a REST request from "A" to "B" to the address http://config-server-1-9-int/actuator/getconfigurations/proxy-gw-1-8-c78d88cbf-nfbh4/proxy-gw/useConfigServer,dev, everything works perfectly, and I get the Environment object (configurations) in response.

application.yaml in config server "B":

spring:
  application:
    name: config-server
  cloud:
    config:
      server:
        health:
          enabled: false
        prefix: /config

I also tried to change the prefix in all of the combinations.

Actuator endpoint in config-server "B":

@Component
@Endpoint(id = "getconfigurations")
@RequiredArgsConstructor
public class GetConfigurationsEndpoint {
    private final RefreshConfigsManagementService refreshConfigsManagementService;

    @ReadOperation
//        (produces = EnvironmentMediaType.V2_JSON)
    public Environment getConfigurations(@Selector String podId, @Selector String serviceName, @Selector String profilesList) {



        return refreshConfigsManagementService.getConfigurations(
            PodId.builder()
                .id(podId)
                .service(serviceName)
                .profilesList(profilesList)
                .build()
        );
    }

}

That's works perfect if I perform REST request.

The exception thrown from org.springframework.boot.context.config.StandardConfigDataLocationResolver:

private Set getReferencesForFile(ConfigDataLocation configDataLocation, String file, String profile) { Matcher extensionHintMatcher = EXTENSION_HINT_PATTERN.matcher(file); boolean extensionHintLocation = extensionHintMatcher.matches(); if (extensionHintLocation) { file = extensionHintMatcher.group(1) + extensionHintMatcher.group(2); } for (PropertySourceLoader propertySourceLoader : this.propertySourceLoaders) { String extension = getLoadableFileExtension(propertySourceLoader, file); if (extension != null) { String root = file.substring(0, file.length() - extension.length() - 1); StandardConfigDataReference reference = new StandardConfigDataReference(configDataLocation, null, root, profile, (!extensionHintLocation) ? extension : null, propertySourceLoader); return Collections.singleton(reference); } } throw new IllegalStateException("File extension is not known to any PropertySourceLoader. " + "If the location is meant to reference a directory, it must end in '/' or File.separator"); }

Debugger is accessing this method only when I trying to make spring access to the actuator endpoint on application loading. I need that because I need to know in my config-server which application is accessing. In my company rest requests network is only option at this moment. I can't use KAFKA or RabbitMq or something else.

Best Regards, Please help❤✌

0

There are 0 answers