ASP.NET Core—access Configuration from static class - asp.net-core-mvc

I want a simple static class that accesses the Configuration object. All the config info is already read in from the appsettings.json file in the Startup class. I just need an easy way to access it. Is this possible?
namespace MyNamespace
{
public static class Config
{
public string Username => Configuration["Username"];
public string Password => Configuration["Password"];
}
}
Anywhere else in the app:
string username = Config.Username;
string password = Config.Password;

A slightly shorter version based on the same principle as above...
public Startup(IConfiguration configuration)
{
Configuration = configuration;
StaticConfig = configuration;
}
public static IConfiguration StaticConfig { get; private set; }
To use in another static class:
string connString = Startup.StaticConfig.GetConnectionString("DefaultConnection");

create the ConfigurationHelper static class in the service layer, so it can be used in other layers without circular dependency.
public static class ConfigurationHelper
{
public static IConfiguration config;
public static void Initialize(IConfiguration Configuration)
{
config = Configuration;
}
}
initialize the ConfigurationHelper inside the ConfigureServices method in the Startup class.
ConfigurationHelper.Initialize(Configuration);
Use it wherever you want including your static classes
e.g: ConfigurationHelper.config.GetSection("AWS:Accesskey").Value;

After much research, this works (in ASPNetCore 2.2) for accessing the appsettings.json config from a static class but for some reason appsettings.development.json no longer loads properly but it might be something else in my project messing that up. The reloadOnChange does work. As a bonus it also has IHostingEnvironment and IHttpContextAccessor. While this works, I have recently decided to switch back to a more DI approach to follow the paradigm shift as others have mentioned.
So here is one of many ways to access some DI stuff (including the configuration) in a static class:
AppServicesHelper.cs:
public static class AppServicesHelper
{
static IServiceProvider services = null;
/// <summary>
/// Provides static access to the framework's services provider
/// </summary>
public static IServiceProvider Services
{
get { return services; }
set
{
if (services != null)
{
throw new Exception("Can't set once a value has already been set.");
}
services = value;
}
}
/// <summary>
/// Provides static access to the current HttpContext
/// </summary>
public static HttpContext HttpContext_Current
{
get
{
IHttpContextAccessor httpContextAccessor = services.GetService(typeof(IHttpContextAccessor)) as IHttpContextAccessor;
return httpContextAccessor?.HttpContext;
}
}
public static IHostingEnvironment HostingEnvironment
{
get
{
return services.GetService(typeof(IHostingEnvironment)) as IHostingEnvironment;
}
}
/// <summary>
/// Configuration settings from appsetting.json.
/// </summary>
public static MyAppSettings Config
{
get
{
//This works to get file changes.
var s = services.GetService(typeof(IOptionsMonitor<MyAppSettings>)) as IOptionsMonitor<MyAppSettings>;
MyAppSettings config = s.CurrentValue;
return config;
}
}
}
}
Startup.cs:
public Startup(IHostingEnvironment env)
{
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
Configuration = builder.Build();
}
public void ConfigureServices(IServiceCollection services)
{
//...
services.AddHttpContextAccessor();//For HttpContext.
// Register the IOptions object
services.Configure<MyAppSettings>(Configuration.GetSection(nameof(MyAppSettings)));
//Explicitly register the settings object by delegating to the IOptions object so that it can be accessed globally via AppServicesHelper.
services.AddSingleton(resolver => resolver.GetRequiredService<IOptionsMonitor<MyAppSettings>>().CurrentValue);
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//...
AppServicesHelper.Services = app.ApplicationServices;
//...
}
Controller:
public class MyController: Controller
{
public MyController()
{
}
public MyAppSettings Config => AppServicesHelper.Config;
public async Task<IActionResult> doSomething()
{
testModel tm = await myService.GetModel(Config.Setting_1);
return View(tm);
}
}
Another class library:
public static class MyLibraryClass
{
public static string GetMySetting_ => AppServicesHelper.Config.Setting_1;
public static bool IsDev => AppServicesHelper.HostingEnvironment.IsDevelopment();
}
MyAppSettings.cs is any class that maps to a MyAppSettings section in appsettings.json:
public class MyAppSettings
{
public string Setting_1 {get;set;}
}
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Warning"
}
},
"AllowedHosts": "*",
"MyAppSettings": {
"Setting_1": "something"
}
}

I've similar problems, and after reading the document from Microsoft. I've resolved it:
Create an static ApplicationSettings class
public static class ApplicationSettings
{
public const string User = "UserOptions";
public static UserOptions UserOptions { get; set; } = new UserOptions();
// other options here...
}
Create an options class
public class UserOptions
{
public string Username { get; set; };
public string Password { get; set; };
}
Init the Options class in Program.cs
ConfigurationManager configuration = builder.Configuration;
configuration.GetSection(ApplicationSettings.User).Bind(ApplicationSettings.UserOptions);
Update your appsettings.json
{
"UserOptions": {
"Username": "input_your_username_here",
"Password": "input_your_password_here"
}
}
You can call it anywhere in your project now
public void MethodA()
{
string username = ApplicationSettings.UserOptions.Username;
string password = ApplicationSettings.UserOptions.Password;
}
public static void MethodB()
{
string username = ApplicationSettings.UserOptions.Username;
string password = ApplicationSettings.UserOptions.Password;
}
Hope this could help you well.

I agree with mcbowes, it's in the docs, but the first example looks more like what you need...want:
public class Program
{
public static IConfigurationRoot Configuration { get; set; }
public static void Main(string[] args = null)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json");
Configuration = builder.Build();
Console.WriteLine($"option1 = {Configuration["option1"]}");
// Edit:
IServiceCollection services = new ServiceCollection();
services.AddOptions();
services.Configure<HelloWorldOptions>(_configuration.GetSection("HelloWorld"));
// And so on...
}
}

Try avoid using a static class and use DI
namespace MyNamespace {
public interface IConfig {
string Username { get; }
string Password { get; }
}
public class Config : IConfig {
public Config(IConfiguration configuration) {
_configuration = configuration;
}
readonly IConfiguration _configuration;
public string Username => _configuration["Username"];
public string Password => _configuration["Password"];
}
}
The setup DI in StartUp class
public class Startup {
public void ConfigureServices(IServiceCollection services) {
//...
services.AddTransient<IConfig, Config>();
...
}
}
And use it like so
public class TestUsage {
public TestUsage(IConfig config) {
_config = config;
}
readonly IConfig _config;
public string Username => _config.Username;
public string Password => _config.Password;
}

You can use Signleton pattern to access your configurations from anywhere
public class ConnectionStrings
{
private ConnectionStrings()
{
}
// property with getter only will not work.
public static ConnectionStrings Instance { get; protected set; } = new ConnectionStrings();
public string DatabaseConnection { get; set; }
}
and in your startup class
public class Startup
{
private readonly IConfiguration configuration;
public Startup(IConfiguration configuration)
{
this.configuration = configuration;
configuration.GetSection("ConnectionStrings").Bind(ConnectionStrings.Instance);
}
public void ConfigureServices(IServiceCollection services)
{
}
public void Configure(IApplicationBuilder app)
{
}
}

This has already been said but I'm going to say it.
I believe .Net Core wants developers to get values through Dependency Inject. This is what I've noticed from my research but I am also speculating a bit. As developers, we need to follow this paradigm shift in order to use .Net Core well.
The Options Pattern is a good alternative to the static config. In your case, it'll look like this:
appsettings.json
{
"Username": "MyUsername",
"Password": "Password1234"
}
SystemUser.cs
public class SystemUser
{
public string Username { get; set; } = "";
public string Password { get; set; } = "";
}
Startup.cs
services.Configure<SystemUser>(Configuration);
And to use the SystemUser class, we do the following.
TestController.cs
public class TestController : Controller
{
private readonly SystemUser systemUser;
public TestController(IOptionsMonitor<SystemUser> systemUserOptions)
{
this.systemUser = systemUserOptions.CurrentValue;
}
public void SomeMethod()
{
var username = this.systemUser.Username; // "MyUsername"
var password = this.systemUser.Password; // "Password1234"
}
}
Even though we are not using a static class, I think this is the best alternative that fits your needs. Otherwise, you might have to use a static property inside the Startup class which is a scary solution imo.

