DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
View Events Video Library
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Integrating PostgreSQL Databases with ANF: Join this workshop to learn how to create a PostgreSQL server using Instaclustr’s managed service

Mobile Database Essentials: Assess data needs, storage requirements, and more when leveraging databases for cloud and edge applications.

Monitoring and Observability for LLMs: Datadog and Google Cloud discuss how to achieve optimal AI model performance.

Automated Testing: The latest on architecture, TDD, and the benefits of AI and low-code tools.

Related

  • The Technology Stack Needed To Build a Web3 Application
  • Externalize Microservice Configuration With Spring Cloud Config
  • A Guide To Build, Test, and Deploy Your First DApp
  • How To Build Web Service Using Spring Boot 2.x

Trending

  • How To Deploy Helidon Application to Kubernetes With Kubernetes Maven Plugin
  • Podman Desktop Review
  • What Is Kubernetes RBAC and Why Do You Need It?
  • Generative AI: A New Tool in the Developer Toolbox

Ratpacked: Externalized Application Configuration

Ratpack has very useful methods to apply application configuration in our application. In this example Ratpack application we use different ways to apply configuration properties.

Hubert Klein Ikkink user avatar by
Hubert Klein Ikkink
·
Dec. 07, 15 · Tutorial
Like (1)
Save
Tweet
Share
2.21K Views

Join the DZone community and get the full member experience.

Join For Free

Ratpack has very useful methods to apply application configuration in our application. We can read configuration properties from files in different formats, like JSON, YAML, and Java properties, and the files can be read from different locations, like classpath or file system. We can also set configuration properties via Java system properties on the command line or use environment variables.

We use the ratpack.config.ConfigData class with the static of method to add configuration properties to our application. We provide a lambda expression or Groovy closure to the of method to build our configuration. Here we specify external files, locations and other configuration options we want to include for our application. If the same configuration property is defined in multiple configuration sources Ratpack will apply the value that is last discovered. This way we can, for example, provide default values and allow them to be overridden with environment variables if we apply the environment variables last.

To use the values that are gathered we use the get method of the ConfigData instance. We can apply the configuration properties to the properties of a configuration class that is then automatically instantiated. We add this to the registry so we can use the configuration properties further down in our application.

In the following example Ratpack application we use different ways to apply configuration properties. It is inspired by how Spring Boot reads and applies externalized configuration properties. First we use a simple Map with default values, then the classpath is scanned for files with the names application.yml, application.json and application.properties in either the root of the classpath or a config package. Next the same file names are searched on the file system relative from where the application is started. Next Java system properties starting with sample. are applied to the configuration. And finally environment variables starting with SAMPLE_ are interpreted as configuration properties.

Let's start with the simple configuration class and properties we want to set via Ratpack's configuration ability:

// File: src/main/groovy/com/mrhaki/SampleConfig.groovy
package com.mrhaki

/**
 * Configuration properties for our application.
 */
class SampleConfig {

    /**
     * URL for external service to invoke with HTTP client.
     */
    String externalServiceUrl

    /**
     * URI to access the Mongo database.
     */
    String mongoUri

    /**
     * Indicate if we need to use a HTTP proxy.
     */
    boolean useProxy

    /**
     * Simple message
     */
    String message

}

Next we have a very simple Ratpack application. Here we use ConfigData.of with a lot of helper methods to read in configuration properties from different sources:

// File: src/ratpack/Ratpack.groovy
import com.google.common.io.Resources
import com.mrhaki.SampleConfig
import ratpack.config.ConfigData
import ratpack.config.ConfigDataBuilder

import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths

import static groovy.json.JsonOutput.prettyPrint
import static groovy.json.JsonOutput.toJson
import static ratpack.groovy.Groovy.ratpack

