How to Read Environment Specific Properties File in Spring
Spring has rich support for complex configurations. The born support for profiles and externalized configuration gives you lot a practiced degree of freedom to construct environment specific configuration that can exist bundled into a single, self-contained awarding archive.
Merely virtually developers will still confront the key question of how to develop an awarding locally, and then deploy that application to an environment where the configuration values, similar the database connexion strings (and especially the passwords they may embed), must be kept hole-and-corner.
One solution is to push environment specific configuration into the environment in the course of surround variables. This is a perfectly valid choice, but when y'all have an application server hosting multiple applications, conscientious attention must be paid to the environs variable names to ensure application specific configurations don't collide.
Some other solution is to change the application as it's being deployed to inject awarding and environs specific configuration. For example, you may accept a connection string for a database on localhost
saved into a configuration file. This configuration tin be safely checked into source command, providing developers with the power to clone, build and run locally. Just during deployment, the connection string for a item surroundings overwrites the default value, resulting in an environment specific deployment with credentials that are kept hidden from prying eyes.
Octopus has long supported this kind of configuration file modification for .Internet config files and JSON files. This was accomplished either by agreement the specific format of the .Cyberspace XML files in social club to brand the appropriate modifications, or by allowing specially named variables to button values into JSON files.
Typically though, Coffee and Spring applications have defined configuration in YAML, XML, or Properties files. With Octopus 2020.4.0, support has been added to push variables into XML, YAML, and Properties files, giving Java and Jump developers the ability to create surround specific deployments from generic application archives.
In this blog post, we'll look at some common strategies for deploying environment doubter Spring applications to specific environments.
Modifying the Spring application.yml file
Permit'southward start with a simple example where we modify the proper name of the agile profile to lucifer the environment. The code shown beneath comes from the Random Quotes sample application.
In the awarding.yml
file beneath we have set the jump.profiles.active
property to local
to indicate we are working in a local development environment:
# The configuration defines the settings used in a local evolution environment # to give developers the ability to clone, develop and build without whatever # additional configuration. server: port : 5555 spring: profiles: agile: local h2: panel: enabled: true jpa: database-platform: org.hibernate.dialect.H2Dialect datasource: url: jdbc:h2:mem:testdb dbcp2: driver-class-proper noun: org.h2.Driver flyway: locations: classpath:db/migration/{vendor}
In that location are no secrets in this configuration file, making information technology safe to commit directly to source command, and removing any boosted local configuration by developers to get-go working on the code.
The active contour tin can be exposed as a holding on a Spring object by injecting a value with a SpEL expression:
@Value("${spring.profiles.agile:unknown}") individual String activeProfile;
Somewhen this value is shown in the web page exposed by the application:
Allow'south assume nosotros want to supervene upon the spring.profiles.active
property value with the name of the environment where the application will be deployed. We start by enabling the Structured Configuration Variables feature on the step.
This characteristic was previously called JSON Configuration Variables, just in 2020.4.0, we expanded the feature to support many new configuration files:
We then configure the step to inject values into the awarding.yml
file with the glob **/application.yml
:
Finally, nosotros define a variable called leap:profiles:active
with the value #{Octopus.Environment.Name}
:
During deployment, Octopus will extract the application annal (usually a JAR or WAR file), inject the value of the variable called spring:profiles:active
into the YAML file, repackage the application, and upload the resulting archive to either an application server or relieve it on disk, depending on the particular footstep that was used. Nosotros tin see the application now reports that it is running in the Dev environment:
Modifying the web.xml file
Spring is flexible in its ability to ascertain configuration files, just the traditional Java XML configuration files are quite limited in their ability to reference external data (like environment variables) or assume different file names. For example, the spider web.xml
file, which is used in traditional Coffee web applications to define awarding settings, can only be called web.xml
and does not include whatsoever expression language to load external values or conditionally define settings.
In the past, this has made the web.xml
file a particularly hard way to define environment specific configurations, simply with the new ability to inject values into XML files, Octopus now makes information technology trivial to modify this file during deployment with environment specific values.
Here is the web.xml
file from our sample awarding:
<web-app version="3.0" xmlns="http://java.sunday.com/xml/ns/javaee" xmlns:xsi="http://world wide web.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sunday.com/xml/ns/javaee/web-app_3_0.xsd"> <distributable /> <display-name>Random Quotes</brandish-name> </web-app>
To modify this file, we add it to the Structured Configuration Variables feature with the glob **/web.xml
, and then define a variable with the proper name //*:display-name
and a value Random Quotes #{Octopus.Environment.Name}
, which will embed the Octopus surroundings into the brandish name of the application. We can see this application name in the Tomcat manager:
The XPath of //*:display-name
uses the version two style of namespace selection. This is by far more than convenient than the version ane selector which would usually look like //*[local-name()='brandish-name']
, but both styles can be used.
Complex configuration changes
So far we have injected variables into existing values in our configuration files in a i-to-one fashion. This is nice for simple configuration changes, merely there will be cases where environs specific configuration will result in some pregnant changes with entirely new fields and old settings removed. For case, here is an application.yml
file that configures an external Postgres database instead of the in-memory H2 database used when developing locally:
server: port : 5555 bound: profiles: agile: Dev jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect backdrop: hibernate: default_schema: randomquotes datasource: url: jdbc:postgresql://databaseserver:5432/postgres username: postgres password: docker flyway: locations: classpath:db/migration/{vendor}
All H2 configuration has been removed, and the JPA configuration includes new nested properties. Then how do nosotros create this new configuration file?
We tin get close enough past replacing the body of the jpa
and datasource
backdrop with new YAML objects.
Here is the value of the variable called spring:datasource
:
url: jdbc:postgresql://databaseserver:5432/postgres username: postgres password: docker
And here is the value of the variable called jump:jpa
:
database-platform: org.hibernate.dialect.PostgreSQLDialect properties: hibernate: default_schema: randomquotes
Annotation that the variable values are standalone YAML documents. These documents are then used to replace the children of the spring.datasource
and spring.jpa
properties during deployment. The end result is an application.yml
file that looks like this:
# The configuration defines the settings used in a local development environment # to give developers the ability to clone, develop and build without whatever # boosted configuration. server: port: 5555 spring: profiles: active: Dev h2: console: enabled: true jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect properties: hibernate: default_schema: randomquotes datasource: url: jdbc:postgresql://databaseserver:5432/postgres username: postgres countersign: docker flyway: locations: classpath:db/migration/{vendor}
This may get us the outcome nosotros demand, but the h2
settings are still divers. Nosotros could of course replace the unabridged contents of the spring
property to remove the unwanted properties, just for more than radical transformations a better solution may be to have a second file that we use to replace the application.yml
file during deployment.
Configuration files and script hooks
Given that our environment specific configuration requires a mix of adding and removing content, nosotros'll create a second template file to represent this new structure called postgres-awarding.yml
. This file contains the structure that we expect, but information technology has placeholder values for annihilation sensitive:
server: port : 5555 spring: profiles: active: Dev jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect properties: hibernate: default_schema: randomquotes datasource: url: jdbc:postgresql://replaceme:5432/postgres username: replaceme password: replaceme flyway: locations: classpath:db/migration/{vendor}
We tin can re-create this template over the original awarding.yml
file using a custom deployment script, which is enabled every bit a characteristic:
The Pre-deployment script of cp Web-INF\classes\postgres-application.yml Spider web-INF\classes\application.yml
then copies the environment specific template over the default:
The variables are and then injected into application.yml
equally normal, and the result is the environment specific configuration file with but the values nosotros wanted.
Templates
To this point we take been pushing variables into configuration files. This allows us to have a configuration file used for local development, and then replace it inline with whatever environs specific variables.
Having now seen how custom deployment scripts can be used to replace configuration files at deployment, nosotros have the choice to create templates that make use of Octopus variable substitution to pull variables into a file. For instance, we may have an environment specific configuration file that looks like this:
server: port : 5555 spring: profiles: active: Dev jpa: database-platform: org.hibernate.dialect.PostgreSQLDialect properties: hide: default_schema: randomquotes datasource: url: jdbc:postgresql://#{DatabaseServer}:5432/postgres username: '#{DatabaseUsername | YamlSingleQuoteEscape}' countersign: "#{DatabasePassword | YamlDoubleQuoteEscape}" flyway: locations: classpath:db/migration/{vendor}
This template expects the DatabaseServer
, DatabaseUsername
, and DatabasePassword
variables to be defined in Octopus. These values are embedded into the YAML using the new filters YamlSingleQuoteEscape
and YamlDoubleQuoteEscape
to ensure that they are properly escaped given their context.
We then enable the Substitute Variables in Templates
feature to let the variables to be processed:
Instead of matching the file in the Structured Configuration Variables section, we now lucifer information technology in the Substitute Variables in Templates section:
Conclusion
Creating surround agnostic application packages that support local evolution with no special tooling provides developers with a straight forward clone, build, run workflow, while also assuasive a single compiled application to be deployed in many environments with any specific configuration needed. In this mail, we looked at a typical example of pushing variables into XML and YAML files, and pulling variables into a YAML template. We too saw how the custom deployment scripts tin be used to replace a local development configuration file with an environment specific one.
With the ability in Octopus 2020.iv to push variables into XML, YAML, and Backdrop files, it is easier than ever to create environment agnostic Java packages. Meanwhile the new Octostache filters YamlSingleQuoteEscape
, YamlDoubleQuoteEscape
, PropertiesKeyEscape
, and PropertiesValueEscape
allow variables to exist pulled into templates, taking care of any format specific escaping that is required.
We hope this new functionality volition heighten your Coffee deployments by making deployments to multiple environments smooth and painless.
Happy deployments!
Source: https://octopus.com/blog/spring-environment-configuration
0 Response to "How to Read Environment Specific Properties File in Spring"
Post a Comment