How to Read Environment Specific Properties File in Spring

Spring configuration strategies across environments

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:

Random Quotes application with the environment name shown

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:

Configuration features in the Octopus Web Portal

We then configure the step to inject values into the awarding.yml file with the glob **/application.yml:

Image showing the injected glob

Finally, nosotros define a variable called leap:profiles:active with the value #{Octopus.Environment.Name}:

Variables defined in the Octopus Web Portal

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:

Random Quotes application with the environment name shown

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.

Tomcat manager displaying the embedded Octopus environment

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                  

YAML variables in the Octopus Web Portal

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:

Enabling the custom deployment script in the Octopus Web Portal

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 pre-deployment script

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:

Enabling substitute variables in templates in the Octopus Web Portal

Instead of matching the file in the Structured Configuration Variables section, we now lucifer information technology in the Substitute Variables in Templates section:

The substitute variables templates section of the deployment process

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!

poorequist1988.blogspot.com

Source: https://octopus.com/blog/spring-environment-configuration

0 Response to "How to Read Environment Specific Properties File in Spring"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel