Everytime we take our application to a new environment, there are always settings that have to be adjusted. We don't want to edit code. Instead, it's easier if we could just override various properties. And we can!
This was touched on briefly in Chapter 1, Quick Start with Java, under the guise of overriding Spring Boot's property settings. However, the fact that we can write our own custom configuration property beans makes this a powerful feature for application customization.
To recap the rules listed in Chapter 1, Quick Start with Java, property settings can be overridden in the following order, highest to lowest:
- @TestPropertySource annotations on test classes.
- Command-line arguments.
- Properties found inside SPRING_APPLICATION_JSON (inline JSON embedded in an env variable or system property).
- ServletConfig init parameters.
- ServletContext init parameters.
- JNDI attributes from java:comp/env.
- Java System properties (System.getProperties()).
- OS environment variables.
- RandomValuePropertySource that only has properties in random.*.
- Profile-specific properties outside the packaged JAR file (application-{profile}.properties and YAML variants).
- Profile-specific properties inside the packaged JAR file (application-{profile}.properties and YAML variants).
- Application properties outside the package JAR file (application.properties and YAML variants).
- Application properties inside the packaged JAR file (application.properties and YAML variants).
- @PropertySource annotations on any @Configuration classes.
- Default properties (specified using SpringApplication.setDefaultProperties).
One of the most common tactics is to create an application-{profile}.yml file that will be automatically applied when <profile> is in effect. Since Cloud Foundry apps get the cloud profile, it would be natural to create an application-cloud.yml file.
However, since we adopted the Spring Cloud Config Server and specified that the chat service is governed by chat.yml, we instead merely need to add a chat-cloud.yml file. Then we know the following cloud-specific settings will be applied when deployed to Cloud Foundry:
server: port: 8080 eureka: client: serviceUrl: defaultZone: http://user:password@learning-spring-boot-
eureka-server.cfapps.io/eureka/ instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
These settings can be explained as follows:
- The server.port is the same as before
- The eureka.client.serviceUrl.defaultZone is changed to the public-facing URL for our Eureka service, so the chat service can find it
- Since the public-facing URL for our chat service is terminated by a proxy, we have to override eureka.instance.hostname with ${vcap.application.uris[0]} to avoid registering an unreachable IP address with Eureka
- We must also register that we are visible (non-secure) on port 80
The following settings are identical for comments-cloud.yml:
server: port: 8080 eureka: client: serviceUrl: defaultZone: http://user:password@learning-spring-boot-
eureka-server.cfapps.io/eureka/ instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
And the same for images-cloud.yml:
server: port: 8080 eureka: client: serviceUrl: defaultZone: http://user:password@learning-spring-boot-
eureka-server.cfapps.io/eureka/ instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
Finally, we need to set the same instance details for the Eureka service itself via eureka-cloud.yml, as shown here:
server: port: 8080 eureka: instance: hostname: ${vcap.application.uris[0]} nonSecurePort: 80
If you'll notice, there is no eureka.client.serviceUrl.defaultZone given that this IS the Eureka service!
These additional settings added to https://github.com/gregturn/learning-spring-boot-config-repo/tree/production will ensure that our apps function smoothly in the cloud.
If we want to see our newly minted property settings, we can visit http://learning-spring-boot.cfapps.io/configprops and look for ChatConfigProperties.
The configuration properties can be described as follows:
- The name is captured as the prefix + the canonical path of the class
- The prefix, lsb, is displayed
- The properties lists the named properties we can tap (nesting displayed if that were the case)
From this, we can easily glean that lsb.origin is the property to override should we have some reason to adjust this.