Spring boot edit application.properties - properties

Is it possible to add new properties to application.propertiesor overwrite existing values?
resource = new ClassPathResource("/application.properties");
Properties props = PropertiesLoaderUtils.loadProperties(resource);
Things i already tried:
Using store:
props.put("spring.datasource.url", "<my value>");
prop.store(new FileOutputStream("xyz.properties"), null);
Using ConfigurableEnvironment:
#Autowired
ConfigurableEnvironment env;
...
props.put("spring.datasource.url", "<my value>");
environment.getPropertySources().addFirst(new PropertiesPropertySource("myProps", props));
Then when i use props.get(key) it prints the correct value, but the next time i use
Properties props = PropertiesLoaderUtils.loadProperties(resource);
it isn't there.
So did i do something wrong, or is there another way to accomplish this?

Related

cachingframework.redis - need to isolate some keys from other keys

I'm using library cachingframework.redis.
I want to use some mechanism to isolate some keys from other keys (keys belongs to different microservices).
How can I do it?
Maybe something like this - StackExchange.Redis.IDatabase.WithKeyPrefix - but I dont know how to apply it to cachingframework.redis
I think the library could expose an optional configuration option to set a key prefix when creating the RedisContext.
For example:
private static RedisContext _context = new RedisContext(
"localhost:6379",
new DatabaseOptions() { KeyPrefix = "YourPrefix:" }
);
...
_context.Cache.SetObject("key", "value"); // Will be stored at key "YourPrefix:key"
I've created an Issue Here to track this.

Dependency Injection Access While Configuring Service Registrations in asp.net Core (3+)

I have cases, where I want to configure services based on objects which are registered in the dependency injection container.
For example I have the following registration for WS Federation:
authenticationBuilder.AddWsFederation((options) =>{
options.MetadataAddress = "...";
options.Wtrealm = "...";
options.[...]=...
});
My goal in the above case is to use a configuration object, which is available via the DI container to configure the WsFederation-middleware.
It looks to me that IPostConfigureOptions<> is the way to go, but until now, I have not found a way to accomplish this.
How can this be done, or is it not possible?
See https://andrewlock.net/simplifying-dependency-injection-for-iconfigureoptions-with-the-configureoptions-helper/ for the I(Post)ConfigureOptions<T> way, but I find that way too cumbersome.
I generally use this pattern:
// Get my custom config section
var fooSettingsSection = configuration.GetSection("Foo");
// Parse it to my custom section's settings class
var fooSettings = fooSettingsSection.Get<FooSettings>()
?? throw new ArgumentException("Foo not configured");
// Register it for services who ask for an IOptions<FooSettings>
services.Configure<FooSettings>(fooSettings);
// Use the settings instance
services.AddSomeOtherService(options => {
ServiceFoo = fooSettings.ServiceFoo;
})
A little more explicit, but you have all your configuration and DI code in one place.
Of course this bypasses the I(Post)ConfigureOptions<T> entirely, so if there's other code that uses those interfaces to modify the FooSettings afterwards, my code won't notice it as it's reading directly from the configuration file. Given I control FooSettings and its users, that's no problem for me.
This should be the approach if you do want to use that interface:
First, register your custom config section that you want to pull the settings from:
var fooSettingsSection = configuration.GetSection("Foo");
services.Configure<FooSettings>(fooSettingsSection);
Then, create an options configurer:
public class ConfigureWSFedFromFooSettingsOptions
: IPostConfigureOptions<Microsoft.AspNetCore.Authentication.WsFederation.WsFederationOptions>
{
private readonly FooSettings _fooSettings;
public ConfigureWSFedFromFooSettingsOptions(IOptions<FooSettings> fooSettings)
{
_fooSettings = fooSettings.Value;
}
public void Configure(WsFederationOptions options)
{
options.MetadataAddress = _fooSettings.WsFedMetadataAddress;
options.Wtrealm = _fooSettings.WsFedWtRealm;
}
}
And finally link the stuff together:
services.AddTransient<IPostConfigureOptions<WsFederationOptions>, ConfigureWSFedFromFooSettingsOptions>();
The configurer will get your IOptions<FooSettings> injected, instantiated from the appsettings, and then be used to further configure the WsFederationOptions.

Serialization error with Elasticsearch NEST/C#

I'm using NEST to index my objects and I'm running into a Newtonsoft error on serialization. One of my objects has a self referencing loop. Would there be a way for me to access the JsonSerializer and change how it handles self-references without having to modify the source code?
You can register custom converters on your client:
public void AddConverter(JsonConverter converter)
{
this.IndexSerializationSettings.Converters.Add(converter);
this.SerializationSettings.Converters.Add(converter);
}
This might be of help.
There is no direct way to alter the JsonSerializerSettings used in the client though.
There is a new api now, take a look at:
var cs2 = new ConnectionSettings(new Uri("http://localhost:9200"))
.SetJsonSerializerSettingsModifier(settings => settings.TypeNameHandling = TypeNameHandling.None)
.EnableTrace();
Thanks for adding the support!

