Static state and Maven build.

Recently I had to deal with a weird and occasional Maven build fails from different plugins failing with this same exception:

Caused by: java.lang.NullPointerException
at org.apache.http.impl.conn.SystemDefaultRoutePlanner.determineProxy(SystemDefaultRoutePlanner.java:79)
at org.apache.http.impl.conn.DefaultRoutePlanner.determineRoute(DefaultRoutePlanner.java:77)
at org.apache.http.impl.client.InternalHttpClient.determineRoute(InternalHttpClient.java:124)

Since it was only failing on my local box and subsequent build would run fine I kept on ignoring it until it started to constantly fail on our Jenkins box after I had to add a new plugin to one of our sub-project pom.xml.
First reaction was to blame on the new plugin, and it took me to totally wrong direction.

I finally decided to look at SystemDefaultRoutePlanner.java source code and discovered that it was accessing a static variable without null check. But why would this static variable be null?
The only explanation is that some plugin or unit test from previous project builds where setting it to null

Keep in mind that Maven by default will build all projects within a single JVM instance and one project build static state change will be reflected onto another project build.

After some online research I found that one of Maven sub project was using SOAPUI plugin for integration testing and it was setting that static variable to null and never reverting it back after the tests. And since the Apache HttpClient that SystemDefaultRoutePlanner is part of, is used by many plugins it was failing on the subsequent project builds when trying to download the new plugin that I mentioned earlier.

Currently there are defects against SOAPUI plugin and HttpClient around this problem. Here is the one for HttpClient: https://issues.apache.org/jira/browse/HTTPCLIENT-1766.

This is a good example to take extra precaution when calling static methods or setting global variables inside unit test that can not only break other unit test but also break maven build.
The best practice is to avoid altering static state in unit test, but if really needed you have to use Junit’s @After annotation that allows you to cleanup and revert any static state you might have altered inside your unit test (even if your unit test fails or throws exception).

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>