Life Codecs @ NamingCrisis.net

Ruminations. Reflections. Refractions. Code.

Sep 20, 2010 - general personal poetry

A Tribute to Vajra

I just gave away my laptop of some 8 years. Its hostname was “vajra“, a Sanskrit multi-semantic word – some meanings rather less subtle than others, but that’s a tale for another rainy day. The meaning I first encountered for it however was ‘diamond’. That is the name I gave to it.

I do not know if I can confer this name on to an equally worthy machine in the future – whether I do, or do not – equality in this case will never replace Vajra’s intrinsic identity.

The Vajra that just left was truly a diamond, it stuck with me through thick and thin, all throughout my university and personal life – the whole of my time in Melbourne. A most resilient machine. It was sad seeing it go having been a significant part of my life for so long. Yet it is well that it went to someone who wanted to reuse it as a small mail server, as my main use for it has, sadly, since dissolved.

While a university student with a tight budget, it gave me no trouble. Many days it ran at least 10-15 hours a day, compiling code, browsing the net, playing music, yapping on IRC. It has been a companion for the longest time.

I remember that on the way to Melbourne, the first time, I managed to lose its original power adapter due to tardiness at the airport security check. I found an original, new, and cheap replacement not long after though. Truly it was Divine synchronicity. Even when I messed up, it remained kind to me.

2-3 years ago, the one thing that died was its hard drive. I replaced it the next day, and it was buzzing with life once more.

Vajra – a Compaq Presario 1700 AP – has the following featureset:

  • Pentium 3 (Coppermine), 750 MHz
  • 384 MB RAM
  • 110 GB HDD (the original was 40GB I believe)
  • NIC
  • Built-in (soft-)modem
  • Floppy drive-bay

It has accomodated several OS spirits during its time with me:

  • Linux: Mandrake, Redhat 7.2, Debian, and most recently Ubuntu Karmic
  • Windows: WinME, WinXP

I wish it well, and when the time comes – may its various elements evolve further: the minerals powering its chipsets, the metals of its frame, the luminous atoms of its LCD.

May the spirit of Vajra, the diamond, be forever. In one form or another.

Sep 19, 2010 - general personal

Walking Down (Virtual) Memory Lane

I’ve been gathering up my old machines to either give away, or recycle. As part of this I’ve had to look at contents of old hard drives to decide what needs to stay, and what can go. It has been a rather emotional process – not a very easy one at times. So much lies in those bits and bytes. Chunks of life from days gone by. People, names, places, items. Some which test old wounds (dang, how deep). A timescale quite close to a decade for me.

Much of the material was not well-organised – so there was a lot of grepping for patterns of files that I might want to keep. I did not find a heap to keep, but those that I did find – they would be in the calibre of things, which, if I did suddenly remember about them, and realised that I had deleted them – well let’s just say it would not be a great feeling. At some point, one perhaps has to let go of it all – but for now I was glad to find those files.

In Indonesian, we have this interesting phrase, ‘napak tilas’, I don’t actually know what it means literally – but metaphorically, it’s an act of reflection – to revisit places (sometimes very much physically revisit places), or things, and reflect on the values gained from those, how one has changed or not changed, what one has learnt or not learnt, etc. – much like a deep, psycho-emotional XP retrospective for the Agile software-development-inclined.

I can’t help but think that so much ‘napak tilas’ must occur in the digital world these days – photos, music, writings, even code. This is of course in addition to ongoing life in the physical world. One lives, quite literally, in a multidimensional world today.

Night, (multidimensional) world.

Aug 27, 2010 - general personal

Daffodils

Australia has this thing called Daffodil Day. It is essentially an annual initiative by the Cancer Council to raise money for cancer research by selling bright yellow merchandise – daffodils obviously being one prominent item. I’ve always wanted to participate (that is, donate) on Daffodil Day (I know I can donate any other day, but Daffodil Day sounds so much cooler) – so today – Daffodil Day 2010-08-27 – I went ahead and got some daffodils (oh and a teddy bear in a yellow tee which is now placed in the centre table of our work pod).

I wasn’t quite sure what to do with them really… so on reaching home, I emulated what femmes and flower lovers usually do, put the flowers in a vase with water. I know, brilliant.

My first problem made itself known — I do not have a vase.

I could not just wait and let the flowers without water, they were already in my backpack for most of the day :-(. So using my high IQ (the same IQ that thought of emulating well-known procedures), I emulated a vase. I had an empty tin can of Astor Wafer Sticks – good stuff that, highly recommended – washed it up, filled it with cold water, and placed the daffodils in them.

A couple of hours later in the middle of the night, these amazing flowers just bloomed… quite surreal. As ruby2shoes (gotta love handles) once told me – paraphrasing a bit – “daffodils are hardy flowers, like ‘whee! we’re here!! hi hi!’”.

I am glad I got them now :-).

