Archive for August, 2006

Where Are Your Log4j Log Files?

Monday, August 28th, 2006

Although you can configure Log4j programmatically, it’s far more common to put log4j.properties or log4j.xml in your classpath to trigger autoconfiguration. But one problem that I always have is specifying the location of my log files. From what I can tell, these are your options:
(more…)

In Defense of Protected Variables

Saturday, August 26th, 2006

Yakov Fain argues at JavaLobby that there’s no good use for protected variables, even going so far as to ask in a comment response

If someone decides to create a brand new object-orient programming language, should s/he even include the keyword protected there?

This seems surprisingly naive from someone with Yakov’s experience. We need more access levels in Java, not fewer. It’s a huge pain that protected variables are also package-default, and there’s no friend concept like in C++. But that’s a rant for another day.

I often put a line like this in an abstract base class:

protected transient final Logger _log = Logger.getLogger(getClass());

Then all subclasses get logging for free – no need to build up a logger instance because it’s already done for you. I could have made the field private and created a protected accessor – getLogger() – but why bother?

It’s not static, so I can use the runtime class (getClass()) instead of hard-coding the base class, e.g.

protected transient static final Logger LOG = Logger.getLog(BaseClass.class);

This would be very bad – all subclasses would log as “BaseClass” and reading log files I wouldn’t know what subclass was actually sending the message.


Protected fields are great for constructor parameters that are used by the class and subclasses but aren’t part of its public API, e.g.

protected final Parser _parser;
protected final Helper _helper;
...
protected BaseThing(Helper helper, Parser parser) {
  _parser = parser;
  _helper = helper;
}

In this case I could make the fields private with protected accessors, but again, why bother? And I certainly wouldn’t automatically make a public accessor for them, unless the design requires it. If I only need these objects for internal use, why publish them? If they’re not immutable, then I’d need to make defensive copies even though they’re final. All huge overkill for class/subclass-internal fields.

To address the specific concern of Yakov’s original post, it looks like there’s a disconnect between what the framework developers and Yakov consider public data. Either they were overzealous in hiding access, or Yakov is misusing the API in ways not intended by the original design. It’s impossible to know because he didn’t cite the actual code or even the framework that he’s talking about. So this is more of a generic defense for protected methods and variables. They’re very useful in some cases, and not applicable in others. So if you don’t understand this or have no use for them, don’t use them.

Schadenfreude – “Pleasure taken from someone else’s misfortune”

Thursday, August 17th, 2006

Misfortune in this case being an inability to write decent Java code. I recently quit a side project that I spent a great deal of time on. I wrote most of the original application prototype code and I have to admit it was fun for a while. The pay was good, but it got to the point where the lack of direction and general cluelessness of the project got too irritating, so I left. I still have access to the source code repository, so I update about once a day and take great pleasure in seeing the team’s flailing (and unbelievably slow) attempts at implementing features.

So in the spirit of The Daily WTF, The BileBlog, and general schadenfreude, here’s some fun nuggets from the code base that have been added since I left (no particular order).
(more…)

Some New Features in Eclipse 3.2

Thursday, August 10th, 2006