Change application.conf runtime?

I want to set the database connection at run time for my Play project. I know that I can set a property run time with the following code:
#OnApplicationStart public class Bootstrap extends Job
{
#Override public void doJob()
{
// now set the values in the properties file
Play.configuration.setProperty("db.driver", dbDriver);
Play.configuration.setProperty("db.url", dbUrl);
Play.configuration.setProperty("db.user", dbUsername);
Play.configuration.setProperty("db.pass", dbPassword);
}
}
But when executing the code above the file is not actually changed, I think just in memory.
How can I set the database properties and force Play! to use this properties in order to connect to the right database onApplicationStart?
Thanks!
UPDATE 2012-01-29
Solution is possible via a plugin. In this plugin I have to override onConfigurationRead() and apply the properties to the configuration file at that moment. I will try to post some code as soon as I have time for this.
By the time you change the properties, the DB plugin is already initialized. You need to write a plugin and overwrite the onConfigurationRead() method, then put your new settings there. Paly's dbplugin will init later on.
I faced with the necessity of programmatically obtaining values from aws secret manager in runtime before using that values in play framework configuration. You can override initial default values from application.conf and add new.
Work for play framework v2.7.3
import com.typesafe.config.ConfigValueFactory;
import play.api.Configuration;
import play.api.inject.guice.GuiceApplicationBuilder;
import play.api.inject.guice.GuiceApplicationLoader;
public class ExtendedGuiceApplicationLoader extends GuiceApplicationLoader {
#Override
public GuiceApplicationBuilder builder(Context context) {
Configuration configuration = new Configuration(
context.initialConfiguration().underlying()
.withValue("db.default.username",
ConfigValueFactory.fromAnyRef("aws.secret.db.username"))
.withValue("db.default.password",
ConfigValueFactory.fromAnyRef("aws.secret.db.password"))
);
return super.builder(
new Context(context.environment(),
configuration,
context.lifecycle(),
context.devContext())
);
}
}
DonĀ“t forget add this string to application.conf
play.application.loader="youpackage.ExtendedGuiceApplicationLoader"
Are you sure this is what you really intend to do?
Play offers the possibility to add different configurations in your application.conf
for example you could have:
db.url=mydefaulturl
%uat.db.url=uaturl
%prod.db.url=produrl
%prod1.db.url=prod1url
And then start the app with play start --%uat or play start --%prod

Multiple Zend_Mail configurations in application.ini

I'm am using Zend Framework.
I need to put multiple mail configurations in application.ini for Zend_Mail (using Zend_Application_Resource_Mail). Is it possible to do this using the standard classes in Zend Framework or do I need to create my own class?
I am using the latest stable version of Zend Framework.
Thanks for the answers
It does not appear to be possible to set multiple configurations for Zend_Mail with Zend_Application_Resource_Mail.
You could add the various configurations to application.ini but you will have to write your own class/functions to make the desired configuration active.
The things that are set by Zend_Application_Resource_Mail that you will have to override are Zend_Mail::setDefaultTransport($newTransport);, Zend_Mail::setDefaultReplyTo($email);, and Zend_Mail::setDefaultFrom($email);.
I tested something and found an easy thing you can do.
Set up your different configurations like this in application.ini:
mail_config.mail_test.transport.type = smtp
mail_config.mail_test.transport.host = "smtp.example.com"
mail_config.mail_test.transport.auth = login
mail_config.mail_test.transport.username = myUsername
mail_config.mail_test.transport.password = myPassword
mail_config.mail_test.defaultFrom.email = john#example.com
mail_config.mail_test.defaultFrom.name = "John Doe"
mail_config.mail_test.defaultReplyTo.email = Jane#example.com
mail_config.mail_test.defaultReplyTo.name = "Jane Doe"
Note how we are setting up options under mail_config. This will be the set of options to apply. mail_test is an example configuration. You can have multiple by setting mail_config.mail_test2, mail_config.corporate_mail, or mail_config.production etc.
Next, create an empty class that extends from Zend_Application_Resource_Mail. Preferably, it should be named and placed so it can be autoloaded.
The class:
<?php
class Application_Service_MailSettings extends Zend_Application_Resource_Mail { }
Now, here is how to override the default mail configuration easily with something else.
This example assumes you are in a controller:
// get the bootstrap, so we can get mail_config options
$bootstrap = $this->getInvokeArg('bootstrap');
$options = $bootstrap->getOption('mail_config');
// initialize the resource loader with the options from mail_config.mail_test
$mailSettings = new Application_Service_MailSettings($options['mail_test']);
$mailSettings->init(); // call init() so the settings are applied
// now the default transport, from, and reply to are set using mail_config.mail_test options.
// to use a different set of options, just do
// $mailSettings = new Application_Service_MailSettings($options['other_config');
This should accomplish what you want with very little new code.