Saturday, April 17, 2010

Identity Crisis: JPA @Id

Who am I?

Allow me to show you a simple JPA mapping,

@MappedSuperclass
public class Domain implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")
private Integer id;

public Integer getId() {
return id;
}

public void setId(Integer id) {
this.id = id;
}
}



Do you see the thorny issue here?

Look again.

Yes, you're right - the setter method!

@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ID_SEQ")

public void setId(Integer id) {
this.id = id;
}



In my view, the setter method should not be there at all as id property is marked as "sequence". How often do you invoke setId(Integer) method? I believe rarely or almost never.

A question emerges from the back of your mind - "But I need that for my unit test?!".

If you populate this property yourself, then there's something wrong with your unit test and I strongly suggest that you rethink the way you write your test code.

I admit I've done this before many times. You are not alone my friend.

"Who is it that can tell me who I am?"

Sunday, February 21, 2010

I Wanna Be A JavaDoc Writer

Dear Sir or Madam will you read my JavaDoc?
It took me 'while to write, agonise will you take a look?
It's based on a spec by a person very dear
And I need a job and I wanna be a JavaDoc writer,
JavaDoc writer...


Do you write JavaDocs? I'm not sure how productive this would be to you, but I personally find writing JavaDoc for trivial methods, especially those requires a little thinking, ensures that I fully understood what I need to do before I start my Pee Wee's big adventure.

Once upon a time, on one lazy Friday afternoon, I restricted myself with TDD approach, that is write test code before implementation. It occurred to me that my input field will be populated by a name thus, I need to break them down into first name and last name. Easy-peasy, invoke split method from String class and pass space character as delimeter! The first element of returned String array will always represent the first name and second element will always represent the last name.

Before I started the name-parser method implementation, I wrote a small documentation right on top instead. Since I never had a poetic license in my entire life, let alone enrolled myself in three semesters of English-lit during my Uni days, my JavaDoc documentation was, is and will never be written as technical, as formal as I want it to be. I always end up with mediocre technical English documentation. I know I'm useless.

"Oh Uncle Bob, where art thou?"

One thing struck me as I happily started typing my doco - clackity-clack, what happens when someone calls himself "Donkey Kong Jr."? Clackity-clack.

(For argument's sake, let's put the spec aside for now.)

Surely, I can assume his first name is "Donkey" and last name is "Kong Jr." What about "King Henry VIII" and "Don Quixote de la Mancha"?

Hmmm, doesn't sound right, does it...?

I found myself dumbstruck at that particular instance, not to the problem nor to the solution, but to myself - a sudden self-pity, self-realisation of how naive and simple-minded I was.

So, do you want to be a JavaDoc writer?

Clackity-clack.

Saturday, November 7, 2009

PowerMock - Mocking Static Methods

Déjà vu!

I feel a bit uneasy when writing unit test against codes that invoke "heavyweight" static methods. The static methods that I have seen are unusually full of testosterone, hairy and they do stuffs that are quite unimaginable such as reflection, acquiring network resources, class loading and ahem... Do we still need to go further?

As I sit here and start recalling the static methods I last looked at, indeed, life is BLEAK.

At times, I really wish that I could close my eyes and quietly sweep them under the carpet - "Look Ma, I don't have to worry about static methods anymore!"


Wishful thinking.

One way to get around this problem is to provide a helper class with non-static wrapper methods. I personally wouldn't want to go down this path as it adds an extra class and methods, not to mention complexity, to the codebase just to delegate calls to static methods without introducing any real benefit. Another way is to partial mock or...


PowerMock to the rescue!

After searching high and low for the best way to solve this by mocking, my friend Google suggested that I look at PowerMock.

To see PowerMock in action, let's write a sample class with static method:
SimonGarfunkel.java

1:  package test1;  
2: public class SimonGarfunkel {
3: public static void simonSaysGarfunkel() {
4: System.out.println("simon says garfunkel");
5: }
6: }


And the test class:
SimonGarfunkelTest.java

1:  package test1;
2: import org.junit.Test;
3: import org.junit.runner.RunWith;
4: import org.powermock.api.easymock.PowerMock;
5: import org.powermock.core.classloader.annotations.PrepareForTest;
6: import org.powermock.modules.junit4.PowerMockRunner;
7: @RunWith(PowerMockRunner.class)
8: @PrepareForTest(SimonGarfunkel.class)
9: public class SimonGarfunkelTest {
10: @Test
11: public void simonSaysGarfunkel() {
12: System.out.println("simonSaysGarfunkel");
13: SimonGarfunkel.simonSaysGarfunkel();
14: }
15: @Test
16: public void mockSimonSaysGarfunkel() {
17: System.out.println("mockSimonSaysGarfunkel");
18: PowerMock.mockStatic(SimonGarfunkel.class);
19: SimonGarfunkel.simonSaysGarfunkel();
20: PowerMock.expectLastCall().atLeastOnce();
21: PowerMock.replay(SimonGarfunkel.class);
22: SimonGarfunkel.simonSaysGarfunkel();
23: PowerMock.verify(SimonGarfunkel.class);
24: }
25: }


