Archive for the ‘Software Engineering’ Category

RadSem software development visualized with Gource

Tuesday, December 22nd, 2009

Since the beginning of 2008 we spent more than 2 person years on developing RadSem. RadSem is a semantic image annotation and retrieval tool. During the last two years a number of papers about this tool and its features have been published. Using Gource, Patrick (a student at DFKI) created a video of the source code repository activity since 2008 using Gource. And this is the result:

With a little hacking, he even got our continuous integration server running Hudson to create the latest version of the video each night automatically. The video above is a snapshot which has been uploaded to Youtube. Also watch out for the “HD” version on Youtube as the original video has been generated in HD quality.

Sonar in MEDICO

Tuesday, June 9th, 2009

It took some time, until we got it finally running: Various source code measurements for the MEDICO code base using SONAR.

Sonar 1244542402460

The overview page is online here: http://www.dfki.uni-kl.de/sonar/projects

However, we decided to put a password protection on all further pages due to open licensing questions.

Automated UI Tests with Hudson on Debian

Thursday, April 2nd, 2009

At DFKI we are using Java, Maven2 and Hudson for a Continuous Integration System within the research project MEDICO .

Until now, this works really fine for console based JUnit tests. However, the test coverage of our source code is far from 100% (ashes on me!). This is why I decided to test from two “directions”:

  1. Bottom-up using JUnit tests for simple methods. These tests are easy to write and to maintain. In theory, the whole application works correctly if all methods work correctly. Thus, this requires that you have 100% test coverage for your code. This condition is far from being met by our code base.
  2. To come up with this, we decided to add Top-down tests. Using the Java UI test framework FEST we specified test scripts which perform certain operations on the application level. Each of these scripts define the expected behavior of the UI and the data presented on the screen. Examples are below.

It took me several hours to set this up. The following steps assume that you have already installed Debian Linux, Maven2, Hudson as described here.

Here are the necessary steps:

1. Install Xorg

On a Debian system, you just have to do an

apt-get install xorg

2. Configure Xorg

Since we do not care about any special support for the graphics card (in fact, I run all these services on VMWare instances) you can just use automatic configuration routines from Xorg to find a minimal server layout. Just type

Xorg -configure

This will create a “xorg.conf.something” in the current working directory. To use it, you just have to copy it to “/etc/X11/xorg.conf”.

3. Install an appropriate window manager

I also tried running Xorg completely without any window managers and with tinywm. This is certainly not a good idea since some of my UI tests require the program windows to run maximized. But window maximization seems to require certain functions from the window manager. With the latter two window managers, I got this error message:

“Platform does not support maximizing frames”

This problem was solved by installing ICEWM. On Debian, all you have to do is:

apt-get install icewm

No further configuration needed.

4. Make Xorg start before Tomcat

For this purpose I created a “/etc/init.d/xorg” file with the following content:

case $1 in
start)
startx &
sleep 15
export DISPLAY=:0.0
xhost localhost
;;
stop)
killall -9 xinit
;;
restart)
killall -9 xinit
sleep 5
startx &
sleep 5
xhost localhost
export DISPLAY=:0.0
;;
esac
exit 0

Link this file to /etc/rc2.d/S98xorg to have it started before tomcat. As you can see above, this also activates access to the Xserver for all applications running on the local server. This only makes sense for dedicated servers without any user accounts that could interfere with the UI tests.

5. Export DISPLAY variable to the Tomcat init file

Add this line to /etc/init.d/tomcat

export DISPLAY=:0.0

and make sure that you have no “java.awt.headless=true” parameters in any of the Tomcat or Catalina startup scripts.

6. Define a sample application

Somehow a “Hello World”, here is a very simple sample application:

public class FrameSample {

public static JFrame frame;

public static void main(String[] args) {
frame = new JFrame(“TestFrame”);
frame.setName(“TestFrame”);

JButton button = new JButton(“TestButton”);
button.setName(“TestButton”);

frame.add(button);
frame.pack();
frame.setVisible(true);
}
}

7. Define a UI test for it

A really minimalistic example, that only checks for the presence of the “TestButton” is shown below:

public class FrameSampleTest {

private FrameFixture window;

@Before
public void setUp() {
dfki.km.medico.uisample.FrameSample.main(new String[] {});
window = new FrameFixture(FrameSample.frame);
window.show(); // shows the frame to test

}

@Test
public void testButtonExists() {
window.maximize();
window.button(“TestButton”).requireEnabled();
}
}

Documentation about more complex tests can be found in the FEST wiki.

Sonar on Debian with Tomcat 6

Sunday, March 29th, 2009

After moving all MEDICO related code to Maven2 and adopting a Continuous Integration cycle for it, I decided to take the next step and perform automatic code Monitoring with Sonar. We had been doing code monitoring before with Hudson and different plugins for PMD, Checkstyle etc. But it turned out that accessing the resulting information via the Hudson interface is not convenient if you want to monitor the quality of several software projects over time.

