Search This Blog

Monday, April 20, 2009

J-Spring 2009 part 2

The second keynote was given by Jos Warmer, a Model Driven Architecture evangelist. Jos has a lot of experience with MDA and you can see that from his talk. His talk was about Mod4j. According to the website: “Mod4j (Modelling for Java) is an open source DSL-based environment for developing administrative enterprise applications.”

Mod4j is an environment in which DSL’s are used to generate specific parts of a Java application. At the moment three DSL’s are implemented (and a fourth is on its way) which focuses on specific architectural layers of the application. These DSL’s are:

  • Business Domain DSL
  • Data Contract DSL
  • Service DSL

The business domain DSL implements the concepts to specify the business objects in your application. These are: business objects with properties, associations between business objects and constraints. Consider the following example:

association Order order one -> many OrderLine orderLines ordered;

The above sample DSL generates a one-to-many association from the Order to the OrderLines class including the necessary Hibernate mapping files. A lot of boilerplate code is generated by using the business domain DSL.

The Service DSL is used to specify services for your domain objects. Examples are the CRUD operations of a specific domain object and finder methods. The code generator for this DSL takes care of generating the required Java code. Consider the following code:

from RecordShopDataContract import SimpleCustomerDto;
create createCustomer for SimpleCustomerDto ;
read readCustomer for SimpleCustomerDto ;
update updateCustomer for SimpleCustomerDto ;
delete deleteCustomer for SimpleCustomerDto ;

The preceding code generates the CRUD methods for the SimpleCustomerDto in the service class.

What’s nice about Mod4j is that no visual models are used for code generation. Domain Specific Languages are used instead. The DSL’s can be put in a version control system where you are able to use the version control system’s merge and history abilities; something which is hard to implement when using visual models. There are also a lot of extension points to modify the generated code. But when you find yourself modifying too much of the generated code, you must ask yourself if the code generator should be modified instead. With mod4j this is possible because it is open source. What’s also nice is that there is an Eclipse plug-in to facilitate Mod4j development. With this plug-in you get code completion on the provided DSL’s.

Although I am not a big fan of Model Driven Architecture tools, I like the concept and principles of Mod4j mainly because coding is central. When should you use Mod4j? I find this a difficult question. When working on a large multi-layered application in Java with technologies like Hibernate, Mod4j can make sure that a consistent architecture is used across all layers. New developers can be more easily brought up to speed.

But when looking at the DSL’s used for generating code, I immediately thought of the Grails framework, based on Groovy. Grails uses a lot of DSL’s. Consider the following Grails example which creates an Author business object:

class Author {
static hasMany = [ books : Book ]
String name
static constraints = {
name(size:5..15,blank:false)
}
}

The above code is the Author business object in Grails with a one-to-many association to the Book class. It also implements a constraint on the name property. Because of the dynamic nature of Groovy, you get the CRUD operations, dynamic finders and the relationship handling for free. If you want to customize the mappings you can modify the Hibernate mapping files if you want.

So the DSL Grails uses is what I call an executable DSL whereas the DSL’s that Mod4j uses are used to generate Java code.

Despite this there is still place for a technology like Mod4j. Not everyone is in the position to use Grails (or Rails) to facility high speed web development. When plain Java web development is used, Mod4j provides a viable alternative to speed-up this development. I will definitely keep an eye out for Mod4j!

Service Oriented Architecture

The next session I went to was about Service Oriented Architectures from Tijs Rademakers. His presentation turned out to be a very practical session which included a lot of his own experiences when implementing Service Oriented Architectures. I like this approach very much. He clarified some misunderstandings when using ESB’s. When an ESB is used, often a lot of code has to be written inside the ESB. Think of transformation and routing logic. This code has to be maintained as well which is often underestimated.

Tijs also talked about how to handle XML messages in a Service Oriented Architecture. I always thought that Groovy has superior XML handling capabilities compared to Java. Tijs mentioned Groovy as one of the most effective ways for handling XML. I agree! So when working with XML in Java (Service Oriented Architecture or not), consider using the Groovy language for the XML handling logic.

Conclusion
Despite the economical situation, 4 people of my company (including me) went to the J-Spring. At QNH we find it very important to continue to invest in knowledge. Individuals are the most important part of a company in which you should invest.

I found the J-Spring 2009 a very good day with lots of good speakers and sessions with a great variety of subjects well worth the investment. If you’re a Dutch Java developer and was not part of J-Spring, make sure you will be at J-Fall later this year.

Keep up the good work!

Friday, April 17, 2009

