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.
Related
Although I have a working test suite, I'm still very new to the world of Java, Selenium and Cucumber. I've kind of inherited a project and most of it I've rewritten in a way that's maintainable and extensible. However, one thing still bothers me.
The program uses a certain class to initialize variables needed. It does the following things:
Read variables from a properties file
Validate those properties
Exposes public static final variables for things like the host to test against, other urls needed, etc.
Call Boni GarcĂa's WebDriverManager setup which checks the version of the local browser and downloads a compatible webdriver
All these things either need only run once or are expensive. This class is a Singleton and I understand it only gets instantiated once. Sounded good to me, but then I read that Singletons in general are a bad idea.
Since Cucumber is an extension to Junit, there is no main(), at least not in this program and I haven't seen examples using it. So, what would be a good way to do those operations?
I read about DI, but then, I would need to pass this class to all classes that need access to these variables like the url of the site to test. Also, having WebDriverManager check browser version every time doesn't seem like a good idea.
I read about the static block, but how can I know this class is loaded first?
So, where do I go from here?
Singletons are a pattern. And like all patterns they have advantages and disadvantages. You'll have to make the choice if those trade-offs are worth it. If not, you'll have to change the pattern.
And very generally speaking those trade-offs are not worth it. Unless you have a single expensive resource you should probably not consider using singletons at all. Dependency injection -with or without a framework- is usually the better way to go.
However you have a single expensive object. The Webdriver. So the singleton pattern is worth considering. And broadly speaking, if you do not intend to run your tests in parallel there is no reason not use a singleton pattern.
I read about DI, but then, I would need to pass this class to all classes that need access to these variables like the url of the site to test. Also, having WebDriverManager check browser version every time doesn't seem like a good idea.
I read about the static block, but how can I know this class is loaded first?
You can combine the Singleton pattern with lazy initialization. Rather then immediately creating the singleton as a static variable when the classes is loaded, you create an static getter method. When this method is called the first time you create the singleton instance and return it. When called a second time, you return the created singleton instance.
private static WebDriver driver;
public static WebDriver getWebDriver(){
if (driver != null){
return driver;
}
driver = // create driver here
return driver;
}
Since Cucumber is an extension to Junit, there is no main(), at least not in this program and I haven't seen examples using it. So, what would be a good way to do those operations?
You can use cucumber-piccontainer It's a very simple form of DI.
https://github.com/cucumber/cucumber-jvm/tree/main/picocontainer
I am confused.
Spring's default bean scope is Singleton. That means that once you define a bean of your class, every time a new "message" comes in, it will be processed by the same instance of that class.
But that also means that you cannot have mutable instance variables in that singleton bean because the next call of a method of that class will see data from past calls..
Example:
Calculator is my bean (singleton)
public class Calculator {
private List<String> operations = new ArrayList<String>();
public void calculate(String op, double val) {
operations.add(op);
// do some calculations
}
public List<String> getAllOperations() {
return operations;
}
}
Here's the client (useCalc is invoked many times!):
public class CalculatorClient{
#Autowired
private Calculator calculator;
public void useCalc () {
calculator.calculate("Add",100);
calculator.calculate("Div",100);
calculator.calculate("Diff",100);
List<String> allOperations = calculator.getAllOperations();
// Do something..
}
}
So let's say CalculatorClient useCalc gets called several times with different operations..
eventually operations in Calculator will contain all of the operations ever done on that calculator.
So the question is this:
Is this Spring's limitation - not being able to effectively share information between methods within a class? And if it is so, how to share that kind of information between methods?
I know there is the prototype bean scope. Is that the only solution in this case?
BTW, prototype is not a solution here because with prototype a new class will get instantiated with every call to calculator:
calculator.calculate("Add",100); // New
calculator.calculate("Div",100); // New
calculator.calculate("Diff",100); // New
And since Singleton is the default scope - aren't developers inadvertently introduce such bugs?
A common use case for singleton beans are to inject services into other objects.
Example, to provide an object a service to connect to the database, you "autowire" a database connection bean.
You don't want to create a new instance of the database every time, so singleton beans make sense.
Usually, the object itself that uses the autowire is a singleton as well (in a web app, the Controllers are also created just once, you don't want to create a controller for every request).
aren't developers inadvertently introduce such bugs?
Since the idea is to process several requests concurrently, all of those objects are usually already coded without having common state shared using instance variables.
This is not a "limitation", but rather a default for the most common use case.
I know there is the prototype bean scope. Is that the only solution in this case?
It sounds like a good "solution" to this, in that case a new bean will be created. Note that it would not make sense to autowire a prototype bean into a singleton since in that case there will only be once instance anyway.
Another possibility more commonly used is autowiring a singleton bean that acts like a factory, then ask that factory for a new object each time you need one.
The factory can be a singleton since you don't want more than one factory, but it would then return new objects in every call to its "create" method.
So in your example, you could do something like
#Autowired
private CalculatorFactory calcFactory;
public void useCalc () {
calculator = calcFactory.createCalculator();
calculator.calculate("Add",100);
calculator.calculate("Div",100);
calculator.calculate("Diff",100);
List<String> allOperations = calculator.getAllOperations();
// Do something..
}
}
There's a lot of conflation going on here. Let me try to unravel the premises.
The whole point of dependency injection is to make it so that you don't have multiple instances of a critical application service, which would lead to things getting out of sync or result in erratic behavior (e.g. multiple database connections, multiple access points to a JMS queue, multiple ways to query a database, etc).
It is not a mandate to make everything injectable.
If something is not inherently reusable, or you would not gain anything from registering it in the component scan, then there is no reason to make that thing either a bean or a component.
It is fairly reasonable to assume that beans shouldn't store state, but that doesn't mean that something else couldn't store that state on its behalf. For instance, you could put those operations into some other backing store as opposed to in-memory, and you'd still be able to keep the state of operations you've done.
The big thing that I'm seeing is that you've kind of implemented your Calculator class half-thinking that it was a bean, and half-thinking that it was newed up somewhere. By having that list in your class, you're subconsciously forcing yourself to hold onto the state in any instance created, which violated the inversion of control principle - you don't control the lifecycle of the object.
To get around this...you have a few options available.
Change how you're storing the state of your operations. Put it into a SQLite database or a file or somewhere that isn't dependent on an instance maintaining it.
Inject your own. You can create a bean that is of type List<String>, and require your Calculator to inject it when it's needed.
Don't create a bean. You can new this and Spring isn't really going to fuss at you. It'd make it harder to test, though.
The first two approaches abstract away the notion of storing the data from an operation and reading the data from the operations. You can either read from the injected operations bean or from the SQLite database or from the flat file to get the result of operations that you want.
I asked a general Spring question: Auto-cast Spring Beans and had multiple people respond that calling Spring's ApplicationContext.getBean() should be avoided as much as possible. Why is that?
How else should I gain access to the beans I configured Spring to create?
I'm using Spring in a non-web application and had planned on accessing a shared ApplicationContext object as described by LiorH.
Amendment
I accept the answer below, but here's an alternate take by Martin Fowler who discusses the merits of Dependency Injection vs. using a Service Locator (which is essentially the same as calling a wrapped ApplicationContext.getBean()).
In part, Fowler states, "With service locator the application class asks for it [the service] explicitly by a message to the locator. With injection there is no explicit request, the service appears in the application class - hence the inversion of control.
Inversion of control is a common feature of frameworks, but it's something that comes at a price. It tends to be hard to understand and leads to problems when you are trying to debug. So on the whole I prefer to avoid it [Inversion of Control] unless I need it. This isn't to say it's a bad thing, just that I think it needs to justify itself over the more straightforward alternative."
I mentioned this in a comment on the other question, but the whole idea of Inversion of Control is to have none of your classes know or care how they get the objects they depend on. This makes it easy to change what type of implementation of a given dependency you use at any time. It also makes the classes easy to test, as you can provide mock implementations of dependencies. Finally, it makes the classes simpler and more focused on their core responsibility.
Calling ApplicationContext.getBean() is not Inversion of Control! While it's still easy to change what implemenation is configured for the given bean name, the class now relies directly on Spring to provide that dependency and can't get it any other way. You can't just make your own mock implementation in a test class and pass that to it yourself. This basically defeats Spring's purpose as a dependency injection container.
Everywhere you want to say:
MyClass myClass = applicationContext.getBean("myClass");
you should instead, for example, declare a method:
public void setMyClass(MyClass myClass) {
this.myClass = myClass;
}
And then in your configuration:
<bean id="myClass" class="MyClass">...</bean>
<bean id="myOtherClass" class="MyOtherClass">
<property name="myClass" ref="myClass"/>
</bean>
Spring will then automatically inject myClass into myOtherClass.
Declare everything in this way, and at the root of it all have something like:
<bean id="myApplication" class="MyApplication">
<property name="myCentralClass" ref="myCentralClass"/>
<property name="myOtherCentralClass" ref="myOtherCentralClass"/>
</bean>
MyApplication is the most central class, and depends at least indirectly on every other service in your program. When bootstrapping, in your main method, you can call applicationContext.getBean("myApplication") but you should not need to call getBean() anywhere else!
Reasons to prefer Service Locator over Inversion of Control (IoC) are:
Service Locator is much, much easier for other people to following in your code. IoC is 'magic' but maintenance programmers must understand your convoluted Spring configurations and all the myriad of locations to figure out how you wired your objects.
IoC is terrible for debugging configuration problems. In certain classes of applications the application will not start when misconfigured and you may not get a chance to step through what is going on with a debugger.
IoC is primarily XML based (Annotations improve things but there is still a lot of XML out there). That means developers can't work on your program unless they know all the magic tags defined by Spring. It is not good enough to know Java anymore. This hinders less experience programmers (ie. it is actually poor design to use a more complicated solution when a simpler solution, such as Service Locator, will fulfill the same requirements). Plus, support for diagnosing XML problems is far weaker than support for Java problems.
Dependency injection is more suited to larger programs. Most of the time the additional complexity is not worth it.
Often Spring is used in case you "might want to change the implementation later". There are other ways of achieving this without the complexity of Spring IoC.
For web applications (Java EE WARs) the Spring context is effectively bound at compile time (unless you want operators to grub around the context in the exploded war). You can make Spring use property files, but with servlets property files will need to be at a pre-determined location, which means you can't deploy multiple servlets of the same time on the same box. You can use Spring with JNDI to change properties at servlet startup time, but if you are using JNDI for administrator-modifiable parameters the need for Spring itself lessens (since JNDI is effectively a Service Locator).
With Spring you can lose program Control if Spring is dispatching to your methods. This is convenient and works for many types of applications, but not all. You may need to control program flow when you need to create tasks (threads etc) during initialization or need modifiable resources that Spring didn't know about when the content was bound to your WAR.
Spring is very good for transaction management and has some advantages. It is just that IoC can be over-engineering in many situations and introduce unwarranted complexity for maintainers. Do not automatically use IoC without thinking of ways of not using it first.
It's true that including the class in application-context.xml avoids the need to use getBean. However, even that is actually unnecessary. If you are writing a standalone application and you DON'T want to include your driver class in application-context.xml, you can use the following code to have Spring autowire the driver's dependencies:
public class AutowireThisDriver {
private MySpringBean mySpringBean;
public static void main(String[] args) {
AutowireThisDriver atd = new AutowireThisDriver(); //get instance
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
"/WEB-INF/applicationContext.xml"); //get Spring context
//the magic: auto-wire the instance with all its dependencies:
ctx.getAutowireCapableBeanFactory().autowireBeanProperties(atd,
AutowireCapableBeanFactory.AUTOWIRE_BY_TYPE, true);
// code that uses mySpringBean ...
mySpringBean.doStuff() // no need to instantiate - thanks to Spring
}
public void setMySpringBean(MySpringBean bean) {
this.mySpringBean = bean;
}
}
I've needed to do this a couple of times when I have some sort of standalone class that needs to use some aspect of my app (eg for testing) but I don't want to include it in application-context because it is not actually part of the app. Note also that this avoids the need to look up the bean using a String name, which I've always thought was ugly.
One of the coolest benefits of using something like Spring is that you don't have to wire your objects together. Zeus's head splits open and your classes appear, fully formed with all of their dependencies created and wired-in, as needed. It's magical and fantastic.
The more you say ClassINeed classINeed = (ClassINeed)ApplicationContext.getBean("classINeed");, the less magic you're getting. Less code is almost always better. If your class really needed a ClassINeed bean, why didn't you just wire it in?
That said, something obviously needs to create the first object. There's nothing wrong with your main method acquiring a bean or two via getBean(), but you should avoid it because whenever you're using it, you're not really using all of the magic of Spring.
The motivation is to write code that doesn't depend explicitly on Spring. That way, if you choose to switch containers, you don't have to rewrite any code.
Think of the container as something is invisible to your code, magically providing for its needs, without being asked.
Dependency injection is a counterpoint to the "service locator" pattern. If you are going to lookup dependencies by name, you might as well get rid of the DI container and use something like JNDI.
Using #Autowired or ApplicationContext.getBean() is really the same thing. In both ways you get the bean that is configured in your context and in both ways your code depends on spring.
The only thing you should avoid is instantiating your ApplicationContext. Do this only once! In other words, a line like
ApplicationContext context = new ClassPathXmlApplicationContext("AppContext.xml");
should only be used once in your application.
One of Spring premises is avoid coupling. Define and use Interfaces, DI, AOP and avoid using ApplicationContext.getBean() :-)
One of the reasons is testability. Say you have this class:
interface HttpLoader {
String load(String url);
}
interface StringOutput {
void print(String txt);
}
#Component
class MyBean {
#Autowired
MyBean(HttpLoader loader, StringOutput out) {
out.print(loader.load("http://stackoverflow.com"));
}
}
How can you test this bean? E.g. like this:
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
// execution
new MyBean(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get, result::append);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
Easy, right?
While you still depend on Spring (due to the annotations) you can remove you dependency on spring without changing any code (only the annotation definitions) and the test developer does not need to know anything about how spring works (maybe he should anyway, but it allows to review and test the code separately from what spring does).
It is still possible to do the same when using the ApplicationContext. However then you need to mock ApplicationContext which is a huge interface. You either need a dummy implementation or you can use a mocking framework such as Mockito:
#Component
class MyBean {
#Autowired
MyBean(ApplicationContext context) {
HttpLoader loader = context.getBean(HttpLoader.class);
StringOutput out = context.getBean(StringOutput.class);
out.print(loader.load("http://stackoverflow.com"));
}
}
class MyBeanTest {
public void creatingMyBean_writesStackoverflowPageToOutput() {
// setup
String stackOverflowHtml = "dummy";
StringBuilder result = new StringBuilder();
ApplicationContext context = Mockito.mock(ApplicationContext.class);
Mockito.when(context.getBean(HttpLoader.class))
.thenReturn(Collections.singletonMap("https://stackoverflow.com", stackOverflowHtml)::get);
Mockito.when(context.getBean(StringOutput.class)).thenReturn(result::append);
// execution
new MyBean(context);
// evaluation
assertEquals(result.toString(), stackOverflowHtml);
}
}
This is quite a possibility, but I think most people would agree that the first option is more elegant and makes the test simpler.
The only option that is really a problem is this one:
#Component
class MyBean {
#Autowired
MyBean(StringOutput out) {
out.print(new HttpLoader().load("http://stackoverflow.com"));
}
}
Testing this requires huge efforts or your bean is going to attempt to connect to stackoverflow on each test. And as soon as you have a network failure (or the admins at stackoverflow block you due to excessive access rate) you will have randomly failing tests.
So as a conclusion I would not say that using the ApplicationContext directly is automatically wrong and should be avoided at all costs. However if there are better options (and there are in most cases), then use the better options.
The idea is that you rely on dependency injection (inversion of control, or IoC). That is, your components are configured with the components they need. These dependencies are injected (via the constructor or setters) - you don't get then yourself.
ApplicationContext.getBean() requires you to name a bean explicitly within your component. Instead, by using IoC, your configuration can determine what component will be used.
This allows you to rewire your application with different component implementations easily, or configure objects for testing in a straightforward fashion by providing mocked variants (e.g. a mocked DAO so you don't hit a database during testing)
Others have pointed to the general problem (and are valid answers), but I'll just offer one additional comment: it's not that you should NEVER do it, but rather that do it as little as possible.
Usually this means that it is done exactly once: during bootstrapping. And then it's just to access the "root" bean, through which other dependencies can be resolved. This can be reusable code, like base servlet (if developing web apps).
There is another time when using getBean makes sense. If you're reconfiguring a system that already exists, where the dependencies are not explicitly called out in spring context files. You can start the process by putting in calls to getBean, so that you don't have to wire it all up at once. This way you can slowly build up your spring configuration putting each piece in place over time and getting the bits lined up properly. The calls to getBean will eventually be replaced, but as you understand the structure of the code, or lack there of, you can start the process of wiring more and more beans and using fewer and fewer calls to getBean.
I've only found two situations where getBean() was required:
Others have mentioned using getBean() in main() to fetch the "main" bean for a standalone program.
Another use I have made of getBean() are in situations where an interactive user configuration determines the bean makeup for a particular situation. So that, for instance, part of the boot system loops through a database table using getBean() with a scope='prototype' bean definition and then setting additional properties. Presumably, there is a UI that adjusts the database table that would be friendlier than attempting to (re)write the application context XML.
however, there are still cases where you need the service locator pattern.
for example, i have a controller bean, this controller might have some default service beans, which can be dependency injected by configuration.
while there could also be many additional or new services this controller can invoke now or later, which then need the service locator to retrieve the service beans.
You should to use: ConfigurableApplicationContext instead of for ApplicationContext
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.
My application requires access to certain Objects throughout the application. These objects are populated through the DB.
I would like to populate the objects on server startup , and then in the application on a need -to -do basis.
What is the best pattern to implement this, i have read about the Registry pattern, but not sure that is exactly what i want.
I am also using Spring 3.x in my application , is there something in Spring that can help me?
Since you say you are using Spring. The best solution is to use FactoryBean. What this class allows you to do is create a bean of whatever type you like and return it to the Spring context. Spring will manage this bean and expose it to other beans by making it a singleton. An example:
public class MyObjectFooFactoryBean extends SimpleJdbcDaoSupport implements FactoryBean<ObjectFoo> {
private String query;
#Override
public String getObject() throws Exception {
return an ObjectFoo here using SimpleJdbSupport (Because I also extended SimpleJdbcDaoSupport)
}
#Override
public Class<?> getObjectType() {
return ObjectFoo.class;
}
#Override
public boolean isSingleton() {
return true;
}
}
Above does two things. 1) Extends SimpleJdbcSupport which allows you to have access to the databse, and 2) Implements FactoryBean which returns the object to Spring's context. After this is done, you can #Autowire it or use it in the xml file.
Are you sure your application really requires that?
Global objects are artifacts from the past of programming, they shouldn't exist anymore in a proper object-oriented environment, and are usually considered an anti-pattern.
Surely you don't need to access these objects everywhere. Why don't you just inject them in the classes that need them? If you use Spring, that's even easier, only have to declare the dependency in the context.
If there are many of these objects that you need, you could wrap them all in one holder class, that you inject as needed.
When I use global objects I usually wrap each object in a singleton pattern. It's the simplest solution, and you can even lazy load it only when needed.
In some cases this is a very valid pattern. For example in any iphone app you have a singleton Application object which is accessible globally through a public static method
This can get a bit hairy if your application is deployed in multiple servers (each with its own VM, thus having singletons as static fields will get messy, and having context-based attributes won't work unless the servers are set to replicate and that's unreliable as well). I'd recommend using a database memory table instead, or some other sort of server-independant memory cache. ( http://memcached.org/ for instance)
What about defining a global object to store these information? You can control access to this object. If you want to monitor this object's state, you can use observer patterns.