Tuesday, July 27, 2010

Fun with bytecode generation, minus problems with generic signatures

One thing that has been on my TODO list for multiple years moved up to my "current tasks" list: that of using Java bytecode generation for something useful: for "materializing interfaces" (typically simple Bean interfaces), that is, constructing concrete implementations of interfaces that only consist of simple getter and/or setter methods. It will be one of major new features for Jackson 1.6, codename "Mr Bean". In fact there is just one other such mental todo task from that era (which would be "use Groovy for something useful")...

Implementation was started by my colleague Sunny G at Ning (which is big reason why it got started at all!) and uses minimalistic, lean and mean ASM bytecode generation package for actual low-level work. This is good in keeping dependencies to minimal (in fact, Jackson mrbean module will embed repackage version of ASM 3.3), and will probably also result in simple bytecode. But the downside is that code to write is quite low-level.

Working with low-level code generation actually brings back memories from last millennium -- I wrote 68000 assembly in early 90s, and 6502 machine code before that in late 80s. Name ASM is actually quite apt for the package as using ASM is quote similar to using full-feature Assembler package, which is still a notch above bare machine code or using machine code monitor (for those who remember what that meant on, say, Commodore-64). This is to say, it's actually bit of fun for me; although amount of time spent on actual debugging and troubleshooting is considerably higher than with "normal" Java coding. But at least you don't have to manually calculate various offsets (local variable and stack sizes for example), or allocate constant Strings in per-class constant tables. Writing actual code is still rather involved however.

At this point basic functionality works acceptably, leading to the first snapshot release of Jackson-1.6.0. But there is one serious problem that I have been unable to resolve. Although ASM actually does provide some support for dealing with generics -- that is, ability to declare generic signatures of fields, methods, and supertypes -- and although I am using functionality exactly as it should be (including verifying exact form signatures need, compared to type-erased 'description' parameters), end result is only half-working. Half meaning that if disassembling resulting class bytecode using ASM itself, generic signatures are found; but when using JDK reflection (java.lang.reflect.Method/Field, getGenericType()), only type-erased information is found. I still hope to resolve this; I hope someone on ASM users list can point out what I am doing wrong. There shouldn't be anything fundamentally hard about making it work.

Anyhow, I thought this might be somewhat interesting; I'll get back to working on finalizing 1.6.0 so it gets released before summer ends and it is time to (yet again!) contemplate brewing of dreaded Blackberry Beer! :-)

Saturday, July 10, 2010

Every day JSON work: comparing JSON documents for equality ("are these JSONS same?")

One JSON task that may seem trivial but is not is that of checking whether two given JSON documents are equal: that is, have same structure and values, and ordering of array values is same. It is not sufficient to use String equality comparison because while equality of Strings does mean contained JSON is equal, differing Strings does not mean they are not equal, since:

  • It is possible to quote characters differently using \uXXXX mechanism
  • Order of properties of JSON objects is undefined (at conceptual level); meaning that physical ordering may differ while conceptually JSON is still identical

So how should one compare equality? With Jackson, simplest way is to construct JSON tree (JsonNode) for documents to compare and just use JsonNode.equals()! Like so:

  ObjectMapper mapper = new ObjectMapper();
  JsonNode tree1 = mapper.readTree(input1);
  JsonNode tree2 = mapper.readTree(input2);
  boolean areEqual = tree1.equals(tree2);

I realized that this (fact that JsonNode.equals() works "as expected", doing deep value comparison) is not documented outside of Javadocs (it will be now, I will add something at FasterXML Jackson Wiki). But hopefully it was already known by experienced Jackson users. Either way, here's how JSON content comparison can be done easily and reliably.

Friday, July 02, 2010

Comments, yes please!

Hurrah! Thanks to Bryce's excellent recommendation, commenting is again possible here using Discus (which I had seen being used by a few blogs).

To celebrate this new-found capability, I will be taking next week off and will neither be writing entries nor reading any comments added. :-)

... but when I get back, there's bumper crop of Jackson 1.6 features to write about, from kick-ass "binary JSON" format (aka "Smile"), to automatically generated interface implementations and tons more smaller improvements to usability. Latter mostly due to lately having to eat my own dog food (and having to serve it for co-workers as well!) on regular basis.

Related Blogs

(by Author (topics))

Powered By

About me

  • I am known as Cowtowncoder
  • Contact me at@yahoo.com
Check my profile to learn more.