Beware of Maven resource filtering – AGAIN!

I recently blogged about problems I’d encountered with Maven filtering resource files that I didn’t actually want filtering resulting in corrupted resources in my target artifact. So you’d think I’d more careful from that point on, right?

Well, it’s just happened again! In the first situation I blogged about, the resource files in question were TrueType font files. In this latest occurrence I couldn’t understand why some native DLLs which I am packaging with my app appeared not to be loading correctly. After much head scratching, it finally dawned on me that they could be getting corrupted during the Maven build. When I checked the POM I found that I’d inadvertently switched on filtering for all resources by mistake with the result that the DLLs were being filtered and ending up corrupted. Once I’d corrected the filtering switch everything started working again.

So the moral is always be aware of the implications of switching Maven resource filtering on!

Passing arguments to surefire when using the Maven release plugin

I’ve recently been using the Maven release plugin more and more at work to simplify the process of releasing various Maven artifacts that we produce. I’ll not go into detail about the release plugin as you can read more about it here, but what I will say is that it does a lot of the manual grunt work for you associated with the release of an artifact e.g. checking for unresolved SNAPSHOT dependencies, updating POM versions, committing to your SCM, creating SCM tags etc. There are a few gotchas and quirks to getting it working reliably (hey, this is Maven we’re talking about!) but once it’s working it makes life a little easier.

We use Hudson extensively as our Continuous Integration server to build and test our Maven projects, and we’ve got several jobs configured to allow releases to be performed using the M2 release Hudson plugin. This was all working just fine until we attempted to release something which had unit tests requiring certain properties to be set defining the environment the tests should be executed in. Doing this from the command line involves passing a couple of properties to the surefire plugin using the argLine plugin parameter as discussed here. However, when the tests were executed as part of the release plugin lifecycle, these properties just weren’t being recognised.

Eventually after some Googling (how often is that the case!) we came across a blog post which discussed a little-documented feature of the release plugin that allows arguments to be passed to the surefire plugin using the -Darguments option. And with a bit of careful nesting of single and double quotes were finally able to get the required properties into the surefire plugin as part of the release plugin lifecycle as follows:

-Darguments=”-DargLine=’-Denv=dev -Dsite=london'”

Substance custom table cell renderers

I use the Substance Look & Feel in most of my Java Swing GUIs these days. It’s a very well engineered, mature, configurable implementation of a Swing look & feel which can transform the appearance of any Swing GUI. The author Kirill Grouchnikov has done a great job with it over the years and I’d like to thank him for his work on this project (and his other projects such as the Trident animation library and Flamingo component suite).

Although Substance is extremely configurable, one area that I’ve had problems with in the past is that of custom table cell renderers. Substance provides default renderers for common cell value classes such as strings, numbers, booleans etc. which covers most use cases. However, if you want to customise the cell renderer behaviour and still benefit from all of the Substance effects such as row striping, selection highlighting animation etc. you’re quite limited because Substance enforces that your custom renderer is sub-classed from the SubstanceDefaultTableCellRenderer, which itself sub-classes DefaultTableCellRenderer. This is fine as long as your custom renderer is happy to be, effectively, a sub-class of JLabel, but for anything involving custom painting it’s no good.

This is one area that I think Substance could possibly be improved to make it a bit more extensible and flexible.

One specific situation I encountered this problem with recently was where I wanted to display a mini bar-chart in a table cell. The actual custom bar component was a trivial amount of custom painting but I couldn’t see an easy way of getting this into a Substance table cell renderer. I tried creating a simple cell renderer which extended the bar component and implemented the obligatory TableCellRenderer interface, and although this worked to a degree, I lost all of the nice Substance effects mentioned above by virtue of the fact that the renderer wasn’t derived from SubstanceDefaultTableCellRenderer. I managed to get row background striping back quite easily by calling the SubstanceStripingUtils.applyStripedBackground() method but that wasn’t good enough.

Then I had a mini flash of inspiration triggered when I noticed that Substance provided a default renderer for icons…

Because the Substance default renderer is based on a label, I could set the icon property to an implementation of the javax.swing.Icon interface to get my custom painting “injected” into the renderer. The steps involved were:

  1. Make my custom bar component implement the Icon interface. This was simply a case of moving my custom painting code from the paintComponent method to paintIcon and also providing implementations of the getIconWidth and getIconHeight methods.
  2. Create a simple SubstanceDefaultTableCellRenderer sub-class which wraps an instance of my bar component. In the renderer constuctor I call setIcon to attach the bar component to the renderer. The renderer also needs to override the two setBounds methods so that it can set the size of the wrapped bar component, otherwise it wouldn’t resize with the table cell! Oh, and of course an overridden setValue method needs to update the wrapped bar component value as appropriate.

As a result, my two classes looked something like this:

BarIconComponent

package com.purplegem.substanceplay;

import javax.swing.*;
import java.awt.*;

/**
 * Simple custom component which renders a mini bar chart.
 * Implements the Icon interface so it can be used where an Icon can.
 */
public class BarIconComponent extends JComponent implements Icon {

  private double value = 0.5d;

  public BarIconComponent() {
    setSize(40, 20);
  }

  public double getValue() {
    return value;
  }

  public void setValue(double value) {
    this.value = value;
  }

  @Override
  public void paintIcon(Component c, Graphics g, int x, int y) {
    Graphics2D g2 = (Graphics2D) g;
    g2.setColor(Color.GREEN);
    g2.fillRect(0, 0, (int) (getIconWidth() * value), getIconHeight());
  }

  @Override
  public int getIconWidth() {
    return getWidth();
  }

  @Override
  public int getIconHeight() {
    return getHeight();
  }

  @Override
  protected void paintComponent(Graphics g) {
    paintIcon(this, g, 0, 0);
  }

}

BarCellRenderer

package com.purplegem.substanceplay;

import org.pushingpixels.substance.api.renderers.SubstanceDefaultTableCellRenderer;

import java.awt.*;

/**
 * Custom Substance table cell renderer which renders a mini bar
 * chart using the wrapped BarIconComponent instance
 */
public class BarCellRenderer extends SubstanceDefaultTableCellRenderer {

  private BarIconComponent barComponent = new BarIconComponent();

  public BarCellRenderer() {
    // attach our bar component as an icon
    setIcon(barComponent);
  }

  @Override
  public void setBounds(int x, int y, int width, int height) {
    super.setBounds(x, y, width, height);
    // ensure we update the size of the wrapped bar component
    barComponent.setSize(width, height);
  }

  @Override
  public void setBounds(Rectangle r) {
    super.setBounds(r);
    // ensure we update the size of the wrapped bar component
    barComponent.setSize((int) r.getWidth(), (int) r.getHeight());
  }

  @Override
  protected void setValue(Object value) {
    if (value != null) {
      // update the value of the bar component for this particular table cell
      barComponent.setValue((Double) value);
    }
  }

}

Once I’d implemented all of this I then had exactly the result I was expecting – a mini bar chart in a table cell with all the expected Substance table cell effects :-)

I’m loving MiG Layout :-)

My Java Swing layout manager of choice to date has been the good old GridBagLayout (with a healthy dose of BorderLayout where applicable). However, there’s a new kid on the block (well, at least on my block)… and that is the MiG Layout (http://www.miglayout.com/)

I heard about MiG Layout ages ago and from what I read about it, it sounded pretty cool. But I’d never actually used it – until now.

I’ve just been doing some GUI work which required some hairy layout management so I thought I’d give MiG Layout a try to see how it fared. And I’m glad to report that it handled it with ease. So I’d definitely recommend you give it a try if you haven’t already.