J-Spring 2009 part 1

April 15th I went to the Dutch Java user group conference named J-Spring. This is the first of two blog entries about this conference. The J-Spring is a popular 1 day conference about Java and related technologies. It is a good place to get an overview about the current state of technology and meet fellow developers.

The introductory keynote was given by Sherali Karimov from Atlassian who talked about how agile is implemented at Atlassian.

Two things in his presentation I found particular interesting. These were:

  • The disturbed
  • Blitz tests

The disturbed
We are all familiar with it. Sometimes you and your team members get so many questions from different people that your own work suffers from it. At Atlassian they introduced the role: the disturbed. Whenever someone has the disturbed role, he/she is expected NOT to do any work but instead answer all questions from outside. The other team members can focus on delivering. The disturbed role is changed every week to another team member. Every week a new team member is responsible for answering questions from people outside the team. Besides shielding the team from outside questions, the disturbed role has another advantage. By switching team members to answer questions, gradually each team member gains the knowledge to answer those questions. It is an effective and practical way to share knowledge within the team.

Blitz tests
Another concept that was introduced is Blitz tests. Atlassian uses there own products inside there own company. Whenever a new release of a particular product is released, it is deployed on the company’s production environment. People from within the company can subscribe to test the new functionality. The experience at Atlassian was that a lot of people subscribed and were eager to test the new functionality. They gave a lot of good feedback to the development team which resulted in higher quality software. I believe you gain a lot when you have the possibility to test every new release by certain people in your own company before releasing the product to your customers.

JEE and JavaFX
The next session I went to was from Paul Bakker. This session was about the future of web development with JEE6 and JavaFX. Paul gave a very complete overview about all the technologies involved in JEE6 and JavaFX. A couple of technologies used in JEE6 are JSF 2.0, JAX-RS and JPA 2.0. After giving a brief overview about every technology, Paul showed how to build a web application with JSF and JavaFX together. Basically, JavaFX was used for the highly interactive parts and JSF for the HTML forms. JavaScript was used to act as a bridge between the HTML page and the JavaFX applet. He also showed how to pass parameters between the applet and the HTML page and vice versa. This seems like an effective way to combine JavaFX with regular web development. JEE6 and JavaFX definitely look very promising!

Look out for the second post of the J-Spring which will highlight some interesting points from the other sessions I attended.

Monday, April 6, 2009

J-Spring

Next week, April 15th, I am going to the Dutch Java User Group conference named J-Spring. This one-day conference is a good place in helping to keep your knowledge up-to-date. There are a lot of interesting sessions which you can attend and a lot of fellow developers to have discussions with. I Am planning to attend the following sessions:

  1. Developing web applications of the future: Combining JavaFX & JEE 6
  2. Java Programming in a Multicore World
  3. SOA, it's a hard knock life
  4. REST, the web as the database?
  5. Hop on Board the Java Troubleshooting Platform

I will post my experience of the J-Spring next week.

Monday, February 23, 2009

Introduction to Genetic Algorithms with JGAP

Out of interest I am familiarizing myself in genetic algorithms, in short GA. My interest in GA came when I first heard about the JGAP project. As mentioned on the project's site "JGAP (pronounced "jay-gap") is a Genetic Algorithms and Genetic Programming component provided as a Java framework.". For a newcomer I found it difficult to get a good overview about all the concepts introduced in genetic algorithms. Before diving into JGAP, I think it is essential that these concepts are well understood. This post is an introduction to genetic algorithms (GA) with JGAP and is explained with a concrete example. In one of my next posts I will demonstrate solving a problem with genetic programming (GP).

So what is a genetic algorithm? Given is the following definition from John R. Koza:

The genetic algorithm is a probabilistic search algorithm that iteratively transforms a set (called a population) of mathematical objects (typically fixed-length binary character strings), each with an associated fitness value, into a new population of offspring objects using the Darwinian principle of natural selection and using operations that are patterned after naturally occurring genetic operations, such as crossover (sexual recombination) and mutation.

In genetic algorithms, a potential solution is called a chromosome. A chromosome consists of a fixed length of genes. A gene is a distinct component of a potential solution. During the evolution of the genetic algorithm, multiple solutions (chromosomes) are combined (crossover and mutation) to form, potentially, better solutions. The evolution is done over a population of solutions. The population of solutions is called a genotype and consists of a fixed-length of chromosomes. During each evolution, natural selection is applied to determine which solutions (chromosomes) make it to the next evolution. The input criteria for the selection process is the so-called fitness of a potential solution. Solutions with a better fitness value are more likely to appear in the next evolution than solutions with a worse fitness value. The fitness value of a potential solution is determined by a user-supplied fitness function.

