After more than a year’s time, we have decided that we can’t keep going in the same direction anymore – it costs too much time and money and frustration. Munjari as it was conceived stays exactly the same – a dead-simple way for anyone to get their data online – but, since the first of the year, we rethought the project from the ground up and made quite a few changes.
With more experience, we now know that basic components that we expected would already exist, simply aren’t available or suffer from such massive quality problems that they can’t be used. Given that, we have come to the conclusion that we must write much more of the software ourselves instead of being able to follow in others’ footsteps. We looked for and found a new programming language, some new libraries, including a fair share that we are writing ourselves and, most of all, new hope and drive to get Munjari into your hands as quickly as possible.
When we started Munjari, we were also starting our business. Since Munjari is a privately-funded internal project, we had to figure out how to make it manageable in terms of both time and money invested. We decided on a strategy of building software for clients using the same technologies as we used in Munjari, so each could benefit from experience gained while working on the other.
At the time, we made what seemed like a relatively safe choice: we decided on Java. The backend software would be written in Java, as would the web site itself. All the cool kids were doing it.
We knew which components we needed:
Though the ORM is necessary for most projects, Munjari’s didn’t require one as both the project files and user data were far too generic to warrant using one.
We were drawn to Java because it’s one of the industry-standard languages – and we sure weren’t going to use C++! With the addition of annotations and rudimentary generics support, it had matured into a language worth using. The sheer number of libraries and open-source projects available is impressive. It seemed like a slam dunk.
We were not prepared for several disappointments:
Though there are literally dozens of web frameworks, they mostly support POJOs (Plain Old Java Objects). That is, they make it possible to render literally anything. They do not, however, provide any default rendering of objects or any framework that takes redundant work off of an application developer’s hands. In its native form (without, for example, the BeanForm library), Tapestry requires that you place all controls by hand, binding each to a property of the POJO, and writing in labels by hand. Even with BeanForm, the meta-data describing the form is defined in the page containing the form.
In essence, it seemed that many of the difficult bits of building applications – those that can be generalized for all web applications – were always left as “an exercise for the reader”. We increasingly noticed the time saved by using a framework being eaten up by the time invested bolting missing functionality onto a design that was often quite resistent to change. Already we were thinking more and more: if we were going to all of this effort, it seemed we could at least invest it into a design we believed in.
We began by using Tomcat as a local development server, which was an absolutely painful decision. Though it’s the industry standard for server deployment, it was sorely lacking as a development server. The key feature of a web server used for development is speed. It needs to start and stop quickly. Tomcat took, on average, about 5–10 seconds to start. Combined with the Tapestry start time of 10–30 seconds, this was completely unacceptable for development.
A server needs to be able to disable all caching or reload automatically anything that has changed. We started on Tomcat 4, which had shaky support for automatic reload, then moved to Tomcat 5, which was better, but still flawed. It seemed to understand that it should reload changed files, but still got confused, after which you were once again left to dig through its various on-disk caches to clean them out manually. Combined with a horrendous memory leak in Tapestry (discussed below), we were lucky to get 2 or 3 runs out of the server before it got unusably slow or simply generated an “out of memory” error.
After finding several tips online, we moved to the Jetty Java Container, which was considerably faster and more stable. The server start time itself was tiny, leaving us only with the Tapestry startup time to slow us down.
Even using Jetty, we were still surprised to find how often the server still needed to be restarted because the running JVM could not be hot-patched. It seems that this capability is limited to altering the implementation of defined methods. When it worked, it was wonderful – you can make a change, save the file and the execution point jumps back to the start of the function. It just didn’t work like that very often, for various reasons:
Compared to web development with other scripting languages, like PHP, development with Java was incredibly slow and annoying, getting in the way at nearly every step.
Tapestry is a Java web application framework, which takes a component-based approach to building web pages. Each page is a tree of components, each of which renders HTML output; together, they define the output sent back to the user. The engine within which this all occurs is a complex network of services that are instantiated and connected by the required companion technology, called Hivemind. Hivemind is an IOC (Inversion of Control) container; suffice it to say that it is a way of building an application, whose components are only very loosely coupled using Java interfaces.
If that all sounds horribly complicated, it’s because it is. Determining what exactly is going on during the handling of a page request is fraught with danger and uncertainty. Problems include:
Over the last year, Tapestry has fragmented more and more, with the founder of the library, Howard Lewis Ship, moving on to work on Tapestry 5, a new web framework, which is completely incompatible with Tapestry 4. Just as Tapestry 4 was more-or-less completely incompatible with Tapestry 3. Though Tapestry 5 looks quite promising and seems to address many of the problems found with the development model of Tapestry 4, it is still a long way off and we need a solution now.
Of all of the components that disappointed us, it’s Hibernate that came as the biggest surprise. Hibernate is an enormous open-source project with wide industry support and is used by hundreds, if not thousands, of applications around the world. Our attempts to shoehorn it into service were met with strong resistance. Upon digging deeper, we discovered we were neither at fault, nor alone. However, though others online were encountering the same bugs, they were far more likely to forgive Hibernate than we were.
Among the bigger problems were:
instanceof unusable.We came to the conclusion that our time was better invested in another solution than in programming around Hibernate’s rather egregious errors.
After a post-mortem like that, we decided to start fresh and looked around at other web frameworks. Our search came up with some interesting candidates:
So, that’s the latest news about Munjari. We’re working hard, but have had to backtrack a bit. We’ve put some bad experiences behind us and have learned from them. We’ll let you know soon which direction we’ve chosen and what kind of progress we’re making with our new solution as soon as we can.