I have a piece of code that I have been using to manage properties for a while now. My boss didn't like this solution on the ground that property management should be done by well-known libraries, like Spring/Guice. That's understandable, and I'm looking for alternatives, but I can't find one that gives me the features that I want (or maybe I don't know how to use them properly).
The features I'm looking for are:
SUPER easy to add new properties to a class during coding
No need to touch constructor, add dedicated field or setters
Uses Java code (as much as possible)
Easy to add defaults. No need to edit property file if you just want make something quickly configurable and keep the code working
Can use any types (can define conversion from String within the framework)
Custom validation that are run at config load time for each properties
E.g. check for existence for a file, check if defined conversion succeeds etc.
Ability to inject parameters to final fields
Ability to auto-generate property file TEMPLATE
Especially ability to define description, preferably in Java code which is then written to the template
Ability to update config at runtime, in a thread-safe manner
Are there any library that gives me these features?
If I'm missing something and these can all be satisfied by Spring/Guice, are there any good resource online?
Example usage of my solution
Sample of generated property file TEMPLATE (you copy and edit this)
No need to touch constructor, add dedicated field or setters
That is not the dependency injection pattern. You might substitute the resource locator pattern, but doing that well (in particular, in a way the retains testability) is not trivial: With a setter, I can easily reconfigure the class under test. If that class depends on a config file, will I write a separate config file whenever I need to change settings for the unit test? Will I mock the config class? Possible, but not exactly straighforward ...
Ability to auto-generate property file TEMPLATE
As already pointed out in the comments, this doesn't seem very useful, as it can not migrate an old config file.
Ability to update config at runtime, in a thread-safe manner
That, in general, requires support from the component being configured (for instance, changing a setting for thread pool size involves starting / stopping worker threads ...). In general, the only simple way to handle that is restarting the application ...
If you drop these requirements, Spring's PropertyOverrideConfigurer fits nicely.
Alternatively, if you run inside a servlet container, you could pepper your Spring config with JNDI lookups.
If you really want to generate templates, I don't know a ready-made solution. I might do something like:
class Configuration {
int threadCount = 10;
String secretKey;
#Description("Number of workers. Default value is number of available cores.")
int workerThreadCount = Runtime.getRuntime().availableProcessors();
/** Use default settings */
Configuration() {
}
/** read the settings from the file */
Configuration(Properties props) {
for (String prop : props) {
Field f = getClass().getField(prop);
f.set(this, props.getValue(prop));
// TODO: type conversion,
// e.g. with PropertyEditors,
// or Spring's ConversionService,
// or invoking the constructor that takes a single string argument,
// or ...
}
}
void save() {
for (Field f : getClass().getFields()) {
// TODO save the setting
}
}
}
Writing the default configuration would be a simple as new Configuration().save(file), or upgrading an existing configuration as simple as `new Configuration(file).save(file)'.
Unlike your approach, this approach is statically type safe, and doesn't clutter the code accessing the configuration settings with redundant type specifiers. That is, instead of
if(config.value(Prop.PROXY_ENABLED,Boolean.class)){
you could simply write
if (config.proxyEnabled) {
and because the field can be of type boolean (not Boolean), you don't even risk a NullPointerException here.
Related
I have a library doing reporting, and each projects using it need to provide custom values.
So I have 2 ways for setting these values:
Use properties file
Provide an abstract class to provide values in the library and let projects override it.
My question is which one is preferable?
e.g. 2 values: consumer & producer
Option 1 - properties application.yml:
consumer: con
producer: pro
Then read into a properties class.
Option 2 - Java class:
Public Abstract Class MyConfig{
// project will override method and return "con";
protected abstract getConsumer();
protected abstract getProducer();
}
Arguments for using properties file:
java way is probably better when default values can be used by most projects. But since most values here do need customisation for each project, Using config file is a clearer, easier and less-pollution-to-core-business way.
To be specific, if we use java way instead:
need to write more lines
need to worry about injecting the new class to spring
people who don’t care about this library will see the new class and need to figure out what it does
for those who do care about the library, instead of an easy to find property file, they’ll have to dig into the many java files in order to change related values
Arguments for using Java:
It's for the same reason why we are writing code in an IDE instead of a text in a text editor.
With a config file, nobody checks the semantics of the config. If the underlying library changes, there will be no compiler telling you that something is wrong.
With Java class, documentation will be in place as method comments, API will be discoverable as you just check what can be overridden if needed.
We will follow what Springboot is pushing, which is java based config. We would avoid silly errors, like incorrect syntax in the text config, which will break something, etc.
I have a little design issue on which I would like to get some advice:
I have several classes that inherit from the same base class, each one can accept the same data and analyze it in a slightly different way.
Analyzer
|
˪_ AnalyzerA
|
˪_ AnalyzerB
...
I have an input file (I do not have control over the file's format) that defines which analyzers should be invoked and their parameters. Plus it defines data-extractors in the same way and other similar things too (in similar I mean that this is an action that can have several variations).
I have a module that iterates over different analyzers in the file and calls some factory that constructs the correct analyzer. I have a factory for each of the archetypes the input file can define and so far so good.
But what if I want to extend it and to add a new type of analyzer?
The solution I was thinking about is using a property file for each factory that will be named after the factories name and it will hold a mapping between the input file's definition of whatever it wants me to execute and the actual classes that I use to execute the action.
This way I could load that class at run-time -> verify that it's implementing the right interface and then execute it.
If some John Doe would like to create his own analyzer he'd just need to add a new property to the correct file (I'm not quite sure what would be the best strategy to allow this kind of property customization).
So in short:
Is my solution too flawed?
If no what would be the most user friendly/convenient way to allow customization of properties?
P.S
Unfortunately I'm confined to using only build in JDK classes as the existing solution, so I can't just drop in SF on them.
I hope this question is not out of line I'm just not used to having my wings clipped this way, not having SF or some other to help me implement an elegant solution.
Have a look at the way how the java.sql.DriverManager.getConnection(connectionString) method is implemented. The best way is to watch the source code.
Very rough summary of the idea (it is hidden inside a lot of private methods). It is more or less an implementation of chain of responsibility, although there is not linked list of drivers.
DriverManager manages a list of drivers.
Each driver must register itself to the DriverManager by calling its method registerDriver().
Upon request for a connection, the getConnection(connectionString) method sequentially calls the drivers passing them the connectionString.
Each driver KNOWS if the given connection string is within its competence. If yes, it creates the connection and returns it. Otherwise the control is passed to the next driver.
Analogy:
drivers = your concrete Analyzers
connection strings = types of your files to be analyzed
Advantages:
There is no need to explicitly bind the analyzers with their type of file they are meant for. Let the analyzer to decide itself if it is able to analyze the file. If not, null is returned (or an exception or whatever) to tell the AnalyzerManager that the next analyzer in the row should be asked.
Adding new analyzer just means adding a new call to the register() method. Complete decoupling.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I'm creating a program that requires some options values to be set along with some paths to image files, path to a SQLite database, some information about the text on various buttons, information about which database to use (SQLite / MySQL for example), etc.
So far, I had a helper class in which I made everything static and I accessed it from everywhere in the program, but it was becoming a mess and I read that this is sort of bad practice since it doesn't follow object-oriented programming guidelines.
So what I did is make that class a singleton with its reference in my controller object. To access my options, I now call controller.getOptionName instead of calling Helper.getOptionName directly.
I have a feeling I'm approaching this the wrong way, especially because from what I've read, if many of my objects depend on a single class (the helper class), I'm not separating everything enough.
I don't know what I should be doing instead, is there a "standard" on where to keep all my options? I thought about using a XML file or something along those lines, but I'm going to end up having to access it from everywhere anyway, so it feels like this would create the same problem.
The Problem: Configuration Sprawl Over time, programs gain features and options. When they connect to external systems and services (e.g. databases, event brokers, cloud/web services), they must also keep a growing set of configs and credentials for those services handy.
The traditional places to store this information at runtime are global variables and OS environment variables. Both suck.
Config data logically is "global environment" or context in which the app is running, but you can't easily depend on either global or environment variables.
The other traditional mechanism, config files--whether XML, INI, .properties, or whatever--help store config data between runs, but do nothing to organize configs/options for the program code, or during its execution.
You can clean things up a bit by making options into properties of your application's classes. This is the traditional "next step." Unfortunately, it can take a lot of up-front "what goes where??" thinking. IMO, more than it's worth. Even if you get those choices right, it won't last. If you have a reasonably feature-ful app, the number of options and settings will become overwhelming over time. You'll spend a lot of time hand-coding defaults and options in object constructors and the arguments/code of other methods. Trying to perfectly partition configurations among classes not only expends effort, it can lead to highly interdependent classes. So much for clean encapsulation!
I've banged my head against this particular wall often, especially when aiming for code that has "reasonable" or "intelligent" defaults and behaviors for everything, that allows users to override defaults at any time, and that presents a simple interface that doesn't require understanding the complete interplay of app classes and components to use its services.
Solution: Delegate to a Config Object The best solution I've found is to encapsulate option/config data into its own designated object. A fancy way of describing this pattern: For configuration, settings, and option data, use delegation rather than inheritance or composition.
How you build a config mapping depends on the language you're working in. In many languages, constructing your own Config object gives you a nice "look":
if opts.verbose:
print "..."
which I find more readable than the more explicit "getter" opts.get("verbose") or "indexer" opts['verbose'] ways of accessing a property. But you usually don't have to make your own Config class, which basically is just a mapping.
● The Easy Way ● Use a generic mapping: e.g. in Python a dict, in Perl a %hash, in Java a Dictionary or HashMap. Even better, there are extensions of these designed for, or especially suited to, configuration data. In Python, e.g., I use stuf and TreeDict for their simple dot-access and other nice properties. In Java, Properties is a similar specific-for-configs extension. E.g.:
from stuf import stuf # stuf has attributes!
opts = stuf(
show_module=False, # comment explaining what show_module means
where=True, # ...
truncate=False, # ...
everything=False, # ...
allvars=False, # ...
allkeys=False, # ...
yaml=False, # ...
on=True, # ...
ret=None, # ...
)
if opts.truncate:
...
This way, all your config and option data is in one place, neatly accessible, and clearly delineated from all of the other program, class, instance, and function/method data it's used side-by-side with. This helps maintain clarity over time, as the program evolves. You can quickly determine "Is this part of the core data? Or is it related to the context in which the core data is being processed?"
To make things even better, if you pre-load config data from a config file, load or copy those values directly into your config object. And if you take arguments from the command line, load or copy those values directly into your config object. Now you have one unified source of all the "what does the user want me to do, with what options and settings?" information.
TL;DR - 90% of apps or services are just fine with a simple config/options mapping. Everything that follows is for advanced use cases. Because this was a design/patterns question, here's why this approach isn't a one-off, but extends to successively more sophisticated/intricate use cases.
● Per-Instance Config ● You can have multiple levels of config/option data. The most common use for this would be defaults set at a class or module level, then potentially different options for each instance. A server app might have an instance per user, with each user/instance needing its own customized settings. The config map is copied at instance creation/initialization, either automatically or explicitly.
●● Multiple Config Objects ●● You can partition config/option data into several config objects, if that makes sense. For example, you might partition options for data retrieval from those for data formatting. You can do this at the start of the design, but need not. You can start with one monolithic config object, then refactor over time (generally, as you start to refactor the underlying functions). Obviously you don't want to "go crazy" adding config objects, but you can have a few without adding much program complexity. If you partition config objects, you can proxy multiple config "domains" through a single API--giving you quality information decomposition internally, but a very simple outward appearance.
◆ Chain Gang ◆ More elegant than copying config data per instance: Use chainable or hierarchical mapping (e.g. in Python, ChainMap) that lets you "overlay" the values of one mapping with those of another (similar to "copy-on-write" schemes, or "union" and "translucent" file systems). Instance options then refer directly to class/default options--unless they are explicitly set, in which case they're instance-specific. Advantage: If class/default/global settings are changed during program execution, subsequent instance method invocations will "see" the changed defaults and use them (as long as they haven't been overridden at the instance level).
◆◆ Transient Config ◆◆ If you need configs/options changeable "on the fly"--say for the scope of a given method invocation--the method can extend the instance option chained mapping. In Python, that's what ChainMap.new_child() does. It sounds complicated, but as far as the method code is concerned, it's drop-dead-simple. There's still just a single config object to refer to, and whatever it says is the option, use it.
◆◆◆ Arbitrary Duration Overlay ◆◆◆ There's nothing magical about the temporal scope of method invocation. With the proper setup, any level of configuration can be transiently overlaid for as long as needed. For example, if there's some period during program run you'd like to turn on debugging, logging, or profiling, you can turn that on and off whenever you like--just for certain instances, or for all of them at once. This hors catégorie usage requires a Config object slightly beyond stock ChainMap--but not by much (basically just a handle to the chain mapping).
Happily, most code doesn't come close to needing these "black diamond" levels of config sophistication. But if you want to go three or four levels deep, delegating to separate config objects will take you there in a logical way that keeps code clean and orderly.
I would recommend placing your options into some sort of file (whether it be xml or a .properties) especially if the values can change (such as a database username, etc). I would also say that you can break up these configuration files by component. Just like you break up your code, the components that need database information likely do not need image paths. So you can have a file for database info, image path info, etc. Then have your components load the file that they need.
In the java-specific case, you can put these files on your classpath and have your components reference them. I like using .properties files because java has a nice class, Properties, for dealing with them.
So here's a tiny example for an image provider that gives you a BufferedImage, given the filename.
image.properties
icon.path=/path/to/my/icons
background.path=/path/to/my/backgrounds
Make sure this file is on your classpath. Then here's my provider class
public class ImageProvider {
private static final String PROP_FILE = "image.properties";
private static final String ICON_PATH = "icon.path";
private Properties properties;
public ImageProvider() {
properties = new Properties();
properties.load(getClass().getClassLoader().getResourceAsStream(PROP_FILE));
}
public BufferedImage getIcon(String icon) {
return ImageIO.read(properties.getProperty(ICON_PATH) + icon);
}
}
times when configuration was kept in static variables or when every component access them independently has ended long ago. since then mankind has invented IoC and DI. you take a DI library (e.g. spring), use it to load all the configuration (from files, jndi, environment, user, you name it) and inject it to every component that needs it. no manual resource loading, no static configuration - it's just evil
I'm writing a small web server, and it takes a configuration file with all sorts of different options: how many threads to run, which class deals which each file extension, which file to display by default and so on and so forth. To represent this, I'm parsing the config file into a Configuration object which contains all these settings, and the main class holds this object.
However, the config data is required on almost every level of the server - classes within classes within classes...
My question is, what is the best practice to use here? Should I give the config as a parameter for many many classes and pass it back and forth? Should I make it a singleton? Is there another solution I don't see?
Use Guice! Guice is a dependency-injection framework which effectively replaces your use of the new keyword. You define your object bindings in a Module like this:
bind(Configuration.class).to(MySpecificConfiguration.class);
bind(WebServer.class).to(MySpecificWebServerImplementation.class);
And then, instead of newing up WebServer directly, you just ask Guice to do it for you:
WebServer ws = Guice.createInjector(yourModule).getInstance(WebServer.class);
Which will magically create MySpecificWebServerImplementation for you. If MySpecificWebServerImplementation is defined as follows:
public class MySpecificWebServerImplementation {
#Inject
public MySpecificWebServerImplementation(Configuration configuration) {
}
}
Then MySpecificWebServerImplementation will automatically get given the configuration and you don't have to worry about passing it around.
Passing an instance of Configuration around adds a lot of unnecessary clutter to your code. A Singleton is a good idea or add some sort of Manager class that provides all those shared resources, like configuration data.
If you go for singleton, consider implementing the enum pattern:
public enum Config{ DATA;
private int value1;
private int value2;
private int value3;
public load(File configFile) {
// some magic to store the values
}
public int getValue1() {return value1;}
public int getValue2() {return value2;}
public int getValue3() {return value3;}
}
You can use it everywhere in your code:
int property = Config.DATA.getValue1();
Although Singletons are no longer favored by many professionals for various reasons - I think there is still a good use case to use a Ssingleton`.
However - ask yourself if the webserver's requirements really require a single common configuration for all aspects of the server. And if yes - how likely are they to change soon?
For example - lets say your server hosts 3 web sites. And now you are asked to put bandwidth limitations on one of them - how will you configure this?
I really favor a good singleton - although you have to mind the whole thread-safety issue when initializing it in a multi-threaded environment (Although it sounds like you won't have this problem as you won't have multiple threads before initializing it.
Keep in mind that singletons live within a ClassLoader and if you have multiple ClassLoaders (e.g. for each .war you load) you will have multiple copies of this "Singleton".
Consider all the aspects of your server, and if it is really simple - A Singleton will save you a lot of headache - and will make the code much more maintainable and readable.
As mentioned already in one or two of the answers - dependency injection is a good alternative to Singletons - they help you make your JUnits easier.
One note about JUnit, I understand (didn't try it yet) that Mockit can allow you to replace an actual implementation during a test run, so you can still create different JUnit test cases for different scenarios without modifying your Singleton to be testable.
Making it a singleton seems like a reasonable solution. I think it would be a mistake to pass the config around as a parameter to other other classes constructors or method calls as this will tend to pollute the method arguments and make them unnecessarily complex.
If you do decide to make a singleton, then I'd recommend devising a mechanism whereby you can inject new instances of the config into the singleton class so that the singleton doesn't make your unit tests very hard to run.
If you're doing this in Java, I would place all the configuration in Spring and then either use the Application Context to lookup the settings or simply inject them into your beans. Spring excels at this sort of thing.
We have your properties set as system properties. These are accessed by a SystemProperties class. This class is final with a private constructor, the properties are accessed via static methods only, so it is technically a Singleton. It is itself contained in a commons.jar every other project is depending on.
So there is no need to pass anything around as the settings are available directly where you need them.
I definitively would make the configuration holder class a Singleton! I's the classical use case for a Singleton instance.
Configuration not, but It's good to have one singleton object ServerManager. Too many globally accessible objects are are little bit confusing. Configuration should by owned by "component":
ServerManager.getServerManager.getConfigurationComponent(Configuration.class);
ServerManager should create and read configuration object at start time. Save and close it before leaving.
If you use it more than once in any class store it as private final field.
I have used this a lot. I do multiple installations of products, and they are not always in the same place. However the installation, integration, and implementation of the product is usually the same. So in order to compensate for this, I write a config properties class, that looks at a config.properties file. You would go in and modify the properties file first to the locations, values, etc... of what you need before hand. Then compile the class with the config class, and carry that through with the application.
Example below. config.properties file
import_dir=c:\\temp\\test\\import
export_dir=c:\\temp\\test\\export
system_dir=c:\\temp\\test\\system
username=mainman
role=admin
domain=
server=
hostname=
etc...
I then created a class inside of my class.
public static class Config {
private static Properties defaultProps = new Properties();
static {
try {
FileInputStream in = new FileInputStream("config.properties");
defaultProps.load(in);
in.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getProperty(String key) {
return defaultProps.getProperty(key);
}
}
I am sure you could also create a stand alone class, but this works as well.
Then inside of my method, or in the main class I get the values I need and assign them to whatever I need. I can then pass them to the corresponding method that needs them.
domain = Config.getProperty("domain");
server = Config.getProperty("server");
hostname = Config.getProperty("hostname");
It is pretty cool!
I also use this on multiple OS's.
I'm at the point in my first real application where I am adding in the user settings. I'm using Java and being very OO (and trying to keep it that way) so here are my ideas:
Load everything in the main() and
pass it all 'down the line' to the
required objects (array)
Same as above, but just pass the
object that contains the data down
the line
Load each individual setting as
needed within the various classes.
I understand some of the basic pros and cons to each method (i.e. time vs. size) but I'm looking for some outside input as to what practices they've successfully used in the past.
Someone should stand up for the purported Java standard, the Preferences API... and it's most recent incarnation in JDK6. Edited to add, since the author seems to savvy XML, this is more appropriate than before. Thought I believe you can work XML juju with Properties too, should the spirit take you.
Related on SO: Preferences API vs. Apache solution, Is a master preferences class a good idea?
(well, that's about all the standing up I'm willing to do.)
Use a SettingsManager class or something similar that is used to abstract getting all settings data. At each point in the code where you need a setting you query the SettingsManager class - something like:
int timeout = SettingsManager.GetSetting("TimeoutSetting");
You then delegate all of the logic for how settings are fetched to this single manager class, whose implementation you can change / optimize as needed. For instance, you could implement the SettingsManager to fetch settings from a config file, or a database, or some other data store, periodically refresh the settings, handle caching of settings that are expensive to retrieve, etc. The code using the settings remains blissfully unaware of all of these implementaton decisions.
For maximum flexibility you can use an interface instead of an actual class, and have different setting managers implement the interface: you can swap them in and out as needed at some central point without having to change the underlying code at all.
In .NET there is a fairly rich set of existing configuration classes (in the System.Configuration) namespace that provide this sort of thing, and it works out quite well.
I'm not sure of the Java equivalent, but it's a good pattern.
Since configuration / settings are typically loaded once (at startup; or maybe a few times during the program's runtime. In any way, we're not talking about a very frequent / time-consuming process), I would prefer simplicity over efficiency.
That rules out option number (3). Configuration-loading will be scattered all over the place.
I'm not entirely sure what the difference is between (1) and (2) in your list. Does (1) mean "passing discreet parameters" and (2) mean "passing an object containing the entire configuration"? If so, I'd prefer (2) over (1).
The rule of thumb here is that you should keep things simple and concentrated. The advantage of reading configuration in one place is that it gives you better control in case the source of the configuration changes at some point.
Here is a tutorial on the Properties class. From the Javadocs (Properties):
The Properties class represents a
persistent set of properties. The
Properties can be saved to a stream or
loaded from a stream. Each key and its
corresponding value in the property
list is a string.
A property list can contain another
property list as its "defaults"; this
second property list is searched if
the property key is not found in the
original property list.
The tutorial gives the following example instantiation for a typical usage:
. . .
// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();
// create application properties with default
Properties applicationProps = new Properties(defaultProps);
// now load properties from last invocation
in = new FileInputStream("appProperties");
applicationProps.load(in);
in.close();
. . .
You could, of course, also roll your own system fairly directly using a file-based store and an XML or YAML parser. Good luck!
We have recently started using JSR-330 dependency injection (using Guice from SVN) and found that it was possible to read in a Properties file (or any other map) and bind it inside Guice in the module in the startup code so that the
#Inject #Named("key") String value
string was injected with the value corresponding to the key when that particular code was called. This is the most elegant way I have ever seen for solving this problem!
You do not have to haul configuration objects around your code or sprinkle all kinds of magic method calls in each and every corner of the code to get the values - you just mention to Guice you need it, and it is there.
Note: I've had a look at Guice, Weld (Seam-based) and Spring which all provide injection, because we want JSR-330 in our own code, and I like Guice the best currently. I think the reason is because Guice is the clearest in its bindings as opposed to the under-the-hood magic happening with Weld.