-
1. Re: Configuration Information Best Practice
supertbone Dec 12, 2001 8:56 AM (in response to hunterhillegas)i mostly use the env-entry tags in the deployment description, if the extra config is to complicated for an entry then i use resources(ClassLoading mechanism) with a property or xml file.
But there isn't any pattern shows how this should be done.(except for the resource loading by the classloader)
Greetz Tbone, -
2. Re: Configuration Information Best Practice
alu1344 Dec 14, 2001 6:46 PM (in response to hunterhillegas)Mine could not be the best config in the world, I have rewritten it fully at least three times.
I have encapsulated in one class (singleton) all the env-entry variables. At construction time it reads everything. The drawback is that you then have to specify these variables in web.xml, not in ejb-jar.xml (since the config variables are common to all the app). The reason is because I use these variables *very* often and performance was suffering.
I also use two ResourceBundles, since I need to keep some client i18n messages.
Whenever you need to specify a text string more than once in the code, I specify it as a static final public in the Config class. I am talking about the name of everything that gets referenced via JNDI or via a ResourceBundle, or in a HttpSession.
For URLs I use an ad hoc Factory. Could not be the best approach in the world, but it happens that I haven't found anything better.
With this approach I know I could keep things in the Database. I have moved config info from static code to the JNDI without consecuences in the rest of the app. -
3. Re: Configuration Information Best Practice
sikandar Dec 15, 2001 4:43 PM (in response to hunterhillegas)What about plain vanilla window's ini file/registry concept?
I load config name-value parameters from properties file at load time. This way I can change them at production m/c without recompiling code. -
4. Re: Configuration Information Best Practice
foglesa Dec 18, 2001 3:14 AM (in response to hunterhillegas)I have been on contracts where it is done in basically one of two ways. One which i hate, and the other fairly common. so the one i hate? A static class. Its not bad if things do not change much, but you have locked the client into needing to recompile if anything changes.
the other one is just a plain old properties file. Works great, can be edited by anyone almost, it is very system admin friendly :)
Al -
5. Re: Configuration Information Best Practice
fcrabus Dec 18, 2001 6:38 AM (in response to hunterhillegas)> I have been on contracts where it is done in
> basically one of two ways. One which i hate, and the
> other fairly common. so the one i hate? A static
> class. Its not bad if things do not change much, but
> you have locked the client into needing to recompile
> if anything changes.
>
> the other one is just a plain old properties file.
> Works great, can be edited by anyone almost, it is
> very system admin friendly :)
>
> Al
But with your plain ol' properties file you'll get some
problems - at least later on.
- In a cluster you have to update all files.
- You have to put it somewhere in the filesystem which
can be a pain in the ass or you have to package it
along with your jars (which is basically very nice, but
it's somewhat cumbersome to edit it then).
- If you need those properties often then you need to
cache them (so typically you have a singleton along
with your properties file which will be a problem in
cluster of course)
- loads of other problems (I've had my share of experience there)
So a better thing to do is to put your properties in
a db. Then you'll add an accessor class with some
built-in caching and store it in JNDI.
Or as a compromise you store you're properties dynamically into JNDI:
Let's say on startup a properties file is read, its
values are stored in JNDI. And later on you can change
those values via a servlet and a web front end.
But there're for sure other better solutions...any
ideas?
Bye,
Fabian -
6. Re: Configuration Information Best Practice
kryptontri Jan 25, 2002 6:41 PM (in response to hunterhillegas)Just a simple question to all you heavies ..
Assuming I build an application that requires regular config updating, what would be the best way without restarting the server/services ?
1. From the web container, write a utility class to continually check a given config file for date changes and then reload when the file has been changed. This obviously involves IO or using xml files - still IO ?
2. Within the EJB Container do the same. But am i allowed to do this ie call IO to monitor a file via a helper class ? Surely if this util is not an EJB so this should be ok ?
Any thoughts would be appreciated. -
7. Re: Configuration Information Best Practice
vincent Jan 28, 2002 12:55 AM (in response to hunterhillegas)JMX anybody ?
The EJB/WEB talks to a JMX to get sth.
This JMX can be "stop/start" or "reload" to get a new version of a xml file or any "string like" parameter.
Or attach to a Timer to reload itself dynamically.
JMX JMX JMX ouh ah... -
8. Re: Configuration Information Best Practice
sleepycrom Jan 30, 2002 2:33 AM (in response to hunterhillegas)Do you have some nice samples that do all this ?
- How do this work in cluster ? Do you have to you the RMI Connector ? -
9. Re: Configuration Information Best Practice
vincent Jan 30, 2002 11:40 PM (in response to hunterhillegas)Writing a MBean is a lot more simple than writing a EJB ;)
Simply write a class and its MBean interface and it starts. Look at ... all Jboss to find example.
I don't use cluster and don't know exactly how to handle this problem in JMX. (BTW is the marc/juha book on JMX out ?). For the moment I would simply deploy my MBean in all the servers I am running. For example I use 2 servers at devel time on for tomcat 3.2 and one for ejb, ... Both runs the MBean.
I could use the RMI connector (I tries it without problems) but it is a jboss specific so I prefer not using it anymore.
What took me long time to catch is the fact that MBean is not just there for JBoss. It is also there for a lot of configuration issue that users face in any project. IMHO, using env definition in ejb is less and less a good option for "configuration" stuff.
Example :
public class EISIntegratorLoader
extends FileLoader
implements EISIntegratorLoaderMBean{
// ----------------------------------------------------------------- Logging
transient static Category cat=Category.getInstance(EISIntegratorLoader.class);
private String fileName;
private boolean started;
private Map mapping = new Hashtable();
public String getName(){
if (cat.isDebugEnabled()) cat.debug("getName()");
return "SecureActionLoader";
}
public String getConfigFile(){
if (cat.isDebugEnabled()) cat.debug("getConfigFile()");
return fileName;
}
public void setConfigFile(String fileName)
throws FileNotFoundException{
if (cat.isDebugEnabled()) cat.debug("setConfigFile("+fileName+")");
this.fileName = fileName;
Document doc = extractDoc(findFile(fileName));
List list = doc.getRootElement().getChildren("mapping");
//List list = doc.getMixedContent();
if (cat.isDebugEnabled()) cat.debug("MAPPING Number = "+list.size());
Iterator i = list.iterator();
while (i.hasNext()){
Element el = (Element)i.next();
String source = el.getChildText("source");
String destination = el.getChildText("destination");
if (!mapping.containsKey(source)){
mapping.put(source,destination);
if (cat.isDebugEnabled()) cat.debug("MAPPING : "+source+" ==> "+destination);
}
}
}
public Map getMapping(){
if (cat.isDebugEnabled()) cat.debug("getMapping");
return this.mapping;
}
public void start() throws Exception{
cat.info("start()");
started = true;
}
public void stop(){
cat.info("stop()");
started = false;
}
// ----------------------------------------------------------------- Private
/** This will build the Document object
* @param url the URL for the XML configuration file
* @return a {@link Document} representing the actions
* definition
*/
private Document extractDoc(URL url){
if (cat.isDebugEnabled()) cat.debug("Executing extractDoc");
SAXBuilder builder = new SAXBuilder();
if (cat.isDebugEnabled()) cat.debug("Builder="+builder);
// build the document
Document doc;
try{
doc = builder.build(url);
if (cat.isDebugEnabled()) cat.debug("Doc="+doc);
} catch (Exception e){
cat.debug("Exception",e);
throw new IllegalStateException("JDOMException"+e.getMessage());
}
Document actionDoc = new Document(doc.getRootElement().getChild("mappings"));
return actionDoc;
}
The interface is
public String getConfigFile();
public void setConfigFile(String fileName) throws FileNotFoundException;
public Document getDocument();
public void start() throws Exception;
public void stop() throws Exception;
With FileLoader being
protected URL findFile(String fileName) throws IllegalStateException {
Class confClass = this.getClass();
ClassLoader loader = confClass.getClassLoader();
URL fileURL = loader.getResource(fileName);
// Was the resource found?
if (fileURL == null) {
cat.error("Can't find the file: '" + fileName + "'");
throw new IllegalStateException("Can't locate file: '" + fileName + "'");
}
else {
return fileURL;
}
}
The call is done like this (in j2ee pattern singleton ServiceLocator) :
private ServiceLocator() {
if (cat.isDebugEnabled()) cat.debug("Constructor");
try{
if (useCache) cache = new Hashtable();
// Get the JNDI Initial Context (local and remote)
initial = new InitialContext();
if (cat.isDebugEnabled()) cat.debug("InitialContext="+initial);
// Get the Deployment Description
ArrayList servers = MBeanServerFactory.findMBeanServer(null);
if (cat.isDebugEnabled()) cat.debug("List of MBean Server = " + servers);
if (servers == null || servers.size() == 0) {
// Try to connect remotely (TestSecAConfigurator will do that)
// Remove it for jboss 3.0 compatibility
//JMXConnector server = new RMIClientConnectorImpl(InetAddress.getLocalHost().getHostName());
//ObjectName objName = new ObjectName("HubMethods:service=EISIntegratorLoader");
//mapping = (Map) server.getAttribute(objName, "Mapping");
mapping = new FastHashMap();
} else {
try{
MBeanServer server = (MBeanServer) servers.get(0);
ObjectName objName = new ObjectName("HubMethods:service=EISIntegratorLoader");
mapping = (Map) server.getAttribute(objName, "Mapping");
}catch (Exception e){
cat.warn("EISIntegratorLoader MBean could not be accessed "+e.getMessage());
mapping = new FastHashMap();
}
}
if (cat.isDebugEnabled()) cat.debug("Mapping Size : "+mapping.size());
}catch (Exception e){
cat.error("Exception",e);
}
}