spring

Spring struts integration example

We have studied about  configuring a web-application to use Spring MVC in the previous example.
In this example we will talk about how we integrate the Spring and Struts framework to get the best of both worlds.

Struts2 is a quite popular MVC framework. It has an XML file : struts.xml which is mainly responsible for all the configuration. This results in less code for compilation when making a change to the web-application.

It has custom JSP tags that make it easier to represent data on the view layer. In the same way, the values entered by the user can be pushed on the value-stack and can be available on the controller layer. This helps the developer to focus mainly on the domain and business logic.

Struts2 has built-in Framework for validation of the input which is robust and extensible.

Spring, on the other hand, has a very powerful and robust Inversion of Control feature. IoC helps in loosely coupled code,seperation of concern and easy testing of the web-application.

 
Here we will try to merge the two frameworks and see how it can be done to get the best out of the both. Let’s start with the web.xml

web.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?xml version="1.0" encoding="UTF-8"?>
  <display-name>SpringMVCloginExample</display-name>
   
  <welcome-file-list
    <welcome-file>jsp/login.jsp</welcome-file
  </welcome-file-list>
   
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath://resource//springBeanConfiguration.xml
    </param-value>
</context-bparam>
   
<listener>
      <listener-class>
         org.springframework.web.context.ContextLoaderListener
      </listener-class>
   </listener>
 
 
 
   <filter>
      <filter-name>struts2</filter-name>
      <filter-class>
        org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
      </filter-class>
   </filter>
 
   <filter-mapping>
      <filter-name>struts2</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
   
</web-app>

We configure the ContextLoaderListener to start the spring-bean factory, so that it can inject the bean where they are to be injected. The StrutsPrepareAndExecuteFilter filter intercepts each request and maps it to the struts.xml.

struts.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
 
<struts>
    <constant name="struts.devMode" value="true" />
    <package name="helloworld" extends="struts-default">
        <action name="login" class="strutsController" method="execute">
            <result name="SUCCESS">/jsp/welcome.jsp</result>
 
            <result name="Failure">/jsp/login.jsp</result>
        </action>
    </package>
</struts>

The struts.xml redirects the requests it receives to the appropriate Action class files. The struts.xml invokes the proper method and returns the view as per the string returned by the action class. In the struts.xml instead of passing the fully qualified name of the class we are passing the name of the bean we have registered with the spring-bean factory. The spring bean factory is defined using the springBeanConfiguration.xml file.

springBeanConfiguration.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    xsi:schemaLocation="
 
    <bean id="strutsController" class="com.jcg.examples.controller.StrutsController">
        <property name="loginDelegate" ref="loginDelegate"></property>
        <property name="loginBean" ref="loginBean"></property>
    </bean>
 
    <bean id="loginDelegate" class="com.jcg.examples.delegate.LoginDelegate">
        <property name="userService" ref="userService"></property>
    </bean>
 
    <bean id="loginBean" class="com.jcg.examples.viewBean.LoginBean"></bean>
 
    <bean id="userService" class="com.jcg.examples.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
 
    <bean name="userDao" class="com.jcg.examples.dao.impl.UserDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
 
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/jcg" />
        <property name="username" value="root" />
        <property name="password" value="toor" />
    </bean>
 
</beans>

The Spring-bean factory instantiates and injects the action class and other classes like the bean classes and the delegates into the struts.xml for serving the request.

We have created a sample Login JSP, wherein the user enters the username and password to login into the web-application.

Here’s the login.jsp

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
<%@include file="include.jsp"%>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
        <title>Login</title>
    </head>
    <body>
        <font color="red">${message}</font>
        <s:form action="login">
      <s:textfield name="username" label="Enter User Name"/><br/>
      <s:password name="password" label="Enter Password"/><br/>
      <s:submit></s:submit>
   </s:form>
    </body>
</html>

In the include.jsp we can import the common files like the tag libraries, javascript libraries etc.

include.jsp

1
<%@ taglib prefix="s" uri="/struts-tags"%>

When the user submits the form using the submit button, the request reaches the StrutsController via the struts.xml and the execute method is invoked.

StrutsController.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package com.jcg.examples.controller;
 
 
import java.sql.SQLException;
 
import org.apache.struts2.ServletActionContext;
 
import com.jcg.examples.delegate.LoginDelegate;
import com.jcg.examples.viewBean.LoginBean;
import com.opensymphony.xwork2.ModelDriven;
 
 
public class StrutsController implements ModelDriven<LoginBean>
{
 
        private LoginDelegate loginDelegate;
 
        public LoginBean loginBean;
 
        public LoginBean getLoginBean()
        {
                return this.loginBean;
        }
 
        public void setLoginBean(LoginBean loginBean)
        {
                this.loginBean = loginBean;
        }
 
        public String execute() throws SQLException
        {
                String target = "";
                boolean isValidUser = loginDelegate.isValidUser(loginBean.getUsername(), loginBean.getPassword());
                if (isValidUser)
                {
                        System.out.println("User Login Successful");
                        ServletActionContext.getRequest().setAttribute("loggedInUser", loginBean.getUsername());
                        target = "SUCCESS";
                }
                else
                {
                        ServletActionContext.getRequest().setAttribute("message", "Invalid credentials!!");
                        target = "Failure";
                }
                return target;
        }
 
        public LoginDelegate getLoginDelegate()
        {
                return this.loginDelegate;
        }
 