Aug 16, 2010 - general

HUT RI ke-65!

Selamat Hari Ulang Tahun RI ke-65, 17 Agustus! Merdeka!

(Happy 65th Indonesian Independence Day! Freedom!)

Aug 10, 2010 - general

Happy Fasting

To my Muslim friends, Happy Fasting during the Holy Month of Ramadhan!

May the Divine’s Blessings be with us (on any month, really, is the wish :P). I humbly apologise for any errors I have committed.

Apr 5, 2010 - software dev

Generics and Method Selection: A Backwards Compatibility Gotcha

If you managed to read through the rather long post title… let’s move on to a much longer post.

I recently came across an interesting bug at work which was rather eye-opening on just how nasty backwards-compatibility (which prompted type erasure!) can be. Credits are due to my friend and colleague Marcus Hasslinger who reasoned through the issue with me from a backwards compatibility viewpoint.

Some background: we use Java 5 and EJB 3, we also make use of annotated methods that are inspected by custom EJB 3 interceptor(s). A sample EJB might implementation might be:

1
2
3
4
5
6
7
8
9
10
11
@Local
public interface Foo {
    void doSomething();
}

@Stateless
@Interceptors({TransactionHandlerInterceptor.class})
public class FooServiceImpl implements Foo {
    @RollbackWhen(...)
    public void doSomething() { /* ... */ }    
}

In the above, the interceptor (TransactionHandlerInterceptor) is an around-invoke type interceptor which intercepts doSomething(), reads the annotation on it (RollbackWhen) and decides some rollback logic.

The defect was that in a particular EJB, it would not detect the method as having this annotation, and thus the necessary rollback logic was never executed. Thus begins our saga. Rather than going through work artifacts (which I probably can’t show anyway) and bore you with our business domain, I’ll create an essentially similar example using the classic ‘Shape’ set of objects (I know.. I know…).

This particular EJB had the following structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// package foo
// Domain objects
public interface Shape {
}

public class Circle implements Shape {
}

// Services
public interface ShapeService<T extends Shape> {
    void draw(T shape);
}

@Local
public interface CircleService extends ShapeService<Circle> {
}

@Stateless
@Interceptors({TransactionHandlerInterceptor.class})
public class CircleServiceImpl implements CircleService {
    @Override
    @RollbackWhen(...)
    public void draw(final Circle shape) {
        System.out.println("Drawing circle");
    }
}

// Sample dumb, non-EJB client
public class Client {
    public static void main(final String[] args) {
        final CircleService circleService = new CircleServiceImpl();
        circleService.draw(new Circle());
    }
}

The issue was that whenever the interceptor intercepted CircleServiceImpl.draw(), it would not detect that it was annotated with @RollbackWhen. So I printed out the actual method.toString() output from within the interceptor – this turned out to be:

1
public void draw(Shape)

instead of the expected:

1
public void draw(Circle)

Obviously draw(Shape) is not annotated with @RollbackWhen, draw(Circle) is. Hmm. So where exactly does draw(Shape) come from though, we only ever implemented draw(Circle) in CircleServiceImpl. It’s time to look at type-erasure in action under the hood using ‘javap’ – a useful little bytecode disassembler that comes as part of the stock JDK. The following output was obtained by running ‘javap -c ’ (without the .class).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// javap -c Shape Circle ShapeService CircleService CircleServiceImpl Client
Compiled from "Shape.java"
public interface foo.Shape{
}

Compiled from "Circle.java"
public class foo.Circle extends java.lang.Object implements foo.Shape{
public foo.Circle();
  Code:
   :   aload_0
   1:   invokespecial   #10; //Method java/lang/Object."":()V
   4:   return

}

Compiled from "ShapeService.java"
public interface foo.ShapeService{
public abstract void draw(foo.Shape);

}

Compiled from "CircleService.java"
public interface foo.CircleService extends foo.ShapeService{
}

Compiled from "CircleServiceImpl.java"
public class foo.CircleServiceImpl extends java.lang.Object implements foo.CircleService{
public foo.CircleServiceImpl();
  Code:
   :   aload_0
   1:   invokespecial   #10; //Method java/lang/Object."":()V
   4:   return

public void draw(foo.Circle);
  Code:
   :   getstatic       #18; //Field java/lang/System.out:Ljava/io/PrintStream;
   3:   ldc     #24; //String Drawing circle
   5:   invokevirtual   #26; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   8:   return

public void draw(foo.Shape);
  Code:
   :   aload_0
   1:   aload_1
   2:   checkcast       #35; //class foo/Circle
   5:   invokevirtual   #37; //Method draw:(Lfoo/Circle;)V
   8:   return

}

