RSS

Spring Web Flow basic example

07 Jul

Visit my new website http://java4developers.com

In this post we are going to see a Spring Web Flow simple example. For that, we need to use the Java code we talked about in JPA basic example with EntityManager , Spring and Maven and Criteria JPA 2.0 and database metamodel auto generation with Maven. Spring Web Flow allow us to create our own web application in an easy and fast way using flows. Transitions happens from some pages to others depending on which actions are ocurring, as clicking a specified button for example.


Our project structure is as follows:
estructuraProyecto-hop2croft-wordpress-com

We can notice that the only difference we find with previous project is that there is a webapp folder where our configuration and jsps files are. Spring Web Flow will use services we created in previous posts, for example getCars() method will return a car list from our mySql database.

We are going to explain our file structure within Spring WebFlow. In the next diagram the arrows mean that a file use another file in our configuration (the one where the arrows end up).

estructuraWebFlow-hop2croft-wordpress-com

The web.xml file is the main configuration file in any web application. In this file we are going to define two things.
Our application context. In our case we are going to define our context in the carMvc-service.xml file. In this file we have to add a bean service to access to our service layer.
A org.springframework.web.context.ContextLoaderListener listener that manages our application context.
In second place we need to define in the servlet elemen the servlet that deals with the web application requests. Our servlet will be named as carMvc (we are going to configure it in the carMvc-servlet.xml file) and will be a org.springframework.web.servlet.DispatcherServlet instance. We have to say this servlet which urls is responsible for. Our servlet will manage the ones that are requested to /flows/* url. Our web.xml :

<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

	<display-name>aplicación de ejemplo</display-name>

	<!-- indicamos que nuestros beans de contexto serán los que se indiquen
		en el fichero carMvc-service.xml -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>/WEB-INF/carMvc-service.xml</param-value>
	</context-param>

	<!-- será la clase que se encargará de cargar nuestro contexto indicado en el context-param -->
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>

	<!-- nuestro servlet se llamará carMvc. Tendremos que crear un fichero carMvc-servlet
		donde tendremos que incluir el fichero donde definamos nuestros flows (carMvc-webflow.xml)-->
	<servlet>
		<servlet-name>carMvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<!-- nuestro servlet carMvc será el encargado de gestionar nuestros flows -->
	<servlet-mapping>
		<servlet-name>carMvc</servlet-name>
		<url-pattern>/flows/*</url-pattern>
	</servlet-mapping>
</web-app>

Our carMvc-service.xml file where we define our application context is next.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<bean name="carService" class="com.hopcroft.examples.service.CarService" />

		<!-- The rest of the config is covered below -->
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		p:driverClassName="com.mysql.jdbc.Driver" p:url="jdbc:mysql://localhost/test"
		p:username="root" p:password="" p:initialSize="5" p:maxActive="10">
	</bean>

	<bean
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
		id="entityManagerFactory">
		<property name="dataSource" ref="dataSource" />
	</bean>

	<context:component-scan base-package="com.hopcroft.examples.dao">
		<context:include-filter type="annotation"
			expression="org.springframework.stereotype.Repository" />
	</context:component-scan>

	<bean class="org.springframework.orm.jpa.JpaTransactionManager"
		id="transactionManager">
		<property name="entityManagerFactory" ref="entityManagerFactory" />
	</bean>

</beans>

Our carMvc-servlet.xml only imports carMvc-webflow.xml file where we are going to manage our flow states.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<!-- se declaran los flows en otro fichero -->
	<import resource="carMvc-webflow.xml" />

</beans>

s

There are two different parts within the carMvc-webflow.xml file.
There is a web-flow:executor element to deal with our web flows through a specified controller bean that belong to org.springframework.webflow.mvc.servlet.FlowController class. Our flowController class is just a simple server that deals with our flows.
Besides that we have a webflow:flow-registry where we indicate that (bienvenido.xml) file will be the responsible of defining our application flows. carMvc-webflow.xml file is:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:webflow="http://www.springframework.org/schema/webflow-config"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/webflow-config
http://www.springframework.org/schema/webflow-config/spring-webflow-config-2.0.xsd">

	<bean name="/*" class="org.springframework.webflow.mvc.servlet.FlowController">
		<property name="flowExecutor" ref="flowExecutor" />
	</bean>

	<webflow:flow-executor id="flowExecutor"></webflow:flow-executor>

	<webflow:flow-registry id="flowRegistry">
		<webflow:flow-location path="/WEB-INF/flows/welcome/bienvenido.xml"></webflow:flow-location>
	</webflow:flow-registry>
</beans>

There is only one file left to explain. Within bienvenido.xml there are the two jsp files our project need. As we mentioned previously, our bienvenido.xml file defines our application flow diagram. Something important to say is that flow diagram files follow the Convention over configuration patter. What does it mean?. That means that if we say there will be a trasition from A view state to B view state, then there will be two jsp called A.jsp and B.jsp. Our bienvenido.xml content.

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<flow xmlns="http://www.springframework.org/schema/webflow"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/webflow
http://www.springframework.org/schema/webflow/spring-webflow-2.0.xsd">

	<view-state id="bienvenido">
		<transition on="next" to="list"></transition>
	</view-state>
	<view-state id="list">
		<on-render>
			<evaluate expression="carService.getCars()" result="requestScope.cars"></evaluate>
		</on-render>
	</view-state>
</flow>

There are two Spring Web Flowview states.
Bienvenido state will be our initial view state. Its visual aspect will be defined by the jsp named with the same name, i.e. , bienvenido.jsp. Bienvenido.jsp will be

<html>
<head>Bienvenido</head>
<body>
<a href="${flowExecutionUrl}&_eventId=next">Next</a>
</body>
</html>

Take a look at bienvenido.xml and bienvenido.jsp files, we can find out how our application flow diagram is built. Bienvenido.jsp will have a link to a next event . When we click our link we will make a trasition to list view state.
List.jsp. will show our car list. If we take a look to bienvenido.xml we can see that carService.getCars() method is called before showing the car list. We add the response in a requestScope variable named cars. This cars variable will be used by our jsp to show our cars.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>

<html>
<head>
<title>Car list</title>

</head>
<body>
	<table>
		<tr>
			<th>Company</th>
			<th>Model</th>
			<th>Price</th>
		</tr>
		<h2>Car list</h2>
		<c:forEach items="${cars}" var="car">
			<tr>
				<td><c:out value="${car.company}" /></td>
				<td><c:out value="${car.model}" /></td>
				<td><c:out value="${car.price}" /></td>
			</tr>
		</c:forEach>
	</table>

</body>
</html>

Here it is my pom.xml to define dependencies. We have to include the jetty plugin to use it directly from Maven.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.hopcroft.examples.spring</groupId>
	<artifactId>simpleWebFlowApp</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<build>
		<plugins>
			<plugin>
				<groupId>org.mortbay.jetty</groupId>
				<artifactId>jetty-maven-plugin</artifactId>
				<version>8.0.0.M3</version>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>javax.security</groupId>
			<artifactId>jacc</artifactId>
			<version>1.0</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>5.1.10</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.8</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>commons-dbcp</groupId>
			<artifactId>commons-dbcp</artifactId>
			<version>1.2.2</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.0.5.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>3.0.5.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>3.0.5.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-aspects</artifactId>
			<version>3.0.5.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>javassist</groupId>
			<artifactId>javassist</artifactId>
			<version>3.12.1.GA</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>3.5.6-Final</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.ow2.easybeans</groupId>
			<artifactId>easybeans-uberjar-hibernate</artifactId>
			<version>1.2.1</version>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-jpamodelgen</artifactId>
			<version>1.0.0.Final</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.webflow</groupId>
			<artifactId>spring-webflow</artifactId>
			<version>2.3.0.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>3.0.5.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>3.0.5.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>commons-logging</groupId>
			<artifactId>commons-logging</artifactId>
			<version>1.1.1</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.webflow</groupId>
			<artifactId>spring-binding</artifactId>
			<version>2.3.0.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.webflow</groupId>
			<artifactId>spring-js</artifactId>
			<version>2.3.0.RELEASE</version>
			<type>jar</type>
			<scope>compile</scope>
		</dependency>
	</dependencies>
</project>

We can see our web application in our brower as follow (notice that you can see flow states in the url):

pantallaInicioWebFlow-hop2croft-wordpress-com

pantallaListadoWebFlow-hop2croft-wordpress-com

Our application is quite easy and it only needs Spring Web Flow view states. But Spring Web Flow has also state, decision, subflow and end states.

We use jsp pages in our application but in Spring Web Flow we can add different JSF frameworks such as IceFaces, RichFaces, or the one you prefer. Spring has its own JSF framework called Spring Faces. We can also use the Dojo toolkit through the Spring Javascript framework.

 
13 comentarios

Publicado por en 7 julio, 2011 en J2EE, Spring Web Flow

 

Etiquetas: , , , , , , , ,

13 Respuestas a “Spring Web Flow basic example

  1. Web Development Company

    18 julio, 2011 at 11:33 am

    Thank you for sharing this post about the Web Development. This is very useful for Web Development Application Development. Thanks again 🙂

     
  2. Pingback: JavaPins
  3. Emad Al-Bloushi

    10 junio, 2012 at 9:20 am

    Great Job 🙂

     
  4. 0555111111

    23 junio, 2012 at 3:47 pm

    Great simple example, but how to just code and jsp in order to select one of the cars in the list using Spring Webflow? Thanks.

     
    • hop2croft

      24 junio, 2012 at 11:08 am

      Thank you for reading me!. Well, you can use the select spring tag to populate it and after that select one of them from it. Once you populate the select tag you can receive it once you submit the page within the specified controller.

       
  5. Diana Munteanu

    20 agosto, 2012 at 12:24 pm

    I am getting the the following exception

    java.lang.ClassCastException: org.springframework.web.servlet.DispatcherServlet cannot be cast to javax.servlet.Servlet

    does anybody know why???

     
  6. Diana Munteanu

    20 agosto, 2012 at 12:41 pm

    Sorry!!
    My fault !, I wrote a wrong name in package-scan …

     
  7. aironman2k

    9 May, 2013 at 3:33 pm

    hi, could you share the code on github? It will be useful for a lot of people.

    Thanks in advance

    alonso

     
  8. aironman2k

    9 May, 2013 at 3:34 pm

    http://java4developers.com returns a 403. check it!

    thank you

     
    • hop2croft

      15 agosto, 2013 at 8:59 pm

      Thank yo Aironman.

      I’ve already made it work.

       

Deja un comentario