In life, choice is a good thing. But sometimes we are overwhelmed with too much choice. In selecting a framework for web applications, we are confronted with a wide variety of frameworks, application servers, SDK's, libraries, etc. It can even be hard to figure out what belongs in which category and what are the differences between them. Making a decision in the J2EE environment is especially hard. Every time I search the net, I seem to come across still another framework about which I knew nothing.
In such a scenario, the tendency is to select one based on brand, popularity or familiarity. Exploring and evaluating the options is just not viable. We understand that the motivation behind each option is to simplify development. The war cry 'DRY' (don't repeat yourself) of Ruby on Rails, perhaps best describes the intention. Hence, to a certain extent, we can choose any framework as it will save us effort. Still the concern remains, why are there so many options? These include :
The net effect is
If the choice of frameworks is bad enough, the combinations of frameworks which can reasonably solve a problem is truly mind boggling. Hence, rather than looking at various frameworks and what each one does, it is desirable to look at the fundamentals and look at the problems which are being addressed. Using an example helps. We will choose TurboGears, a Python based framework, because it is composed of multiple projects, each addressing a well defined need and each conceptually distinct from the other.
The boundaries of the alternatives in the Java environment are often not as well defined. We will give some names selecting the primary problem domain of the framework.
We have users using a variety of web-browsers communicating with a web server, which will need to deliver dynamic content.
The first problem we need to resolve is the web server. It must accept a request from a client and deliver the response to the same client. We as developers do not wish to be concerned about the protocol and the low-level issues associated with this task. A web server like Apache will do this job very well except for dynamic content. The burden of handling cgi scripts will fall on the programmer.
So, our web server must also be able to handle requests for dynamic content easily. It must be a 'container' for the server side code. In TurboGears, these tasks are performed by CherryPy.
There must also be a way to map the request coming from a client to the code in the server which needs to be executed. This is often accomplished by XML configuration files. The increasingly preferred option now is to use conventions instead of configurations. This is because the web applications have become very complex and maintaining the necessary configuration files becomes a pain. Unless conventions are followed, trying to figure out what went wrong and why, can be very difficult for programmers, especially if they did not write the affected code.
One of the conventions is RESTful interfaces. The client communicates with server using a URL. This is in contrast to SOAP-like interfaces. In CherryPy, in a URL like http://host:port/thePage, thePage represents the application dependent part, which corresponds to a Python object and a method of the object. The default method is 'index'. The get or post parameters are the parameters to the method. Instead of the URL representing a tree of directory and file structures, it represents a tree of Python objects.
A key aspect in selecting the web server will be looking at the way the URL's are mapped to the servlets keeping in mind that flexibility is not necessarily a good thing. Another issue will be integrating the web server with, say, Apache, and the volume of transactions it can handle.
In the Java world, the open source options include Tomcat, Jetty and Resin.
Let's look at a Hello World example in CherryPy.
This will return the expected string. If we wanted to send a formatted html page, the code for the HelloWorld class will look like:
The readability of the code goes down by several orders of magnitude. Mixing of html and Python like syntax creates a mess. A solution is obvious. Let us refactor the code and see where it leads us.
TurboGears uses KID as the templating engine. It is Pythonic. In the Java world, the common templating engines are Velocity and Freemarker, which surprisingly are not commonly used!
There is an alternate to the messy code problem. Especially in the early days of the web, most of the html page was tagged with a only a part of the page containing dynamic data. Hence, a natural approach was to create a language which used tags like html but allowed flexibility of a programming language. This approach has been immensely successful with PHP. Java followed a similar model and created JSP.
The Struts 2 J2EE framework uses Freemarker templates internally but allows the user to use JSP, Velocity or Freemarker for creating the html pages. If the project had compelled organizations to switch from JSP, it would have doomed the framework to oblivion!
So, the second problem the frameworks are trying to solve is a convenient way to present the information to the user. The layout will have inputs from the designers. Evaluation should seriously look into the implications of designers changing page layouts and its impact on development. Templating engines may provide a better insulation of the code than JSP though Java Server Faces with JSP may also prove very helpful.
In the Java world, the options include JSP/JSTL, Struts, Struts 2, JSF, MyFaces, Seam.
Options in Java world include Ajax4jsf/RichFaces. Frameworks like Struts 2 and Seam support the creation of rich client interfaces.
Finally, all the work the user does has to be saved somewhere. We come to the Model part of the MVC pattern. We would like to be able to work with and manipulate data as objects and not have to worry too much about the database hidden behind this layer. Since the common databases are relational, we are looking at object relational mapping(ORM). Turbogears uses SQL Object for ORM, which uses the Active Record pattern. Ruby on Rails also uses the Active Record pattern. In the Java world, the most common ORM is Hibernate and, now, EJB3.
Earlier version of EJB's were quite complex to use. This resulted in attempts to create frameworks which were easier to use but still allowed the business data model to be separated from the rest of the application. A successful example of this is Spring.
Working with a web page does not depend upon the technologies being used on the server. Web services make it easy for us to work with different applications. Hence, it is possible for us to choose a framework based on the need and appropriateness for the problem under consideration. We are not trying to suggest that we should have a zoo of application frameworks on our server but that we do not have to stick to a decision made earlier if better options are available.
The convention over configuration approach of Rails, Django, TurboGears and the advantages of agility available by using scripting languages have also appealed to many people who are using Java and J2EE frameworks. It is possible to run simple Rails applications using JRuby. People are experimenting with running Django, TurboGears and Pylons using Jython. Another promising entry is Grails, a Rails clone built using Groovy and on top of existing J2EE frameworks like Spring and Hibernate.
The choice is about to get wider; but it is definitely worth exploring and adopting one of these frameworks for, at least, the less frequently used application components and get more features with same effort. What more can one want.
Other Articles >