Compiled from "Client.java"
public class foo.Client extends java.lang.Object{
public foo.Client();
  Code:
   :   aload_0
   1:   invokespecial   #8; //Method java/lang/Object."":()V
   4:   return

public static void main(java.lang.String[]);
  Code:
   :   new     #16; //class foo/CircleServiceImpl
   3:   dup
   4:   invokespecial   #18; //Method foo/CircleServiceImpl."":()V
   7:   astore_1
   8:   aload_1
   9:   new     #19; //class foo/Circle
   12:  dup
   13:  invokespecial   #21; //Method foo/Circle."":()V
   16:  invokeinterface #22,  2; //InterfaceMethod foo/CircleService.draw:(Lfoo/Shape;)V
   21:  return

Let’s start with the simple cases: Shape and Circle – Shape is a simple interface, all fine and dandy. Circle is a class implementing Shape, we can see the default constructor generated since we didn’t provide one of our own.

Next we look at ShapeService – a bit more interesting – it has an abstract method draw(Shape). Generics information is erased, there’s no ‘T’ anywhere. T is replaced by its upperbound, i.e. Shape. Thus the generated method too is draw(Shape). So far so good.

Moving on to CircleService – once more, the parameterisation is nowhere to be seen, there’s therefore no notion of Circle in CircleService, it simply extends ShapeService, and thus inherits the same method signature: draw(Shape). This is what got me – it of course, needs to be this way due to type erasure. You get the illusion of full type-safety, as if a new method draw(Circle) is automatically generated in CircleService – since after all, compile-time code completion, etc. in your IDE works just dandy on a reference of type CircleService – CircleService.draw(Circle) – never does it show CircleService.draw(Shape)!

Let’s move on further – things are getting more interesting. CircleServiceImpl has 2 overloaded methods, draw(Circle) which is our code converted to bytecode, and a compiler generated draw(Shape) – which casts (or at least does a cast-check – haven’t read the bytecode description) to ensure the supplied Shape is indeed a Circle, and then delegates on to our draw(Circle). Think about this for a moment – by itself, it’s just madness – but from a backwards compatibility viewpoint — 2 methods need to be there, our own draw(Circle) which as you can see, did not override any method in the interface as such(!), and draw(Shape) the compiler generated one – which is needed to satisfy the type-erased interfaces we implemented!

One final piece of the puzzle — client code: once more we see a default constructor is generated since we didn’t create one. And then the main() method which in fact calls draw(Shape), not draw(Circle). This is once more correct in a backwards-compatible-whacky way — as we saw above CircleService only ever had draw(Shape) — since we used the CircleService reference, that’s the method we got. And thus the implementation class needs to generate draw(Shape) and delegate to our draw(Circle).

In as far as our defect goes — this is exactly why it did not detect the annotation — it was intercepting the client-invoked, compiler-generated draw(Shape) which in turn invoked draw(Circle). draw(Circle) is of course an internal invocation, not accessed via the EJB proxy anymore, and hence never intercepted again.

Ah backwards compatibility.

That aside, there are a few observations to be made:

  • A generics call in the above fashion will always incur an additional cast check and method call, not a big deal for most code, but within a loop, etc. best to measure it. On the bright side, the checkcast is a single JVM instruction. Another optimisation – if you can even call it that! – is to explicitly declare a method draw(Circle) in CircleService – then it is generated as per normal, and client code goes directly to CircleServiceImpl.draw(Circle) – at this time, this is our workaround for the defect. I’ll leave the discussion of where the annotation should belong for another time (i.e. implementation class or interface – this is more a design principle/responsibility issue)
  • It’s interesting that specifically from an EJB 3 interception and transactional semantics viewpoint – this is quite nasty since you do not intercept a method that you think is part of your EJB interface, nor does the transactional semantics get applied (apart from the default ‘required’ of course)! I wonder if it might be better, if in an EJB 3 class, the generated draw(Shape) method did not do a plain invocation of draw(Circle), but accessed it via an internal EJB proxy reference (circleServiceEjbRef.draw(Circle)) – this would ensure proper transactional semantics and interception. Wait – the generated method in fact should not enforce any transaction type either — it should just be (if I recall correctly) using ‘supports’ semantics. As it stands, if draw(Circle) were annotated with a transaction attribute other than ‘required’ – this would not be picked up at all since it was a direct invocation, not via the EJB transactional proxy! Nasty, nasty! It could lead to some very obscure bugs!

Hmm.. I never remember reading about this in any generics book :P. Anyway, if you got this far, hope it was an informative read.