Monday, May 18, 2009

AspectJ for Java logging: suppressing System.out debugging calls - part 7

We have all been there, adding a few System.out calls here and there to our Java code during development to help debug something that defies (bad) logic.

It seems all too common to, ahem, leave some of those calls behind, which introduces several problems in a product. Don't we love to see the occasional "WE ARE HERE!!" graffiti in the server console, or a 50MB trace file that cannot be opened by any text editor?

One way to prevent this problem is to continuously demand that developers pay attention to it, either deleting the offending statements or converting them to a Logger.log call. That approach also has drawbacks in that mistakes are, well, mistakes. A complementary approach to pleading with developers is to intercept the requests to System.out and System.err and route the "println" commands to a trace call.

Here are the changes to the Logging serviceability aspect. I still want to find a way to use the name of method calling System.out.println in the trace calls, but for now, here are the interesting bits:

...

public aspect Logging pertypewithin((my..*) && !Exception+){

/**
* Trace handler for each type.
*/
private static Logger trace = Logger.getLogger("my.project" ) ;

private static TracePrintStream sysoutTrace = null;

...

/**
* After the initialization of all classes in this project.
*/
after(): dcofpClassInitializer() {
String classname = thisJoinPointStaticPart.getSourceLocation()
.getWithinType().getName();
classname = LoggingUtil.normalizeClassName(classname);
trace = Logger.getLogger(classname);
sysoutTrace = new TracePrintStream(trace, "System.out", System.out);
}

...

/**
* Replace calls to SystemOut with trace calls
*/
PrintStream around(): dcofpSystemOutPrintln() {
return sysoutTrace;
}

...

/**
* Inner class used to convert System.out.println calls to trace calls.
*/
public class TracePrintStream extends PrintStream {
...
public void println(String str) {
trace.logp(Level.FINER, trace.getName(), method, str);
}
...
}
}

Tuesday, May 12, 2009

Generated Java-XML bindings and external builders in Eclipse

Our project is using the Apache XMLBeans tool to bind XML schemas to Java code.

One possibility to deal with the bindings is to generate them on a local machine and check in the generated code. The drawback is that people maintaining the code need to deal with all sorts of file operations for things as simple as a namespace change. The Java bindings wiggles at the will of its source XSD file, so that checking it in is not far from checking in a generated JAR or WAR file.

The other possibility is to generate the code during build time, using the xmlbean ant task, which would be sort of annoying for developers using the Eclipse environment. Whenever the project was imported anew from the source control system, they would have to first invoke the generation target and then refresh their workspace.

It turns out Eclipse has a great solution for this, in the form of a project builder.


I created a new builder, which invoked the correct ant target every time a developer used "clean" or "build".

That was it for the easy part. The next trick was to make the Ant target as efficient as possible, since it would be impractical for developers to wait several seconds for the "xmlbean" task completion every time they did something as simple as updating an unrelated Java source file.

That is when the Ant conditional targets come in handy. It was only a matter of setting a property if the files had never been generated or if the source XSD file was updated after they had been generated.

<property name="xmlbean.javac.optimize" value="on" />
<property
name="xmlbean.verbose" value="false" />
<property
name="xmlbean.quiet" value="true" />
<property
name="design.info.schema" value="${dir.schema}/DesignInfo.xsd" />

...

<condition property="xmlbean.designinfo.updated">
<or>
<not>
<available
file="${dir.build.xml.classes}" />
</not>

<uptodate targetfile="${design.info.schema}">
<srcfiles
dir="${dir.build.xml.classes}" />
</uptodate>
</or>
</condition>

 

<target name="genxmlbeans.designinfo" if="xmlbean.designinfo.updated">

<xmlbean schema="${design.info.schema}"
classgendir="${dir.build.xml.classes}"
classpathref="class.path"
failonerror="true"
optimize="${xmlbean.javac.optimize}"
verbose="${xmlbean.verbose}"
quiet="${xmlbean.quiet}" />

</target>

Monday, May 4, 2009

DDTUnit snippet to represent a HashMap containing complex objects

As a big fan of DDTUnit for Java unit testing, this gets me every time. I often need a java.util.HashMap object with complex values. Here it is for posterity (and later lookup) :

    <obj id="masterResults" type="java.util.HashMap" 
hint="map" keytype="string" valuetype="com.company.project.LogFileResult">
<item>
        <key type="java.lang.String">
            data/com.com.company.project.custom/config/Lotus/Domino/nl/example.log
</key>
            <value type="com.company.project.LogFileResult" hint="call"
                   method="constructor">
</value>

        </item>
    </obj>






The Java code to retrieve it inside the DDTUnit fixture:







    HashMap masterResults = (HashMap) getObject("masterResults");