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);
}
Comments:

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 08:35 AM 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 09:46 AM PDT #

Why is System.setProperty thread-unsafe and GFSystem.setProperty not?

Posted by Dies Koper on September 11, 2007 at 10:30 AM PDT #

j'

Posted by guest on January 10, 2011 at 10:02 PM PST #

What do you mean by 100% thread hostile? Are you saying changing it in multi threaded env would cause problems?

Posted by guest on August 15, 2012 at 03:40 PM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

ByronNevins

Search

Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today