Friday, October 8, 2010

Improved JUnit support in NetBeans 7.0

The 7.0 release of NetBeans will extend the support for the JUnit framework addind the following functionalities (I'm told some of them can already be found on Eclipse):
  • The 4.8.2 release of the JUnit library has been integrated.
  • You can now run or debug a single test case (method) in a suite (class) from the editor context menu.
  • It's now possible to rerun only failed tests.
  • The filtering of the test results view was improved. It' now allowed to select the result states (passed, failed, error) which will be hidden in the result view.
  • The tabbed output was implemented for the test results view.
All the relevant informations can be found on the official NetBeans site.

Thursday, October 7, 2010

Don't forget the content type

In one of our legacy projects all web services were exposed through SAAJ servlets; having to expose a new one we opted for a newer JAX-WS style, also thanks to everything that NetBeans gives you right out of the box.

So we created a new Web Service (you can check this tutorial to see how it is done) and wrote all the tests and code we needed. Everything went fine, until we tried to test the whole project (which should be mandatory before you commit).

At this point some of our old tests failed, all reporting the same error:
SAAJ0532: Absent Content-Type
The offending code builds a message that we use to test the parser:
private SOAPMessage buildMessage(String filename) throws IOException,  SOAPException {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(basepath + filename);
MessageFactory messageFactory = MessageFactory.newInstance();
SOAPMessage message = messageFactory.createMessage(new MimeHeaders(), resourceAsStream);
return message;
}
At first it caught me off balance because our additions and changes went nowhere near the code related to the failure. Then it must be something related to the environment, which is the fact that NetBeans added a dependency on the JAX-WS 2.1 library that probably has some conflicts with the SOAP jars we use.

As some manual tests seemed to confirm that the application is working normally, we deferred the investigations (not for very much longer!) and simply fixed the test:
private SOAPMessage buildMessage(String filename) throws IOException,  SOAPException {
InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(basepath + filename);
MessageFactory messageFactory = MessageFactory.newInstance();
MimeHeaders headers = new MimeHeaders();
headers.addHeader("Content-Type", "text/xml");
SOAPMessage message = messageFactory.createMessage(headers, resourceAsStream);
return message;
}
And now an afterthought. The test failed, yet the application did not. Does this mean our test was wrong? Actually it only means that the previous library was more forgiving, because the test has proved useful for a long time (also spotting a regression). It is better to have a not-so-perfect test than none at all.

Wednesday, October 6, 2010

InfoQ: Technical Debt a Perspective for Managers

Another interesting article on technical debt; the most important thing that emerges is that management must buy and support the need for getting rid of it.

The price you pay for technical debt is not on the barrelhead: it's all an hidden cost, and it grows in a non-linear manner with time. Think about it.

Monday, September 27, 2010

Nemo propheta in patria

I wonder why, when they have a subject matter expert close at hand at no cost, people almost always go looking for (very expensive) perfect strangers to (try and) solve their problems.

On repositories

I was writing code for a (actually not so) massive data export in a legacy application and I needed to retrieve all objects of a certain type modified after a given date, so I started writing a repository.

The simplest test that came into my mind was something like this:
@Test
public void queryingWithDateInTheFutureReturnsEmptyList(){
DateTime tomorrow = new DateTime().plusDays(1);
List<MyObject> result = instance.findModifiedAfter(tomorrow);
assertTrue(result.isEmpty());
}
Some clickety-clack (SHIFT+CTRL+I, ALT+SHIFT+F, CTRL+s, CTRL+F6 for the most curious) and NetBeans gives me a red bar. That's good as there's no code yet :-)

The first implementation was really too easy to write it, but as a very few people believe I work this way and all the rest think I'm wasting time I'll publish it anyway, saving my opinion for another occasion:

public List<MyObject> findModifiedAfter(DateTime startDate){
return Collections.emptyList();
}
So far, so good. Now, in the framework used in this project all persistent objects inherit from MyPersistenceObject (names have been changed to protect the innocents), which is a sort of Active Record with a hint of Row Data Gateway. Persistent object may also be managed by a MyPersistenceObjectController object, which is a sort of DAO that also manages transactions. Should you wonder, the class is not a controller at all, but the original developers thought that the name would fit. Before we go on, let me say that the framework works pretty well under many circumstances.

