Jenkins StackOverflow Exception during JUnit Test

Problem

The build of a Maven job in Jenkins fails due to a StackOverflowException or a OutOfMemoryException during a JUnit test.

Analysis

Most likely, there is a bug in your application, which leads to infinite recursion or an infinite allocation in resources. So first try to run your test in a different environment (for instance in eclipse, directly through Maven or as plain Java application).

However, sometimes, as in my case, the application works correctly and just requires more memory/stack size than is provided by the JVM during default settings. In this case, you will need to adjust the JVM settings in order to allow for more memory/stack size.

Solution

The JVM parameters, which allow to allocate more memory or stack size to a JVM are:

1. 

-Xss(x)m

where x is the size of the stack you would like to use. For instance: -Xss4m for a 4 MB stack size.

2.

-Xmx(x)m

where x is the size of the Java heap space (=memory) you would like to use. For instance: -Xmx1024m for a 1024 MB heap space.

Unfortunately, there are multiple places in which these parameters can be configured. Essentially, if the increased heap space requirement is in your application, you will need to adjust the parameters for the JUnit test runner in Maven:


<plugin>
 <groupId>org.apache.maven.plugins</groupId>
 <artifactId>maven-surefire-plugin</artifactId>
 <version>2.12.4</version>
 <configuration>
 <argLine>-Xss18m</argLine>
 </configuration>
 </plugin>

However, if the adjusted parameters are required for building your application, you might have to adjust them for the Maven Build Process.

This can be done by adding the parameters to MAVEN_OPTS either:

  • for your job: [Your Job] / Configure / Build / Advanced / MAVEN_OPTS
  • or for the Jenkins instance: Jenkins / Manage Jenkins / Configure System / Maven Project Configuration / Global MAVEN_OPTS

The last possible culprit might be the Jenkins server itself.

You can set the JVM parameters for Jenkins either by specifying them when:

  • starting Jenkins through java [your JVM parameters here] -jar jenkins.war or
  • by editing the jenkins.xml in your JENKINS_HOME folder.

Resources

Increasing Memory of junit Testcases

Stackoverflow – Jenkins build fails after running Cucumber tests on Java heap space exception

Increase heap size in java

Stackoverflow – How to give Jenkins more heap space when it´s started as a service under Windows?

 

Maven Module for gwt-exporter

gwt-exporter is an awesome library to generate usable JavaScript APIs for Google Web Toolkit applications.

It allows writing powerful libraries in Java and reuse the features these libraries provide in JavaScript applications!

I have assembled a small Maven Module for gwt-exporter 2.4 (M1), which readily configures gwt-exporter to be used as part of an OSGi-enabled project. This is particularily useful, if one wants to develop using the excellent eclipse plug-in development platform (which is useful for far more than developing eclipse plugins).

The source code is hosted as part of the osgi-maven project: thrdGwtExporter24.

The Maven dependency and repository are as follows:

Dependency:


 <dependency>
 <groupId>de.mxro.thrd.gwtexporter24</groupId>
 <artifactId>thrdGwtExporter24</artifactId>
 <version>0.0.1</version>
 </dependency>

Repository:


<repositories>
 <repository>
 <id>onedb Releases</id>
 <url>http://dl.dropbox.com/u/957046/onedb/mvn-releases</url>
 </repository>
</repositories>

If you would like to use gwt-exporter in a vanilla Maven project (without OSGi), you can use the gwt-exporter artefact hosted on Maven central:


<dependency>
 <groupId>org.timepedia.exporter</groupId>
 <artifactId>gwtexporter</artifactId>
 <version>2.4.0-M1</version>
 <scope>provided</scope>
 <exclusions>
<exclusion>
<groupId>com.sun</groupId>
<artifactId>tools</artifactId>
</exclusion>
 </exclusions>
</dependency>

(The exclusion is necessary to avoid dependencies to the Sun/Oracle JVM.)

Restlet Quickstart

The Restlet framework is one of the possible options to provide Restful web services in Java. In many framework comparison, Restlet is criticized for being a little bit difficult to understand as well as to perform slightly worse than competing frameworks (e.g. Apache Wink, Jersey, …) (Sangeetha, 2011). However, Restlet is also a very flexible framework and it is very lightweight, in that it has very few dependencies to heavyweight components, for instance servlet containers. This enables Restlet to play nicely with a number of technologies including Google Android, Google App Engine and Google Web Toolkit applications.

The tutorials on the Restlet homepage appear to be a bit confusing and outdated. Therefore, I have assembled a little example to get started with Restlet in a few traceable steps.