This is where Sonar comes into play. Quoting from their website:

“Sonar enables to collect, analyze and report metrics on source code. Sonar not only offers consolidated reporting on and across projects throughout time, but it becomes the central place to manage code quality.”

Sonar 1238344318231

Since Sonar does not officially support deployment in Tomcat 6, the rest of this post explains how to install Sonar on Debian Linux running Apache Tomcat version 6.0.18 and JDK 1.6.0_07-b06.

1. Preparing the WAR file

Prepare the WAR file accroding to the Sonar Full Installation Guide.

2. Before Deployment

With the standard Tomcat 6 setup you will run into java.lang.OutOfMemoryError Exceptions for the PermGen space. These look like that in the “catalina.<date>.log” file:

SEVERE: An exception or error occurred in the container during the request processing

java.lang.OutOfMemoryError: PermGen space

at java.lang.Throwable.getStackTraceElement(Native Method)

at java.lang.Throwable.getOurStackTrace(Throwable.java:591)

at java.lang.Throwable.printStackTrace(Throwable.java:510)

at java.util.logging.SimpleFormatter.format(SimpleFormatter.java:72)

at org.apache.juli.FileHandler.publish(FileHandler.java:129)

at java.util.logging.Logger.log(Logger.java:472)

at java.util.logging.Logger.doLog(Logger.java:494)

at java.util.logging.Logger.logp(Logger.java:694)

at org.apache.juli.logging.DirectJDKLog.log(DirectJDKLog.java:167)

at org.apache.juli.logging.DirectJDKLog.error(DirectJDKLog.java:135)

at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:274)

at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)

at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:433)

at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)

at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)

at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)

at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:286)

at org.apache.coyote.ajp.AjpAprProcessor.process(AjpAprProcessor.java:419)

at org.apache.coyote.ajp.AjpAprProtocol$AjpConnectionHandler.process(AjpAprProtocol.java:378)

at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1509)

at java.lang.Thread.run(Thread.java:619)

Apparently, not even the deployment of Sonar worked. Thus, you have to change your “catalina.sh” according to this article. Search for the JAVA_OPTS variable and add these parameters:

JAVA_OPTS=”-Dfile.encoding=UTF-8 -server -Xms1536m -Xmx1536m

-XX:NewSize=256m -XX:MaxNewSize=256m -XX:PermSize=256m -XX:MaxPermSize=256m -XX:+DisableExplicitGC”

The article cited above also suggests to add “-Djava.awt.headless=true” but that is not applicable for my case since I am running an X-Server on the same machine to perform automated UI tests.

3. Deployment

Now you can deploy your WAR file, e.g., via the Tomcat Manager application or just moving the “sonar.war” file to the webapps directory of you Tomcat installation.

4. Database Setup

After logging into Sonar for the first time, it asks for the Database Setup.

I created just the default integrated database. Performing this step took several seconds, but then Sonar was up and running!

5. First login

Just a hint (I had to look that up): The default password for user “admin” is “admin”.

After changing this password, you might run into 500 Internal Server errors. As Olivier from the Sonar developers pointed out, this is a known issue: SONAR-514. All you have to do is delete all session cookies and login again.

More Heapspace for JUnit tests on Hudson

Saturday, March 28th, 2009

At DFKI we are running Maven2 along with Hudson for Continuous Integration of our research prototype applications.

Recently, I recognized, that some tests were running fine when executed on my local machine as normal JUnit tests in Eclipse. But running a “mvn verify” on the same project with these tests brought Test errors for the same tests.

A look at the surefire reports in target/surefire-reports/ revealed that the errors were cause by Java OutOfMemory exceptions. In Hudson, they just look like this:

Error Message

Java heap space

Stacktrace

java.lang.OutOfMemoryError: Java heap space

I literally spent hours on playing around with MAVEN_OPTS in Eclipse and Hudson. None of these settings had any impact on the execution of the JUnit test by Maven.

Finally, I found out, that it is the maven-surefire-plugin which needs additional memory. The default configuration for surefire is inherited implicitly from the super pom. You have to override this config by adding this section to your project’s pom.xml:

</build>
</plugins>
</build><plugin>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Xmx512m</argLine>
</configuration>
</plugin>
</plugins>
</build>

The Continuous Integration Game

Thursday, February 12th, 2009

Patrick, one of our students at DFKI , has found a plugin for the Continuous Integration Server Hudson where you can get points for bugfixes, removal of ugly code fragments etc. After Hudson made us at least fix most of our old JUnit test errors, the might help to further improve the overall code quality.

The Continuous Integration Game plugin - hudson - Hudson Wiki 1234451034648

The Continuous Integration Game plugin uses the reports of existing source code checkers to calculate scores:

  • Checkstyle 1.9
  • Findbugs 2.11
  • PMD 1.9
  • Tasks 2.11
  • Warnings 1.8
  • Violations 0.5.4