The code at line 20 and 23 ensures that "SimonGarfunkel.simonSaysGarfunkel()" is invoked at least once.

Also include the following dependencies into the pom file:
pom.xml

   <repositories> 
<repository>
<id>powermock-repo</id>
<url>http://powermock.googlecode.com/svn/repo/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-release-full</artifactId>
<version>1.3.1</version>
<scope>test</scope>
</dependency>
</dependencies>


For some reason, Maven2 didn't quite resolve powermock artifact even after I added the powermock repository. I had to manually download and install this into my local repo.

Friday, October 2, 2009

Integers and Equality Operator

On a lucky day, you could get away by comparing Integers using the equality operator:

1:  public class IntTest {  
2: public static void main(String[] args) {
3: Integer a = 100;
4: Integer b = 100;
5: System.out.println(a == b);
6: }
7: }


Running IntTest.class results to:

 true  


But you may not find yourself lucky if you have a code similar to the one found below:

1:  public class IntTest2 {  
2: public static void main(String[] args) {
3: Integer a = 200;
4: Integer b = 200;
5: System.out.println(a == b);
6: }
7: }


Running IntTest2.class results to:

 false  



Let's write another equality test to check our sanity:

1:  public class IntBox {  
2: public static void main(String[] args) {
3: Integer a1 = 127;
4: Integer a2 = 127;
5: Integer b1 = -128;
6: Integer b2 = -128;
7: Integer c1 = 128;
8: Integer c2 = 128;
9: Integer d1 = -129;
10: Integer d2 = -129;
11: System.out.println("a1 == a1 " + (a1 == a2));
12: System.out.println("b1 == b2 " + (b1 == b2));
13: System.out.println("c1 == c2 " + (c1 == c2));
14: System.out.println("d1 == d2 " + (d1 == d2));
15: }
16: }


Running the code gives us:

 a1 == a1 true  
b1 == b2 true
c1 == c2 false
d1 == d2 false


Yes, comparing 127 and -128 results to true but not 128 and -129.

Let's disassemble IntBox.class to investigate further by running "javap -c IntBox":

1:  Compiled from "IntBox.java"  
2: public class IntBox extends java.lang.Object{
3: public IntBox();
4: Code:
5: 0: aload_0
6: 1: invokespecial #1; //Method java/lang/Object."<init>":()V
7: 4: return
8: public static void main(java.lang.String[]);
9: Code:
10: 0: bipush 127
11: 2: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
12: 5: astore_1
13: 6: bipush 127
14: 8: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
15: 11: astore_2
16: 12: bipush -128
17: 14: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
18: 17: astore_3
19: 18: bipush -128
20: 20: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
21: 23: astore 4
22: 25: sipush 128
23: 28: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
24: 31: astore 5
25: 33: sipush 128
26: 36: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
27: 39: astore 6
28: 41: sipush -129
29: 44: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
30: 47: astore 7
31: 49: sipush -129
32: 52: invokestatic #2; //Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
33: 55: astore 8
34: 57: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
35: 60: new #4; //class java/lang/StringBuilder
36: 63: dup
37: 64: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
38: 67: ldc #6; //String a1 == a1
39: 69: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
40: 72: aload_1
41: 73: aload_2
42: 74: if_acmpne 81
43: 77: iconst_1
44: 78: goto 82
45: 81: iconst_0
46: 82: invokevirtual #8; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
47: 85: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
48: 88: invokevirtual #10; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
49: 91: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
50: 94: new #4; //class java/lang/StringBuilder
51: 97: dup
52: 98: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
53: 101: ldc #11; //String b1 == b2
54: 103: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
55: 106: aload_3
56: 107: aload 4
57: 109: if_acmpne 116
58: 112: iconst_1
59: 113: goto 117
60: 116: iconst_0
61: 117: invokevirtual #8; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
62: 120: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
63: 123: invokevirtual #10; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
64: 126: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
65: 129: new #4; //class java/lang/StringBuilder
66: 132: dup
67: 133: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
68: 136: ldc #12; //String c1 == c2
69: 138: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
70: 141: aload 5
71: 143: aload 6
72: 145: if_acmpne 152
73: 148: iconst_1
74: 149: goto 153
75: 152: iconst_0
76: 153: invokevirtual #8; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
77: 156: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
78: 159: invokevirtual #10; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
79: 162: getstatic #3; //Field java/lang/System.out:Ljava/io/PrintStream;
80: 165: new #4; //class java/lang/StringBuilder
81: 168: dup
82: 169: invokespecial #5; //Method java/lang/StringBuilder."<init>":()V
83: 172: ldc #13; //String d1 == d2
84: 174: invokevirtual #7; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
85: 177: aload 7
86: 179: aload 8
87: 181: if_acmpne 188
88: 184: iconst_1
89: 185: goto 189
90: 188: iconst_0
91: 189: invokevirtual #8; //Method java/lang/StringBuilder.append:(Z)Ljava/lang/StringBuilder;
92: 192: invokevirtual #9; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
93: 195: invokevirtual #10; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
94: 198: return
95: }