Although it is possible to implement the above concepts yourself, JGAP already took care of this. Because the best way to learn is by example, let me first introduce the problem domain which I am going to solve with genetic algorithms. During the example, the concepts mentioned above are further clarified.

Consider a moving company which is specialized in moving boxes (with things in it) from one location to another. These boxes have varying volumes. The boxes are put in vans in which the boxes are moved from location to location. To reduce transport costs, it is crucial for the moving company to use as minimal vans as possible. Problem statement: given a number of boxes of varying volumes, what is the optimal arrangement of the boxes so that a minimal number of vans is needed? The following example shows how to solve this problem with genetic algorithms and JGAP.

First: with the arrangement of the boxes I mean the following: consider 5 boxes with the following volumes (in cubic meters): 1,4,2,2 and 2 and vans with a capacity of 4 cubic meters. When the boxes are put in the vans based on the initial arrangement, the distribution of the boxes in the vans is like this:
VanBoxesSpace wasted
Van 1Box 13
Van 2Box 40
Van 3Box 2, Box 20
Van 4Box 22
Fitness value = 3+2 * 4 = 20. See section fitness function for an explanation of the fitness function for this particular problem.

A total of 4 vans is needed. But when the number of vans needed is calculated, which is the total volume of the boxes divided by the volume of the vans, the optimal number of vans is: 11 / 4 = 2.75. Because no partial vans can be used the optimal number of vans needed is 3. The optimal arrangement of the boxes is the following: 1,2,2,2,4. Based on this arrangement the distribution looks like this:
VanBoxesSpace wasted
Van 1Box 1, Box 21
Van 2Box 2, Box 20
Van 3Box 40
Fitness value of 1 * 3 = 3.

Before implementing the actual solution, the following preparatory steps must be taken. These preparatory steps are always needed if genetic algorithms is used to solve a particular problem.

  1. Define the genetical representation of the problem domain. The boxes which must be put in the vans are represented by an array of Box instances. The genetic algorithm must find the optimal arrangement in the array as how to put the boxes in the vans. A chromosome is a potential solution and consists of a fixed-length of genes. A potential solution in this example consists of a list of indexes where each index represents a Box in the box array. To represent such index, I use an IntegerGene. As mention earlier, a gene is a distinct part of the solution. In this example, a solution (chromosome) consists of as many genes as there are boxes. The genes must be ordered by the genetic program in such a way that it represents a (near) optimal arrangement. For example: if there are 50 boxes, a chromosome with 50 IntegerGene's is constructed, where each gene's value is initialized to an index in the box array, in this case from 0 to 49.
  2. Determine the fitness function. The fitness function determines how good a potential solution is compared to other solutions. In this problem domain, a solution is fitter when fewer vans are needed so less space is wasted.
  3. Determine the parameters used for the run. For the run I use a population size of 50 and a total number of 5000 evolutions. So the genotype (the population) initially consists of 50 chromosomes (potential solutions). These values are chosen based on some experimentation and can vary based on the specific problem.
  4. Determine the termination criteria. The program ends when 5000 evolutions are reached or when the optimal number of vans needed is reached. The optimal number of vans can be calculated by dividing the total volume of the boxes by the capacity of the vans and rounding the result up (because no partial vans can be used).
Initialization
The Box class has a volume. In this example 125 boxes are created with varying volumes between 0.25 and 3.00 cubic meters. The boxes are stored in an array. The following code creates the boxes:
Random r = new Random(seed);
this.boxes = new Box[125];
for (int i = 0; i < 125; i++) {
Box box = new Box(0.25 + (r.nextDouble() * 2.75));
box.setId(i);
this.boxes[i] = box;
}

Before we configure JGAP we must first implement a fitness function. The fitness function is the most important part in genetic algorithms as it determines which populations potentially make in to the next evolution. The fitness function for this problem looks like this:
package nl.jamiecraane.mover;

import org.jgap.FitnessFunction;
import org.jgap.IChromosome;