Add Maven Dependency

Restlet offers a wealth of different editions and optional extensions and it is a little bit difficult to determine the right Maven dependencies. For this basic scenario, we want to run a little server deployed as local Java application. For this purpose, the ext.simple extension is required (here I use the latest milestone release 2.1-M7 – the examples should also work with later releases although this is not guaranteed)


<dependency>

<groupId>org.restlet.jse</groupId>

<artifactId>org.restlet</artifactId>

<exclusions>

<exclusion>

<groupId>org.osgi</groupId>

<artifactId>org.osgi.core</artifactId>

</exclusion>

</exclusions>

<version>2.1-M7</version>

</dependency>

<dependency>

<groupId>org.restlet.jse</groupId>

<artifactId>org.restlet.ext.simple</artifactId>

<version>2.1-M7</version>

</dependency>

In addition, the Restlet repository must be specified


<repositories>
<repository>
<id>maven-restlet</id>
<name>Public online Restlet repository</name>
<url>http://maven.restlet.org</url>
</repository>
</repositories>

<span style="color: black;">

Create a Small Standalone Server

If these dependencies are established, the following server can be implemented:


import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.resource.Get;
import org.restlet.resource.ServerResource;
import org.restlet.routing.Router;

public class RestletServerTest extends ServerResource {

public static void main(final String[] args) throws Exception {
// Create a new Component.
final Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

final Router router = new Router(component.getContext().createChildContext());

router.attach("/test", RestletServerTest.class);

// Attach the sample application.
component.getDefaultHost().attach("/restlet", router);

// Start the component.
component.start();
}

@Override
@Get
public String toString() {
return "hello, world";
}

}

Execute this application and open http://localhost:8182/restlet/test. You should see the message ‘hello, world’.

Provide a Domain Object

In order to provide a domain object, a few more steps need to be undertaken. First, we need to specify the domain object:


import java.io.Serializable;

public class Person implements Serializable {

private static final long serialVersionUID = 1L;

public String name;
public int age;

public Person(final String name, final int age) {
super();
this.name = name;
this.age = age;
}

}

Secondly, we need an interface and a ServerResource implementation for the service, which provides the domain object. The interface does not need to extend any other interface but must use the GET, PUT, DELETE annotations provided by Restlet.


import org.restlet.resource.Get;

public interface PersonResource  {

@Get
public Person retrieve();

}
<pre>

The ServerResource implementation must extend ServerResource and implement the interface PersonResource:


import org.restlet.resource.ServerResource;

public class PersonServerResource extends ServerResource implements PersonResource {

private static volatile Person person1 = new Person("Peter", 40);

@Override
public Person retrieve() {

return person1;
}

}
<pre>

Finally, the main routine starting the server needs to be altered. Also, a little client is added, which reads out the domain object from the server:


import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.resource.ClientResource;
import org.restlet.routing.Router;

public class RestletServerTest  {

public static void main(final String[] args) throws Exception {
// Create a new Component.
final Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

final Router router = new Router(component.getContext().createChildContext());

router.attach("/person", PersonServerResource.class);

// Attach the sample application.
component.getDefaultHost().attach("/restlet", router);

// Start the component.
final Thread t = new Thread() {

@Override
public void run() {
try {
component.start();
} catch (final Exception e) {
e.printStackTrace();
}
super.run();
}

};

t.run();

final ClientResource cr = new ClientResource("http://localhost:8182/restlet/person");

final PersonResource resource = cr.wrap(PersonResource.class);
final Person person = resource.retrieve();

System.out.println(person.name);

}

}
<pre>

The domain object is serialized using the Java Serialization mechanism. We can also navigate to http://localhost:8182/restlet/person using a web browser. However, only a binary file will be downloaded by the server. Restlet does provide extensions to provide the domain objects serialized as in RDF, XML and JSON format.

Emulate a RPC Call Using Domain Objects

Apart from reading domain (and writing using PUT) domain objects, Restlet can easily be used to implement a kind of remote procedure calls (RPC) or functionality similar to Java Remote Method Invocation (RMI). Such calls being made over Restlet do not only have the advantage of running cleanly over HTTP but are also rather performant when compared to remote invocations building on XML serializations (Java Serialization, although slow, is often faster than XML Serialization) such as used by XML-RPC or SOAP/WDSL based web services.

First we change the PersonResource Service description and define a POST service, which makes a copy of a person object.

import org.restlet.resource.Post;

public
interface PersonResource {

@Post
public Person copy(Person p);

    

}

Next we change the implementation of the service:

import org.restlet.resource.ServerResource;