Results are available online at the Leader Board.

Continuous Integration in MEDICO

Tuesday, February 10th, 2009

I am a fan of automatic quality assessment since I had been involved in software quality assessment in an internship in a small software company in Munich in 2001.

In the last two months we set up a number of components and services at DFKI for Continuous Integration. Now, our system looks like this:

ci

Part 1: Migrate the complete code base to Maven2

We are using Eclipse and Java. Thus the migration to Maven2 was rather straigtforward. Maven provides us with a declarative build and dependency management. Some of our software projects have dependencies to more than 100 external libraries. Before Maven, this resulted in a JAR hell of more than 100 JARs checked into our SVN, sometimes with conflicting versions.

In Maven, you just specify the direct dependencies to external libraries (in Maven’s terminology: “artifacts”). Maven then takes care to download them and even the transitive dependencies of them.

Part 2: Setup a common repository for Maven2 artifacts

We use Artifactory version 2 to store our own artifacts and cache artifacts from others.

Our artifactory is online at http://www.dfki.uni-kl.de/artifactory2/

screenshot-artifactory2

Part 3: Use SVN as a Source Code Management System

We use trac as an integrated Wiki, ticket and source code management system. All changes and commits are communicated via email to all project members.

screenshot-trac

Part 4: Hudson as a Continuous Integration server

Hudson continuously checks the SVN for changes. Whenever code has been changed, it checks out the latest version, runs all JUnit tests, creates reports about the code style, code coverage with JUnit tests, etc. and tries to build the application. If this fails, everybody gets an email with the error messages and the name of the user who commited the code that broke everything. ;-)

screenshot-hudson

I’ve already described the setup of the Continuous Integration server Hudson on Debian Linux. Our Hudson instance is available via internet: http://www.dfki.uni-kl.de/hudson/

Installing Hudson on Debian

Wednesday, January 28th, 2009

This post describes how to setup the continuous integration tool Hudson on a Debian Linux system.

1. Update your /etc/apt/sources.list.

You definitely need the non-free components which include the official Sun Java packages. Therefore you should have a line like the follwing in your /etc/apt/sources.list:

deb http://ftp.de.debian.org/debian/ etch main non-free contrib

2. Install JRE and JDK 1.6

On a root shell, type:

apt-get install sun-java6-jre sun-java6-jdk

3. Configure Debian to use exactly this version as the system-wide default

On a root shell, type:

update-alternatives -–config java
update-alternatives -–config javac

4. Install Tomcat

On a root shell, type:

apt-get install tomcat5.5 tomcat5.5-admin tomcat5.5-webapps

5. Make Tomcat listen on port 8080

The default for Tomcat on Debian is to start on port 8180. We want it to start on port 8080. Thus, you need to change your /etc/tomcat5.5/server.xml. In the section

<Connector port=”8180″ maxHttpHeaderSize=”8192″
maxThreads=”150″ minSpareThreads=”25″ maxSpareThreads=”75″
enableLookups=”false” redirectPort=”8443″ acceptCount=”100″
connectionTimeout=”20000″ disableUploadTimeout=”true” />
you have to replace “8180″ by “8080″.

6. Disable Tomcat’s security mechanism

Hudson brings it’s own security management system. The Tomcat security mechanism for wepapps block the startup of Hudson and have to be in /etc/default/tomcat5.5 disabled. Search for “TOMCAT5_SECURITY” and change the line to make it look like this:

TOMCAT5_SECURITY=no

Instead, you should configure Hudsons internal security management system.

7. Setup a home directory for Hudson

In a root shell, type:

mkdir /home/hudson

chown tomcat55:nogroup /home/hudson

8. Set Hudson’s home directory environment variable

Open /etc/init.d/tomcat5.5 and add this line:

export HUDSON_HOME=/home/hudson

9. Deploy the hudson.war via the Tomcat Manager

After this step, you should be able to log into Hudson via Web browser and start configuring via the web interface.

10. Install Maven2

On a root shell, type:

apt-get install maven2

Setup your MAVEN_HOME environment variable. Open /etc/init.d/tomcat5.5 and add this line:

export MAVEN_HOME=/usr/share/maven2/

Create a Maven2 home directory for Hudson. This has to be located in /usr/share/tomcat5.5/.m2. Execute the following commands on a root shell:

mkdir /usr/share/tomcat5.5/.m2

chown tomcat55:nogroup /usr/share/tomcat5.5/.m2

11. Install ant and junit

On a root shell, type:

apt-get install ant ant-optional junit

Setup your ANT_HOME environment variable. Open /etc/init.d/tomcat5.5 and add this line:

export ANT_HOME=/usr/share/ant

12. Install SVN access plugin for Hudson

Open via http://localhost:8081/hudson/pluginManager/available in a web browser and choose SVNCompat14 Plugin for installation. Please note: For me, the install stopped with this exception at the first time:

javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:190) at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1591) at …

But at the second try it ran through.