Not having a dedicated database that gets populated for each test end cleaned afterwards (did I mention the fact that this is a legacy application?) the next test tried to retrieve some data:

@Test
public void queryingSinceLastMonthReturnsAtLeast5kObjects(){
DateTime lastMonth= new DateTime().minusMonths(1);
List<MyObject> result = instance.findModifiedAfter(lastMonth);
assertTrue(result.size() > 5000);
}

I know it's not great, and that it breaks if someone truncates the corresponding table, but we must start from somewhere, right? Reading the tests also suggests that the method should probably be named findModifiedSince, but that is hardly the point now - even if it shows another useful feature of writing tests.

A little lookup on the existing code easily gave me a first implementation based on the "glorious" copy-paste-fix pattern:

public List<MyObject> findModifiedSince(final DateTime date) {
if (date == null || date.isAfterNow()) {
return Collections.emptyList();
}

try {
Object[] values = new Object[]{date.getMillis()};
String[] orderBy = null;
Criteria criteria = new Criteria("tms", "MyObjectImpl");
SimpleCondition simple = new SimpleCondition("tms", SimpleCondition.GE);
criteria.add(Criteria.NOP, simple);
Vector objects = new MyObjectImpl().retrieveByAlternateKey(
criteria,
values,
orderBy);
List<MyObject> result = new ArrayList<MyObject>();
result.addAll(objects);
return result;
} catch (Exception ex) {
return Collections.emptyList();
}
}
Clickety-clack, CTRL+F6...

...
...
(yawn)
...
...
(wtf?)
...
...

Green bar. After an insane amount of time. A little logging informed me that the test took 16 seconds to run, excluding the time needed to start and stop the persistence container.

A little profiling confirmed that also the memory usage grew abnormally. And all this for a little more than 6000 objects...

Now, to quote Eric Evans, a repository is

...an object that can provide the illusion of an in-memory collection of all objects of that type.

Well, this framework cannot provide that illusion, at least not whithout freezing everything else. I must admit that lately I was quite in clover, as using Hibernate I could simply write the very same method like this:


public List<MyObject> findModifiedSince(DateTime date) {
return HibernateUtil.getSession().
createCriteria(MyObject.class).
add(Restrictions.ge("tms", date)).
setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY).
list();
}
and get my list, which is actually a list of proxies, in about no time. Now Evans says that repositories

...return fully instantiated objects or collections of objects whose attribute values meet the criteria, thereby encapsulating the actual storage and query technology.

Proxies are not exactly fully instantiated objects, but as they pretend to be I'm prepared to live with that :-)

At this point all I could do was to revert to the old give-me-the-ids-and-I'll-get-the-objects-myself :-(

Friday, September 24, 2010

More on classloaders

As an update for my post on classloaders, PMD informs me that in J2EE I should use
Thread.currentThread.getContextClassloader()
My bars are green, a manual end-to-end test makes my testers happy, so this will be our preferred syntax from now on.

Tuesday, September 21, 2010

NetBeans dependent project in Hudson

While configuring a Hudson job for the single project of ours which still hadn't one I had some problems, as it is a NetBeans project that depends on other NetBeans projects. That is not a problem per se, as everything has run as smooth as silk for years on each and every developer's machine.

When run on the CI server, the build reported this error:

BUILD FAILED
C:\HudsonWorkspace\.hudson\jobs\myProject\workspace\myProjectFolder\NBProject\nbproject\build-impl.xml:558: Warning: Could not find file C:\HudsonWorkspace\.hudson\jobs\myProject\workspace\myOtherProject\dist\myOtherProject.jar to copy.

Unwilling to give up the "depend on project" feature on NetBeans (my colleagues would skin me alive), I investigated a little. Once you know where to look, everything seems quite easy, and as a matter of fact it is.

The dependency is defined, as you would expect, in the project.properties file, where you can find something like this:

project.myOtherProject=../../myOtherProject
reference.myOtherProject.jar=${project.myOtherProject}/dist/myOtherProject.jar

In practice, the first line defines where the other project is while the second defines where to find the relative jar file.

All you have to do is then override these properties in the job configuration in Hudson, either using the path relative to the build.xml file or using the absolute path of the referenced project on the Hudson server.

Now you have no more excuses... :-)