Archives for November 2007
Two weeks with the ZK framework
The ZK framework seemed to be a very compelling user interface solution when teamed with Grails. For those who don't know, ZK is an AJAX/XUL framework implemented in Java. It also has support for several scripting languages (Groovy, Ruby, and Python) in addition to Java to wire events and access components. The event-based model used by the framework sometimes is reminiscent of Swing.
Normally in a Grails application. your domain controller does most of the heavy lifting and both sends and receives data to/from the presentation layer. However, when using the ZK plugin, that doesn't seem to be possible. The controller can receive events but has no way to transmit objects back. Despite having static functions to do so, it seems that the ZK code is not in scope when trying to call it from the controller(NPEs abound). In a non-Grails application, I don't believe this issue would exist but our current framework within a framework configuration doesn't fancy it much. Given that I have less than two weeks until go live, I think I'm going to go with the less sexy route (GSP + CSS) and revisit the matter later. Echo2 does look interesting. The APIs appear to be easily targetable with a builder and the example code looks generally clean. I think an Grails-Echo2 application would need to shift most of the event handling code to the application instances and use the controller mainly for context switching. [I've looked at it for less than an hour, so it's not substantiated and ymmv].
On another note, for some reason, I'm really excited by the eee pc. I think it's because it's size makes it somewhat of a large PDA/ultra-mobile PC. It would be really cool to have lightweight Groovy apps running on an ultra-portable laptop. Unlike the XO-1, it runs a normal distro so besides space, getting Groovy to run would be a breeze.
On Making a Grails-Powered Blog
People often tell say "you get what you pay for," but a lot of times, you don't even get that. Or at least that has been the case with my current webhost. I've had more downtime than on the free service I "upgraded" from. Since it's inevitable that I'm moving, I decided to move to a Java host and build my blog with the features I want.
Setting up the backend stuff was much simpler than I thought, especially the ability to add multiple URL mappings. The initial design will sport a hopefully swappable ZK frontend, comments moderation, and an admin console, just enough to make it worthwhile to do from scratch.
In other news: As of Nov 16th, I am officially an alum of the Google Summer of Code. I received my t-shirt, certificate of participation, and a couple stickers. In lieu of the stickers, I would have preferred a cool pen or notebook...
Groovy on Android-Not Quite There Yet
Edit(3 AUG 09): Since this post was written there has been some success with getting some low level Groovy running on Android. Check out the project here: http://code.google.com/p/discobot/downloads/list
Disclaimer: This is the product of some 5-6 hours or so of messing around.There might be a better way to do things. The main goal of this entry is to get people thinking about it.
First the good news.
The UI for Android doesn’t use Hildon or some other abstract ui framework. If you can layout a web page with absolute positioning with ease, you’ll have no problems here. Android uses very readable XML files for the layouts.
Now for the bad news:
Because it doesn’t use a full J2SE JRE/JDK, Groovy doesn’t work out of the box. Here’s what I’ve got so far.
1. After installing the Android SDK, create a new application with the command: ./activityCreator.py --out myproject your.package.name.ActivityName
or you could use the Eclipse plugin.
2. Add a Groovy compile task to the generated Ant build file and include the appropriate library jars on its classpath.
3. You can compile right now with ant and install the application to the emulator(after starting the emulator) with adb install
4. All classes need to be converted to Davlik’s dex format. The dx command does this. I tried to convert the groovy-all jar and the contents of the groovy/lib directory in separate attempts but I was getting heap overflow errors. To remedy this, I expanded the jar into bin/classes and removed the swing specific bits. It’s not required to remove them but it lessens the likelyhood of a heap over flow. Now rerun the ant task to include them in the application package.
5. We get complaints about java.beans.Inspector which is located in rt.jar(in one of the jre directories). I extracted all the files in the java.beans directory into bin/classes. The next missing dependency is one of the classes in sun.reflect.misc. I extracted all the files from that directory into bin/classes as well.
The final status: A ClassNotFoundException and ClassCastException from inside the android jar. Here’s the output from the log
D/dalvikvm( 636): Exception java/lang/ClassNotFoundException from ApplicationLoaders.java:188 not caught locally
D/dalvikvm( 636): NOTE: loadClass ’groovy/runtime/metaclass/CustomMetaClassCreationHandle’ 0x4001d608 threw an exception
D/dalvikvm( 636): Exception java/lang/ClassNotFoundException from ApplicationLoaders.java:188 not caught locally
D/dalvikvm( 636): NOTE: loadClass ’groovy/runtime/metaclass/org/codehaus/groovy/runtime/ScriptBytecodeAdapterMetaClass’ 0x4001d608 threw an exception
D/dalvikvm( 636): Exception java/lang/ClassCastException from MetaClassRegistryImpl.java:168 not caught locally
D/dalvikvm( 636): Exception java/lang/RuntimeException from Looper.java:76 not caught locally
D/dalvikvm( 636): Exception java/lang/RuntimeException from ZygoteInit.java:1176 not caught locally
D/AndroidRuntime( 636): Shutting down VM
W/dalvikvm( 636): threadid=3: thread exiting with uncaught exception (group=0x4000e648)
E/AndroidRuntime( 636): Uncaught handler: thread Main exiting due to uncaught exception
E/AndroidRuntime( 636): java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{groovy.tests/groovy.tests.HelloWorld}: java.lang.ClassCastException
E/AndroidRuntime( 636): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1338)
E/AndroidRuntime( 636): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1410)
E/AndroidRuntime( 636): at android.app.ActivityThread.access$1200(ActivityThread.java:76)
E/AndroidRuntime( 636): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:980)
E/AndroidRuntime( 636): at android.os.Handler.dispatchMessage(Handler.java:80)
E/AndroidRuntime( 636): at android.os.Looper.loop(Looper.java:71)
E/AndroidRuntime( 636): at android.app.ActivityThread.main(ActivityThread.java:2506)
E/AndroidRuntime( 636): at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 636): at java.lang.reflect.Method.invoke(Method.java:380)
E/AndroidRuntime( 636): at android.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1170)
E/AndroidRuntime( 636): at android.os.ZygoteInit.main(ZygoteInit.java:1121)
E/AndroidRuntime( 636): at android.dalvik.NativeStart.main(Native Method)
E/AndroidRuntime( 636): Caused by: java.lang.ClassCastException
E/AndroidRuntime( 636): at java.util.Arrays.binarySearch(Arrays.java:365)
E/AndroidRuntime( 636): at org.codehaus.groovy.reflection.CachedMethod.find(CachedMethod.java:59)
E/AndroidRuntime( 636): at groovy.lang.MetaClassImpl.applyPropertyDescriptors(MetaClassImpl.java:1659)
E/AndroidRuntime( 636): at groovy.lang.MetaClassImpl.setupProperties(MetaClassImpl.java:1429)
E/AndroidRuntime( 636): at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:2319)
E/AndroidRuntime( 636): at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:2299)
E/AndroidRuntime( 636): at org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl.getMetaClass(MetaClassRegistryImpl.java:160)
E/AndroidRuntime( 636): at org.codehaus.groovy.runtime.Invoker.invokeStaticMethod(Invoker.java:120)
E/AndroidRuntime( 636): at org.codehaus.groovy.runtime.InvokerHelper.invokeStaticMethod(InvokerHelper.java:84)
E/AndroidRuntime( 636): at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeStaticMethodN(ScriptBytecodeAdapter.java:230)
E/AndroidRuntime( 636): at groovy.tests.HelloWorld.
E/AndroidRuntime( 636): at java.lang.Class.newInstance(Native Method)
E/AndroidRuntime( 636): at android.app.Instrumentation.newActivity(Instrumentation.java:760)
E/AndroidRuntime( 636): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1334)
E/AndroidRuntime( 636): ... 11 more
Not quite there yet but it’s close...failing just before the ApplicationLoader. I wish I could root around more in the android jar. So that’s it kids, I hope you don’t hold it against me if you thought I had a solution. There is a decent penalty for all the extra classes. The final versions spins for about 3 secs before failing.