ratpack {

    bindings {
        final ConfigData configData = ConfigData.of { builder ->
            // Set default value, can be overridden by
            // configuration further down the chain.
            // The map must have String values.
            builder.props(['app.useProxy': Boolean.TRUE.toString()])

            loadExternalConfiguration(builder)

            // Look for system properties starting with
            // sample. to set or override configuration properties.
            builder.sysProps('sample.')

            // Look for environment variables starting
            // with SAMPLE_ to set or override configuration properties.
            builder.env('SAMPLE_')

            builder.build()
        }

        // Assign all configuration properties from the /app node
        // to the properties in the SampleConfig class.
        bindInstance(SampleConfig, configData.get('/app', SampleConfig))
    }

    handlers {
        get('configprops') { SampleConfig config ->
            render(prettyPrint(toJson(config)))
        }
    }

}

private void loadExternalConfiguration(final ConfigDataBuilder configDataBuilder) {

    final List<String> configurationLocations =
            ['application.yml',
             'application.json',
             'application.properties',
             'config/application.yml',
             'config/application.json',
             'config/application.properties']

    configurationLocations.each { configurationLocation ->
        loadClasspathConfiguration(configDataBuilder, configurationLocation)
    }

    configurationLocations.each { configurationLocation ->
        loadFileSystemConfiguration(configDataBuilder, configurationLocation)
    }
}

private void loadClasspathConfiguration(
        final ConfigDataBuilder configDataBuilder,
        final String configurationName) {

    try {
        final URL configurationResource = Resources.getResource(configurationName)
        switch (configurationName) {
            case yaml():
                configDataBuilder.yaml(configurationResource)
                break
            case json():
                configDataBuilder.json(configurationResource)
                break
            case properties():
                configDataBuilder.props(configurationResource)
                break
            default:
                break
        }
    } catch (IllegalArgumentException ignore) {
        // Configuration not found.
    }

}

private void loadFileSystemConfiguration(
        final ConfigDataBuilder configDataBuilder,
        final String configurationFilename) {

    final Path configurationPath = Paths.get(configurationFilename)
    if (Files.exists(configurationPath)) {
        switch (configurationFilename) {
            case yaml():
                configDataBuilder.yaml(configurationPath)
                break
            case json():
                configDataBuilder.json(configurationPath)
                break
            case properties():
                configDataBuilder.props(configurationPath)
                break
            default:
                break
        }
    }
}

private def yaml() {
    return hasExtension('yml')
}

private def json() {
    return hasExtension('json')
}

private def properties() {
    return hasExtension('properties')
}

private def hasExtension(final String extension) {
    return { filename -> filename ==~ /.*\.${extension}$/ }
}

Next we create some external configuration files:

# File: src/ratpack/application.yml
---
app:
  mongoUri: mongodb://mongo:27017/test
# File: src/ratpack/application.properties
app.externalServiceUrl = http://remote:9000/api
app.message = Ratpack rules!

Let's run the application and see the output of the configprops endpoint:

$ http localhost:5050/configprops
...
{
    "externalServiceUrl": "http://remote:9000/api",
    "useProxy": true,
    "message": "Ratpack rules!",
    "mongoUri": "mongodb://mongo:27017/test"
}

Next we stop the application and start it with the Java system property -Dsample.app.useProxy=false and the environment variable SAMPLE_APP__MESSAGE='Ratpack rocks!'. We check the configprops endpoint again:

$ http localhost:5050/configprops
...
{
    "externalServiceUrl": "http://remote:9000/api",
    "useProxy": false,
    "message": "Ratpack rocks!",
    "mongoUri": "mongodb://mongo:27017/test"
}

Written with Ratpack 1.0.0.

This is the 1000th blog post on the Messages from mrhaki blog. I've blogged about many different subjects, starting with Apache Cocoon, Netbeans, followed by Groovy and Groovy related technologies like Grails, Gradle. Also about other developer subjects like Asciidoctor and much more. I hope you enjoyed the first 1000, because I am not finished and will continue with more blog posts about great technologies.

application Property (programming) File system

Published at DZone with permission of Hubert Klein Ikkink, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • The Technology Stack Needed To Build a Web3 Application
  • Externalize Microservice Configuration With Spring Cloud Config
  • A Guide To Build, Test, and Deploy Your First DApp
  • How To Build Web Service Using Spring Boot 2.x

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: