There has been much discussion about moving from Echo2 to Cooee and what's involved in the process in the Echo2 Forums. As such the Karora team laid down a challenge to one of its developers to migrate an established Echo2 project to Cooee in the shortest time possible.
The Challenge
For the challenge, the Karora team decided to port a project known as "Echo2Impress". Karora developer Daniel Murley was enlisted to complete challenge the challenge comprising of the following requirements in following in under 3 hours.
For successful completion, Daniel had to:
- Start at 2pm on a Friday with a stomach full of indian food and a cup of coffee
- Grab the Echo2Impress source code
- Convert Echo2Impress to use Maven
- Convert it to use Cooee
- Get it up and running
- Create a simple sample app using Echo2Impress
- Be at the pub by 5pm for a beer.
Failure meant no beer. A horrible punishment, deserving of no one.
Checking out the code
All went smoothly. There was no Eclipse project definition, but thats cool - Project was set up in a matter of minutes.
Mavenising
Using the Maven plugin for eclipse, a POM is very quickly set up. So we start off with the following:
<?xml version="1.0" encoding="UTF-8"?> <project> <modelVersion>4.0.0</modelVersion> <groupId>Echo2Impress</groupId> <artifactId>Echo2Impress</artifactId> <packaging>war</packaging> <version>0.0.2</version> <description>WooT</description> </project>
Notice we've set the packaging to war. This will be helpful later on (I hate testing in Tomcat!).
A glance through the source code suggests that we have two dependencies - Echo2 and javax.servlet. Both are pretty easily resolved. So the pom now starts to resemble this:
<dependencies>
<dependency>
<groupId>org.karora</groupId>
<artifactId>cooee</artifactId>
<version>0.2-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.4</version>
<scope>provided</scope>
</dependency>
</dependencies>
Notice that we've put Cooee in a compile scope. This means when we create our war, Cooee will get bundled with it. However, we've put javax.servlet in a provided scope. This is because our container should provide this for us, and we really don't want any of the associated classloader issues that may come with an additional javax.servlet library. So basically, Maven will make the library available for us to compile against, however it won't package it.
Now we're almost sorted out with Maven - we just need to add the Karora snapshot repository so that Maven knows where to find Cooee.
So we add in:
<repositories> <repository> <releases /> <id>Karora Releases</id> <url>http://www.karora.org/maven-repository</url> </repository> <repository> <snapshots /> <id>Karora Snapshots</id> <url>http://www.karora.org/maven-snapshots</url> </repository> </repositories>
Note that the repositories are split into two, if you don't want snapshots - don't use them. Same goes for releases.
So our pom should now look like this:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>Echo2Impress</groupId> <artifactId>Echo2Impress</artifactId> <packaging>war</packaging> <version>0.0.2</version> <description>WooT</description> <dependencies> <dependency> <groupId>org.karora</groupId> <artifactId>cooee</artifactId> <version>0.2-SNAPSHOT</version> <scope>compile</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> </dependencies> <repositories> <repository> <releases /> <id>Karora Releases</id> <url>http://www.karora.org/maven-repository</url> </repository> <repository> <snapshots /> <id>Karora Snapshots</id> <url>http://www.karora.org/maven-snapshots</url> </repository> </repositories> </project>
Total Time: 15 minutes (including writing this garbage as I went along)
Could I have done this with ant: Yeah, if you could be bothered. Maven however is much easier for simple stuff like this.
Refactoring
My basic approach is remove all the echo2 imports, and then use the "Organise imports" function of Eclipse to help me sort out the mess.
GOTCHA: For the images to work with maven, you will need to move the it.fridrik.echo2impress.image class to /src/main/resources or it won't get picked up when packaging or using Jetty.
In the Echo2Impress library, there was luckily only a few classes to change. I refactored:
- Controller.java
- Echo2Impress.java
- EntrySevelet.java
- Slide.java
- LabelListTemplate.java
- MessageSlide.java
- GUIUtils.java
To all use Cooee libraries. The change here was only package imports. No code changes were required. This is expected as a project goal of Cooee is to maintain as much compatibility with Echo2 as possible.
Total Time: 5 minutes (including three sips of coffee).
Give it a go
At this point I'm reasonably happy. So i'm going to use the magic of Maven to give this a go. Of course, certain things are never easy, and due to the fact that Maven's jetty plugin isn't an official plugin (or some rubbish), I need to add a few more lines into my pom.
This is what is required:
<build>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>maven-jetty-plugin</artifactId>
<configuration>
<scanIntervalSeconds>10</scanIntervalSeconds>
<connectors>
<connector
implementation="org.mortbay.jetty.nio.SelectChannelConnector">
<port>8080</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
<webAppSourceDirectory>
${basedir}/WebContent
</webAppSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
This tells maven that we want to use the Jetty plugin, and a few bits of info to go along with it.
Total Time: 5 minutes, I had to lookup the XML to do it ![]()
*Note: * If you're writing java5 specific code, you'll also need to configure Maven's compile plugin to be java5 aware. Again this is about 3-4 lines of XML.
Attempting to run this, its at this point I realise that when Maven pops up:
[INFO] [compiler:compile] [INFO] No sources to compile
that i'm quite possibly in a bit of trouble. Simply because the structure of the Echo2Impress project doesn't match that which Maven so loves and desires.
Easy fixed though, instead of /src, we need to change it to /src/main/java. In about 30 seconds with Eclipse, I've fixed the package structure. See the screenshot here: http://www.karora.org/wiki/download/attachments/950304/impress-shot2.jpg (Note: The screenshot is missing the Echo2Impress image resources in the correct location - /src/main/resources)
So off we go again!
A call to mvn jetty:run, highlights one simple thing - no web.xml! Again, easy fixed, but starting to curse the Echo2Impress guys! (Nah, just kidding, I love you dudes
)
Ok, so 5 minutes later we've got this:
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Echo2Impress</display-name> <servlet> <servlet-name>EntryServlet</servlet-name> <servlet-class> it.fridrik.echo2impress.EntryServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>EntryServlet</servlet-name> <url-pattern>/entry</url-pattern> </servlet-mapping> </web-app>
With that in place, we're up and running.
However I'm short an example - and running low on time. Mid way through the challenge, the Karora guys felt the need to get in the way of the challenge by having some kind of meeting that they thought was important. Something about fixing bugs... sure... whatever ![]()
So short on an example I find the Echo2ImpressBlank class. Which looks kinda like this:
public class Echo2ImpressBlank { public static Presentation build() { Presentation presentation = new Presentation("Echo2Impress Running On Cooee Demo"); Topic welcomeTopic = new Topic("Welcome Topics are Great"); Slide welcomeSlide = new Slide("Welcome"); welcomeSlide .setContent(new MessageSlide( "Echo2Impress helps you building presentations using the Echo2 framework", 18, 0)); welcomeTopic.add(welcomeSlide); presentation.add(welcomeTopic); presentation.setFirstSubTopicId(welcomeSlide.getId()); return presentation; } }
Looks good to me. So I wire this in - however I'm plagued by a bunch of null pointers coming out of the EntryServlet. Sadly I'm at the point where I just don't care anymore (I can't risk the beer!), so I decide I'll break the rules - and change the code. Here is the change in EntryServlet.java:
public void init() throws ServletException { super.init(); String pbm = getInitParameter("presentation.builder.method"); clazz = Echo2ImpressBlank.class; method = "build"; }
As you can see, i just bypassed the initialisation parameters for locating the presentation and forced it to load mine. (Because I don't care about anyone elses presentations!!).
A bit of the old "mvn clean jetty:run", and we're in business!

At this point everything is happily running on Cooee.
Heres the final stats:
Total Time: 1.25hr
Total time spent looking for examples for Echo2Impress: 15 mins
Injury time (see: time wasted by people annoying me): 20mins
Music Required: Pink Floyd - The Wall
Coffee Required: One large cup
Looks like its going to be a POETS Friday! Beer beer beer!
Play time!
So with my new screen presentation framework for Cooee up and running, I figured I'd put together a bit of a five second demo.
Check it out here ... http://www.karora.org/Echo2Impress2Cooee/entry
Download it!
The final source code, including a war binary can be downloaded from here: http://www.karora.org/wiki/download/attachments/950304/Echo2Impress.zip
The war is quite literally a drop and run from a container of your choice. The project is fully mavenised and eclipsified for those who use either technology.
About the author
Daniel Murley is a Senior Developer for Karora. In his spare time he likes to sit on the couch and eat chips. Sometimes, when he's feeling really... saucy, he might even have a beer as well.

Add Comment