Darwin 2: Guide to configuring a Darwin application

Introduction to Configuring Darwin 2

Configuration is performed via XML files which define a set of interacting beans which, together, run the evolution required. Out of the box, Darwin 2 uses the BeanPot project for its dependency-injection configuration tool. However, there is no reason that you could not use Spring, Guice (or something else). If you do that, you will need to write your own version of the Darwin class, and/or update the BeanContainer class in the com.rubecula.util package.

Also note that any tags which come before the <beans> tag, are specific to the BeanPot. They won't make sense to any other container. For more details of the specifics of how to use the BeanPot for Darwin application, see BeanPot: Brief Guide to Configuration for Darwin Applications.

The bean definitions themselves should be usable with relatively few changes by Spring/Guice with no changes (although that hasn't been tested). Nevertheless, there are some differences:

The order of the beans in the configuration file can be significant. In particular, if bean A is referenced as a constructor argument by bean B, then bean A's definition must precede B's definition. However, if bean A is referenced as the value of a property, or as part of a member relationship, then the order is immaterial.

By deliberate policy, Darwin requires that all java objects are constructed either via a factory class, in which case the constructor(s) will be of default scope only, or explicitly defined in the configuration file. In other words there are no implicitly-defined classes. While it can sometimes save a few lines of code (and time) to omit default stuff, our experience is that this time saving is often far outweighed by time spent figuring out why something apparently magic is happening (or not happening).

This guide explains the usage, parameters, etc. of each of the beans. In general, you should be careful that you don't share beans that can have properties indirectly set at run time by other beans, as this is a likely source of errors.

You will find that it is essential to look up the classes referenced in the apidocs in order to understand what constructor args they are expecting and which properties may be set.

Configuring the Out of the Box application

To run the out-of-the-box application (hereafter referred to as OOB), simply execute the main method of the Darwin class with no further parameters.

The configuration file starts thus:

<?xml version="1.0" encoding="ISO-8859-1" ?>
<configuration>

Here we specify an identifier for the application being configured:

    <id>Out of the box</id>

At this point, we see a comment, reproduced here:

    <!--
        This is the configuration for the out-of-the-box running of Darwin. It
        is an extremely simple evolution and its sole purpose is to have
        something which will run "out of the box" using all of the standard
        components (none of the classes used for beans have had to be extended
        to make this work). It defines: an evolution based on calendar years;
        a realm; a random number source. It includes the definitions
        referenced by the include directive.
    
-->

Beans

Now comes the beans tag, followed by as many beans as need to be specified in this top-level configuration file.

Following this point is a list of the beans used for the standard out-of-the-box application (some beans will be specified in include files). Note that order is important. In particular, if bean A is referenced as a constructor argument by bean B, then bean A's definition must precede B's definition. However, if bean A is referenced only by a property, or as a member of bean A, then the order is immaterial.

Beans can have any name you like, although it is helpful to give them sensible names which are based on the interface which they implement. There is a set of required bean names, although there is likely to be only one definition in it ("Applet"). The list can be found in the Beans interface.

    <beans>

The first bean is required for all Darwin evolutions. We call it the "Evolution" bean because it is a singleton bean implementing the Evolution interface but, as usual, its name is arbitrary. What makes it special is that it implements the Runnable and Configurable interfaces. It is the sine qua non of the Darwin beans. The Evolution bean manages the evolution of a set of evolvables. There are two ways to define the evolvables: the (recommended) "member" way and the "list" way. For an example of the list way of doing it see the BeanPot: Brief Guide to Configuration for Darwin Applications.

This bean must implement the interface Evolution. For details of the constructor arguments and properties, see the API for Evolution_Calendar, which is a concrete implementation of com.rubecula.darwin.evolution.Evolution which, by default, is based on calendar time (in seconds), starting from now. Thus it is suitable for an evolution that runs in real time. If you need an evolution that, for example, simulates the Jurassic period, then you need to define your own implementation of Evolution (or perhaps use the constructor which takes a start calendar object). This particular bean is defined to run year-by-year, hence the first constructor argument. If you want to go with the default, you can simply remove the first constructor argument and evolutionary time will be seconds, starting "now".

Note that there is one normally at least one evolvable, namely the Darwin bean which corresponds to the "system" that we are studying. As described elsewhere, a system can generally be thought of as a single species.

An evolution proceeds at a certain rate, with one "tick" corresponding to a particular time period. An evolution keeps track of a potentially large number of evolvable objects, each undergoing a new generation every so many ticks. For this application, there is only one evolvable (the Darwin bean) and it undergoes a new generation for every tick. Thus the value for the evolvables map corresponding to "!Darwin" is 1.

        <bean id="Evolution" class="com.rubecula.darwin.evolution.Evolution_Calendar">
            <constructor-arg class="com.rubecula.darwin.evolution.TimeUnit">
                <value>Year</value>
            </constructor-arg>
            <constructor-arg class="Boolean">
                <value>true</value>
            </constructor-arg>
        </bean>

The next bean, Realm, is required for all Darwin evolutions. You may of course implement your own concrete class and reference it here. All that is required is that it implements the Realm interface, as required by various Environment and Taxon beans. The concrete implementation referenced here is the standard implementation of the interface Realm.

The realm more or less "hosts" the "model". It is one of the three top-level cooperating classes that make up a Darwin application, the others being the "Evolution" bean and user interface.

For details of the constructor arguments and properties, see the API for Realm_Wallacian.

        <bean id="Realm" class="com.rubecula.darwin.domain.world.Realm_Wallacian">
        </bean>

The random number generator bean is at the heart of the evolutionary process. Since the developers of Java (viz. Sun, now Oracle) weren't kind enough to provide an interface for random number generators, we use a class provided by the Jakarta Commons math package: org.apache.commons.math.random.RandomAdaptor. Random_Standard is basically just an extension of RandomAdaptor which utilizes the java.util.Random class as its random number generator. You could instead use your own random number generator, provided that it implements the interface org.apache.commons.math.random.RandomGenerator. It is highly recommended while you are developing an application that you set the seed property here so that you will always get the same sequence of numbers. Of course, once the application goes into production, you want to have it use a random seed (just leave the seed property unset). For details of the constructor arguments and properties, see the API for Random_Standard.

        <bean id="Random" class="com.rubecula.util.random.Random_Standard">
        </bean>

Finally, we close up the beans tag.

    </beans>

Include files

This is where we specify the include file(s) which contains the remainder of the configuration. In this case, there is only one include file. The include directive is followed by closing the configuration tag. The filename specified is relative to the class whence the configuration is initiated, typically the Darwin class.

    <include>MendelsPeas.xml</include>
</configuration>