Dart has a standard way to externalize settings like Java properties? - dart

I'm looking for the right way to externalize the settings in my server Dart application.
In Java the common way would be a property file. Exists something similar in Dart?

You can just use a Dart script for your settings. No point in using a different format if there is no specific reason.
With a simple import you have it available in a typed way.

When the Resource class is implemented, I would just use a JSON file that is deployed with my program.

You could use a global variables, for example:
DB_URL = 'localhost:5432/mydb';
DB_PASS = 'my_pass';
then you could create a different configuration file for every enviroment. For example, for production you could create a production_config.dart which could contains:
loadConfig() {
DB_URL = '123.123.123.123:5432/mydb';
DB_PASS = 'my_prod_pass';
}
Then in your main function you could call production_config.loadConfig if environment is production, for example:
import 'production_config.dart' as prodConfig;
main(List<String> args) {
var ENV = getEnvFromArgs(args);
if(ENV == 'PROD') {
prodConfig.loadConfig();
}
//do other stuff here
}
In that way if you want to change from development to production you only need to pass an argument to your dart program for example:
dart myprogram.dart -env=PROD
The advantages of this approach are that you don't need to create a separate properties, json or yaml file for this, and you don't need to parse them. Furthermore the properties are type-ckecked.

I like putting configuration in a Dart class like what Günter Zöchbauer was talking about, but there is also the option of using the safe_config package. With this you enter the values in a yaml file. Quoting from the docs:
You define a subclass of Configuration with those properties:
class ApplicationConfiguration extends Configuration {
ApplicationConfiguration(String fileName) :
super.fromFile(File(fileName));
int port;
String serverHeader;
}
Your YAML file should contain those two, case-sensitive keys:
port: 8000
serverHeader: booyah/1
To read your configuration file:
var config = new ApplicationConfiguration("config.yaml");
print("${config.port}"); // -> 8000
print("${config.serverHeader}"); // -> "booyah/1"
See also an example from a setup in Aqueduct.

main() {
var env = const String.fromEnvironment("ENV", defaultValue: "local");
print("Env === " + env);
}
Give environment as option while running Dart App
pub serve --port=9002 --define ENV=dev
References:
http://blog.sethladd.com/2013/12/compile-time-dead-code-elimination-with.html
https://github.com/dart-lang/sdk/issues/27998

Related

How to pass configuration to a module

