Requirements

Prerequisite knowledge
Prior experience working with Flex Builder to create applications is useful, but not required. Some knowledge of working with BlazeDS is also helpful.
 
User level
Intermediate
Required products
Flash Builder 3 (Download trial)
BlazeDS (Download trial)
Sample files
todolist2.zip (8 KB)

 
Additional Requirements

 
Spring
Welcome to the second installment of this three-part article series. In Part 1 I described the process for creating and configuring a classic standalone Flex module built with flex-mojos. In this section, I'll continue with the development of the sample project (to-do list application) and describe how to create the back-end module, using Spring, Hibernate and MySQL. In Part 3 of this article series I'll cover how to connect the front-end of the application with the back-end using BlazeDS.
 

 
Creating a WAR module

In this section we'll get started creating the back-end of the to-do list sample application. First, open a command line in the todolist directory that we created in Part 1 of the series and run the following command:
 
mvn archetype:create \ -DgroupId=org.epseelon.samples \ -DartifactId=todolist-web \ -DarchetypeArtifactId=maven-archetype-webapp
The command above creates a new todolist submodule inside the root todolist module. Next, edit the POM of this newly created module to add the following dependencies:
 
<dependency> <groupId>org.springframework</groupId> <artifactId>spring</artifactId> <version>2.5.2</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.5.4</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>3.2.6.ga</version> </dependency>
The dependencies added above are required for Spring and Hibernate to work.
 
Last but not least, update the configuration of the Java compiler plug-in in this module so that we can use generics and annotations in our code. Add the following plug-in configuration to the project/build/plugins node:
 
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.5</source> <target>1.5</target> </configuration> </plugin>
At this point we've set up the module for the back-end, to prepare it for development. In the next section, we'll build the interface for the to-do list service using Java.
 

 
Writing Java code to develop the interface

In the previous section we prepared the module for the back-end of the to-do list application. Now let's write the interface for our main service. Create an "org.epseelon.samples.todolist.business" package in src/main/java, and then create a TodoService interface inside, using the following code:
 
package org.epseelon.samples.todolist.business; import java.util.List; import org.epseelon.samples.todolist.domain.TodoItem; public interface TodoService { void remove(TodoItem todoItem) throws Exception; TodoItem save(TodoItem todoItem) throws Exception; TodoItem findById(TodoItem todoItem) throws Exception; List<TodoItem> getList() throws Exception; }
The TodoService interface above is a very classic example of a CRUD service. Notice that the TodoItem class is being used as both a parameter and a return type for some of these methods. Normally I would never do this in a project, because when you have a situation like this where several entities have links between them, you run the risk of encountering LazyInitializationException problems on the client side. This occurs when you attempt to access linked entities while outside of a Hibernate transaction. This is not considered a best practice and should be avoided. But for the purposes of this sample project, it will work for the short term.
 
In production projects I like to use the value-object pattern, where I define data transfer objects for each entity and only use these objects as return types and parameters. I'm skipping over that part for the sake of clarity in this sample project—since there is only one entity in our domain. This is something you can add in later, after completing the steps to build the initial to-do list application.
 
Now we're ready to implement this service in the same package:
 
package org.epseelon.samples.todolist.business; import java.util.List; import org.epseelon.samples.todolist.domain.TodoItem; import org.epseelon.samples.todolist.domain.TodoItemRepository; public class TodoServiceImpl implements TodoService { private TodoItemRepository todoItemRepository; public void setTodoItemRepository(TodoItemRepository todoItemRepository) { this.todoItemRepository = todoItemRepository; } public TodoItem save(TodoItem item) throws Exception { try { this.todoItemRepository.save(item); return item; } catch (Exception e) { throw new Exception("Could not save item because: " + e.getCause()); } } public void remove(TodoItem item) throws Exception { try { this.todoItemRepository.remove(item); } catch (Exception e) { throw new Exception("Could not delete item because " + e.getMessage()); } } public TodoItem findById(TodoItem item) throws Exception { try { return this.todoItemRepository.findById(item); } catch (Exception e) { throw new Exception("Could not find item because " + e.getMessage()); } } public List<TodoItem> getList() throws Exception { try { return this.todoItemRepository.getList(); } catch (Exception e) { throw new Exception("Could not list items because " + e.getMessage()); } } }
As you can see, this implementation accesses a TodoItemRepository in package "org.epseelon.samples.todolist.domain". Here is the code used to create the interface:
 