From line 10 to 33, the compiler converts our integer assignments to calling Integer.valueOf(int).

Looking at Integer.java source, the Integer class performs special cache operation whenever valueOf(int i) method is called:

(From JDK6):
1:  public static Integer valueOf(int i) {  
2: if(i >= -128 && i <= IntegerCache.high)
3: return IntegerCache.cache[i + 128];
4: else
5: return new Integer(i);
6: }


and for private static class IntegerCache found in Integer.java (neglect line 8 to 15 to keep things simple for now):

1:  private static class IntegerCache {  
2: static final int high;
3: static final Integer cache[];
4: static {
5: final int low = -128;
6: // high value may be configured by property
7: int h = 127;
8: if (integerCacheHighPropValue != null) {
9: // Use Long.decode here to avoid invoking methods that
10: // require Integer's autoboxing cache to be initialized
11: int i = Long.decode(integerCacheHighPropValue).intValue();
12: i = Math.max(i, 127);
13: // Maximum array size is Integer.MAX_VALUE
14: h = Math.min(i, Integer.MAX_VALUE - -low);
15: }
16: high = h;
17: cache = new Integer[(high - low) + 1];
18: int j = low;
19: for(int k = 0; k < cache.length; k++)
20: cache[k] = new Integer(j++);
21: }
22: private IntegerCache() {}
23: }


* Line 17 initialises the cache array to 256 in size, assuming 127 is the highest value
* Line 19 to 21 create the integer objects from -128 to 127 and stores them into "cache" variable

From the statements above, we see that Integers are cached starting from -128 to 127 and that suggests why a1/a2 and b1/b2 equality operator comparison works but not for c1/c2 and d1/d2.

Sunday, September 27, 2009

Deployment Plan Patch Contribution for Clownfish

I admit I've been out of action since the last release of Clownfish v0.1.1-SNAPSHOT, not to mention my original Clownfish blog had been removed by Blogger.com for unknown reason - can't be bothered to chase this up. :D

During my absence, I've spent a little bit of time looking at Android+ZXing early this year and MyFaces Orchestra recently. (Still trying to get my hands dirty with Google App Engine - ported Hibernate Annotations to JPA, still have a long way to go.)



Yesterday, I went back to have a look at my plugin, with much surprise a "Good Samaritan" offered a patch code that would enable Clownfish to deploy through a deployment plan, unit tests included! This is one of the functionality that I left off that I find I hardly use. I'm glad that someone had tried using Clownfish as a Maven2 Glassfish deployer!

Looking forward this coming long weekend to review and hopefully merge this patch back to Clownfish codebase.

Burned by Public Constants

We define two classes, one class exposes a public constant while the other class consumes the constant value.

Const.java:
1:  public class Const {  
2: public static final int VALUE = 600;
3: public void test() {
4: int a = VALUE;
5: System.out.println("a=" + a);
6: }
7: public static void main(String[] args) {
8: new Const().test();
9: }
10: }


ConstClient.java:
1:  public class ConstClient {  
2: public void test() {
3: int b = Const.VALUE;
4: System.out.println("b=" + b);
5: }
6: public static void main(String[] args) {
7: new ConstClient().test();
8: }
9: }


Compile and run both classes:
Const.java displays:
 a=600  


ConstClient.java displays:
 b=600  


So far so good, this is what we expected.

