Monday, May 21, 2012

From ugly to glossy

This is about showing how the exact same data can be displayed with the same original idea, yellow text on a red circle, from Java and Swing.

OK, that's the first shot. The circle is itchy, it's anything but attractive. Let's add some anti-alias to the picture:

The edge of the circle looks better, the way the font is rendered too. But a nicer font should help too

The flat background is not looking good. Let's add a gradient to it, going from red to dark red, from the top to one third of the diameter.

That's better, but quite not there yet... We would need some glossy effect. That one is interesting, and surprisingly simple. The dark red background is flat (no gradient), the glossy effect comes from the light gray oval drawn on top, that one has a gradient, from light gray to dark red, going vertically, from the top of the circle, to one third of the diameter.

A shadow in the background would bring some bevel to the picture. It is a RadialGradientPaint.

Now that looks better!
The java code is not specially complicated, and it can certainly be reused.
Here is an example of some code using this technique.
And by the way, forget about dark red... Black is much classier.

All the code demonstrated in this article is available here.

Thursday, May 03, 2012

Dynamic Java Compilation

In some Unit Test project, we had a need for a dynamic code generation, naturally followed by a compilation.
The goal was to assemble several Unit Tests into a single Test Suite. The natural path is to write a Test Suite class, compile it, and run it. The problem happens when you want to automate this kind of process... There is in Java 1.6 a class named javax.tools.JavaCompiler, that can help. The steps are the following ones:
  • Generate the java code, in a String (StringBuffer, byte array, CharSequence, what not)
  • Compile the code - into a class
  • Load the compiled code with the ClassLoader so it is available in the classpath
  • Run the generated class
The default behavior of the JavaCompiler is to write the compiled class on the disc, and this is not what we wanted, as the directory you run your code from might very well be a read-only directory. There is actually a way to keep the compiled class in memory, as illustrated by the attached file.
There is some frustrating restriction though. The JavaCompiler cannot be used with a custom ClassLoader. This means that a class generated by a dynamic compilation as described above cannot be used for any further dynamic compilation. For example, you generate ClassA. Then you generate ClassB, extending ClassA, generated and loaded. The compilation of ClassB throws a ClassNotFoundException about ClassA...
You cannot pass your own ClassLoader to the JavaCompiler, for reasons I will not discuss here.
That is something to keep in mind. If this issue remains, a workaround would be to generate JVM byte code, using libraries like ASM; it works very well, but this makes the code a bit more difficult to debug, and beside, Java and JVM byte code are two (very) different languages.