i have gone ahead and implemented this myself
Hello all,
I am sure there is a neater or better way to implement this but it is
working for me. There is no testcase but I have tested this using the
"main" method.
This code is free for anyone to use and I would be delighted if it was
included in spring.
/*
* Created on 30 août 2004
*/
package ie.jestate.temp.spring;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.BeansException;
import org.springframework.context.support.AbstractXmlApp licationContext;
/**
* @author Administrateur
*
*/
public class ConditionalClassPathXMLApplicationContext
extends AbstractXmlApplicationContext {
public static void main(String[] args) {
Map mappings = new HashMap();
mappings.put("jestate.testing=true","classpath:tes t/ie/jestate/applicationContext-hibernate.xml");
mappings.put("jestate.db=true","classpath:test/ie/jestate/applicationContext-hibernate.xml");
mappings.put("jestate.anothervar=true","classpath: test/ie/jestate/anothervar.xml");
Map variables = new HashMap();
variables.put("jestate.testing","true");
variables.put("jestate.db","false");
variables.put("jestate.anothervar","false");
ConditionalClassPathXMLApplicationContext test = new ConditionalClassPathXMLApplicationContext(mappings ,variables);
}
private String[] configLocations ;
public ConditionalClassPathXMLApplicationContext(Map mappings, Map variables)
throws BeansException {
Set mappingKeys = mappings.keySet();
Set variableKeys = variables.keySet();
Set configLocationSet = new HashSet();
Iterator variableKeysIterator = variableKeys.iterator();
while (variableKeysIterator.hasNext()) {
String variableKey = (String ) variableKeysIterator.next();
String mapping = (String) variables.get(variableKey);
String mappingKey = variableKey + "=" + mapping;
logger.debug("mappingKey='" + mappingKey + "'");
logger.debug("mappings.get(mappingKey)='" + mappings.get(mappingKey) + "'");
if(mappings.get(mappingKey) != null) {
configLocationSet.add(mappings.get(mappingKey));
}
}
configLocations = new String[configLocationSet.size()];
Iterator iterator = configLocationSet.iterator();
configLocations = (String[]) configLocationSet.toArray(configLocations);
for (int ii = 0; ii < configLocations.length; ii++) {
logger.debug(configLocations[ii]);
}
refresh();
}
/* (non-Javadoc)
* @see org.springframework.context.support.AbstractXmlApp licationContext#getConfigLocations()
*/
protected String[] getConfigLocations() {
return configLocations;
}
}
Re: sorry just one more thing
Quote:
Originally Posted by mperham
But spring already supports this in a much cleaner method (IMO) without conditionals by just specifying the context files you want to use:
Code:
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
new String[] {"applicationContext-domain.xml",
"applicationContext-domain-test.xml" });
Where domain is my live configuration and test overrides certain values in it to use a Hypersonic VM db instead. The override capability is why you don't need conditionals.
Quote:
Originally Posted by bryanhunt
This would mean that you could have one set of spring configuration files
for your entire application.
Just setting the testing property would enable your testing or live
configuration.
You would no longer have to maintain seperate config files for web and
multiple testing files for different configurations.
The problem with that is that if you were using the contextLoader Servlet,
contextLoaderListener or HessianServiceExporter or HttpInvokerExporter
you would need to subclass them and add your own conditional logic
to load appropriate configuration files.
With my approach you don't need to do this. You have one set of files
for everything ie testing/live/with transactions/without transactions/
with method interception from ageci/without method interception from ageci and it all works the same based on either
a) A properties file
or
b) A preference set in the system registry.
Re: sorry just one more thing
Quote:
Originally Posted by bryanhunt
The problem with that is that if you were using the contextLoader Servlet, contextLoaderListener or HessianServiceExporter or HttpInvokerExporter you would need to subclass them and add your own conditional logic to load appropriate configuration files.
But I don't have a single line of conditional logic. And I think that is the common case.
Quote:
Originally Posted by bryanhunt
With my approach you don't need to do this. You have one set of files for everything ie testing/live/with transactions/without transactions/with method interception from ageci/without method interception from ageci and it all works the same based on either a) A properties file or b) A preference set in the system registry.
Why on earth would you want to support all those configuration permutations? I have a production configuration which I have settled on. My unit tests mock that configuration as closely as possible without any conditional logic. I am extremely pleased with how "right" the Spring context design feels. Adding conditional logic to the design seems like it is a recipe for allowing people to do the wrong thing.
Re: sorry just one more thing
Quote:
Originally Posted by mperham
Quote:
Originally Posted by bryanhunt
The problem with that is that if you were using the contextLoader Servlet, contextLoaderListener or HessianServiceExporter or HttpInvokerExporter you would need to subclass them and add your own conditional logic to load appropriate configuration files.
But I don't have a single line of conditional logic. And I think that is the common case.
Quote:
Originally Posted by bryanhunt
With my approach you don't need to do this. You have one set of files for everything ie testing/live/with transactions/without transactions/with method interception from ageci/without method interception from ageci and it all works the same based on either a) A properties file or b) A preference set in the system registry.
Why on earth would you want to support all those configuration permutations? I have a production configuration which I have settled on. My unit tests mock that configuration as closely as possible without any conditional logic. I am extremely pleased with how "right" the Spring context design feels. Adding conditional logic to the design seems like it is a recipe for allowing people to do the wrong thing.
Probably because you have a simple system.
Here are (some ) of the configurations I need to support
1 with remoting support and acegi security support
2 with remoting support and without acegi security
3 without remoting support
4 client mode ie only a desktop application
3 setup mode ( to add core users,areas to the database )
4 unit testing of services
5 unit testing of services using mock DAO objects
6 unit testing of services with real DAO objects
etc etc etc etc ......
So you may have some idea why I need something where
I can set the configuration using the preferences API
Also I want the *User/Administrator* to be able to change these
settings. I do not want them to have to have ANT installed,
I do not want them to have to know what a properties file is
I do not want them to have to know how to edit a properties
file.
I want a flexible system where i dont have to *** HARD CODE ***
the different configuration options into my components.
What meets your needs is not necessarily the same thing that
meets MY needs or my USERS needs.
There is no one size fits all solution and that is why i am trying to
do this and if it is usefull to others well then that is a good thing.
--b
conditional loading context
Based on my own experience, it's 100% needed. I have to create my own singleton (non-spring) named as IocContextManager to load the context instead of depending on the web.xml.
In an enterprise environment, we have to implement a lot of features and make them “backward” compatible. For example, swapping out the JDBC and replacing with WebSphere data source, swapping out MQ connection with JCA connectors’ implementation, etc. In order to make it work, I have to create two context files using the same interface but swap the files during the run-time. So if anything goes wrong at the very end of the project cycle, a “fall-back” is still possible to be as a last resort.
As the coding-test-build-test-deploy kind of project life cycle going on, we can’t modify the web.xml to remove a context definition at the end. However, changing a property flag (test condition) is acceptable from the project manager’s point of view as long as both the implementations have been tested. Also, changing a conditional switch is so much easier to deal with than telling our deployer to figure out which context file(s) to be removed from the web.xml.
It’s also much easier to test because the Spring Context will be reloaded when my singleton destroyed (but not the web.xml).
That’s the reality.
Re: conditional loading context
It's wierd the way that anytime you suggest anything in life there is
a certain number of people who say .. no it should never be done like
that ... it wont work etc ....
I have two virtually identical spring config files.
I'm using acegi ,security interception, transactions, hibernate etc etc
The two files are nearly identical but I have to maintain two parallel
files and shift changes from one to the other constantly.
I think a simple "ifdef" conditional processing mechanism would
simplify things rather than make them more complicated.
I also wonder what stage in their project a lot of people that replied
were at because this is the kinda thing that starts to stress you as
you get close to deployment stage.