Friday, October 15, 2010

Meet Dozer

Integration between systems is one of the most typical reasons of failure in complex projects. Yet, we find ourselves doing it day after day, so after some strategic mapping you have to get your hands dirty and map your wonderful objects to that incredible garbage other vendors still insist to call code. Or was it the other way round?

Let's assume a simple interaction via web services exposed on, say, an i-Series platform. I don't know whether all RPGLE programmers work in the same way, but almost all services of that kind I've seen so far have a single port with a thousand parameters for a hundred of different purposes and it is up to you to try and understand which of them must be used in which occasion. If that was not enough (and for me it is) it seems there is a contest for the use of the most cryptic parameter names, for which vowels seem to be banished and six characters is considered more than ehough (when not a waste of space).

One of the many things you learn with DDD is that code should be as close as possibile to your mental representation of the domain: well, LDLSDC does not make me think of a list of documents, but maybe it's my fault.

That said, before I use those objects in my code I'll have to convert them. The typical mapper has a signature similar to the following one:
public MyObject convert(YourObject yours, MyObject mine)
or
public MyObject convert(YourObject yours, MyObject.class)
The implementation is normally something like this:
myObject.setPropertyOne(yourObject.getPropertyOne);
myObject.setPropertyTwo(yourObject.getPropertyTwoButHasDifferentName)
(repeat ad lib for each property to be mapped)

This is very frustrating and most of all error prone. This is where several libraries step forward, most of them based on reflection, each of them having pluses and minuses. So far, the most interesting one I've found is Dozer, a bean to bean mapper that recursively copies data from one object to another (of a different type, of course! where would the fun be otherwise?). By the way, integrating different systems is just one of many reasons you have for mapping between different objects.

Using Dozer is just as easy as downloading the jar file, adding it to the classpath (don't forget the dependencies!) and coding right away:
Mapper mapper = new DozerBeanMapper();
Destination destination = mapper.map(source, Destination.class);
(almost utterly copied from the official tutorial). That's it. All fields with the same name are automagically mapped, with Dozer taking care of the necessary conversions (at least the more common ones). Should you need to customize mappings you may add some xml files that define how Dozer should behave:
<?xml version="1.0" encoding="UTF-8"?>
<mappings xmlns="http://dozer.sourceforge.net"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://dozer.sourceforge.net
http://dozer.sourceforge.net/schema/beanmapping.xsd">

<configuration>
<stop-on-errors>true</stop-on-errors>
<date-format>MM/dd/yyyy HH:mm</date-format>
<wildcard>true</wildcard>
</configuration>

<mapping>
<class-a>yourpackage.yourSourceClassName</class-a>
<class-b>yourpackage.yourDestinationClassName</class-b>
<field>
<A>yourSourceFieldName</A>
<B>yourDestinationFieldName</B>
</field>
</mapping>

other custom class mappings would go here.......

</mappings>
And this is copied from the official manual.

You can also introduce a custom converter that you can reuse through your application:
<converter type="org.dozer.converters.TestCustomConverter" >
<class-a>org.dozer.vo.CustomDoubleObject</class-a>
<class-b>java.lang.Double</class-b>
</converter>
and its corresponding class:
public class TestCustomConverter implements CustomConverter {

public Object convert(Object destination, Object source, Class destClass, Class sourceClass) {
if (source == null) {
return null;
}
CustomDoubleObject dest = null;
if (source instanceof Double) {
// check to see if the object already exists
if (destination == null) {
dest = new CustomDoubleObject();
} else {
dest = (CustomDoubleObject) destination;
}
dest.setTheDouble(((Double) source).doubleValue());
return dest;
} else if (source instanceof CustomDoubleObject) {
double sourceObj = ((CustomDoubleObject) source).getTheDouble();
return new Double(sourceObj);
} else {
throw new MappingException("Converter TestCustomConverter used incorrectly. Arguments passed in were:" + destination + " and " + source);
}
}
}
And now a personal reminder: if you have to map an array of objects, but you know the types that you will find in specified positions AND want to avoid class cast exceptions (and I guess you do), you can use this syntax:
<field>
<a>myObjects[0]</a>
<b>other.propOne</b>
<a-hint>java.lang.Long</a-hint>
</field>
<field>
<a>myObjects[1]</a>
<b>other.propTwo</b>
<a-hint>java.lang.Short</a-hint>
</field>
Next thing I'm gonna try is the mapping for POJOs and JAXB objects...

Spiderman busted!

This is the revenge of J.Jonah Jameson...


The picture is one of the most beautiful ones shot by Los Angeles Times Photographers in 2009; find the others here.

Tuesday, October 12, 2010

InfoQ: Agile Team Meets a Fixed Price Contract

I found another interesting article on fixed price contracts managed in an agile way. It also adds some considerations on budget spent, which you don't normally find in articles of the same kind.

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.