Friday, May 22, 2009

How to integrate: Struts 2+Spring+iBatis (NetBeans 6.5)





Assignment: Use Struts2/Spring/Hibernate framework to Authenticate user credential i.e. username and password. If Authentication is success then render result like “User logged successfully.” else remain in the same Login Input form.

Solution: To achieve the above assignment, I am using NetBeans 6.5 IDE and other mentioned framework and supporting libraries.

Framework:
MVC - Struts 2
Bussiness Layer - Spring 2.5
Persistance - iBatis
IDE - Netbeans 6.5
Plug-ins - Struts 2 – spring - plugin


Create Project and Add supporting Libraries:

Step 1:
Open NetBeans 6.5

Step 2:
Select File > New Project > Select the following Options
Categories: Java Web
Projects: Web Application

Step 3:
Once Java Web and Web Application are selected then Select Next (Ref. Figure 1)



Figure 1



Step 4:

Provide the following details in Name and Location Screen:
Project Name:
Project Location:

Step 5:

Select the following options in Server and Settings Screen:
Server : Tomcat 6.0 (For me it’s Tomcat 6.0)
Java EE Version : Java EE 5
Context Path : ssidemo


Step 6: Tick the check box for the following Frameworks:



Figure 2

Step 7:

IDE will add couple of jar files related spring/struts 2. Apart from that Add the following jar files in the Libraries:

1. struts2-spring-plugin-2.0.12.jar
2. commons-dbcp-1.2.1.jar
3. commons-pool-1.2.jar
4. commons-collections-3.0.jar
5. Java DB Driver - derby.jar
6. Java DB Driver - derbyclient.jar
7. Java DB Driver - derbynet.jar

(You can get 1….4 jar files by a quick search and download and 5, 6, 7 jar files is available in JDK/NetBeans)

Note:
Select Library folder and right click on it or other way and select “Add Library” and select “Java DB Driver” library to add To add jar files select “Add Jar/Folder” and select the jar files (1….4) to add

Configure Framework and Create Project Folder structure for the Assignment:

Project Folder Structure created by IDE:

Web Pages - It stores the entire files/resourced required for web app deployment
Configuration Files - All the config (.xml) files
Server Resources - Not in use for this exercise
Source Packages - Java Source Code
Test Packages - Not in use for this exercise
Libraries - All the jar/zip files
Test Libraries - Not in use for this exercise

Development Folder Structure used for this Assignment:

Struts Action - com.hcl.action
DAO - com.hcl.dao
Service - com.hcl.service
Model - com.hcl.model
JSP Pages - WEB-INF/jsp

Register Spring Details in web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>


Do not worry about this web.xml; our IDE is smart enough to create it. But ensure that these are not missing.

Configure Hibernate / Datasource / Transaction / Struts Action with spring

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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-2.0.xsd">
<!—REGISTER STRUTS ACTION -->
<bean id="action.Login" class="com.hcl.action.Login" scope="prototype">
<property name="daoService" ref="service.DAOServiceBean"/>
</bean>
<!—REGISTER IBATIS FACTORY BEAN -->
<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"
value="classpath:/sql-map-config.xml" />
<property name="dataSource" ref="dataSource" />
</bean>
<!—REGISTER DATASOURCE -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.apache.derby.jdbc.ClientDriver" />
<property name="url" value="jdbc:derby://localhost:1527/DEMODB" />
<property name="username" value="DEMODB" />
<property name="password" value="DEMODB" />
</bean>
<!—REGISTER DATASOURCE WITH IBATIS-->
<bean id="sqlMap" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation" value="classpath:/sql-map-config.xml"/>
<property name="dataSource" ref="dataSource" />
</bean>
 
<!—REGISTER DATASOURCE WITH TRANSACTION MANAGER -->
<bean id="txManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<alias name="txManager" alias="transactionManager" />
<bean id="DAOIntfBean" class="com.hcl.dao.DAOImpl">
<property name="sqlMapClient" ref="sqlMapClient" />
</bean>
<bean id="service.DAOServiceBean" class="com.hcl.service.DAOServiceImpl">
<property name="daoInft" ref="DAOIntfBean"/>
</bean>
</beans>

Little big than web.xml but logically very memorable.

Struts configuration

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.devMode" value="true" />
<constant name="struts.action.extension" value="action"/>
<include file="example.xml"/> <!—ADDED BY IDE NOT IN USE FOR THIS-->
<!-- Configuration for the default package. -->
<package name="default" extends="struts-default">
<action name="Login" class="action.Login" method="doLogin">
<result name="login">/jsp/Login.jsp</result>
<result name="input">/jsp/Login.jsp</result>
<result name="error">/jsp/Login.jsp</result>
<result name="success">/jsp/Success.jsp</result>
</action>
</package>
</struts>


Here “action.Login” is a bean defined in ApplicationContext.xml

Configure SQL Queries with iBatis

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd">
<sqlMapConfig>
<settings
cacheModelsEnabled="true"
enhancementEnabled="true"
maxSessions="64"
maxTransactions="8"
maxRequests="128"
/>
<sqlMap resource="UserDetails.xml"/>
</sqlMapConfig>