        public void setLoginDelegate(LoginDelegate loginDelegate)
        {
                this.loginDelegate = loginDelegate;
        }
 
        @Override
        public LoginBean getModel()
        {
                return loginBean;
        }
}

We have implemented the ModelDriven interface so that the values entered by the user are directly made available into the Java Object. This frees up the developer’s time to concentrate on the business logic rather than the minor request tit-bits. The LoginBean is injected into the Action class from the Spring-Bean factory and is populated with the values entered by the user.

LoginBean.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.jcg.examples.viewBean;
 
public class LoginBean
{
        private String username;
 
        private String password;
 
        public String getPassword()
        {
                return this.password;
        }
 
        public String getUsername()
        {
                return this.username;
        }
 
        public void setUsername(String username)
        {
                this.username = username;
        }
 
        public void setPassword(String password)
        {
                this.password = password;
        }
 
        @Override
    public String toString()
    {
            return "LoginBean [username=" + this.username + ", password=" + this.password + "]";
    }
 
 
}

We extract the username and password from the loginbean and forward it to the LoginDelegate which does the task of authenticating the user. The LoginDelegate is itself injected into the action class via the Spring-Bean Factory.

Want to master Spring Framework ?
Subscribe to our newsletter and download the Spring Framework Cookbook right now!
In order to help you master the leading and innovative Java framework, we have compiled a kick-ass guide with all its major features and use cases! Besides studying them online you may download the eBook in PDF format!

Here’s the LoginDelegate.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.jcg.examples.delegate;
 
import java.sql.SQLException;
 
import com.jcg.examples.service.UserService;
 
public class LoginDelegate
{
        private UserService userService;
 
        public UserService getUserService()
        {
                return this.userService;
        }
 
        public void setUserService(UserService userService)
        {
                this.userService = userService;
        }
 
        public boolean isValidUser(String username, String password) throws SQLException
    {
            return userService.isValidUser(username, password);
    }
}

The LoginDelegates delegates to the UserService the task to manage the authentication of the user. The UserService interface is implemented by the UserServiceImpl.

UserService.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
/**
 *
 */
package com.jcg.examples.service;
 
import java.sql.SQLException;
 
/**
 * @author CENTAUR
 *
 */
public interface UserService
{
        public boolean isValidUser(String username, String password) throws SQLException;
}

UserServiceImpl.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package com.jcg.examples.service.impl;
 
import java.sql.SQLException;
 
import com.jcg.examples.dao.UserDao;
import com.jcg.examples.service.UserService;
 
public class UserServiceImpl implements UserService
{
 
        private UserDao userDao;
 
        public UserDao getUserDao()
        {
                return this.userDao;
        }
 
        public void setUserDao(UserDao userDao)
        {
                this.userDao = userDao;
        }
 
        @Override
        public boolean isValidUser(String username, String password) throws SQLException
        {
                return userDao.isValidUser(username, password);
        }
 
}

The UserServiceImpl communicates with the UserDao to connect with the Database to determine if the user is present in the database and the password is correct.

UserDao.java

01
02
03
04
05
06
07
08
09
10
11
12
13
package com.jcg.examples.dao;
 
import java.sql.SQLException;
 
/**
 * @author CENTAUR
 * This interface will be used to communicate with the
 * Database
 */
public interface UserDao
{
        public boolean isValidUser(String username, String password) throws SQLException;
}

UserDaoImpl.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.jcg.examples.dao.impl;
 
 
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
 
import javax.sql.DataSource;
 
import com.jcg.examples.dao.UserDao;
 
 
/**
 * @author CENTAUR
 */
public class UserDaoImpl implements UserDao
{
 
        DataSource dataSource;
 
        public DataSource getDataSource()
        {
                return this.dataSource;
        }
 
        public void setDataSource(DataSource dataSource)
        {
                this.dataSource = dataSource;
        }
 
        @Override
        public boolean isValidUser(String username, String password) throws SQLException
        {
                String query = "Select count(1) from user where username = ? and password = ?";
                PreparedStatement pstmt = dataSource.getConnection().prepareStatement(query);
                pstmt.setString(1, username);
                pstmt.setString(2, password);
                ResultSet resultSet = pstmt.executeQuery();
                if (resultSet.next())
                        return (resultSet.getInt(1) > 0);
                else
                        return false;
        }
 
}

Based on the output returned by the UserDaoImpl the user is redirected to the appropriate view.

If the login is successful the user is shown the welcome.jsp :

welcome.jsp

01
02
03
04
05
06
07
08
09
10
11
12
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Welcome</title>
</head>
<body>
    <center>Welcome ${loggedInUser}</center>
</body>
</html>

If the login fails, the user is shown the same login.jsp with the Invalid Credentials message.

Here’s the output:

LoginView :

Figure 1. Login View
Figure 1. Login View

On Successful login :

Figure 2. Success View
Figure 2. Success View

On Failed Login:

Figure 3. Login Failure
Figure 3. Login Failure

Download the Source Code:

In this example, we studied how to use Spring IoC to inject beans into a Struts web-application.

Download
You can download the source code of this example here: SpringStrutsIntegrationExample.zip
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Chandan Singh

Chandan holds a degree in Computer Engineering and is a passionate software programmer. He has good experience in Java/J2EE Web-Application development for Banking and E-Commerce Domains.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Back to top button