In no particular order, some features that I’ve noticed but don’t remember seeing in the documentation:

  • When you open a closed project it asks if you also want to reopen referenced projects
  • Package Explorer filtering has an option to filter project libraries
  • There’s a Heap monitor widget with a GC button – Window|Preferences|General|Show Heap Status (there are plugins for this but it’s nice to have it as part of the IDE)
  • If you type a semicolon inside a string it inserts it in the string, not at end of line (assuming you have semicolon auto-insert on)
  • Ctrl-Shift-C (comments out the selected text) now works in Linux. That’s been annoying, having switched from Windows (and still using Windows at work). I use a lot of keyboard shortcuts and losing one is frustrating.
  • Typing ${ in the Ant editor autocompletes build properties and it even shows the currently resolved value for the property.
  • An autogenerated default implementation of a method override now inserts a “non-Javadoc” @see comment in addition to the @Override annotation, e.g.
/* (non-Javadoc)
 * @see java.lang.Object#toString()
 */
@Override
public String toString() {
  // TODO Auto-generated method stub
  return super.toString();
}

Autoboxing and Null Pointer Exceptions

Thursday, August 10th, 2006

Updated 08/16/2006: Check out the discussion about this post on The Serverside.


I spent a while earlier today debugging a very small block of code that was throwing a NPE. There were few options for instances that could be null, but since I was looking in the wrong place for the problem, it took longer than it should have to fix.

I wrapped each method call on a potentially null object with null checks but it was still failing, and finally I realized what was going on. I was storing ints as values in a Map, e.g.

Map<Integer, Integer> cycleAreas = ...
for (Cycle cycle : cycles.values()) {
  Area area = _areaDao.create(new Area(
    analysis, tube, cycle, target,
    cycleAreas.get(cycle.getCycle()), creator));
  areas.add(area);
}

The exception occurred in the 3rd line, so either cycleAreas or cycle could be null (not really, but I added tests anyway).

Since you can’t use a primitive as a key or value in a Map, you just use autoboxing and use the associated non-primitive instead. But in this case the Map might not be fully populated, so it took a few iterations to find a case where there was no area for a given cycle.

Under the hood when you autobox and treat an Integer as an int or vice versa, the compiler inserts a call to intValue() or Integer.valueof(). Since the Integer value was null, calling intValue() blew up. For a more straightforward example, consider this code:

Integer z = 5;
Integer i = null;
int j = i;

It will fail at the last line with a NPE. It’s more obvious why if you use a decompiler on the class file:

Integer z = Integer.valueOf(5);
Integer i = null;
int j = i.intValue();

Object-Oriented Ant Build Files

Monday, August 07th, 2006

Powerful features in Ant 1.6 including presetdef, macrodef, and import make it simple to keep common tasks in common locations and simplify the creation of a project’s build script. Further, although Ant scripts are not programs in the traditional sense, these features do allow quasi-OO techniques.

These aren’t new features – Ant 1.6 was released almost three years ago – but it’s always good to be reminded of cool features.

Build files for Java projects tend to contain the same core sets of actions:

  • compile source classes
  • compile test classes
  • run unit tests
  • build javadoc
  • package files into JARs, WARs, EARs, etc.

I find that using Spring and Hibernate in many projects I also generate Hibernate *.hbm.xml files using XDoclet, and I’m also starting to formalize best practices for running test coverage and generating quality metrics as part of the continuous build process, so I’m adding the common elements of those tasks also.

PresetDef

PresetDefs allow you to set default values and even default child elements in existing targets. For example, here’s my PresetDef for the copy target:

<presetdef name='def.copy'>
  <copy preservelastmodified='true' includeEmptyDirs='false' />
</presetdef>

I can override either preservelastmodified or includeEmptyDirs when I call def.copy, but if I leave those attributes out the default values are used. This is essentially like having a protected accessor in a base class.

PresetDefs can contain default child elements too, for example:

<presetdef name='def.junit'>
  <junit
    fork='true'
    haltonfailure='${test.haltonfailure}'
    haltonerror='${test.haltonerror}'
    printsummary='true'>
    <formatter type='plain' usefile='false' />
    <formatter type='xml' />
  </junit>
</presetdef>

In this case I’m defaulting to fork the jvm for testing, I’m using build properties to specify whether to fail the build on error or failure, and I’m including two formatters, one to stdout and one to an XML file.

Declaring a PresetDef creates a new pseudo target whose XML element name is the name attribute.1 Here’s a simple target that’s used in conjunction with compiling Java source; typically you’ll want to copy all non-Java resources from the source path to the class path, e.g. image files, property files, etc. after compiling:

<target name='copy.resources' depends='prepare'>
  <def.copy todir='${dir.classes.src}'>
    <fileset dir='${dir.src}' excludes='**/*.java'/>
  </def.copy>
</target>

In this example I’m using def.copy primarily because I want to maintain the modification date of the files. This wouldn’t make sense if I were changing the file while copying it (e.g. if I were replacing tokens) but I do want to preserve dates in this case so I know that the correct versions of the files were copied.

MacroDef

The primary motivation for adding MacroDef to Ant was to avoid the cost of AntCall. For small projects you probably wouldn’t notice the time and resource costs of AntCalls but for a large and complex project, reloading/reparsing the build script and reinitializing everything can slow down a build significantly. So MacroDef was added to address the need to perform common sequences of tasks with parameter passing, similar to calling a method in a programming language, but in a lightweight fashion.

Here’s a sample MacroDef for running JUnit tests. This one is fairly simple with just two subtasks – running the tests and generating HTML reports from the XML formatter output. There are two attributes, maxMemory (with a typical default value) and report.dir, and two required child elements filesets and classpathElements:

<macrodef name='unitTest'>
  <attribute name='maxMemory' default='-Xmx256m'/>
  <attribute name='report.dir' />
  <element name='filesets' optional='false' />
  <element name='classpathElements' optional='false' />
  <sequential>

    <def.junit>

      <classpath>
        <classpathElements />
      </classpath>

      <jvmarg value='@{maxMemory}' />

      <batchtest todir='@{report.dir}'>
        <filesets />
      </batchtest>
    </def.junit>

    <junitreport todir='@{report.dir}'>
      <fileset dir='@{report.dir}'>
        <include name='TEST-*.xml' />
      </fileset>
      <report format='frames' todir='@{report.dir}' />
    </junitreport>

  </sequential>
</macrodef>

attributes and elements allow simple and complex ‘parameter’ passing. An attribute is a string parameter, like a property, except that the syntax for resolving its value uses an ‘@’ instead of ‘$’ to avoid collisions with build properties. elements allow you to pass entire XML elements (arbitrarily complex) into a MacroDef. Note that Ant does validate the usage and the build will fail if non-optional child elements are missing.

Here’s a sample usage of this MacroDef:

<target name='def.test'
  depends='def.clean, xdoclet.hibernate, def.compile.tests'
  description='run all unit tests'>

  <delete dir='${dir.testresult}'/>
  <mkdir dir='${dir.testresult}'/>

  <unitTest report.dir='${dir.testresult}'>
    <filesets>
      <fileset dir='${dir.test}'>
        <include name='**/*Test.java'/>
        <exclude name='**/Base*Test.java'/>
      </fileset>
    </filesets>
    <classpathElements>
      <path refid='classpath.test'/>
      <pathelement location='${dir.classes.test}'/>
    </classpathElements>
  </unitTest>

</target>

And to see how Ant inserts default values from the PresetDef and parameters from the MacroDef, here’s the equivalent Ant code not using PresetDef or MacroDef:

<target name='def.test'
  depends='def.clean, xdoclet.hibernate, def.compile.tests'
  description='run all unit tests'>

  <delete dir='${dir.testresult}'/>
  <mkdir dir='${dir.testresult}'/>

  <junit
    fork='true'
    haltonfailure='${test.haltonfailure}'
    haltonerror='${test.haltonerror}'
    printsummary='true'>

    <formatter type='plain' usefile='false' />
    <formatter type='xml' />

    <classpath>
      <path refid='classpath.test'/>
      <pathelement location='${dir.classes.test}'/>
    </classpath>

    <jvmarg value='-Xmx256m' />

    <batchtest todir='${dir.testresult}'>
      <fileset dir='${dir.test}'>
        <include name='**/*Test.java'/>
        <exclude name='**/Base*Test.java'/>
      </fileset>
    </batchtest>
  </junit>

  <junitreport todir='${dir.testresult}'>
    <fileset dir='${dir.testresult}'>
      <include name='TEST-*.xml' />
    </fileset>
    <report format='frames' todir='${dir.testresult}' />
  </junitreport>

</target>

As with any code reuse strategy (e.g. base classes or JSP includes) the biggest benefit is centralization. If you copy and paste and need to make changes in the common code, you need to find all instances and make multiple identical changes, risking missing some. But with intelligent code reuse, when you change the code in the base class or included file, or for Ant build files in a PresetDef or MacroDef, and all users immediately see the changes.

Import

So you’ve created a bunch of useful PresetDefs, MacroDefs, Targetss, etc. but how do you use them in your various build scripts? Ant build files are just XML, so the traditional way was to use entity includes. This basically worked but was very inflexible. In Ant 1.6 you can use import to intelligently include a partial or complete build script. It’s intelligent inclusion because you can redefine (override) targets or other elements and you can even continue to use or call the overridden versions.

Here’s a complete sample build script for a project called ‘common’ that contains shared code common to many projects. It imports a file called standard.ant2 located here, which contains the above examples and a few other targets, paths, and property definitions:

<?xml version='1.0' encoding='UTF-8'?>

<project name='common' basedir='.' default='jar'>

  <!-- optional properties file for developer overrides -->
  <property file='build.properties' />

  <import file='standard.ant' />

  <target name='xdoclet.hibernate'
    description='generates hibernate descriptors'
    depends='def.compile.java'>

    <xdocletHibernate>
      <classpathElements>
        <fileset dir='lib/xdoclet/'>
          <include name='*.jar' />
        </fileset>
        <path refid='classpath.libdir' />
      </classpathElements>
      <filesets>
        <fileset dir='${dir.src}' includes='**/model/**/*.java' />
      </filesets>
    </xdocletHibernate>

  </target>

  <target name='jar'
   depends='def.clean, xdoclet.hibernate, def.compile.tests'>

    <jar jarfile='build/common.jar'>
      <fileset dir='${dir.classes.src}' />
      <fileset dir='${dir.classes.test}' />
    </jar>
  </target>

  <target name='init.dependencies' depends='check.javadoc.uptodate'/>

  <target name='javadoc'
    depends='prepare'
    unless='javadoc.uptodate'
    description='Build Javadoc'>

    <delete dir='${dir.javadoc}' />
    <mkdir dir='${dir.javadoc}' />

    <def.javadoc doctitle='Common'/>
  </target>

  <target name='test' depends='def.test' description='Run unit tests' />

  <target name='all' depends='jar, test, javadoc' description='Run unit tests' />

</project>

This is a pretty small build file considering what it does. If you run the all target it will do the following:

  • delete the previous build directory
  • compile Java source
  • compile test Java source
  • generate Hibernate .hbm.xml descriptors for classes in any package whose name contains “model”
  • build a JAR file with source and test classes (to include reusable test base classes), Hibernate descriptors, and all other non-Java resouces in the src and test directories
  • run unit tests
  • generate HTML reports from JUnit XML formatter output
  • build Javadoc

This certainly isn’t all that apparent just by looking at the build script, but that’s a side effect of any code reuse.

Note that Ant properties cannot be changed once they’ve been set, so the statement order is important. First a build.properties file is loaded (if it exists) to give the developer a chance to set custom values. Then standard.ant is imported and any property values that weren’t set from the command line via -D parameters or in build.properties are set.

So you can see that it’s quite simple to extract common build functionality into libraries of reusable components to very quickly create build scripts with significant functionality, with only a minimum of customization. Even the sample build script that I’ve show could be a lot smaller if all projects have the same basic structure (one Java source directory in src/, one test directory in test/, JARs in lib/, etc.). You could easily push even more than I have into standard.ant (and other included files) and have build scripts that contain little more than the title for your Javadoc and the name of your JAR file.

  1. Note that the naming convention of prefixing “def.” to the PresetDef is mine and not a requirement of Ant.[back]
  2. My naming convention for Ant includes is to use “ant” as the file extension to differentiate between including build.xml files and included *.ant files[back]

Developer work environments

Thursday, August 03rd, 2006

This Joel on Software article about developers’ work environments reminded me about a humorously titled but serious blog entry Top 10 Ways to Motivate Geeks from a couple of weeks ago. Both got me thinking about my current situation.

I work at a small biotech startup that was originally in Providence, RI but moved around the first of the year to an office park in Mansfield, MA. It’s closer but still a long commute from Boston, so work from home when practical. It’s not a software shop so I’m support staff (and the only developer at the company), and I go to the office when the scientists need me there or when I need to work with them directly on a feature. I do end up in the office way more than necessary though – it’s hard to estimate when personal interaction will be necessary – but I find most days I go to the office I don’t interact with anyone except socially.

Our management isn’t particularly experienced with small companies or startups, so their approach is more traditional, tending to take more of a big-company approach than a more agile, small-company one. And they certainly leased big-company-style office space, with individual offices for the managers and cubeland for the rest of us.

I’ve worked in a pretty wide range of environments. I did one 6-month stint at a financial services company in downtown Boston where even though I never saw customers, I was still required to wear a suit and tie to work every day. I’m still amazed that I did that – I don’t even wear suits to interviews – but hey, the money was very good. Ironically, I worked two floors above the rest of the team, most of whom were in very cramped quarters. So that ended up being a pretty weird dynamic.

I worked at a great web development company in western New York in the middle of the Dot-Com boom, and they did a good job fostering that fun-but-intense environment where we could walk around barefoot, bring dogs in to work, play foosball, etc. but of course we worked our butts off. The one significant problem with that environment was that they wanted to eliminate the barriers to communication, so we were all in one large room with nothing between the desks. The desks weren’t close – we had plenty of personal space – but with no walls it was pretty distracting.

One of the biggest problems was personal phone calls. We had several small conference rooms with a phone that were available for personal business but often people just made their calls from their desks. You don’t listen but you can’t not hear what’s being said, and I was often amazed at what people would talk about. So this experiment in XP/Agile/etc work space was overall a failure. While it was easy to wheel over to a colleague’s desk to discuss a problem, that was nearly always an extra distraction for people nearby.

My current environment is distracting in a much more traditional sense. My cube is in with the lab scientists’ cubes, and they can be a loud bunch. A few of them are sports fans, and any time you get two or more athletic supporters in a room they will tend to be gregarious. My typical defense is loud music in headphones, but that gets old pretty quickly.

I should note that this probably reads a bit more negatively than I mean it to. I enjoy my work and like my co-workers (and the work I’m doing is contributing nicely to my resume’s acronym count). I suppose that as a grownup and a professional I should be more proactive and air my concerns – the environment certainly supports that. But if I were, for example, to print out Joel’s article and stomp my feet and demand a private office, I wouldn’t have many options given our current space. And at the same time, I feel intrinsically pressured to buck up, quit whining, deal with it. Funny how psychology works.

p.s. I just noticed that there’s an update to the “Top 10 Ways to Motivate Geeks” post that references similar articles, in particular one titled “Top 10 Ways to De-Motivate Geeks“. As with the first article, the points are all great, but #3 and #4 (on communication) are particularly interesting.

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.