Here UserDetails.xml contains the queries used for my purpose.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMap PUBLIC "-//iBATIS.com//DTD SQL Map 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-2.dtd">
<sqlMap>
<resultMap id="model.UserInfo" class="com.hcl.model.UserInfo">
<result property="userName" column="USER_NAME"/>
<result property="password" column="PASSWORD"/>
</resultMap>
<select id="isUserExists" parameterClass="com.hcl.model.UserInfo" resultClass="Integer">
SELECT count(*)
FROM USER_INFO
WHERE USER_NAME=#userName# AND PASSWORD = #password#
</select>
</sqlMap>


It is not a best way to do; you have better way to do it. But for demo there is no problem.

Java Code

Login.java

package com.hcl.action;

import com.hcl.model.UserInfo;
import com.hcl.service.DAOServiceIntf;
import com.opensymphony.xwork2.ActionSupport;

public class Login extends ActionSupport {

private DAOServiceIntf DaoService;
private String userName;
private String password;


public Login() {
}

public String doLogin() throws Exception {
UserInfo userInfo = new UserInfo();
userInfo.setPassword(password);
userInfo.setUserName(userName);
if(DaoService.isUserExists(userInfo)){
return ActionSupport.SUCCESS;
}else{
return ActionSupport.INPUT;
}

}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public DAOServiceIntf getDaoService() {
return DaoService;
}

public void setDaoService(DAOServiceIntf DaoService) {
this.DaoService = DaoService;
}
}

Login-validation.xml – Way to do Validation in Struts 2

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE validators PUBLIC
"-//OpenSymphony Group//XWork Validator 1.0.2//EN"
"http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">
<validators>
<field name="userName">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>Login name is required</message>
</field-validator>
</field>
<field name="password">
<field-validator type="requiredstring">
<param name="trim">true</param>
<message>Password is required</message>
</field-validator>
</field>
</validators>

UserInfo.java

package com.hcl.model;

public class UserInfo {

private String userName;
private String password;

public String getPassword() {
return password;
}

public void setPassword(String password) {
this.password = password;
}

public String getUserName() {
return userName;
}

public void setUserName(String userName) {
this.userName = userName;
}
}

DAOIntf.java (DAO Interface)

package com.hcl.dao;

import com.hcl.model.UserInfo;

public interface DAOIntf {
public boolean isUserExists(UserInfo userInfo);
}


DAOImpl.java (DAO Implementation)

package com.hcl.dao;
import com.hcl.model.UserInfo;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;

public class DAOImpl extends SqlMapClientDaoSupport implements DAOIntf {

public boolean isUserExists(UserInfo userInfo) {
Integer userCount;
boolean result = false;
try{
userCount =(Integer) getSqlMapClientTemplate().queryForObject("isUserExists",userInfo);
}
catch(Exception ex){
ex.printStackTrace();
System.out.println(ex);
return false;
}
if (userCount != null && userCount > 0) {
result = true;
} else{
result = false;
}
return result;
}
}

DAOServiceIntf.java (Service Interface)

package com.hcl.service;

import com.hcl.model.UserInfo;

public interface DAOServiceIntf {
public boolean isUserExists(UserInfo userInfo);
}

DAOServiceImpl.java (Service Implementation)

package com.hcl.service;

import com.hcl.dao.DAOIntf;
import com.hcl.model.UserInfo;

public class DAOServiceImpl implements DAOServiceIntf {

private DAOIntf daoInft;

public boolean isUserExists(UserInfo userInfo){
return daoInft.isUserExists(userInfo);
}

public DAOIntf getDaoInft() {
return daoInft;
}

public void setDaoInft(DAOIntf daoInft) {
this.daoInft = daoInft;
}
}


Result (JSP) Pages

Login.jsp


<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
<s:form name="LoginForm" action="Login" method="post" >
<table>
<tr>
<td>
<s:text name="User Name :"/>
</td>
<td>
<s:textfield name="userName" />
</td>
</tr>
<tr>
<td>
<s:text name="Password :"/>
</td>
<td>
<s:password name="password"/>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<s:submit name="Login" value="Login" align="center"/>
</td>
</tr>
</table>
</s:form>
</body>
</html>

Success.jsp

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<body>
User <s:property value="userName"/> logged successfully.
</body>
</html>

Deployment Folder Structure ( NetBeans 6.5 IDE takes care most of the file location. )

Java Source Code: No need to place class/jar files in WEB-INF/classes or WEB-INF/lib. IDE takes care about it.
xml Files:



If everything goes fine then: URL To Access web Application:

http://localhost:8080/ssi/jsp/Login.jsp

2 comments:

  1. If I am using struts 1.3, then what changes to be done in above example.....

    ReplyDelete

  2. Thanks for this blog, Keep sharing your thoughts like this...
    What is Struts in Java
    Struts Framework in Java

    ReplyDelete