public
class PersonServerResource extends ServerResource implements PersonResource {

    

    @Override

    public Person copy(final Person p) {

        return p;

    }

    

}

And finally change the main method. Note here too that here we run the server and client as part of a unit test (so add JUnit dependency to your pom). This highlights how easy it is to build (almost) fully blown integration tests based on Restlet, which in addition execute very fast.


import org.junit.Assert;
import org.junit.Test;
import org.restlet.Component;
import org.restlet.data.Protocol;
import org.restlet.resource.ClientResource;
import org.restlet.routing.Router;

public class RestletServerTest  {

@Test
public void test_server() throws Exception {
// Create a new Component.
final Component component = new Component();

// Add a new HTTP server listening on port 8182.
component.getServers().add(Protocol.HTTP, 8182);

final Router router = new Router(component.getContext().createChildContext());

router.attach("/person", PersonServerResource.class);

// Attach the sample application.
component.getDefaultHost().attach("/restlet", router);

// Start the component.
final Thread t = new Thread() {

@Override
public void run() {
try {
component.start();
} catch (final Exception e) {
e.printStackTrace();
}
super.run();
}

};

t.run();

final ClientResource cr = new ClientResource("http://localhost:8182/restlet/person");

final PersonResource resource = cr.wrap(PersonResource.class);
final Person originalPerson = new Person("Peter", 20);
final Person copiedPerson = resource.copy(originalPerson);

Assert.assertFalse(originalPerson == copiedPerson);

Assert.assertTrue(originalPerson.name.equals(copiedPerson.name));

System.out.println(copiedPerson.name);

}

}
<pre>

Resources

Restlet Documentation Hello World Application in JavaSE

Maven and Eclipse Indigo

It has been a while since the new release of the eclipse IDE, Indigo, has been released. One of the most interesting new features seems to be a better integration with Maven.

After some very unsuccessful attempts using eclipse IAM and the m2eclipse plugin, I became a bit sceptical of Maven integration into the eclipse IDE. In particular, I want to use the eclipse plugin development environment (PDE) alongside Maven, which seemed impossible at the time. At the moment, I use the eclipse:eclipse Maven Mojo to generate eclipse project files (with PDE support). The projects compile in eclipse and unit test etc run. Just for any Maven specific tasks, I need to change to the command line (eg deploying projects, changing dependencies between projects).

Now I have seen a few negative comments about the new Maven features in eclipse (see below). After spending a lot of time getting eclipse PDE and Maven working together well, I feel a bit anxious to change to eclipse Indigo.

Resources

Changing from m2eclipse to m2e (Eclipse 3.7 – Indigo)

Maven and Eclipse, Top Eclipse Indigo Feature #10 (critique in the comments)

Unit Tests in GWT (using Maven and eclipse PDE/OSGi)

One of the strengths of GWT, from my point of view, is that large portions of the code (eg business logic) can be tested with plain old JUnit tests, without the slightest interference from servers, web browsers and other constraints.

However, certain parts of the code must be tested in a richer context including the compiled java script or client/server communication. Luckily, the GWTTestCase provides a powerful tool to automate tests in such rich contexts.

Following a few pointers, of how these GWT unit tests can be setup in an environment using Maven and the eclipse PDE (the tests are not exactly using this technology but should be able to be part of a possible OSGi module).

  • Create a new gwt module (gwt.xml) in a dedicated package (eg gwttests) in the src/test/java folder such as the following. Make this unit inherit the modules, you want to test.

<?xml
version=“1.0”
encoding=“UTF-8″?>

<module
rename-to=‘nxservergwttests’>

    <!– Inherit the core Web Toolkit stuff. –>

    <inherits
name=‘com.google.gwt.user.User’
/>

 

    <!– Other module inherits –>

    <inherits
name=‘nx.servergwt.client.NxGwtClient’></inherits>

    <inherits
name=“com.google.gwt.junit.JUnit”
/>

 

    <!– Specify the app entry point class. –>

    <entry-point
class=‘nx.servergwt.tests.DummyEntryPoint’
/>

 

    <!– Specify the paths for translatable code –>

    <source
path=
/>

    

    <set-property
name=“gwt.suppressNonStaticFinalFieldWarnings”

        value=“true”
/>

 

</module>

  • Create a class in that package following the naming pattern: “GwtTest*.java”, let this class extend com.google.gwt.junit.client.GWTTestCase. Return a module name pointing to your module (gwt.xml file) for gwtModuleName()

public
class GwtTestClientServerCommunication extends GWTTestCase {

 

    @Override

