Application configuration through JVM properties

Contents

Application configuration through JVM properties

The Java Virtual Machine of the application, or the application server that hosts it, is executed with JVM properties set using the -D command

Features

  • The tool starting the JVM sets up the JVM properties for the process from its own state.
  • Applications read individual properties using System.SetProperty().
  • Applications can use System.setProperty() to set a property

Advantages

  • Can set those properties which control the JVM itself
  • Can set properties which control the application server (such as Log4J options).
  • Can set application properties which must be read using System.getProperty()

Disadvantages

  • On Unix, properties set with on the command line are visible to all users.
  • No hierarchical configuration tree.
  • Properties are usually set and read once only, on application startup.
  • Not thread-safe: properties are shared across all threads running in the same process, which, in an application server, means all web applications.
  • Security managers can raise exceptions when programs try to read properties.

SmartFrog Support

This is one of the key ways that SmartFrog can configure Java applications, because it does not require any changes to the application itself. The Java process is executed with all system properties defined, which can tune both the JVM and pass information down.

Here is an example deployment of JBoss with some system properties for garbage collection (picked up by the JVM) and the application server (which is expected to pick up the jdbc. properties and make use of them)

JBoss deployment
dbserver "database1.example.org";

server extends ServerBase:server {
        arguments [
            "-c",
            config];

        processName "jboss";
        classname "org.jboss.Main";
        
        classpath [
            LAZY tools.jar,
            LAZY launcher.jar
        ];
    
        gcInterval "3600000";
    
        sysProperties [
            ["sun.rmi.dgc.client.gcInterval",gcInterval ],
            ["sun.rmi.dgc.server.gcInterval",gcInterval ],
            ["jdbc.driver", MysqlBinding:driver];
            ["jdbc.binding.url", ("jdbc:mysql://" ++ dbserver ++ ":3306/customers")],
        ];
    
        maxMemory 512;
    }

Java Test Runner support

The SmartFrog testharness has a helper class that extracts system properties. This adds a layer of indirection to allow alternate ways of setting properties, or optionally better logging. The getRequiredTestProperty() method is useful to pull required test properties into a test.

Property extraction methods in org.smartfrog.test.TestHelper
/**
 * get any test property; these are (currently) extracted from the JVM props
 * @param property system property
 * @param defaultValue default value
 * @return the system property value or the default, if that is undefined
 */
public static String getTestProperty(String property, String defaultValue) {
    return System.getProperty(property, defaultValue);
}

/**
 * get any test property; these are (currently) extracted from the JVM props
 *
 * @param property     system property
 * @param defaultValue default value
 * @return the system property value or the default, if that is undefined
 */
public static int getTestPropertyInt(String property, int defaultValue) {
    return Integer.getInteger(property, defaultValue).intValue();
}

/**
 * get a mandatory property for the test,
 * @param property system property
 * @return the value
 * @throws RuntimeException if the property was not found
 */
public static String getRequiredTestProperty(String property) {
    String result = getTestProperty(property, null);
    if (result == null) {
        throw new RuntimeException("Property " + property + " was not set");
    }
    return result;
}

Ant Support

To pass properties down to an Ant process, use the <sysproperty attribute

<junit
    fork="true"
    forkmode="once"
    errorProperty="system.test.failed"
    failureProperty="system.test.failed"
    includeAntRuntime="true"
    >
  <classpath refid="tests.run.classpath" />
  <sysproperty key="test.classes.dir"
      value="${build.classes.dir}"/>
</junit>

This sets the system property test.classes.dir to whatever the value of the Ant property build.classes.dir is.

Setting individual properties is very time consuming; it is often better to pass down a block of Ant properties:

<syspropertyset>
   <propertyref prefix="test."/>
</syspropertyset>

Such a propertyset is evaluated whenever it is used; it can be given an id and used across many tasks:

<propertyset id="proxy.settings">
  <propertyref prefix="http."/>
  <propertyref prefix="https."/>
  <propertyref prefix="socks."/>
</propertyset>

This propertyset can be used on demand; when passed down to a new process, all current ant properties that match the given prefixes are passed down, here propagating proxy settings from Ant to a <junit> run:

<presetdef name="sf-junit">
  <junit printsummary="no"
       fork="true"
       forkmode="once"
       includeantruntime="true"
       showoutput="true"
       timeout="6000000"
       >
    <jvmarg value="-ea"/>
    <jvmarg value="-esa"/>
    <!--copy all proxy settings from the running JVM-->
    <syspropertyset refid="proxy.settings"/>

    <!-- #Tests take system property parameters -->
    <!-- #Formatters for capture and display -->
    <formatter type="xml"/>
    <formatter type="brief" usefile="false"/>
  </junit>
</presetdef>

Get SmartFrog at SourceForge.net. Fast, secure and Free Open Source software downloads