Home Contact Sitemap

Matthew Wells

Java, J2EE & Configurable Systems

February 28th, 2008 | by matthew |

Being a little bit long in the tooth and originally coming from an embedded C background, I occasionally hanker after the flexibility of conditional compilation.

This is a C based mechanism that allows you to build different flavours of a product from the same code base at compile time by a combination of #define and #ifdef primitives and a pre-processing step which occurred before compilation. As the name suggests, this process enabled blocks of code to be included in the final executable (or not) dependent on predefined conditions.

I’ve dabbled with various ways of achieving a similar effect in Java and so far this is the simplest approach that I’ve come up with. Let me know if you have a better strategy. The scheme involves simply running a single ant task prior to invoking the Java compiler which effectively selects the product flavour that you intend to build.
Firstly, define all of the different flavours of product that you wish to build in a class ProductType.java. For example:

  1. public class ProductType {
  2. public static final String BANANAS = “bananas”;
  3. public static final String APPLES = “apples”;
  4. public static boolean isBananas() {
  5. return SetProduct.THIS_PRODUCT.equals(BANANAS);
  6. }
  7. public static boolean isApples() {
  8. return SetProduct.THIS_PRODUCT.equals(APPLES);
  9. }
  10. }

Next, somewhere outside your source code tree, create a product directory for each of the product flavours you need to support. Each of these directories will hold its own version of the SetProduct.java class, which takes the following form:

  1. public final class SetProduct {
  2. public static final String THIS_PRODUCT = ProductType.BANANAS;
  3. }

The ant task for each product flavour copies the SetProduct.java class from the specified product directory into the correct location in your java source code tree.

  1. <target name=”bananas”>
  2. <copy overwrite=”true” todir=”src/mypackage”>
  3. <fileset dir=”products/bananas”>
  4. <include name=”SetProduct.java”>
  5. </fileset>
  6. </copy>
  7. </target>

It is important that no version of this class exists in the source code tree within your version control system. This ensures that a product flavour must be selected via an ant task before the code can be compiled successfully. (Other non-java files, such as web.xml which vary between product flavours can also be copied across at this point by the same ant task, but the SetProduct.java file is the only one that is required to support conditional compilation.)

Within your code base you can now define conditional blocks in the following way:

  1. if (ProductType.isBananas()){
  2. yellow = true;
  3. peelable = true;
  4. }
  5. else if (ProductType.isApples()){
  6. yellow = false;
  7. peelable = true;
  8. }
  1. 1 Trackback(s)

  2. Jul 8, 2011: Alexander1

Sorry, comments for this entry are closed at this time.