    public String getModuleName() {

        return
“nx.servergwt.tests.NxServerGwtTests”;

    }

    

    public
void testNetworkOperations() {

        Network n = Nx.newNetwork();

        String root = “root”;

        Nx.put().node(root).inNetwork(n);

        Nx.append().node(“a string”).to(root).inNetwork(n);

        
 

                    assertTrue(Nx.check().ifNode(root).hasChild(Nx.instanceOf(String.class)).inNetwork(n));

    }

    

}

  • Now you should be able to run this test using “mvn gwt:test” (but make sure to check for the pitfalls below).

Some possible pitfalls

-No compilation unit found for test-

The GWT compiler might report that the class of the test case could not be found:

[INFO] com.google.gwt.junit.JUnitFatalLaunchException: The test class …’ was not found in module …; no compilation unit for that type was seen

In this case, there might be problem with the module (gwt.xml) file you have defined, for instance you forgot to declare “<source
path=
/>

 

-Need to manually open test case in browser-

When executing gwt:test, the maven gwt plugin (or the gwt compile) might report the following:

[INFO] Please navigate your browser to this URL:

[INFO] http://130.216.XX.XX:54530/&#8230;.JUnit/junit.html?gwt.codesvr=130.216.XX.XX:54526

This can be omitted by configuring the maven gwt plugin to utilize htmlunit to lunch a browser. Add the following to the pom.xml:

<plugin>

    <groupId>org.codehaus.mojo</groupId>

    <artifactId>gwt-maven-plugin</artifactId>


    <configuration>

        <htmlunit>IE8</htmlunit>

    </configuration>

    <mode>htmlunit</mode>

Now the tests should run without the need to open a browser manually (see Gwt Maven Plugin Parameters Mode)

 

-Access to junit.framework in eclipse PDE-

Eclipse PDE might report that: “Access restriction: The method assertTrue(boolean) from the type Assert is not accessible due to restriction on required library”

This can mitigated by adding the following dependency:

     <dependency>


<groupId>junit</groupId>


<artifactId>junit</artifactId>


<version>3.8.2</version>


<scope>test</scope>


</dependency>

As well as the following imported package in the configuration of the maven bnd plugin:

org.junit,

com.google.gwt.junit.client,

junit.framework,

After rebuilding the project with “mvn eclipse:clean clean package eclipse:eclipse -Declipse.pde -Declipse.useProjectReferences=false install” and refreshing the files in eclipse, the access restriction error should disappear.

 

-Calls to server Servlets result in 404 errors-

Some calls per RPC to Servlets on the server might result in 404 errors. In your original project, the Servlets could just be declared in the web.xml configuration. In order for Servlets to work in the GWT unit test, they must be declared in the gwt module definition (and here it is sensible to define them in the module you want to test rather than the ‘test’ module).

<servlet path=’/yourservletforrpc’ class=’com.yourpackage.Servlet’></servlet>

 

Resources

Gwt Maven Plugin Parameters Mode (set this to htmlunit)

Maven Gwt Plugin User Guide: Testing

GWT Developer’s Guide: JUnit Testing

 

“build.properties does not exist” and Maven Eclipse Plugin

The Problem

After generating an eclipse project using both the Maven Eclipse Plugin and the Maven Bundle Plugin (BND), eclipse warns that “build.properies does not exist”.

The Solution

Maybe more a workaround than a solution but it is relatively simple to create the build.properties file manually in the eclipse project. Below an example for a build.properties file for a Maven project, which should not result in any errors.

source.. = src/test/java,\


src/main/java/

 

“No required execution environment has been set” from Maven Bundle Plugin

The Problem

After generating the MANIFEST.MF with the Apache Felix Maven Bundle Plugin (BND) for an eclipse project, eclipse warns that “No required execution environment has been set”.

The Solution

The solution is to add an instruction to the configuration of the maven bundle plugin and explicity specify the execution environment as shown below.

<plugin>

                <groupId>org.apache.felix</groupId>

                <artifactId>maven-bundle-plugin</artifactId>

                <extensions>true</extensions>

                <configuration>

                    <instructions>

                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>

                        <Bundle-Version>${project.version}</Bundle-Version>

                        <Import-Package>${module.importedPackages}</Import-Package>

                        <Export-Package>${module.exportedPackages}</Export-Package>

                        <Service-Component>${module.serviceDefinitions}</Service-Component>

                        <Bundle-RequiredExecutionEnvironment>JavaSE-1.6</Bundle-RequiredExecutionEnvironment>

                    </instructions>

                </configuration>

            </plugin>