Personally I like the method used in this link
Essentially it just adding a static field to your options class.
public class WeblogConfiguration
{
public static WeblogConfiguration Current;
public WeblogConfiguration()
{
Current = this;
}
}
Then in any static class you can do:
WeblogConfiguration.Current
Simple and very straight forward

If you are using environment variables as your configuration, you can access the environment variable directly rather than via the configuration object.
using System;
namespace My.Example
{
public static class GetPaths
{
private static readonly string MyPATH =
Environment.GetEnvironmentVariable("PATH");
private static readonly string MySpecialPath =
Environment.GetEnvironmentVariable("PREFIX_SpecialPath");
...
}
}

I think you could use extension function, something like this
public static string ConfigToSomeThing(this IConfiguration config, int value)
{
return config[value.ToString()] ?? "";
}
Then any place , just injection IConfiguration and use extension method
_systemConfiguration.ConfigToSomeThing(123);

I just created below class:
/// <summary>
///
/// </summary>
public static class ConfigurationManager
{
/// <summary>
///
/// </summary>
public sealed class ConfigurationManagerAppSettings
{
/// <summary>
///
/// </summary>
internal ConfigurationManagerAppSettings() { }
/// <summary>
///
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string this[string key] => (TheConfiguration ?? throw new Exception("Set ConfigurationManager.TheConfiguration in Startup.cs")).GetSection($"AppSettings:{key}").Value;
}
/// <summary>
///
/// </summary>
public static IConfiguration? TheConfiguration { get; set; }
/// <summary>
///
/// </summary>
public static readonly ConfigurationManagerAppSettings AppSettings = new ConfigurationManagerAppSettings();
}
and below is my code:
public class Startup
{
public Startup(IConfiguration configuration) {
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services) {
ConfigurationManager.TheConfiguration = Configuration;

I've used this approach and it seems to work well. In your static class, add a public IConfiguration property.
namespace MyNamespace
{
public static class Config
{
public static IConfiguration Configuration { get; set; }
public string Username => Configuration["Username"];
public string Password => Configuration["Password"];
}
}
In Startup.cs constructor, use dependency injection to get the configuration, and then assign it to the public member of your static class.
public class Startup
{
public Startup(IConfiguration configuration)
{
MyNamespace.Config.Configuration = configuration;
}
// The rest of the startup code...
}

I was getting same issue and I wanted to access app setting in static class so I put this solution. Write this below code in static class in my code class name was EncryptionUtility
private static string _saltKey = string.Empty;
private static IConfiguration configuration;
public static void AppSettingsConfigure(IConfiguration _config)
{
configuration = _config;
_saltKey = Convert.ToString(configuration["Security:EncyptPassword"]);
}
Call Appsettingconfiure from the program.cs file. Here, EncryptionUtility is static class or you can only write static method as your requirement. I had put this line above app.Run();
EncryptionUtility.AppSettingsConfigure(app.Services.GetRequiredService<IConfiguration>());
appsettings.json :
{
"Security": {
"EncyptPassword": "Password"
}
}

Here is a way to obtain the configuration values from a NET.Core page without having to reference these statically but then still being able to pass them to other static functions called from the non-static class.
At the top of your non-static class add this:
private readonly IConfiguration _configuration;
Then in the constructor function bring in the existing configuration as input to the function:
IConfiguration configuration
Then assign the configuration to your read only variable inside the constructor function:
_configuration = configuration;
Here is an example of what it should look like:
public class IndexModel : PageModel
{
private readonly IConfiguration _configuration;
public IndexModel(IConfiguration configuration)
{
_configuration = configuration;
}
}
After this you can reference the configuration in any function in the class by referencing _configuration and can even then pass this on to other static functions that you call from other classes:
public async Task OnGetAsync()
{
AnotherClass.SomeFunction(_configuration);
}
Then in the called static class I can make use of the configuration values:
public static string SomeFunction(IConfiguration configuration)
{
string SomeValue = configuration.GetSection("SomeSectionOfConfig")["SomeValue"];
}
I have a class that calls some stored procedures for viewing and amending data and passes parameter values from appsettings.json using this approach.

Consider using the instructions here for ASP.NET Core Configuration.
You can create a class to store your configuration settings and then access the values, something like this:
_config.UserName
In Startup - ConfigureServices:
services.Configure<Config>(Configuration.GetSections("General"));
Then just inject your object wherever you need as:
IOptions<Config> config

The IConfiguration is Injectable anywhere within the Project. But in the case of static class, the option I am using and maybe only approach...
var Configuration = new ConfigurationBuilder()
.AddUserSecrets<Startup>()
.Build();
And, you can add required section, such in this code block above, I added 'UserSecrets'.

Related

ASP.NET Core Web API : dependency injection based on runtime parameter value

I am working on an ASP.NET Core Web API application. My API will accept a country name as one of the input parameter from request body.
Due to nature of the application, we have country wise database with same schema. I have created DbContext for one of the databases and want to initialize the DbContext by the passing the connection string based on input request parameter value.
I have created factory method to return the needed database context based on the parameter passed to the factory method. However, the challenge I am facing is, while initializing the factory class as DI from controller, object of factory class is instantiated before the controller action is called. Hence, parameter value in factory method is empty.
How can I pass a parameter in runtime to initialize an object using dependency injection?
Here is the code...
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
public class MyDBContext : DbContext
{
public MyDBContext(DbContextOptions<MyDBContext> options)
: base(options)
{
}
public virtual DbSet<Student> Students { get; set; }
}
public interface IDbContextFactory
{
public MyDBContext GetDbContext(string
connectionString);
}
public class DbContextFactory : IDbContextFactory
{
public MyDBContext GetDbContext(string connectionString)
{
MyDBContext context = null;
if (!string.IsNullOrWhiteSpace(connectionString))
{
DbContextOptionsBuilder<MyDBContext> _dbContextOptionsBuilder = new DbContextOptionsBuilder<MyDBContext>().UseSqlServer(connectionString);
context = new MyDBContext(_dbContextOptionsBuilder.Options);
}
return context;
}
}
public interface IRepository
{
Student GetData();
}
public class Repository : IRepository
{
private MyDBContext _context;
public Repository(IDbContextFactory dbContextFactory)
{
// Here I need connection string based on input parameter (country) from request to dynamically generate country specific connection string
string connectionString = string.Empty;
_context = dbContextFactory.GetDbContext(connectionString);
}
public Student GetData()
{
return _context.Students.FirstOrDefault();
}
}
public interface IServiceAgent
{
Student GetData();
}
public class ServiceAgent : IServiceAgent
{
IRepository _repository;
public ServiceAgent(IRepository repository)
{
_repository = repository;
}
public Student GetData()
{
return _repository.GetData();
}
}
[ApiController]
[Route("[controller]")]
public class HomeController : ControllerBase
{
private readonly IServiceAgent _serviceAgent;
public HomeController(IServiceAgent serviceAgent)
{
_serviceAgent = serviceAgent;
}
[HttpGet]
public Student Get(string country)
{
return _serviceAgent.GetData();
}
}
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddScoped<IServiceAgent, ServiceAgent>();
services.AddScoped<IRepository, Repository>();
services.AddScoped<IDbContextFactory, DbContextFactory>();
services.AddScoped<DetermineCountryFilter>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}

Unable to resolve service for type with our own class

We are getting this exception when calling a web api controller:
InvalidOperationException: Unable to resolve service for type 'SDS.Lambda.Interfaces.ISecretManager' while attempting to activate 'SDS.Lambda.Controllers.SapController'.\r\n <p class="location">Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, bool isDefaultParameterRequired)
StartUp.cs contains the following:
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<ISecretManager, SecretManager>();
}
The controller has this constructor:
public class SapController : Controller
{
public SapController(ISecretManager secretManager)
{
_secretManager = secretManager;
}
}
We have the same issue with other types being injected into the constructor, but the IConfiguration instance can be injected, for example that parameter does not cause an exception:
public SapController(IConfiguration configuration, ISecretManager secretManager)
The ISecretManager interface looks like this (yes, it really does):
namespace SDS.Lambda.Interfaces
{
public interface ISecretManager
{
}
}
And the class (yes, really - I reduced it down to avoid complexity):
namespace SDS.Lambda.Interfaces
{
public class SecretManager : ISecretManager
{
}
}
Are we providing the interface/concrete type incorrectly?
Is there a way to retrieve the concrete type to test whether it has been provided properly?
When execution reaches the bottom of ConfigureServices, if we look at the services instance result enumeration, in the debugger view, the types we are injecting are listed, so we can't see why they are failing to be instantiated.
UPDATE
To elaborate and explain the issue with another class/dependency in the same solution:
Controller:
namespace SDS.Lambda.Controllers
{
[Route("api/[controller]")]
public class SapController : Controller
{
readonly IHelper helper;
public SapController(IHelper helpme)
{
helper = helpme;
}
...
}
Interface:
namespace SDS.Lambda.Interfaces
{
public interface IHelper
{
}
}
Class:
namespace SDS.Lambda.Helpers
{
public class Helper : IHelper
{
public Helper()
{
}
}
}
StartUp:
namespace SDS.Lambda
{
public class Startup
{
public static IConfiguration Configuration { get; private set; }
private readonly AppSettings _appSettings;
public Startup(IConfiguration configuration)
{
Configuration = configuration;
_appSettings = configuration.GetSection("AppSettings").Get<AppSettings>();
}
public void ConfigureServices(IServiceCollection services)
{
services.AddLogging(logger => logger.AddLambdaLogger());
services.AddSingleton<IHelper, Helper>();
services.AddControllers();
}
...
}

Options are not passed to the class

I'm trying to pass options to the class via the constructor from the appsettings.json file.
The file itself looks like this:
"IDP": {
"UrlCbr": "https://www.cbr-xml-daily.ru/daily_json.js",
"UrlDadata": "https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/currency",
"DadataToken": "94dabe1e8342c21fdad9622be29514d4f0f99bbd8",
"BotToken": "1549046386:AAHJsdsaMVaCT-8O3D_P8VLxw6EKAr4P9JfSU",
"BotName": "Hop_hipBot",
"BotUrl": "https://111295d46c69.ngrok.io/{0}"
}
To do this, I created the IDP.cs class:
public class IDP
{
public string UrlCbr { get; set; }
public string UrlDadata { get; set; }
public string DadataToken { get; set; }
public string BotToken { get; set; }
public string BotName { get; set; }
public string BotUrl { get; set; }
}
Then in the Startup.cs I'm making a connection:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddNewtonsoftJson();
services.Configure<IDP>(Configuration.GetSection("IDP"));
}
I need this data in the implementation of the bot:
class Bot
{
private static TelegramBotClient botClient;
private static IOptions<IDP> _IDPs;
public void Temp(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
public static async Task<TelegramBotClient> GetBotClientAsync()
{
if (botClient != null)
{
return botClient;
}
botClient = new TelegramBotClient(_IDPs.Value.BotToken);
var hook = string.Format(_IDPs.Value.BotUrl, #"api/bot");
await botClient.SetWebhookAsync(hook);
return botClient;
}
}
Well, the bot itself is launched in Startup.cs:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
Bot.GetBotClientAsync().Wait();
}
And when you run the entire application, the _IDPs field in the bot turns out to be null. Why is this happening and how do I need to properly deliver the data to the bot? In other classes, everything works correctly and options are passed
You have a bug in the Bot class. Change:
public void Temp(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
To :
public class Bot
{
.....
private static IOptions<IDP> _IDPs;
public Bot(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
......
}
Change your code like below:
public class Bot
{
private static IOptions<IDP> _IDPs;
public static void Temp(IOptions<IDP> IDPs)
{
_IDPs = IDPs;
}
public static async Task GetBotClientAsync()
{
var data = _IDPs.Value.BotToken;
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
//more services...
services.Configure<IDP>(Configuration.GetSection("IDP"));
var serviceProvider = services.BuildServiceProvider();
Bot.Temp(serviceProvider.GetService<IOptions<IDP>>());
Bot.GetBotClientAsync().Wait();
}
Result:

Access appsettings.json in class library

I search for a solution to access the appsettings.json within a class library. I have a ASP.NET Core web application which depends on a class library. In this class library I must read some properties from the appsettings.json.
Are there any way to do that?
You should probably use Options
It's fairly simple to use. Check this article. it's well explained Src
1/ Create your Options class
namespace UsingOptions.Models
{
public class MyOptions
{
public MyOptions()
{
// Set default value.
Option1 = "value1_from_ctor";
}
public string Option1 { get; set; }
public int Option2 { get; set; } = 5;
}
}
2/ Configure it in the ConfigureServices method (In startup.cs)
public void ConfigureServices(IServiceCollection services)
{
// Adds services required for using options.
services.AddOptions();
// Register the IConfiguration instance which MyOptions binds against.
**services.Configure<MyOptions>(Configuration);**
// Add framework services.
services.AddMvc();
}
3/ Inject IOptions into your controller
public class HomeController : Controller
{
private readonly MyOptions _options;
public HomeController(IOptions<MyOptions> optionsAccessor)
{
_options = optionsAccessor.Value;
}
public IActionResult Index()
{
var option1 = _options.Option1;
var option2 = _options.Option2;
return Content($"option1 = {option1}, option2 = {option2}");
}
}

Get Configuration Data with a Managed Service

Here is my ConfigUpdater class
private final class ConfigUpdater implements ManagedService {
#SuppressWarnings("rawtypes")
#Override
public void updated(Dictionary config) throws ConfigurationException {
if (config == null) {
return;
}
String title = ((String)config.get("title"));
}
}
My question is how can I access String title in any other class? Or how can I get config dictionary in any other class... Method updated will only be called when a config file is changed... once it is changed how can access its data in other class?
In general you would create a service that exposes these properties to other components.
For example, you could give your ConfigUpdater a second interface. Another component can than lookup/inject this interface from the service registry and use it's methods to access the properties.
I created an example project on GitHub: https://github.com/paulbakker/configuration-example
The most important part is the service that implements both ManagedService and a custom interface:
#Component(properties=#Property(name=Constants.SERVICE_PID, value="example.configurationservice"))
public class ConfigurationUpdater implements ManagedService, MyConfiguration{
private volatile String message;
#Override
public void updated(#SuppressWarnings("rawtypes") Dictionary properties) throws ConfigurationException {
message = (String)properties.get("message");
}
#Override
public String getMessage() {
return message;
}
}
The configuration can then be used like this:
#Component(provides=ExampleConsumer.class,
properties= {
#Property(name = CommandProcessor.COMMAND_SCOPE, value = "example"),
#Property(name = CommandProcessor.COMMAND_FUNCTION, values = {"showMessage"}) })
public class ExampleConsumer {
#ServiceDependency
private volatile MyConfiguration config;
public void showMessage() {
String message = config.getMessage();
System.out.println(message);
}
}

Resources