Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to alter constants in Java build process

I have inherited a Java application (servlets) that runs under Tomcat. For historical reasons, the code has different "look and feel" options based on where the application will be deployed (essentially a matter of branding).

There are several constants that control this branding process, which have different functions and should not be compacted into a single constant (i.e. BRAND, MULTI-LANGUAGE, plus the locations of icons and css style sheets, etc.).

Currently the development team must manually change the constants (they are at least localized in one data class and well documented), then recompile the application using ANT.

What is the best way to automate this process assuming at least Ant 1.8 and Java 6.x?

I know that there have not been any good solutions using compiler arguments (like one could do in C or C++), and am leaning to some "best way" to edit either the source file containing the constants, or putting them into another file and swapping them out using the ant build process. I'd like to have a result that would work using something like "ant build brand-x" where changing the brand would change the resulting build.

Thanks,

-Richard

like image 225
Huntrods Avatar asked Dec 31 '08 19:12

Huntrods


3 Answers

Put your values into a properties file, say "myapp.properties" and then load them into your constants from the classpath at startup (see below for how this fits into the build process):

public class Constants
{
    private static final Properties props = new Properties();
    public static final String MY_CONSTANT;

    static
    {
        InputStream input = Constants.class.getResourceAsStream("/myapp.properties");
        if(input != null)
        {
           try
           {
              properties.load(input);
           }
           catch(IOException e)
           {
              // TODO log error
           }
        }

        // Initialize constants (dont' forget defaults)
        MY_CONSTANT = properties.getProperty("constant", "default");
        // .. other constants ...
    }
}

Now, have a separate properties file for each branding. Pass its name to ANT via -D or build.properties and copy the file to your build directory right before you jar (or war) it up.

Obviously, the code above will work, but there are many ways you can clean it up and make it bullet proof.

like image 188
Dave Ray Avatar answered Nov 02 '22 23:11

Dave Ray


Use the replace task in Ant to change the values.

  • Ant Replace
like image 21
Adam Peck Avatar answered Nov 03 '22 00:11

Adam Peck


There's also a "spring" way, which is to use a properties file, and a bean that pulls the value from the properties and injects them into the classes that need them, e.g.:

<bean id="propertyPlaceholder"  class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:configuration.properties" />
</bean>

and then, you can inject properties with an "ant-like" syntax:

<bean id="connectionPool"  class="com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource">
    <property name="databaseName" value="mydb" />
    <property name="url" value="${db.url}" />
    ...

which probably would entail more rewriting than you'd like. If you're going to be changing constants on each compile, I'd watch out for this gotcha (if you're using static finals, that is).

public class Foo {
 public static final int SOME_CONSTANT=1;
..
}

public class Bar {
  ...
   int x=5+Foo.SOME_CONSTANT;
  ...
}

If you then change SOME_CONSTANT in Foo to 2 but don't recompile Bar, Bar will retain the value of 1 for SOME_CONSTANT, as the static finals are compiled in (since the compiler sees that it shouldn't need to ever figure them out again).

like image 42
Steve B. Avatar answered Nov 03 '22 00:11

Steve B.