Here at Windward, we’ve taken some steps forward to make sure you benefit from the latest technology. Our product is automatically compatible with any IaaS cloud service (Infrastructure-as-a-Service), but some of the PaaS (Platform-as-a-Service) providers introduce some constraints.
For example, Google App Engine code must be in pure Java. This isn’t a foreign concept to Java servlet developers, except now the hoops you can jump through to run JNI on a servlet are not allowed.
So here’s how we updated our Engine/library for Google App Engine.
There are some obvious issues to deal with when it comes to running an application on the cloud. In a normal context, the Engine is likely to do the following tasks:
- Loading a template from the disk
- Loading data from the disk (e.g. if you have an XML data source)
- Saving a report or other generated document to the disk
But from a cloud, you don’t have the concept of a disk (and if you do, please contact your security team ASAP). What you have instead is access to certain resources through a server interface.
This could be as simple as using GET and POST requests to a server. For Google App Engine, a number of interfaces as such are available, such as Datastore and Blobstore for Java. We chose to use the datastore mechanism through an Apache Commons VFS plugin known as Google App Engine Virtual File System. This way the API remained fairly similar to how we already dealt with files.
We hadn’t taken care of everything yet though! There are a few packages that utilize JNI, and unfortunately, replacing these packages with pure Java alternatives is non-trivial. For us, those packages are part of the standard Java library. They are javax.imageio and java.awt. We use javax.imageio for image manipulation, and also for just simply reading images from templates. However, java.awt is even more fundamentally implemented in our software because some of its classes we use to represent data for colors and images throughout our entire engine.
Finding replacements for these packages wasn’t easy, although a helpful tip is that the Android platform presents some of the same constraints as Google App Engine in terms of what you can and can’t use in Java. Given that Android developers usually develop consumer applications whereas Google App Engine developers usually develop server applications, Android is generally a much more popular developer platform. By searching for a solution to these problems in the context of Android, we automatically found solutions that also work on App Engine.
For javax.imageio, we found Apache Commons Imaging and for java.awt, we found Apache Harmony’s implementation of the Java standard library. In fact, Apache Harmony was really great news for us since their goal was to implement the Java standard library under the same interface (which means the code change for us could be done with the GNU tools find and sed)!
What’s even cooler? We’re not the first ones that have ventured down this road!! Someone had created a project on Github (originally on Google Code) called appengine-awt whose tagline is “a pure java implementation of the java.awt and javax.imageio packages for use in the Google AppEngine environment.” In fact, appengine-awt uses Apache Harmony and Apache Commons Imaging so we’re in good hands!
There were just a few modifications we made to appengine-awt first before we put it in production.
- First, there was a class, imageio.stream.FileCacheImageInputStream that still used java.io for file handling (which, as we discussed above, doesn’t work with App Engine) so we switched it to use GaeVFS.
- Next, since appengine-awt used the incubator version of Apache Commons Imaging (then known as Sansalen), we replaced it with the latest stable code. With those simple modifications, we were good to go (and we put the modified version of appengine-awt up on GitHub).
- Finally, since javax.imageio was ultimately replaced by Apache Commons Imaging (in appengine-awt), the interfaces changed enough to justify a rewrite of our image handling classes, but they were in need of such a rewrite anyways (and became much simpler for the rest of the engine!)
Author: Marcus Johnson
Other posts by Marcus Johnson