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
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.
Use the replace task in Ant to change the values.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With