What I mean with a meta data driven user interface is an application whose appearance and behavior is managed by a special set of data that is stored in a database and that is linked to attributes of the user. For instance the organization to which the user belongs has a contract whith the web application provider that enables the user to get certain types of information and disables other types. Therefore, a user interface widget, as for example a tree, should display nodes according to the set meta data that is connected to this user. Question is now how set up this stuff using Dojo for the presentation layer and Spring for the server side?
Â Â Â Â Â Â Â JSONObject obj = new JSONObject();Â Â Â Â Â Â Â obj.put("name", "Jan-Peter Balkenende");Â Â Â Â Â Â Â obj.put("address", "The Hague");Â Â Â Â Â Â Â ...Â Â Â Â Â Â Â JSONArray arr = new JSONArray();Â Â Â Â Â Â Â arr.put(obj);Â Â Â Â Â Â Â arr.put(obj2);Â Â Â Â Â Â Â ...
This view technology has the benefit that it is just the data that is transported from the server to the client. For instance when the user expands the tree by clicking a node, it is only the data (and the data only) in JSON format that is traveling tru cyberspace to the browser. A Dojo tree should give the user the experience of a quick widget. This can be enhanced by (1) the fact that the nodes reside in the DOM tree, and therefore are not retrieved again from the server when a node is expanded a next time again, (2) the asynchrone communication of Ajax enables the user to continue working when some operation takes time, and (3) user interface actions can be anticipated and data retrieval already prepared in the background.
Summarized: a rich user interface can be created with good programmer productivity and having a good user experience and performance. JavaServer Faces seems to be a popular framework to build front end applications. The exitement around the announcement by Oracle that ADF Faces soon will come up with a rich client renderer, amazed me because creating nice and user friendly web sites is possible since the introduction of DHTML in 1998. It’s like being exited when you buy a car that contains an airbag or electric windows. An other characteristic of JSF that keeps bothering me is that each request results in the construction and transportation of a complete web page together with repetitive boilerplate content. Why not just the data? It appears to me as a fat thing. (For more JSF bashing, check out timshadel.com/2006/01/19/jsf-the-7-layer-burrito-i-wont-eat-again.)
So far the presentation layer. On the server side we have Spring MVC, service objects, a Dao layer and the good old Oracle database. How could these classes be organized to configure the application behavior by means of the meta data, and to process the Ajax requests send by the Dojo client? We created the following components:
1. MetaDataService. An ordinary Java class on the service layer delivers meta data, for example a MetaTree domain object. This meta tree contains a list of nodes that are retrieved by MetaDataDao object from Oracle. The MetaTree defines the structure of the tree widget for the current user. When querying this tree definition from the database, attributes of a customized Acegi User are taken into account. Of course the MetaDataDao bean is wired into the service by IoC.
2. LoginController. For the time being (because there might be a more elegant solution), the MetaDataService is called by a class that handles the login request. It initializes the application by retrieving the meta data from the service layer and storing it on the session. We use the HttpSession object because it can be accessed quickly and also directly from the view.
3. DojoActionController. The Dojo-Ajax calls are mapped to handlers that have the super type DojoActionController. In the example above, the Dojo attribute:
Â Â Â RPCUrl="tree.do"
means that the calls are mapped to an URL that contains “tree.do”. The Spring ServletDispatcher is instructed only permit “.do” URL’s, and “tree” is mapped to the TreeController, which is a DojoActionController. The latter is a Spring MultiActionController. As the name suggests, a MultiActionController, consists of multiple methods, like for example in case of a tree widget, expanding a tree, or maybe move tree nodes, et cetera. The question is now, when a Dojo-Ajax tree widget is just mapped to the URL pattern “tree.do” and therefore just to a specific MultiActionController, how do we know which specific event on the tree widget is linked to which specific method of the controller? This can be done in an elegant way by means of the Spring class ParameterMethodNameResolver! One of the things this class can do is map the value of a request parameter to a method in the handler. In our example the Dojo parameter “action” is mapped to the methods in the TreeController. Expanding a tree in Dojo results in the Ajax call with parameters:
Â Â Â <bean id="treeController" class=".....TreeController"> <property name="treeService"> <ref bean="treeService" /> </property>Â Â Â Â Â Â Â Â Â Â Â Â Â Â <property name="methodNameResolver"> <ref local="dojoActions" /> </property> </bean>Â Â Â <bean id="dojoActions" class="org.springframework.web.servlet.mvc.multiaction. ParameterMethodNameResolver"> <property name="paramName"><value>action</value></property> </bean>
This is really beautifull, don’t you think? The latter bean definition “dojoActions” relates to ALL events of ALL Dojo widgets. The TreeController contains a method getChildren() in order to handle the expand node event of the Dojo tree. Other events of the tree will get their own method in the TreeController. Other Dojo widgets will get their own Controller class. The DojoActionController class is the super class that contains common functionality. For example a method that gets specfic meta data from the session. Or for example a method that writes directly to the HttpServletRespons object in order to transport the JSONArray back to the browser.
4. DojoWidget bean. An extra, third parameter of the MultiActionController methods is the command class. This is an ordinary Java class that has attributes that map to the request parameters and whose values are automatically bound to the bean. For example, see the signature of the getChildren() method of the TreeController:
Â Â Â public void getChildren(HttpServletRequest request, HttpServletResponse response, DojoWidget bean) throws ServletException, IOException, MetaDataNotFoundException
The DojoWidget bean is a domain object that contains the data JSON string transported by Dojo to the server. In this example the DojoWidget bean is used to construct a TreeNode domain object that represents the current node in the Dojo tree that the user wants to expand. In JSF terms this might be compared with the socalled backing bean.
5. MetaTree. Now we know the current tree node, we need to know what kind of node is the next level in the tree, in order to know what kind of nodes we need to request form the TreeService. Therefore we consult the meta data stored on the session, in this case the MetaTree domain object. This object returns the node type that the user is entitled to. Please note that the tree is generic and dynamic. It doesn’t matter what kind of objects it displays as long as the meta data is in synch with the base dataset. And also certain subscriptions or contracts of customers give permission to extra respectively less tree levels.
6. TreeService. Finally a service bean is called, passing in the current and the next tree nodes, in order to retrieve the tree node data from Oracle. These nodes are wrapped up into JSON format and transported to the browser.