Monitored System.setProperty
System.setProperty() can be an evil call.
- It is 100% thread-hostile
- It contains super-global variables
- GF is very heavily dependent on these variables
- It is extremely difficult to debug when these variables mysteriously change at runtime
I added a super-simple class to Glassfish that wraps System.setProperty() and System.setProperties().
The class is named GFSystem. It is an all-static class and it lives in appserv-commons.
If you always call the wrapper instead of the JDK method you get the following services:
- Every call is logged - by default the Level is FINE but it can be changed with a method call
- You have a place to set a breakpoint when debugging a mysterious System Property bug
Example code:
import com.sun.enterprise.util.system.GFSystem
.....
GFSystem.setProperty("com.sun.aas.instanceRoot", "/somewhere");
-- The class is pretty tiny so I added it below. In answer to Kedar's comment -- by default it is set to FINE level to keep the noise down. To set it to, say, INFO you do this:
GFSystem.setLevel(Level.INFO);
-- to reset to the default level:
GFSystem.resetLevel();
note that setLevel() is not synchronized because it would be pointless...
/*
* GFSystem.java
*
* Created on August 21, 2007, 11:37 AM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package com.sun.enterprise.util.system;
import com.sun.enterprise.util.*;
import com.sun.logging.*;
import java.util.*;
import java.util.logging.*;
/**
* This is a simple class that wraps evil calls to System.setProperty. System.setProperty
* is evil because it's very hard to debug, it's thread-unsafe, it's super-global and it is
* over-used in GF.
* To use it -- simply call GFSystem.setProperty() instead of System.setProperty()
* To debug -- you can turn up the logging level with setLevel() and restore with resetLevel()
* @author bnevins
*/
public class GFSystem
{
private GFSystem()
{
}
public static void setProperty(String name, String value)
{
System.setProperty(name, value);
log(stringy.get("set.property", name, value));
//SystemPropertyConstants.INSTANCE_ROOT_PROPERTY;
}
public static void setProperties(Properties props)
{
System.setProperties(props);
log(stringy.get("set.properties", props));
}
public static void setLevel(Level newLevel)
{
level = newLevel;
}
public static void resetLevel()
{
level = DEFAULT_LEVEL;
}
private static void log(String s)
{
if(logger.isLoggable(level))
logger.log(level, s);
}
private static final Logger logger = LogDomains.getLogger(LogDomains.UTIL_LOGGER);
private static final Level DEFAULT_LEVEL = Level.FINE;
private static Level level = DEFAULT_LEVEL;
private static final LocalStringsImpl stringy = new LocalStringsImpl(GFSystem.class);
}
And how do you set up the fine logging level?
<P>
I suggest we remove the dependence on system properties at the earliest.
<P>
- Kedar
Posted by Kedar Mhaswade on September 11, 2007 at 03:35 PM PDT #
Wow! That <pre> section with the source code is rendered VERY nicely by the blogger engine!
Posted by Byron Nevins on September 11, 2007 at 04:46 PM PDT #
Why is System.setProperty thread-unsafe and GFSystem.setProperty not?
Posted by Dies Koper on September 11, 2007 at 05:30 PM PDT #