/**
* Fitness function for the Mover example. See this
* {@link #evaluate(IChromosome)} for the actual fitness function.
*/
public class MoverFitnessFunction extends FitnessFunction {
private Box[] boxes;
private double vanCapacity;

public void setVanCapacity(double vanCapacity) {
this.vanCapacity = vanCapacity;
}

public void setBoxes(Box[] boxes) {
this.boxes = boxes;
}

/**
* Fitness function. A lower value value means the difference between the
* total volume of boxes in a van is small, which is better. This means a
* more optimal distribution of boxes in the vans. The number of vans needed
* is multiplied by the size difference as more vans are more expensive.
*/
@Override
protected double evaluate(IChromosome a_subject) {
double wastedVolume = 0.0D;

double sizeInVan = 0.0D;
int numberOfVansNeeded = 1;
for (int i = 0; i < boxes.length; i++) {
int index = (Integer) a_subject.getGene(i).getAllele();
if ((sizeInVan + this.boxes[index].getVolume()) <= vanCapacity) {
sizeInVan += this.boxes[index].getVolume();
} else {
// Compute the difference
numberOfVansNeeded++;
wastedVolume += Math.abs(vanCapacity - sizeInVan);
// Make sure we put the box which did not fit in this van in the next van
sizeInVan = this.boxes[index].getVolume();
}
}
// Take into account the number of vans needed. More vans produce a higher fitness value.
return wastedVolume * numberOfVansNeeded;
}
}

The above fitness function loops through all the genes in the supplied potential solution (where each gene in the chromosome represents an index in the box array) and calculates how many vans are needed for this arrangement of boxes to fit in the vans. The fitness value is based on the space wasted in every van when a new van is needed, called the wasted volume. The total volume wasted is multiplied by the number of vans needed. This is done to create a much worse fitness value when more vans are needed. In the above, simplified, example the fitness value of the first solution is 20 and the fitness value of the second, optimal, solution is 3. One term deserves more explanation and that is allele. In the above code the getAllele method on the gene is called. Allele is just another word for the value of the gene. Because all genes all IntegerGene's, the value of each gene is of type Integer.

Next it is time to setup JGAP:
private Genotype configureJGAP() throws InvalidConfigurationException {
Configuration gaConf = new DefaultConfiguration();
// Here we specify a fitness evaluator where lower values means a better fitness
Configuration.resetProperty(Configuration.PROPERTY_FITEVAL_INST);
gaConf.setFitnessEvaluator(new DeltaFitnessEvaluator());

// Only use the swapping operator. Other operations makes no sense here
// and the size of the chromosome must remain constant
gaConf.getGeneticOperators().clear();
SwappingMutationOperator swapper = new SwappingMutationOperator(gaConf);
gaConf.addGeneticOperator(swapper);

// We are only interested in the most fittest individual
gaConf.setPreservFittestIndividual(true);
gaConf.setKeepPopulationSizeConstant(false);

gaConf.setPopulationSize(50);
// The number of chromosomes is the number of boxes we have. Every chromosome represents one box.
int chromeSize = this.boxes.length;
Genotype genotype;

// Setup the structure with which to evolve the solution of the problem.
// An IntegerGene is used. This gene represents the index of a box in the boxes array.
IChromosome sampleChromosome = new Chromosome(gaConf, new IntegerGene(gaConf), chromeSize);
gaConf.setSampleChromosome(sampleChromosome);
// Setup the fitness function
MoverFitnessFunction fitnessFunction = new MoverFitnessFunction();
fitnessFunction.setBoxes(this.boxes);
fitnessFunction.setVanCapacity(VOLUME_OF_VANS);
gaConf.setFitnessFunction(fitnessFunction);

// Because the IntegerGenes are initialized randomly, it is neccesary to set the values to the index. Values range from 0..boxes.length
genotype = Genotype.randomInitialGenotype(gaConf);
List chromosomes = genotype.getPopulation().getChromosomes();
for (Object chromosome : chromosomes) {
IChromosome chrom = (IChromosome) chromosome;
for (int j = 0; j < chrom.size(); j++) {
Gene gene = chrom.getGene(j);
gene.setAllele(j);
}
}

return genotype;
}



In the above code we setup the JGAP library. The provided Javadoc should be self-explanatory. A population (genotype) of 50 potential solutions (chromosomes) is created where every chromosome consists of the same number of genes as there are boxes. Because in this example a lower fitness value is better, theDeltaFitnessEvaluator is used.

Next, it is time to evolve the population. The population is evolved 5000 times. When the optimal amount of vans is reached earlier, the run ends. The following code demonstrates the evolution of the problem solution:
private void evolve(Genotype a_genotype) {
int optimalNumberOfVans = (int) Math.ceil(this.totalVolumeOfBoxes / VOLUME_OF_VANS);
LOG.info("The optimal number of vans needed is [" + optimalNumberOfVans + "]");

double previousFittest = a_genotype.getFittestChromosome().getFitnessValue();
numberOfVansNeeded = Integer.MAX_VALUE;
for (int i = 0; i < NUMBER_OF_EVOLUTIONS; i++) {
if (i % 250 == 0) {
LOG.info("Number of evolutions [" + i + "]");
}
a_genotype.evolve();
double fittness = a_genotype.getFittestChromosome().getFitnessValue();
int vansNeeded = this.numberOfVansNeeded(a_genotype.getFittestChromosome().getGenes()).size();
if (fittness < previousFittest && vansNeeded < numberOfVansNeeded) {
this.printSolution(a_genotype.getFittestChromosome());
previousFittest = fittness;
numberOfVansNeeded = vansNeeded;
}

// No more optimal solutions
if (numberOfVansNeeded == optimalNumberOfVans) {
break;
}
}
IChromosome fittest = a_genotype.getFittestChromosome();

List<Van> vans = numberOfVansNeeded(fittest.getGenes());
printVans(vans);
this.printSolution(fittest);
}

Because we set the preserveFittest property on the JGAP configuration object to true, we have access to the most fittest chromosome with the getFittestChromosome() method. The fittest chromosome consists of 125 genes, the indexes of the boxes in the array, in the arrangement of how to put the boxes in the vans. The actual evolution is performed by JGAP. The fitness value determines which populations have the highest chance to make it to the next evolution. Eventually a (near) optimal solution is formed. This indicates the importance of a well chosen fitness function as it is used in the selection process of the chromosomes. Below is the output of a sample run:
The total volume of the [125] boxes is [210.25989987666645] cubic metres.
The optimal number of vans needed is [49]
Number of evolutions [0]
Fitness value [4123.992085987977]
The total number of vans needed is [63]
Fitness value [3458.197333300851]
The total number of vans needed is [61]
Fitness value [3138.2899569572887]
The total number of vans needed is [60]
Fitness value [2865.5105375433063]
The total number of vans needed is [59]
Fitness value [2562.282028584251]
The total number of vans needed is [58]
Fitness value [2267.7135196251966]
The total number of vans needed is [57]
Fitness value [1981.8050106661412]
The total number of vans needed is [56]
Fitness value [1704.5565017070858]
The total number of vans needed is [55]
Fitness value [1479.769464870246]
The total number of vans needed is [54]
Number of evolutions [250]
Fitness value [1215.9278601031112]
The total number of vans needed is [53]
Fitness value [1002.6487336510297]
The total number of vans needed is [52]
Number of evolutions [500]
Fitness value [774.5352329142294]
The total number of vans needed is [51]
Number of evolutions [750]
Number of evolutions [1000]
Fitness value [535.1696373214758]
The total number of vans needed is [50]
Number of evolutions [1250]
Number of evolutions [1500]
Number of evolutions [1750]
Number of evolutions [2000]
Number of evolutions [2250]
Fitness value [307.8713731063958]
The total number of vans needed is [49]
Van [1] has contents with a total volume of [4.204196540671411] and contains the following boxes:
Box:0, volume [2.2510465109421443] cubic metres.
Box:117, volume [1.9531500297292665] cubic metres.
Van [2] has contents with a total volume of [4.185233471369987] and contains the following boxes:
Box:17, volume [1.0595047801111055] cubic metres.
Box:110, volume [0.5031165156303853] cubic metres.
Box:26, volume [2.6226121756284955] cubic metres.
Van [3] has contents with a total volume of [4.312990612147265] and contains the following boxes:
Box:91, volume [1.8897555340430203] cubic metres.
Box:6, volume [2.423235078104245] cubic metres.
...Further output omitted

As seen in the above output, the optimal number of vans is reached between 2250 and 2500 evolutions. The program also outputs the distribution of the boxes in the vans. The complete source code of the above example can be downloaded from http://code.google.com/p/jc-examples/. The down-loadable artifact is called ga-moving-example-1.0.jar.

Conclusion
Genetic algorithms and programming is an exciting technology but with a lot of concepts which are hard to grasp if you are new to the field. This post is an introduction of the concepts for genetic algorithms and showed how to implement a GA solution with JGAP. In one of my next posts, genetic programming is explained with a concrete example.

The silver bullet rule applies to genetic algorithms as well. To give you an impression, the following problems are good candidates to solve with GA:
  • Problems where it is hard to find a solution but once a solution is found, measure how good this particular solution is.
  • Problems where the search space is very large, complex or poorly understood.
  • Problems where a near optimal solution is acceptable.
  • Problems where no mathematical analysis is available.
Although I am not an expert on the subject, feel free to ask your questions and I will try to answer them as best as possible.

Wednesday, January 28, 2009

I finally found the time to finish my FolderVisualizer application. To recap: FolderVisualizer draws a Tree Map of a selected folder which makes it easy to see which folders/files take up the most space. You can also delete these folders from within the application. I started this project with a colleague to do a comparison between Adobe Air and JavaFX.

Version 2.0.0RC1 is down-loadable from the project's website. The following screenshot gives an impression of the application:

The application implements the following functionality:

  • Select a folder which must be visualized in the tree map

  • drill down to other folders

  • change the number (density) of the folders in the tree map

  • provide a breadcrumb navigation path for easy navigation

  • Delete the selected folder/file

  • Visual effects when changing view stacks

  • More appealing theme/colors than the previous version

Version 2 is a complete rewrite of the whole application. Because a lot of new functionality is added, I restructured the application to make it more maintainable and transparent. As a guideline, I used the principles of MVCS, which is basically a set of design guidelines to implement the Model View Controller Service architecture in Flex applications. It is NOT a framework unlike for example Cairngorm. I Used Cairngorm on another project but I had the impression that the framework gets in your way. I found myself writing to much boilerplate code like commands, custom events, controllers etc. I'm NOT saying that Cairngorm is a bad framework, but I found it to complicated for the task at hand: structuring a Flex application in a well defined matter.

On the other hand, I really like the clarity and simplicity of the MVCS approach and the freedom to adapt the principles to your application's needs. The FolderVisualizer application consists of a couple controllers, a model class which contains references to the application's model objects, a FileService and components which make up the view. To handle user interaction, I used the event bubbling approach. In the event bubbling approach, when the user clicks on a button, a UIEvent is dispatched. This event "bubbles" up to the parent who handles it, usually a controller. This controller is responsible for handling the business logic associated with this specific user action. Consider the following example, taken from the FolderVisualizer application:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Metadata>
[Event(name="uiEvent",type="nl.foldervisualizer.events.UIEvent")]
</mx:Metadata>

<mx:Script>
<![CDATA[
... Some code omitted

[Bindable]
public var model : Model;

private function handleBack(event:Event):void {
dispatchEvent(new UIEvent(UIEventKind.BACK))
}

... Some code omitted
]]>
</mx:Script>

<mx:Spacer width="5"/>
<mx:Button label="Back" click="handleBack(event)"/>
... Some code omitted
</mx:HBox>
The above code is taken from the NavigationControlBar.mxml which implements the navigational actions a user can perform. When a user clicks on the back button, a UIEvent is dispatched of kind UIEventKind.BACK. Also note that this component defines an event "uiEvent" which parent containers can use to add an eventListener which listens for UIEvents. See the following code-snippet taken from FolderVisualizer.mxml, which is the parent container of the NavigationControlBar:
<?xml version="1.0" encoding="utf-8"?>
<mx:HBox xmlns:mx="http://www.adobe.com/2006/mxml"
xmlns:toolbox="http://www.flextoolbox.com/2006/mxml"
xmlns:view="nl.foldervisualizer.view.*"
xmlns:controller="nl.foldervisualizer.controller.*"
xmlns:model="nl.foldervisualizer.model.*"
creationComplete="handleCreationComplete()">

... Some code omitted

<!-- Controllers used in the application, could also use dependency injection here (for example Prana) -->
<controller:AppController id="appController" model="{model}"/>
<controller:NavigationController id="navController" model="{model}"/>

<view:ControlBar width="100" height="100%" uiEvent="appController.handleUIEvent(event);"/>

<mx:VBox width="100%" height="100%" verticalGap="0">
<view:NavigationControlBar height="35" width="100%" verticalAlign="middle" horizontalAlign="left" horizontalGap="0" model="{model}" uiEvent="navController.handleUIEvent(event);"/>
... Some code omitted
</mx:VBox>
</mx:HBox>
As you can see in the above code, the navController.handleUIEvent method handles all UIEvents dispatched from the NavigationControlBar. One way to handle the events in the handleUIEvent method is the use of a switch statement. For every UIEventKind which the controller must handle, a separate case in the switch statement is used which calls the correct method. Consider the following example:
public function handleUIEvent(event:UIEvent) : void {
switch (event.kind) {
case UIEventKind.BACK:
// handle event
break;
case UIEvent.SHUTDOWN:
// Handle event
break;
default:
trace("No event handler defined")
}
}
What I don't like about this implementation is the excessive amount of switch-case code to handle the events. For every controller in your application which must handle UIEvents, a switch block must be implemented. Instead of using a switch block, I used a different approach for handling UIEvents in controllers. I implemented a MultiActionController which acts as a base class of all controllers which must be able to handle UIEvents. The following code snippet comes from the MultiActionController (some code omitted):
public class MultiActionController extends BaseController
{
/**
* Mappings between UIEvent.kind (see UIEventKind) to functions. Those functions are defined in
* the subclass.
*/
protected var _handlerMappings:HashMap = new HashMap();

public function MultiActionController()
{
super();
}

public function handleUIEvent(event:UIEvent) : void {
var funct:Function = _handlerMappings.getValue(event.kind)
if (funct==null) {
trace("No function for [" + event.kind + "] is defined in the handlerMappings. Make sure you define this event to function mapping in the constructor of you base class. See the ASDocs of the MultiActionController.")
throw new IllegalOperationError("No function for [" + event.kind + "] is defined in the handlerMappings. Make sure you define this event to function mapping in the constructor of you base class. See the ASDocs of the MultiActionController.")
}
funct.call(this, event)
event.stopPropagation()
}
}
The MultiActionController defines a _handlerMapping variable of type HashMap. This hashmap contains the mapping between UIEventKind and functions (functions are objects in ActionScript 3). When the handleUIEvent is called, this method looks up the function belonging to the UIEvent.kind property. If this function exists, it is called passing the UIEvent as a parameter and stops propagation for this event. Otherwise an IllegalOperationError is thrown. Now take a look at the NavigationController which extends MultiActionController:
{
public class NavigationController extends MultiActionController
{
private var _model:Model;

public function set model(model:Model):void {
_model = model
}

public function NavigationController()
{
super();
super._handlerMappings.put(UIEventKind.BACK, this.handleBack)
super._handlerMappings.put(UIEventKind.DIRECT_LINK, this.handleDirect)
super._handlerMappings.put(UIEventKind.DENSITY_CHANGE, this.handleDensityChanged)
super._handlerMappings.put(UIEventKind.DRILLDOWN, this.handleDrilldown)
}

private function handleBack(event:UIEvent):void {
... Do actual work here
}

... Some code omitted

}
}
The constructor of the NavigationController defines the mappings between the UIEvents this controller handles, and the corresponding functions to call. As you can see, there is no need to write blocks of switch statements in every controller to handle UIEvents. Just define the mapping between the UIEvents and functions in the constructor of the corresponding controller. One thing to be aware of is that all functions that are called by the MultiActionController accept a single argument of type UIEvent. This should not be a problem because the only way to call these functions is by dispatching a UIEvent. The UIEvent.payload property should contain all data required for the function to do its work.

Note that this is NOT a framework but an implementation variant of the MVCS principle for handling UIEvents. Feel free to use this code in your own project.

Conclusion

Structuring and organizaing a Flex (and any other!) application gives you the following benefits:

  • easier to maintain the application

  • easier to extend the application with new funcitonality

  • easier to test the application

  • easier to understand the application for new team members

  • ...

Implementing the principles of the MVCS approach is an effective way of organizing and structuring Flex applications. The principles of MVCS are not restricted to a particular implementation. Instead, they can be implemented in various ways that best suites the needs of your application. In this post, I showed you a variation of handling UIEvents which reduces the amount of code necessary to handle these events. When you work on moderate to large Flex applications, have a look at the MVCS guidelines to structure the application. The time you invest does get pay back. The complete source code of the FolderVisualizer application can be found here.

One final note: although I did not use a DI framework, for example Prana, using a DI framework can be an effective way to decrease the coupling between components and increase testability. At the moment, my DI framework of choice for Flex applications is Prana.

Resources

Folder Visualizer
MVCS
Tree map component

Tuesday, January 20, 2009

text-image-generator example

As a follow-up on my previous post, here is an example of how to use the text-image generation library. Consider the following code:

TextImage testImage = new TextImageImpl(400, 250, new Margin(0, -5));

// Declare or read the fonts you need
Font header = new Font("Sans-Serif", Font.BOLD, 15);
Font plain = new Font("Sans-Serif", Font.PLAIN, 12);

// Read in any images you need
InputStream is = Test.class.getResourceAsStream("/warning.jpg");
Image warning = ImageIO.read(is);
// Put close() in try-finally block with production code!
is.close();

