What’s the resemblance between Tai Chi and the Spring Framework? Nothing. …Hmm, it might be noted that both support in gaining an healthy architecture, the first regarding the human body, the latter regarding a Java application. The two different worlds of an ancient art and modern Java programming, has been brought together by Amis by developing an administrative system for the International Taoist Tai Chi Society (ITTCS). This Canadian based association, is the largest non-profit tai chi organization in the world. It is spread over more than 20 countries. The application is called Fred after a cat who lived at a ITTCS site (untill a more meaningfull name would come up). More about ITTCS can be found here: www.taoist.org.
- Standards. The framework is created by Rod Johnson and contains years of experience and best practices. It is used on a wide scale and is well supported. See also www.springframework.org. Because Fred is conducted by volunteers for a charity organization, it is important to avoid obscure or proprietary technology. This is the case in Fred, because the only non-open standard code are Oracle database SEQUENCE and TRIGGER objects, that are used to generate a new key value when a new record is inserted in the database. The use of Oracle SQL is regarded as having enough openness (Oracle is in fact one of the key players in defining the SQL standard). SQL is used for creating TABLES, INDEXES and CONSTRAINTS and for accessing the tables.
- Maintainability. Spring is based on Inversion of Control (IoC). Dependencies are injected into Java beans from outside and specified in XML application context configuration files. This technique, together with the heavy use of Java interfaces, makes it well suited to implement major changes later in the life-cycle of the application. Unit testing is also improved by IoC. We try to conduct Fred in an Agile way. Flexibility is therefore important.
- Open Source. Free licenses are suited for a non-profit organization.
The challenge of the project has been the short timeframe (about one month) and the lack of experience with this framework. Apparently Spring is not too hard to grasp for a newby, because two developers of Amis succeeded in delivering a basic application, that can be used in production (taken some user unfriendliness for granted). The application has been installed on a Linux Debian server in Alberta and can be reached at: http://126.96.36.199:5580/fred. The customer has expressed satisfaction with the delivery by Amis. This is not to say that the construction of the appliction is finished. From the beginning it was planned that Amis would provide with a solid basis for further development by a communinity of volunteers (which is by the way in sync with the philosophy of ITTCS, that working together on a goal is as much beneficial as reaching that goal). In order to facilitate this Amis, delivered a collaborative development infrastructure consisting of: Subversion, Maven and Continuum. All Open Source. Continuum can be reached at: http://188.8.131.52:8280/continuum.
Like to join us?
If you like to dive into the Spring framework or for some other reason want to help to extend the functionality of the application, just leave a comment on this post. A document is provided to describing the steps to set up your development environment.
How does Fred look like?
The figure below shows the components of the application:
The components displayed in the green colored boxes belong to the Spring framework. Before we dive into the layers of this J2EE application in more details, letâ€™s have a brief look at them:
- Datasource. Non-Spring. Oracle database does not need any introduction on Amis’ blog. Express Edition (XE) is free! In Fred Oracle SQL is used to guard over the integrity of the data.
- Dao tier. The implementation of a persistence technology like e.g. Hibernate, has been decided to be too costly at the first stage of the project. It has been scoped out for the time being. In Fred 0.1 JDBC is used to talk with the database. Adavantage of JDBC is its high performance.
- Business tier. The business tier consists of Plain Old Java Objects that offer data related tasks like for example register a new member, and objects that implement business logic.
- Web tier. Spring MVC is a framework that controls the flow between web pages. It can be compared with Apache Struts regarding its role in the application, but its technology is quite different. In a nutshell: requests are dispatched to controllers, that use objects from the Business tier to produce domain objects (data like for example a member instance) and puts these into a model. The controller chooses a view (web page) and returns the view and the model to the requestor. Validators can be linked to controllers that can be used to validate user input. These validators overlap to some extend with the validation implemented in the database by Oracle constraints. For example: a Spring validator will note that a required field is missing and respond by presenting an error message to the user. Without this validator the database would have noticed the missing field and would have refused to process the insert or update statement. Benefit of this architecture is that it prevents roundtrips to the database in case of erroneous database statements, while at the same time the database is responsible for its own integrity. The database should not be dependant on clients for validation.
- Presentation. Non-Spring. The web tier is independant of the view technology used. Fred uses the familiar JavaServer Pages. The look and feel of these pages are quite basic in the first version of Fred. In Fred 0.1 just a simple stylesheet (CSS) will be added. The design should be created by graphical designers and should reflect the house style of the customer. Important to note is that the design can be implemented relatively independent from the application by the use of Cascading Style Sheets (CSS).
In the following sections we will dig deeper into each of the layers.
The database is accessed thru JDBC. Currently we use Oracle JDBC drivers packaged in ojdbc14.jar These drivers use an older version of Java, namely JDK 1.4. They implement JDBC 3.0. JDBC talks with the database. Spring talks with JDBC. The developer does not need to use JDBC directly, but indirectly by Springâ€™s JDBC Framework. The major advantage is productivity and quality improvement. Lots of boilerplate code lines are avoided because this is hidden in the framework. The framework also takes care for opening and closing connections, statements and result sets. An example of how creating a new record in the database might look like:
This method is member of class MemberListJdbcDaoImpl. This class is part of the package org.taoist.fred.dao.jdbc. It extends the framework class JdbcDaoSupport. From this class it gets a reference to a DataSource object. With this datasource a JdbcTemplate object is created. This template object offers a lot of functionality. In this example we see that we just have to call an update method and pass in an SQL string and an array of values that are binded to the insert statement defined by the string. Thatâ€™s all.
What we also can see in this example is that a FredUser object is retrieved from the SecureContext. This object contains the username, password and other information like the ID of the member table, the ID of his organization. This User object is created when the user is authenticated during logon. The member ID is inserted into the audit columns CREATED_BY and UPDATED_BY.
The datasource is defined in the servlet container, which is Tomcat 5.5 â€œCatalinaâ€. Tomcat will create a connection pool. The data source will be made available for the servlet by means of adding an element to the servlet configuration file /WEB-INF/web.xml:
Next we need to create a datasource bean in application context configuration file /WEB-INF/dataAccessContext.xml:
All Dao (data access object) classes are specified in this configuration file. This data source bean, named â€œdataSourceâ€ is injected into the other Dao beans. For example:
When the application is instanciated this configuration file is passed to a bean factory that creates the beans (in this case Dao beans). When the MemberListJdbcDaoImpl bean is created, the data source is passed on to its super class JdbcDaoSupport. Now we have returned to the beginning of this paragraph where we discussed the example of the insertMember method of the MemberListJdbcDaoImpl bean.
Fred contains several Dao beans in package org.taoist.fred.dao.jdbc:
These beans implement Dao interfaces. These interfaces define contracts. The JdbcDaoImpl classes are a specific implementation of these contracts. Here we can see the power of Spring, namely we can create a new package org.taoist.fred.dao.Hibernate that contains an implementation that uses Hibernate persistence technology, without touching the rest of the application (except adjusting context configuration file /WEB-INF/dataAccessContext.xml).
The Dao tier is used by the business tier. The purpose of this tier is to offer business logic. In Fred there is not much of this kind of functionality at the moment. An example of this kind of code is the MemberList bean. One of the things this bean can do is to register a new member. When it is doing that is generates a username and a random password. The latter is performed by using the PasswordGenerator class which is an open source product created by Darron Schall. When it has a username and password, it will call the Dao layer to put it in the database. The business beans are stored in package org.taoist.fred.biz They are wired in the application context file /WEB-INF/businessContext.xml.
The business tier is used by the web tier. In Spring this is the MVC framework. The beans that operate on this tier are wired in the application context configuration file /WEB-INF/webContext.xml. They are of several types, namely Controllers, PropertyMethodNameResolvers and Validators. There are different types of Controlles. Fred currently uses:
- URLFilenameViewController. This type of controller takes the filename from the request and returns this directly to the ViewResolver. For example when /secure/help_menu.html is requested, help_menu is returned, without any further custom code being called.
- MultiActionsController. This type of controller looks up the path of the request in order to find the name of a method to be called. The methods are defined in the Controller class. The Controller uses a PropertyMethodNameResolver. This class contains the mapping between the path and the method name. For example take a look at the bean definition in /WEB-INF/webContext.xml of class OrganizationsController in package org.taoist.fred.web:
When /secure/showorganizations.html is requested, then method show() of class OrganizationsController is called. As you can see in the XML definition, the business bean OrganizationTree is injected into the Controller bean. This enables the method show() to request a list of organizations from the database. This list is put into a Map that is on his turn put into a ModelAndView object. This object also contains the name of the view. In Fred a view is a JavaServer Page. This ModelAndView object is returned to a ViewResolver.
- SimpleFormController. This type of Controller is associated directly to a specific view and to a backing bean that holds the state of the fields displayed in the view. SimpleFormControllers can also be linked to a Validator. An example in Fred is the PasswordController:
The requests are mapped to controllers in the context configuration file fred-servlet.xml. This is done by the SimpleUrlHandlerMapping class.
When the Controller has finished, the resulting view is resolved by the ViewResolver. Fred uses InternalResourceViewResolver. This is wired in fred-servlet.xml as follows:
It simply takes the name of the view and adds the prefix /WEB-INF/jsp/ and suffix .jsp, in order to locate the JSP file to be processed and generate the response to the requestor.
In Spring the request â€“ respons flow is quite elegant. Letâ€™s summarize:
- The request contains a virtual path, e.g. /secure/organization.html. In /WEB-INF/web.xml it is specified that all paths ending on .html are routed to the Spring DispatcherServlet.
- The DispatcherServlet is configured (in /WEB-INF/fred-servlet.xml) to map the path to a Controller.
- The Controller is configured to certain operations and will return a view upon completion.
- The DispatcherServlet is configured (in /WEB-INF/fred-servlet.xml) to map the view to a certain real existing JSP file (Fred uses JSP, but this could be another view technology e.g. Velocity, FreeMarker, Excell, PDF, â€¦).
In short: a virtual path is mapped to a real file. For example, in Fred requesting secure/organizations.html is directed to /WEB-INF/jsp/organizations.jsp. What I like here is that the security is defined on the virtual paths, and not on the real JSPs.
Fredâ€™s presentation technology is JavaServer Pages. Most developers are familiar with this. The JSP-files are stored in directory /WEB-INF/jsp. All JSPs include taglibs.jsp, banner.jsp and menubar.jsp.
The file taglibs.jsp contains the taglibs used by Fred. They are:
As can be seen Fred uses some homegrown tags stored in directory /WEB-INF/tags. Currently this consists of two dropdown list HTML widgets. Fred also uses a Spring taglib and a taglib of the Acegi security framework.
As said before, the presentation is quite basic. The JSPs use a simple style sheet. People with HTML, CSS skills and artistic inspiration are invited to modify the look and feel of Fred. For this reason the JSPs have been kept decoupled from layout stuff â€“ as much as possible – by the use of Cascading Style Sheets. Modifying the look and feel should be done by changing the style sheet file (or adding a new CSS file).
Security is provided in Fred by the Acegi Security framework. This framework offers many features. Fred currently uses two of them, namely authentication at logon and authorization by mapping of roles to URIs. Besides these security measures there are some more security functions implemented in Fred.
Acegi Authentication. The beans that provide the Acegi security are wired in context configuration file /WEB-INF/securityContext.xml. Acegi security is provided by filters and is defined outside the servlet container (which makes the application portable). Filters are chained by the FilterChainProxy bean. One of these filters is the AuthenticationProcessingFilter. An AuthenticationManager is injected into this filter. On his turn, this manager gets a specific AuthenticationProvider. Fred uses a DaoAuthenticationProvider. This provider gets injected an AuthenticationDao. Fred uses a custom Dao, because we want to store extra information about a user that needs to be used in order to decide on granting access based on properties like member ID, organization ID. This class is AuthenticationJdbcDaoImpl defined in package org.taoist.fred.security. It creates a FredUser instance when a user is successfully authenticated on logon. This FredUser bean contains the attributes that are used for authorization.
An user is authenticated successfully in Fred when:
- The username and password are correct
- The account is enabled
- At least the role Member is assigned
- The status of the member does not prohibit.
Acegi Authorization. URLs are mapped to roles (Granted Authorities) by the FilterSecurityInterceptor bean, which is defined in the securityContext file. These roles are stored in the database in the table ROLE and assigned to members in table ROLE_ASSIGNMENT. The FredUser bean contains the list of roles assigned to that user. By using a kind of wildcards (ANT patterns) virtual paths can be mapped to roles. In this way access to pages can be managed.
For specific pages it happens that a user has access privilege, but only when this page deals with his own data or data of his organization. By consulting the FredUser bean it can be decided if this is the case. However it does not really help to hide the HTML widget that navigates to this page, because the URL can be rewritten in the browser. This can be solved by an AclManager.
Database audit colums. For all data manipulation actions it is recorded which member performed the action. In columns CREATED_BY and UPDATED_BY the member ID is stored.
I has been fun working with Spring. The quality the framework is very high. And when I happened to hit some kind of issue, then I found tons of information how to deal with it offered by other developers on the web. The version of Spring I have been using was a bit behind, but I hardly met any bug. Also the productivity was quite good. As said before, as newbies we managed to deliver quite a lot in the short timeframe. This is the idea of a framework: a X-mas tree; the developer just needs to deliver the balls and put these into place.
- Cas Stigter : programming and researching Spring
- Wouter van Reeven : installing on Linux Debian Sarge
- Rob van Maris : introducing Subversion, Maven, Continuum
- Lucas Jellema : supporting the project
- Chris Gralike : technical support
- Jeroen Pielage : introducing Spring