What's the right way to pass some configuration parameters to a module that I wrote for neo4j + GraphAware? I believe there should be a way that I can put some config entries in neo4j.conf and read them in my module's code but so far I could not find it.
There is definitely a possibility to pass configuration parameters to your module.
The best way is to look at other modules that use such configuration, GraphAware not being shy to open source modules (https://github.com/graphaware?utf8=%E2%9C%93&q=&type=&language=java) you can find plenty of it.
Let's take the uuid-module as an example :
In the bootstrapper class, you will find the logic for reading configuration parameters from the config file :
String uuidProperty = config.get(UUID_PROPERTY);
if (StringUtils.isNotBlank(uuidProperty)) {
configuration = configuration.withUuidProperty(uuidProperty);
LOG.info("uuidProperty set to %s", configuration.getUuidProperty());
}
https://github.com/graphaware/neo4j-uuid/blob/master/src/main/java/com/graphaware/module/uuid/UuidBootstrapper.java#L55
The found parameters are used to create an immutable Configuration class :
https://github.com/graphaware/neo4j-uuid/blob/master/src/main/java/com/graphaware/module/uuid/UuidConfiguration.java
The end of the module bootstrapping will then pass the configuration object to the constructor of the module :
return new UuidModule(moduleId, configuration, database);
https://github.com/graphaware/neo4j-uuid/blob/master/src/main/java/com/graphaware/module/uuid/UuidBootstrapper.java#L89
You can then use this module with the configuration :
public UuidModule(String moduleId, UuidConfiguration configuration, GraphDatabaseService database) {
super(moduleId);
this.uuidConfiguration = configuration;
this.uuidGenerator = instantiateUuidGenerator(configuration, database);
this.uuidIndexer = new LegacyIndexer(database, configuration);
}
https://github.com/graphaware/neo4j-uuid/blob/master/src/main/java/com/graphaware/module/uuid/UuidModule.java

Maximum recursion getting shared service

I have defined two classes (Environment and ConfigurationReader). Both are registered as shared dependencies.
The Environment class tries get the current environment, but for this, needs read a configuration file via ConfigurationReader.
The sequence diagram is:
The classes are:
class Environment
{
...
public function resolve()
{
$config = DI::getDefault()->getCfg();
$config->getValue('pepe', 'db_name');
}
...
}
class ConfigurationReader
{
...
public function getValue($aConfig, $aKey)
{
$path = $this->getFile($aConfig);
}
protected function getFile($aConfig)
{
$env = DI::getDefault()->getEnv();
$path = 'config/' . $env->getShortName() . '/' . $aConfig . '.yml';
return $path;
}
...
}
And are registered and created in the index.php:
...
$di = new FactoryDefault();
$di->setShared('env', function() use ($di) {
$env = new Services\Environment($di);
$env->resolve();
return $env;
});
$di->setShared('cfg', function() use ($di) {
return new Services\ConfigurationReader($di);
});
$di->getShared('cfg');
$di->getShared('env');
...
So, PHP crash at $config = DI::getDefault()->getCfg(); and says:
PHP Fatal error: Maximum recursion depth exceeded
Any ideas ?
A couple remarks
You're passing the di to the constructor, but end up getting it statically (DI::getDefault())
regarding the infinite loop, it's because cfg needs env who needs cfg who needs env etc.....
To have the framework automatically injecting the DI into your service you should either implement InjectionAwareInterface (https://docs.phalconphp.com/en/latest/reference/di.html#automatic-injecting-of-the-di-itself) or
extend the Component class (If you need event management too, use Plugin instead of Component ). Have a look at this discussion : https://forum.phalconphp.com/discussion/383/plugin-vs-component-what-s-the-difference-
Regarding your use case, you don't give enough context for an exhaustive answer, but I think you could simplify it as:
ConfigService: Unless you use configs from different env namespaces, you should pass the value of $env->getShortName() value to the service constructor (without getting it from the env service). In our apps the env is determined by nginx based on the domain name or other parameters and passed as an environment variable to php. Also, if you don't have hundreds of config files, and your app heavily relies on them, you should read and parse them once on instantiation and store the configs in the service (as associative array, config objects, or whatever you prefer). Add some cache layer to avoid wasting resource parsing all your files on each request. Phalcons provide The Config component to do so. It comes with file adapters (only ini and associative array format but you could easily implement your own yml adapter). If most of your app config relies on configurable values, that will probably be the first component you want to instantiate (or at least declare in the di). It shouldn't dependencies to other services.
EnvService: You can access your config values by calling the config service (If you have it to extend Component, you can do something like $this->cfg->getValue($key)).

Create a file relative path for secure server certificate

I'm working on a Dart HttpServer using SSL, which looks something like this:
class Server {
//The path for the database is relative to the code's entry point (main.dart)
static const String CERTIFICATE_DB_PATH = '../lib/server/';
static const String CERTIFICATE_DB_PASS = '*******';
static const String CERTIFICATE_NAME = 'CN=mycert';
Future start() async {
SecureSocket.initialize(database: CERTIFICATE_DB_PATH, password: CERTIFICATE_DB_PASS);
httpServer = await HttpServer.bindSecure(ADDRESS, PORT, certificateName: CERTIFICATE_NAME);
listenSubscription = httpServer.listen(onRequest, onError: onError);
}
//more server code here
}
This all works exactly as expected, so no problems with the actual certificate or server code. The part that I'm having problems with is mentioned in that first comment. The CERTIFICATE_DB_PATH seems to be relative not to the file the Server class is defined in, but rather to the file that contains the main() method. This means that when I try to write a unit test for this class, the path is no longer pointing to the correct directory. If this were an import, I'd use the package:packageName/path/to/cert syntax, but it doesn't seem that applies here. How can I specify the path of the certificate in a way that will work with multiple entry points (actually running the server vs unit tests)?
I don't think there is a way to define the path so it is relative to the source file.
What you can do is to change the current working directory either before you run main() or pass a working directory path as argument to main() and let main() make this directory the current working directory.
Directory.current = someDirectory;

Variables in External config in Grails

I have an external and internal config in my grails application. Here it is:
Config.groovy
grails {
server = 'abc.com'
}
testing {
test1 = ${grails.server}
}
External config:
grails {
server = 'xyz.com'
}
testing {
test1 = ${grails.server}
}
I want to set the value for test1 to be equal to the overridden value of grails.server but what I see is for test1 the original value is of 'grails.server' is assigned and not the overridden value as in external config.
So at the end I get for test1 the original value obtained from the config file
ie.'abc.com' and not the value overidden in the external config i.e.xyz.com.
If you want test1 to refer to a property like grails.server you'd do the following:
grails {
server = 'xyz.com'
}
test {
test1 = ${grails.server}
}
Surround any property name in the ${} expression and it will return the value of that property. Now your question is confusing because you talk about overriding a property, but it's unclear which property are you overriding. If it's grails.server then this answer is fine. But what's also confusing is the use of test because test is an environment, but I think you are trying to make an abstract example that doesn't imply environments.
Updated: How did you specify your external config files? Did you use grails.config.defaults.locations or grails.config.locations? If you used grails.config.locations that will allow your external config to override Config.groovy, but if you used grails.config.defaults.locations then Config.groovy overrides your external configuration.

How to create a custom yaml config file in Symfony

What I want to do is quite simple: store data in a custom config file that I want to read later on.
I created my file something.yml that I put in the global config directory.
It looks like that:
prod:
test: ok
dev:
test: ko
all:
foo: bar
john: doe
Then I copied the config_handlers.yml and also put it in the config directory and added the following at the top of the file:
config/something.yml:
class: sfDefineEnvironmentConfigHandler
param:
prefix: something_
But if I'm calling sfConfig::get("something_foo"); I keep getting NULL.
What did I do wrong?
I just want to read values, so no need to create a custome config handler, right?
I've read the doc here: http://www.symfony-project.org/book/1_2/19-Mastering-Symfony-s-Configuration-Files even though I'm running 1.4 (I don't think that changed since then).
Edit: Of course I can use sfYaml::load() but I'd like to do things in a better way.
Do not modify the index.php this is dirty!
Juste add this line to your app/frontend/config/frontendConfiguration.class.php
require_once($this->getConfigCache()->checkConfig('config/something.yml'));
(adapt with your own app name)
It's really easy, but also a little bit hacky:
Create the file /config/config_handlers.yml and add this:
config/something.yml:
class: sfDefineEnvironmentConfigHandler
param:
prefix: something_
Then add these two lines to /web/index.php after ... getApplicationConfiguration() (and also add them to frontend_dev.php and wherever you want this config file to be available):
$configCache = new sfConfigCache($configuration);
include($configCache->checkConfig('config/something.yml'));
So your /web/index.php might look like this afterwards:
<?php
require_once(dirname(__FILE__).'/../config/ProjectConfiguration.class.php');
$configuration = ProjectConfiguration::getApplicationConfiguration('frontend', 'prod', false);
$configCache = new sfConfigCache($configuration);
$configCache->checkConfig('config/something.yml');
sfContext::createInstance($configuration)->dispatch();
Btw: This is also in the documentation you cited, although the checkConfig() call is in a different place. Look for this: "When you need the code based on the map.yml file and generated by the myMapConfigHandler handler in your application, call the following line:"
Have fun ;-)
If you're doing this for a plugin you need to load the configuration file in the initialize() method. You can still use config_handlers.yml in your plugin's config directory or let the plugin load the handler too.
class myPluginConfiguration extends sfPluginConfiguration
{
public function setup() // loads handler if needed
{
if ($this->configuration instanceof sfApplicationConfiguration)
{
$configCache = $this->configuration->getConfigCache();
$configCache->registerConfigHandler('config/features.yml', 'sfDefineEnvironmentConfigHandler',
array('prefix' => 'feature_'));
$configCache->checkConfig('config/features.yml');
}
}
public function initialize() // loads the actual config file
{
if ($this->configuration instanceof sfApplicationConfiguration)
{
$configCache = $this->configuration->getConfigCache();
include($configCache->checkConfig('config/features.yml'));
}
}
}
The plugin's config initialize() method is called automatically by sfProjectConfiguration class and all appConfiguration classes (trough inheritance).
if your cached config-file is empty, you have probably forgotten to set the environment in your yml-file.
like:
all:
test: value1
test2: value2
dev:
test2: value3
Works in all application files:
$configCache = sfApplicationConfiguration::getActive()->getConfigCache();
$configCache->registerConfigHandler('config/something.yml', 'sfDefineEnvironmentConfigHandler', Array('prefix' => 'something_'));
include $configCache->checkConfig('config/something.yml');
Then you can use:
sfConfig::get("something_foo");
Have you cleared your cache files?
php symfony cc
In prodution environment all config files, classes, etc... are being cached.

Resources