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 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 #

Post a Comment:
  • HTML Syntax: NOT allowed

This blog copyright 2009 by codeplumber