I didn't find any mention in the documentation how can I do this simple thing.

We develop javascript browser-side application that should consume "final" json-config. Let me show in example:

Assume I create create files in Sping Cloud Config's git repository:

  • application.yml - General config for all applications
  • web.yml - Additional configuration for Web application
  • web-test.yml - Additional config for test profile

Actual behaviour

GET /config-server/web/test

Response:

{
  "name":"web",
  "profiles":[
    "test"
  ],
  "label":null,
  "version":null,
  "state":null,
  "propertySources":[
    {
      "name":"git@repo.git/web-test.yml",
      "source":{
        "param1":"patched"
      }
    },
    {
      "name":"git@repo.git/web.yml",
      "source":{
        "param2":"value2"
      }
    },
    {
      "name":"git@repo.git/application.yml",
      "source":{
        "param1":"value1"
      }
    }
  ]
}

Expected behaviour

GET /config-server/final/web/test

Response:

{
  "param1":"patched",
  "param2":"value2"
}

I have found similar question on StackOverflow.

Comment From: spencergibb

That format is for our internal client. Other formats are documented here: https://github.com/spring-cloud/spring-cloud-config/blob/master/docs/src/main/asciidoc/quickstart.adoc

Though I noticed that the .json endpoint isn't documented.

http://localhost:8888/web-test.json

Comment From: slavashvets

http://localhost:8888/web-test.json works, but it exposes only web-test.yml properties, they are not extended from web.yml and application.yml. It would be handy to get config with property inheritance.

Comment From: spencergibb

Using https://github.com/spring-cloud-samples/config-repo/ as the repo and

and http://localhost:8888/foo/default I see

{
  "name": "foo",
  "profiles": [
    "default"
  ],
  "label": null,
  "version": null,
  "state": null,
  "propertySources": [
    {
      "name": "https://github.com/spring-cloud-samples/config-repo/foo.properties",
      "source": {
        "democonfigclient.message": "hello spring io",
        "foo": "from foo props"
      }
    },
    {
      "name": "https://github.com/spring-cloud-samples/config-repo/application.yml",
      "source": {
        "info.description": "Spring Cloud Samples",
        "info.url": "https://github.com/spring-cloud-samples",
        "eureka.client.serviceUrl.defaultZone": "http://localhost:8761/eureka/",
        "foo": "baz"
      }
    }
  ]
}

And from http://localhost:8888/foo-default.json

{
  "democonfigclient": {
    "message": "hello spring io"
  },
  "eureka": {
    "client": {
      "serviceUrl": {
        "defaultZone": "http://localhost:8761/eureka/"
      }
    }
  },
  "foo": "from foo props",
  "info": {
    "description": "Spring Cloud Samples",
    "url": "https://github.com/spring-cloud-samples"
  }
}

Which has values from both.

If I recall, there is an issue merging objects across property sources like you are trying to do. @dsyer or @philwebb do you remember?

Comment From: slavashvets

@spencergibb At first, your answer discouraged me, because I tested it and it didn't work, but your example works. After a brief searches I've realized that this is because of hyphen in profile name. In this example:

http://localhost:8888/foo/development-db

{
  "name":"foo",
  "profiles":[
    "development-db"
  ],
  "label":null,
  "version":null,
  "state":null,
  "propertySources":[
    {
      "name":"file:///C:/Users/vshvets/repos/config-repo/foo-development-db.properties",
      "source":{
        "combined":"true"
      }
    },
    {
      "name":"file:///C:/Users/vshvets/repos/config-repo/foo.properties",
      "source":{
        "democonfigclient.message":"hello spring io",
        "foo":"from foo props"
      }
    },
    {
      "name":"file:///C:/Users/vshvets/repos/config-repo/application.yml",
      "source":{
        "info.description":"Spring Cloud Samples",
        "info.url":"https://github.com/spring-cloud-samples",
        "eureka.client.serviceUrl.defaultZone":"http://localhost:8761/eureka/",
        "foo":"baz"
      }
    }
  ]
}

http://localhost:8888/foo-development-db.json

{
  "bar":"spam",
  "combined":"true",
  "eureka":{
    "client":{
      "serviceUrl":{
        "defaultZone":"http://localhost:8761/eureka/"
      }
    }
  },
  "foo":"from foo development",
  "info":{
    "description":"Spring Cloud Samples",
    "url":"https://github.com/spring-cloud-samples"
  }
}

Comment From: spencergibb

The dash issue is from our use of dashes in the api definition (<app>-<profile>). Spring MVC can't determine where one starts and the other ends.

Comment From: amenezes

@spencergibb, I know this is a old issue, but I think this behavior cause a litter bit confusion.

I developed and use a spring cloud config client for use in Python applicaitons and there are recurrently questions about whether or not to use the .json extension. I did some tests following the official documentation and using this repository, and I see the same behavior related by @slavashvets .

So is there any pattern of file configuration layout, adjustment or orientation to handle this case?

Below is a sample of tests I performed:

# spring cloud config server instance
docker run -it --rm -p 8888:8888 hyness/spring-cloud-config-server:3.1.0-jre17 --spring.cloud.config.server.git.uri=https://github.com/spring-cloud-samples/config-repo
The HTTP service has resources in the following form:

/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.properties

For example:

curl localhost:8888/foo/development
curl localhost:8888/foo/development/master
curl localhost:8888/foo/development,db/master
curl localhost:8888/foo-development.yml
curl localhost:8888/foo-db.properties
curl localhost:8888/master/foo-db.properties
  • tests
# 1. /{application}/{profile}[/{label}]
curl -s http://localhost:8888/foo/development # same output related in this issue
curl -s http://localhost:8888/foo/development/main # same output related in this issue

# 2. /{application}-{profile}.json
curl -s http://localhost:8888/foo-development # Not Found
curl -s http://localhost:8888/foo-development.json # OK

# 3. /{label}/{application}-{profile}.json
curl -s http://localhost:8888/main/foo-development.json # same output related in this issue

# 4. /{application}-{profile}.json
curl -s http://localhost:8888/foo-development.json # OK