package org.epseelon.samples.todolist.domain; import java.util.List; public interface TodoItemRepository { void remove(TodoItem todoItem); TodoItem save(TodoItem todoItem); TodoItem findById(TodoItem todoItem) throws Exception; List<TodoItem> getList(); }
This is its Hibernate-based implementation, in package "org.epseelon.samples.todolist.domain.hibernate":
 
package org.epseelon.samples.todolist.domain.hibernate; import java.util.List; import org.epseelon.samples.todolist.domain.TodoItem; import org.epseelon.samples.todolist.domain.TodoItemRepository; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; public class TodoItemHibernateDao extends HibernateDaoSupport implements TodoItemRepository { public TodoItem save(TodoItem todoItem) { getHibernateTemplate().saveOrUpdate(todoItem); return todoItem; } public void remove(TodoItem todoItem) { getHibernateTemplate().delete(todoItem); } public TodoItem findById(TodoItem todoItem) throws Exception { long id = todoItem.getId(); todoItem = (TodoItem) getHibernateTemplate().get(TodoItem.class, todoItem.getId()); if (todoItem == null) throw new Exception("Could not find an item with id " + id); return todoItem; } @SuppressWarnings("unchecked") public List<TodoItem> getList() { return (List<TodoItem>) getHibernateTemplate().loadAll(TodoItem.class); } }
And finally, the last piece of the Java puzzle is the code needed to create the org.epseelon.samples.todolist.domain.TodoItem class:
 
package org.epseelon.samples.todolist.domain; public class TodoItem { private long id; private String title; public long getId() { return id; } public void setId(long id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } }
The TodoItem class shown above is a standard implementation for returning the data from the repository.
 
Make sure to run 'mvn install' to ensure that the code compiles before moving on to the next section. In the next part, we'll configure the MySQL database and set up all of the pieces to work together.
 

 
Configuring the MySQL database

This section describes the setup of a MySQL database to store the application data. The first steps involve creating a todolist database and granting a user named "todolist" with the password "todolist" all rights to edit this database. After that is accomplished, we need to create one table in the todolist database.
 
Here is the DDL script to create the table:
 
CREATE TABLE `todoitem` ( `id_todoitem` int(10) unsigned NOT NULL auto_increment, `title` varchar(256) NOT NULL, PRIMARY KEY (`id_todoitem`) ) ENGINE=InnoDB;
Once you have created the table in the database, the next task is to configure the object-relational mapping for Hibernate. Create a TodoItem.hbm.xml file in src/main/java/org/epseelon/samples/todolist/domain/hibernate/hbm with the following content:
 
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="org.epseelon.samples.todolist.domain.TodoItem" table="todoitem"> <id name="id" column="ID_TODOITEM" type="long"> <generator class="native" /> </id> <property name="title" column="TITLE" type="string" not-null="true" length="50" /> </class> </hibernate-mapping>
It is important to note that I could have used JPA annotations, rather than XML, but I prefer to work with XML so that is what I'm using for this sample project.
 
In order for the XML file to be included in our web application we need to add some configuration code to our POM. In the build element, add the following:
 
