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.
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.
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.