Let's try disassembling them with "javap -c Const"
1:  Compiled from "Const.java"  
2: public class Const extends java.lang.Object{
3: public static final int VALUE;
4: public Const();
5: Code:
6: 0: aload_0
7: 1: invokespecial #1; //Method java/lang/Object."<init>":()V
8: 4: return
9: public void test();
10: Code:
11: 0: sipush 600
12: 3: istore_1
13: 4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
14: 7: new #3; //class java/lang/StringBuilder
15: 10: dup
16: 11: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
17: 14: ldc #5; //String a=
18: 16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: 19: iload_1
20: 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
21: 23: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: 29: return
24: public static void main(java.lang.String[]);
25: Code:
26: 0: new #10; //class Const
27: 3: dup
28: 4: invokespecial #11; //Method "<init>":()V
29: 7: invokevirtual #12; //Method test:()V
30: 10: return
31: }


and "javap -c ConstClient"
1:  Compiled from "ConstClient.java"  
2: public class ConstClient extends java.lang.Object{
3: public ConstClient();
4: Code:
5: 0: aload_0
6: 1: invokespecial #1; //Method java/lang/Object."<init>":()V
7: 4: return
8: public void test();
9: Code:
10: 0: sipush 600
11: 3: istore_1
12: 4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
13: 7: new #3; //class java/lang/StringBuilder
14: 10: dup
15: 11: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
16: 14: ldc #5; //String b=
17: 16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: 19: iload_1
19: 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: 23: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
21: 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: 29: return
23: public static void main(java.lang.String[]);
24: Code:
25: 0: new #10; //class ConstClient
26: 3: dup
27: 4: invokespecial #11; //Method "<init>":()V
28: 7: invokevirtual #12; //Method test:()V
29: 10: return
30: }


We see that from Const.class line 11 and ConstClient.class line 10, the constant value 600 is pushed onto the stack memory at slot #1.

Let's try changing Const.java constant value from 600 to 500.
1:  public class Const {  
2: public static final int VALUE = 500;
3: public void test() {
4: int a = VALUE;
5: System.out.println("a=" + a);
6: }
7: public static void main(String[] args) {
8: new Const().test();
9: }
10: }


Compile Const.java and run produces:
 a=500  


Rerun ConstClient without recompilation produces strange result:
 b=600  


Let's take a peek by disassembling Const.class:
1:  Compiled from "Const.java"  
2: public class Const extends java.lang.Object{
3: public static final int VALUE;
4: public Const();
5: Code:
6: 0: aload_0
7: 1: invokespecial #1; //Method java/lang/Object."<init>":()V
8: 4: return
9: public void test();
10: Code:
11: 0: sipush 500
12: 3: istore_1
13: 4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
14: 7: new #3; //class java/lang/StringBuilder
15: 10: dup
16: 11: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
17: 14: ldc #5; //String a=
18: 16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
19: 19: iload_1
20: 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
21: 23: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
22: 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
23: 29: return
24: public static void main(java.lang.String[]);
25: Code:
26: 0: new #10; //class Const
27: 3: dup
28: 4: invokespecial #11; //Method "<init>":()V
29: 7: invokevirtual #12; //Method test:()V
30: 10: return
31: }


We see that line 11 pushes our new constant value 500 onto the stack.

Let's take another peek at ConstClient.class:
1:  Compiled from "ConstClient.java"  
2: public class ConstClient extends java.lang.Object{
3: public ConstClient();
4: Code:
5: 0: aload_0
6: 1: invokespecial #1; //Method java/lang/Object."<init>":()V
7: 4: return
8: public void test();
9: Code:
10: 0: sipush 600
11: 3: istore_1
12: 4: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream;
13: 7: new #3; //class java/lang/StringBuilder
14: 10: dup
15: 11: invokespecial #4; //Method java/lang/StringBuilder."<init>":()V
16: 14: ldc #5; //String b=
17: 16: invokevirtual #6; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
18: 19: iload_1
19: 20: invokevirtual #7; //Method java/lang/StringBuilder.append:(I)Ljava/lang/StringBuilder;
20: 23: invokevirtual #8; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
21: 26: invokevirtual #9; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
22: 29: return
23: public static void main(java.lang.String[]);
24: Code:
25: 0: new #10; //class ConstClient
26: 3: dup
27: 4: invokespecial #11; //Method "<init>":()V
28: 7: invokevirtual #12; //Method test:()V
29: 10: return
30: }


Line 10 tells us that for some reason our program pushes 600 onto the stack not 500 - our constant value is still 600! It seems like javac burned the constant value into ConstClient.class instead of JVM resolving it through Const.class!

- "Extra care should be taken when hot-deploying classes with public constants as they could potentially break your code during runtime."