<resources> <resource> <directory>src/main/resources</directory> </resource> <resource> <directory>src/main/java</directory> <excludes> <exclude>**/*.java</exclude> </excludes> <includes> <include>**/*.xml</include> </includes> </resource> </resources>
At this point our entity is mapped. Now we can move on to the process for configuring Spring. Create a file named applicationContext.xml in src/main/webapp/WEB-INF that contains the following:
 
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd"> <!-- Properties file --> <context:property-placeholder location="/WEB-INF/jdbc.properties"/> <!-- Datasource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <!-- Hibernate SessionFactory --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref local="dataSource"/> </property> <property name="mappingDirectoryLocations"> <list> <value> classpath:org/epseelon/samples/todolist/domain/hibernate/hbm/ </value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> ${hibernate.dialect} </prop> <prop key="hibernate.show_sql">true</prop> </props> </property> <property name="eventListeners"> <map> <entry key="merge"> <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> </entry> </map> </property> </bean> <!-- ========================= BUSINESS OBJECT DEFINITIONS ========================= --> <bean id="todoService" class="org.epseelon.samples.todolist.business.TodoServiceImpl"> <property name="todoItemRepository" ref="todoItemRepository"/> </bean> <bean id="todoItemRepository" class="org.epseelon.samples.todolist.domain.hibernate.TodoItemHibernateDao"> <property name="sessionFactory" ref="sessionFactory"/> </bean> <!-- ========================= TRANSACTION MANAGEMENT ========================= --> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory"/> </property> </bean> <tx:advice id="txAdvice" transaction-manager="txManager"> <!-- the transactional semantics... --> <tx:attributes> <!-- all methods starting with 'get' are read-only --> <tx:method name="get*" read-only="true"/> <!-- other methods use the default transaction settings (see below) --> <tx:method name="*"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut id="todoServiceOperation" expression="execution(* org.epseelon.samples.todolist.business.TodoService.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="todoServiceOperation"/> </aop:config> </beans>
I recommend taking the time to read through the code above, because it includes a couple of intriguing and powerful features available in Spring 2.5.
 
In the first line in the file above, we import properties from a properties file. Let's create that jdbc.properties file in src/main/webapp/WEB-INF and add the following to it:
 
jdbc.driverClassName=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/todolist jdbc.username=todolist jdbc.password=todolist hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
Getting back to applicationContext.xml explanation, we then configure the Hibernate session factory.
 
After that, we create the service beans: todoService and todoItemRepository. And then we configure everything needed to wrap the service calls in transactions.
 
Once again, I could have used annotations to configure the beans and their connections, but I don't like to set it up that way. One of the primary reasons I enjoy working with Spring is that it allows me to gather all the wiring configuration in one place. I prefer keeping the connections in an XML file rather than having to sort through Java files to see how everything is connected.
 
In order to make the application context load into the web application, we have to edit src/main/webapp/WEB-INF/web.xml, like this:
 
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5"> <display-name>Todo List</display-name> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class> org.springframework.web.context.ContextLoaderListener </listener-class> </listener> <listener> <listener-class> org.springframework.web.context.request.RequestContextListener </listener-class> </listener> <welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
At this point we're still missing two things. The first part is to create a log4j.properties file in the src/main/webapp/WEB-INF directory, like this:
 
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n # set root logger level to debug and its only appender to mtf log4j.rootLogger=INFO,development # only for development purposes log4j.appender.development=org.apache.log4j.ConsoleAppender log4j.appender.development.layout=org.apache.log4j.PatternLayout log4j.appender.development.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %5p [%t] (%F:%L) - %m%n log4j.logger.noModule=FATAL log4j.logger.org.springframework=WARN # Log JDBC bind parameter runtime arguments log4j.logger.org.hibernate.type=DEBUG
And finally, we need to put the JDBC connector driver on the classpath of the application. In other words, if you're using JBoss, you have to download mysql-connector-java-5.x.x.jar and place it in $JBOSS_HOME/server/default/lib. In Tomcat, I think you can place it directly in $TOMCAT_HOME/lib. Be aware that it is not a good practice in a production environment to add this connector to your module dependencies in order to bundle it with your application.
 
 
Testing the application
For this first test, we'll just make sure the sample application starts successfully. (Later, we'll check to ensure that services work). Run 'mvn install' on the root module and copy todolist-web/target/todolist-web.war to the deployment directory ($JBOSS_HOME/server/default/deploy for JBoss, $TOMCAT_HOME/webapps for Tomcat). Then start up your server and look at the log. If you don't see any error messages, then you've completed the steps of this section of the article series. If you do get an error message, double check that you've done everything as described in this article, and if the error persists, try Googling the error to see if you can troubleshoot the issue. If it remains unresolved, please contact me and include comments describing the error you are receiving.
 

 
Where to go from here

In the next part of this three-part article series, I'll cover the process for developing the Flex UI and describe how to plug it into our Spring back-end using BlazeDS. Stay tuned!
 
To get more information about working with Hibernate, see the following online resources:
 
And be sure to visit the Flex Developer Center to learn more about developing Flex applications. You'll find the latest articles, tutorials and sample projects to get you started.