// 1. specify font and write text with a newline
testImage.useFont(header).writeLine("Example usage text-image-generator.").newLine();
// 2. enabled the wrapping of text and write text which is automatically wrapped
testImage.useFont(plain).wrap(true).write("This is an example of how to use the text-image generation library. With this library you can dynamically generated textbased content as images (png or jpeg). Notice how this sentence is automatically wrapped. See the code at http://code.google.com/p/textimagegenerator/ for more examples.").newLine();

// 3. Disable text-wrapping again. Write underlined text.
testImage.wrap(false).useColor(Color.BLUE).useFontStyle(Style.UNDERLINED).write("This line of text is underlinedand blue.").useFontStyle(Style.PLAIN).newLine();
testImage.writeLine("You can also embed images in your generated image:");
// 4. embed the actual image. Here we use absolute positioning
testImage.write(warning, 175, 175);

// 5. Write the image as a png to a file
OutputStream os = new FileOutputStream(new File("example.png"));
testImage.createPng(os);
os.close();

The code above generates the following image:


The text-image generation code can be downloaded at http://code.google.com/p/textimagegenerator/. Here you will find more examples of how to use this library. Hope you enjoy.

Tuesday, January 13, 2009

Creating Dynamic Images with Java and GridGain

At my current client we have a requirement to dynamically create images with a specific text, for example an authorization code. These images are created in Java and encoded as a PNG file. For the generation of text based images I created a library which is available on Google Code, see [1]. These images are generated by a servlet of which the URL is embedded in the HTML as an image tag or in a background of a div element.

During performance tests I saw that the generation of images is a very CPU intensive task. Because there are a lot of users who request a dynamically generated image, this functionality can cripple the CPU's which has a negative impact on the throughput and the stability of the system. Because this is a specific, CPU intensive task, it is a perfect candidate to off-load this process to another machine so the CPU intensive task is distributed over a number of machines.

One way to distribute the processing of CPU intensive tasks is to use the open source grid computing platform GridGain. GridGain is "an open source computational grid framework that enables Java developers to improve general performance of processing intensive applications by splitting and parallelizing the workload." See also [3]. Image generation is a perfect candidate to distribute with GridGain.

I have created the following setup to do some first tests with GridGain in this specific scenario:

  1. Created a web application with a servlet which is called by clients. This servlet is responsible for executing the image generation task on the grid and streaming the result back to the client as a PNG.

  2. Created a GridGain task which creates a job which is responsible for the actual image generation. This job can be executed on any of the nodes participating in the grid.

  3. Used two physical nodes in my first setup, node 1: PentiumM 2 GHz with 2 GB's RAM, node 2: Pentium4 2.2 GHz with 1 GB RAM.

  4. Used Apache JMeter to create a load test [4].


See the following diagram for an overview of my setup:


I used 5 concurrent threads (users) in my JMeter script with a ramp-up time of 0ms which means all 5 users are active at once.

  1. My first test run was used to create a baseline. This version did not use the grid at all and the image generation logic was implemented directly in the servlet. This test was run on node 1. With a couple of tests there was an average of 6.7 transactions per second.

  2. My second test was used to determine the overhead of the grid. I expect the throughput to be a little less than in my first test. The same node was used as in 1. With a couple of tests there was an average of 6.5 transactions per second. Almost as good as without the grid. In this specific scenario the overhead of the grid is negligible. However, this can vary based on your specific situation.

  3. In my third test I added a second node, node 2, to the grid. With a couple of tests there was an average of 9.5 transactions per second. This is a throughput increase of 46%. Pretty impressive. In my test, both nodes had 100% CPU utilization.


This is really impressive considering the amount of work I had to install and configure GridGain, almost nothing. With the default configuration, GridGain uses IP multi-cast to discover all the grid nodes. I just had to start gridGain on the second node and this node automatically participated in the grid. Other strategies can be used to implement the discovery process, for example JMS topics. When a given task is executed for the first time on a given node, the grid takes care of deploying this task on that specific node. No need for manual deployment of tasks. Failover and load balancing of tasks to other nodes when a node has crashed is enabled by default. Everything is also well documented which really helps creating a consistent package.

Conclusion
Distributing CPU intensive tasks across several physical machines is an effective way to increase the throughput and reducing the risk that this process will become a bottleneck or has a negative impact on the stability of the system as a whole. GridGain is a platform which enables (Java) developers to create a computing grid and execute tasks on this grid. When you have computational intensive tasks in your application, make sure you check out GridGain.

Resources
[1] Image Text library
[2] GridGain
[3] Highscalability.com
[4] JMeter