Вы находитесь на странице: 1из 72

1 POTHURAI

Struts
A frame work simplifies the development of the complex applications. The frame work softwares are designed based on very good architecture. Ex: - Struts, Spring MVC, web works are designed based on MVC architecture. A frame work contains the code that is commonly required as part of almost every project. A frame work provides a standard procedure for doing every task. This makes the development of the application: easier than development of an app with without using a frame work. package org.students; import javax.servlet.*; import javax.servlet.http.*; import java.io.*; public class OurActionServlet extends HttpServlet { public void init( )throws ServletException { System.out.println("----reading xxx.xml----"); } public void service(HttpServletRequest request,HttpServletResponse response) throws ServletException, IOException { System.out.println("----OurActionServlet----"+request.getRequestURI( )); } } D:\Pskr\Struts>javac -d . OurActionServlet.java <web-app> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.students.OurActionServlet</servlet-class> <load-on-startup>2</load-on-startup> </servlet> <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> </web-app> Start weblogic server ----reading xxx.xml---http://localhost:8000/str/one.do ----OurActionServlet----/str/one.do http://localhost:8000/str/xxx/yyy.do ----OurActionServlet----/str/xxx/yyy.do

SUDHEER REDDY

2 POTHURAI

action(*.do) web.xml

/one.do /xxx/yyy.do

init( ) { ----------} org.students.OurActionServlet

Browser

xxx.xml web container The following steps will be carried out while starting the above web application: 1) Web container reads web.xml. 2) As we have used load-on-startup, web container creates OurActionServlet obj. 3) Web container calls the init( ). 4) The init( ) method reads the information available in xxx.xml. Note: - Web container executes OurActionServlet code when it receives the request sent using the URL that ends with .do We get the following things as part of Struts frame work: 1) A set of tag libraries like struts-html, struts-logic, struts-bean, struts-tiles etc 2) A servlet class with the name org.apache.struts.action.ActionServlet. 3) A set of classes like Action, ActionForm, ActonError, ActionErrors etc these classes are used as part of our code. Procedure for setting up a struts based web applications: 1) Create a Root directory for the web application Ex: - d:\str 2) Copy struts-blank.war to d:\pskr 3) Using cd command move to the directory str & use the jar command to extract the content of the war file d:\str>jsr cf struts-blank.war . 4) Copy str directory & place this directory in weblogic D:\bea\user_projects\domains\sunil\applications\ directory In tomcat D:\Tomcat5.0\webapps\ directory <web-app> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <load-on-startup>2</load-on-startup> </servlet> SUDHEER REDDY

3 POTHURAI <servlet-mapping> <servlet-name>action</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <taglib> <taglib-uri>/tags/struts-bean</taglib-uri> <taglib-location>/WEB-INF/struts-bean.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-html</taglib-uri> <taglib-location>/WEB-INF/struts-html.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-logic</taglib-uri> <taglib-location>/WEB-INF/struts-logic.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-nested</taglib-uri> <taglib-location>/WEB-INF/struts-nested.tld</taglib-location> </taglib> <taglib> <taglib-uri>/tags/struts-tiles</taglib-uri> <taglib-location>/WEB-INF/struts-tiles.tld</taglib-location> </taglib> </web-app> The following steps will carry out when a struts base application will start: 1) Web container reads web.xml 2) Web container creates a servlet object based on ActionServlet class 3) Web container calls the init( ) method on ActionServlet. 4) Struts code that is part of the init( ) method reads the information available in struts-config.xml Note: - Web container executes the code of the ActionServlet, when it receive a request that ends with .do action(*.do) web.xml /aone.do

init( ) { struts code } org.apache.struts.action.ActionServlet

/axxx.do Browser

struts-config.xml

web container SUDHEER REDDY

4 POTHURAI In order to take care of various tasks (actions), various action classes must be provided in our Struts based project. An Action class is sub class of org.apache.struts.action.Action To compile the Action classes: - 1) copy struts.jar, servlet-api.jar/weblogic.jar to the working directory (d:\pskr\struts\). 2) Use the command shown below for setting the class path D:\pskr\struts>set CLASSPATH=.;struts.jar;servlet-api.jar; (or) D:\pskr\struts>set CLASSPATH=.;struts.jar;weblogic.jar; import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionOne extends Action { public ActionOne( ) { System.out.println("----ActionOne created----"); } public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----ActionOne:execute----"); return null; } } D:\Pskr\Struts>set CLASSPATH=.;struts.jar;servlet-api.jar; D:\Pskr\Struts>javac ActionOne.java Procedure for using the Action class in a Struts project: 1) Copy the Action class in WEB-INF/classes directory. 2) Provide the information about the Action class in struts-config.xml <action-mappings> <action path="/aone" type="ActionOne"/> <action path="/atwo" type="ActionTwo"> <forward name="fone" path="/one.jsp"/> action-mapping <forward name="ftwo" path="/two.jsp"/> </action> </action-mappings> http://localhost:8000/str/aone.do ----ActionOne created-------ActionOne:execute---The following steps will be carried out in the container when it receives the request for /aone.do: Step1: - Web container creates req, resp objects 2) Web container starts the execution of the struts code of Action Servlet by providing req, resp objects. SUDHEER REDDY

5 POTHURAI ActionServlet obj

req resp

/aone.do

action(*.do)

execute(. ) ActionOne obj

Web browser

web server 3) The Struts code gets the name of the Action class (ActionOne) mapped to the path /aone. 4) If required ActionOne object will be created by struts code. 5) Struts code calls the execute method on ActionOne object (req, resp created in step1 will be provided to the execute( ) method). 6) As the execute( ) method returns null the struts code stops processing the request. Struts code creates the ActionForward objects & places the information available in the forward tag in this object. Struts code places the information available action tag inside the ActionMapping object. name=fone path=/one.jsp path=/atwo type=ActioTwo ActionMapping obj ActionForward name=ftwo path=/two.jsp ActionForward import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionTwo extends Action { public ActionTwo( ) { System.out.println("---- ActionTwo created----"); } public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----ActionTwo:execute----"); System.out.println(mapping.getPath( )); SUDHEER REDDY

6 POTHURAI System.out.println(mapping.getType( )); ActionForward af1,af2,af3; af1=mapping.findForward("fone"); System.out.println("af1--->"+af1); af2=mapping.findForward("ftwo"); System.out.println("af2--->"+af2); af3=mapping.findForward("fthr"); System.out.println("af3--->"+af3); return af1; } } D:\Pskr\Struts>javac ActionTwo.java <% System.out.println("---one.jsp---");%> op generated by one.jsp http://localhost:8000/str/atwo.do ---- ActionTwo created-------ActionTwo:execute---/atwo ActionTwo af1--->ForwardConfig[name=fone,path=/one.jsp,redirect=false,contextRelative=false] af2--->ForwardConfig[name=ftwo,path=/two.jsp,redirect=false,contextRelative=false] af3--->null ---one.jsp--op generated by one.jsp ActionServlet obj req resp Web browser /atwo.do

action(*.do)

execute(. ) ActionTwo obj one.jsp

Web server The following steps will be carried out in the container when it receives the request for /aone.do: Step1: - Web container creates req, resp objects 2) Web container starts the execution of the struts code of Action Servlet by providing req, resp objects. 3) The Struts code gets the name of the Action class (ActionTwo) mapped to the path /atwo. SUDHEER REDDY

7 POTHURAI 4) If required ActioTwo object will be created by struts code. 5) Struts code calls the execute method on ActionTwo object (req, resp created in step1 will be provided to the execute( ) method). 6) As the execute( ) method returns af1 the struts code forward the request to one.jsp. 7) one.jsp generate to the output. import javax.servlet.http.*; import org.apache.struts.action.*; public class GDAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { java.util.Vector v=new java.util.Vector( ); v.add("DIOne"); v.add("DITwo"); v.add("DIThree"); v.add("DIFour"); request.setAttribute("svdata",v); System.out.println("Stored vector in req"); System.out.println("Returning genop fwd"); return mapping.findForward("genop"); } } D:\Pskr\Struts>javac GDAction.java <action-mappings> <action path="/gda" type="GDAction"> <forward name="genop" path="/genrep.jsp"/> </action> </action-mappings> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <% System.out.println("---genrep.jsp---"); %> <c:forEach var="s" items="${requestScope.svdata}"> <c:out value="${s}"/> <br> </c:forEach> http://localhost:8000/gda/gda.do Stored vector in req Returning genop fwd ---genrep.jsp--DIOne DITwo DIThree DIFour

SUDHEER REDDY

8 POTHURAI The following steps will be carried out in the container when it receives the request for /gda.do: ActionServlet obj req svdat a resp execute(. ) GDAction obj genrep.jsp Vector Web Container Step1: - Web container creates req, resp objects. 2) Web container starts the execution of the struts code available in Action Servlet. 3) If required struts code creates GDAction object. 4) Struts code calls the execute method on GDAction. 5) The code of GDAction stores a vector object that contains 4 string objects inside t he request & returns a forward with the name genop. 6) Struts code forward the request to genrep.jsp. 7) genrep.jsp generates the output that contains the string objects available in the vector. SQL> select * from student; SNO SNAME FNAME ADDR ---------- -------------------- -------------------- ----------------1 sone fone aone 1 stwo ftwo atwo package org.students; public class StudentBean { String studNo; String studName; String fatherName; String addr; public void setStudNo(String studNo) { System.out.println("----setStudNo---->"+studNo); this.studNo=studNo; } public String getStudNo( ) { SUDHEER REDDY Web browser String objects /gda.do

action(*.do)

9 POTHURAI System.out.println("----getStudNo---->"+this.studNo); return this.studNo; } public void setStudName(String studName) { System.out.println("----setStudName---->"+studName); this.studName=studName; } public String getStudName( ) { System.out.println("----getStudName---->"+this.studName); return this.studName; } public void setFatherName(String fatherName) { System.out.println("----setFatherName---->"+fatherName); this.fatherName=fatherName; } public String getFatherName( ) { System.out.println("----getFatherName---->"+this.fatherName); return this.fatherName; } public void setAddr(String addr) { System.out.println("----setAddr---->"+addr); this.addr=addr; } public String getAddr( ) { System.out.println("----getAddr---->"+this.addr); return this.addr; } } D:\Pskr\Struts>javac d . StudentBean.java import javax.servlet.http.*; import org.apache.struts.action.*; import java.sql.*; public class GSDAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con=DriverManager.getConnection SUDHEER REDDY

10 POTHURAI ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger"); String vsql="select * from student"; java.util.Vector v=new java.util.Vector( ); Statement stmt=con.createStatement( ); ResultSet rs=stmt.executeQuery(vsql); while(rs.next( )) { org.students.StudentBean sb=new org.students.StudentBean(); sb.setStudNo(rs.getString("sno")); sb.setStudName(rs.getString("sname")); sb.setFatherName(rs.getString("fname")); sb.setAddr(rs.getString("addr")); v.add(sb); } con.close( ); request.setAttribute("svsdata",v); return mapping.findForward("gensrep"); } } <action-mappings> <action path="/gsda" type="GSDAction"> <forward name="gensrep" path="/gensrep.jsp"/> </action> </action-mappings> <%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %> <% System.out.println("---gensrep.jsp---"); %> <c:forEach var="s" items="${requestScope.svsdata}"> <c:out value="${s.studNo}"/> <br> <c:out value="${s.studName}"/> <br> <c:out value="${s.fatherName}"/> <br> <c:out value="${s.addr}"/> <br> ---------------<br> </c:forEach> http://localhost:8000/gsda/gsda.do ----setStudNo---->1 ----setStudName---->sone ----setFatherName---->fone ----setAddr---->aone ----setStudNo---->1 ----setStudName---->stwo ----setFatherName---->ftwo ----setAddr---->atwo ---gensrep.jsp------getStudNo---->1 ----getStudName---->sone SUDHEER REDDY

11 POTHURAI ----getFatherName---->fone ----getAddr---->aone ----getStudNo---->1 ----getStudName---->stwo ----getFatherName---->ftwo ----getAddr---->atwo 1 sone fone aone --------------1 stwo ftwo atwo --------------The following steps will be carried out in the container when it receives the request for /gsda.do: ActionServlet obj req svsdat a resp execute(. ) GSDAction obj gensrep.jsp Vector Web Container Step1: - Web container creates req, resp objects. 2) Web container starts the execution of the struts code by passing req, resp objects. 3) If required GSDAction object will be created by struts code. 4) Struts code calls the execute method on GSDAction. 5) The code of GSDAction performs the following steps. a) Executes select statement for getting data from student table. b) Creates s Vector object. c) Loads the data in StudentBean object & place these objects inside the Vector. d) Places the Vector inside the request object. e) Returns a forward with the name gensrep. 6) Struts code forward the request to gensrep.jsp. 7) gensrep.jsp generates the output that contains the data available in StudentBean objects. i18n: - Struts support (simplifies) the development of i18n application. SUDHEER REDDY

/gsda.do op generated by gensrep.jsp Web browser StudentBean

action(*.do)

12 POTHURAI D:\psr\J2EE>java HWebServer1 8000 http://localhost:8000/ Accept-Language: en_US Internet Explorer Tools internet option languages

Click add button

click ok button

Re-start the browser SUDHEER REDDY

13 POTHURAI http://localhost:8000/ Accept-Language: te Locale Accept-Language: en_US US (english) Accept-Language: te Client Client

te (telugu) As part of every request Accept-Language Header will be sent by the browser. This Header provides Locale (language code, country code) setting of the browser tp the server (web application). As part of our Servlets/ JSPs, the code shown below can be used for getting the information about the Locale setting of the browser. <% java.util.Locale loc; loc=request.getLocale( ); out.println(loc); %> http://localhost:7001/i18n/loc.jsp te Select the language French (Canada) [fr-ca] in the internet explorer. http://localhost:7001/i18n/loc.jsp fr_CA <html> <head> <title> Welcome </title> </head> <body> <br> Welcome to Our web App <br> line two pone <br> line three of pone </body> </html> Note: - The html tags are same for the entire Locales.

These Strings must be different for various Locales

SUDHEER REDDY

14 POTHURAI In a i18n application the Locale specific Strings should not be used directly as shown above JSP. Procedure for developing i18n application: Step 1: - We must provide the information about the Locale specific strings in the properties files as shown below pone.title=Welcome pone.lone=welcome to our web app pone.ltwo=line two of pone pone.lthr=line three of pone pone.title=Welcome in fr pone.lone=welcome to our web app in fr pone.ltwo=line two of pone in fr pone.lthr=line three of pone in fr

ourres_en_US.properties

ourres_fr_CA.properties

Note: - We must use the name ourres.properties, to use this as default in our web application. The properties files must be placed under WEB-INF\classes directory. Step 2: - Provide the information about the properties file in struts-config.xml as shown below <message-resources parameter="ourres"/> Step 3: - We can use message tag of struts-bean tag library, for accessing the resources available in the properties files. <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <html> <head> <title> <bean:message key="pone.title"/> </title> </head> <body> <bean:message key="pone.lone"/> <br> <bean:message key="pone.ltwo"/> <br> <bean:message key="pone.lthr"/> <br> </body> </html> http://localhost:7001/i18n/pone.jsp welcome to our web app in fr line two of pone in fr line three of pone in fr Select the language English (United States) [en-US] in the internet explorer. http://localhost:7001/i18n/pone.jsp welcome to our web app line two of pone line three of pone SUDHEER REDDY

15 POTHURAI <% Object o=application.getAttribute("attname"); out.println(o); %> http://localhost:7001/i18n/aobj.jsp null <% Object o=application.getAttribute("org.apache.struts.action.MESSAGE"); out.println(o); %> http://localhost:7001/i18n/mobj.jsp org.apache.struts.util.PropertyMessageResources@14c7cd org.apache.struts.action.MESSAGE ServletContext(application obj) Resources of ourres.properties PropertyMassageResources

During startup the struts code PropertyMassageResources objects, loads the MassageResources available in properties files with the base home ourres. Struts code stores PropertyMassageResources inside the application object with the attribute name org.apache.struts.action.MESSAGE (this is called as default key). The PropertyMessageResources object will be stored in ServletContext with the attribute name xxx, if we provide the information as shown below in struts-config.xml. <message-resources key="xxx" parameter="ourres"/> <% Object o=application.getAttribute("org.apache.struts.action.MESSAGE"); out.println(o); %> http://localhost:7001/i18n/mobj.jsp null <% Object o=application.getAttribute("xxx"); out.println(o); %> http://localhost:7001/i18n/xobj.jsp org.apache.struts.util.PropertyMessageResources@1c1eceb xxx ServletContext(application obj) Resources of ourres.properties PropertyMassageResources SUDHEER REDDY

16 POTHURAI http://localhost:7001/i18n/pone.jsp Error 500--Internal Server Error javax.servlet.jsp.JspException: Cannot find message resources under key org.apache.struts.action.MESSAGE if key is specified as xxx in the struts-config.xml file, then we must used the message tag as shown below. <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <html> <head> <title> <bean:message key="pone.title" bundle="xxx"/> </title> </head> <body> <bean:message key="pone.lone" bundle="xxx"/> <br> <bean:message key="pone.ltwo" bundle="xxx"/> <br> <bean:message key="pone.lthr" bundle="xxx"/> <br> </body> </html> http://localhost:7001/i18n/pone.jsp welcome to our web app line two of pone in line three of pone in If there is more number of resources in a properties file then it will be typical to manage. In this case it is better to go for multiple sets of properties files as shown below. one.rone=value of one.rone one.rtwo=value of one.rtwo one.rthr=value of one.rthr one.rone=value of one.rone in fr one.rtwo=value of one.rtwo in fr one.rthr=value of one.rthr in fr two.rone=value of two.rone two.rtwo=value of two.rtwo two.rthr=value of two.rthr two.rone=value of two.rone in fr two.rtwo=value of two.rtwo in fr two.rthr=value of two.rthr in fr resone.properties Set I resone_fr_CA.properties

restwo.properties Set II restwo_fr_CA.properties

Struts-config.xml must be configured as shown below for using the above two Sets. <message-resources parameter="resone"/> <message-resources key="xxx" parameter="restwo"/> SUDHEER REDDY

17 POTHURAI <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <bean:message key="one.rone"/> <br> <bean:message key="one.rtwo"/> <br> <bean:message key="one.rthr"/> <br> <bean:message key="two.rone" bundle="xxx"/> <br> <bean:message key="two.rtwo" bundle="xxx"/> <br> <bean:message key="two.rthr" bundle="xxx"/> <br> http://localhost:7001/i18n/test.jsp value of one.rone value of one.rtwo value of one.rthr value of two.rone value of two.rtwo value of two.rthr Select the language French (Canada) [fr-ca] in the internet explorer. http://localhost:7001/i18n/test.jsp value of one.rone in fr value of one.rtwo in fr value of one.rthr in fr value of two.rone in fr value of two.rtwo in fr value of two.rthr in fr <%@ taglib uri="/tags/struts-bean" prefix="bean" %> <bean:message key="one.rfour"/> <br> non existing resources <bean:message key="two.rfour" bundle="xxx"/> <br> http://localhost:7001/i18n/test.jsp Error 500--Internal Server Error
javax.servlet.jsp.JspException: Missing message for key "one.rfour"

if non existing resources are used an exception may be thrown or a String will be sent to the browser indicating at the value is not known (???fr_CA.one.rfour???, ??? fr_CA.two.rfour???) An exception will be thrown if the properties if the properties fill are configured as shown below <message-resources parameter="resone"/> <message-resources key="xxx" parameter="restwo"/> A String will be sent to the browser with question marks (?), if the properties fill is configured as shown below <message-resources parameter="resone" null="false"/> <message-resources key="xxx" parameter="restwo" null="false"/> http://localhost:7001/i18n/test.jsp ???fr_CA.one.rfour??? ???fr_CA.two.rfour??? SUDHEER REDDY

18 POTHURAI <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <% request.setAttribute("xxx","aaaa"); %> <logic:present name="xxx" scope="request"> -------</logic:present> <logic:notPresent name="xxx" scope="request"> ******** </logic:notPresent> http://localhost:7001/i18n/pre.jsp ------- <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <logic:present name="xxx" scope="request"> -------</logic:present> <logic:notPresent name="xxx" scope="request"> ******** </logic:notPresent> http://localhost:7001/i18n/pre.jsp ******** We can use the code shown below to check whether the MessageResources are loaded with the default key. <%@ taglib uri="/tags/struts-logic" prefix="logic" %> <logic:notPresent scope="application" name="org.apache.struts.action.MESSAGE" > ERROR---- message resources are not loaded ******** </logic:notPresent> <logic:present scope="application" name="org.apache.struts.action.MESSAGE" > message resources are available </logic:present> http://localhost:7001/i18n/mrpre.jsp message resources are available ActionErrors & ActionError: - ActionError object represents single error. ActionErrors object represents multiple errors.

ActionError

ActionErrors ActionError SUDHEER REDDY

19 POTHURAI Ex: - ActionError ae1, ae2; ae1=new ActionError(eone.msg); key of the Error message ae2=new ActionError(etwo.msg); ActionErrors aes=new ActionErrors( ); aes.add(propOne,ae1); Property name aes.add(propTwo,ae2); Note: - The information about the error messages must be provided in the properties files as shown below. eone.msg=Error Message one etwo.msg=Error Message two eone.msg=Error Message one in fr etwo.msg=Error Message two in fr messageResources.properties messageResources_fr_CA.properties

Struts-config.xml must be configured as shown below. <message-resources parameter="messageResources"/> import javax.servlet.http.*; import org.apache.struts.action.*; public class TEAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { ActionErrors aes=new ActionErrors( ); ActionError ae1,ae2,ae3; System.out.println("---aes-1-->"+aes.size( )); ae1=new ActionError("eone.msg"); aes.add("propOne",ae1); ae2=new ActionError("etwo.msg"); aes.add("propTwo",ae2); ae3=new ActionError("ethr.msg"); aes.add("propThr",ae3); System.out.println("---aes-2-->"+aes.size( )); saveErrors(request,aes); return mapping.findForward("disperrs"); } } D:\Pskr\Struts>javac TEAction.java saveErrors( )method stores the ActionErrors object in the request object. Struts-config.xml must be configured as shown below. <action-mappings> <action path="/er" type="TEAcion"> <forward name="disperrs" path="/de.jsp"/> </action> </action-mappings> SUDHEER REDDY

20 POTHURAI <%@ taglib uri="/tags/struts-html" prefix="html" %> List of Error Messages <br> <html:errors /> http://localhost:8000/err/er.do ---aes-1-->0 ---aes-2-->3 List of Error Messages Error Message one Error Message two Select the language French (Canada) [fr-ca] in the internet explorer. http://localhost:8000/err/er.do ---aes-1-->0 ---aes-2-->3 List of Error Messages Error Message one in fr Error Message two in fr <%@ taglib uri="/tags/struts-html" prefix="html" %> List of Error Messages <br> <html:errors property="propOne"/> ----------------<br> <html:errors property="propTwo"/> http://localhost:8000/err/er.do ---aes-1-->0 ---aes-2-->3 List of Error Messages Error Message one in fr --------------- Error Message two in fr The errors tag generates the list of error messages using ActionError objects available in ActionErrors object which is available in request object. Problem: - The error tag internally uses the following four resources will generating the list of errors. errors.header=<UL> errors.prefix=<LI> errors.suffix=</LI> errors.footer=</UL> The errors tag forces us to add the html tags to the properties files. Adding the html tags to the properties file is not a good practice. As an alternative for errors tag, Struts team has provided messages tag. For using messages tag we need to use the html tags in the property files.

SUDHEER REDDY

21 POTHURAI <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> List of Error Messages <br> <html:messages id="msg"> <bean:write name="msg"/> <br> </html:messages> http://localhost:8000/err/er.do ---aes-1-->0 ---aes-2-->3 List of Error Messages Error Message one in fr Error Message two in fr ActionError object can be used to represent an error message. But as part of our project we may be using several messages. Some of these messages may not be error messages. For representing error messages as well as other messages we can use ActionMessage object. ActionMessage is provided as an alternative for ActionError. ActionMessages is provided in an alternative for ActionErrors. saveMessages is provided is an alternative for saveError( ) method. import javax.servlet.http.*; import org.apache.struts.action.*; public class MTEAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { ActionMessages ams=new ActionMessages( ); ActionMessage am1,am2,am3; System.out.println("---ams-1-->"+ams.size( )); am1=new ActionMessage("eone.msg"); ams.add("propOne",am1); am2=new ActionMessage("etwo.msg"); ams.add("propTwo",am2); am3=new ActionMessage("ethr.msg"); ams.add("propThr",am3); System.out.println("---ams-2-->"+ams.size( )); saveMessages(request,ams); return mapping.findForward("disperrs"); } } D:\Pskr\Struts>javac MTEAction.java Struts-config.xml must be configured as shown below. <action-mappings> <action path="/mer" type="MTEAcion"> SUDHEER REDDY

22 POTHURAI <forward name="disperrs" path="/mde.jsp"/> </action> </action-mappings> <%@ taglib uri="/tags/struts-html" prefix="html" %> <%@ taglib uri="/tags/struts-bean" prefix="bean" %> List of Error Messages <br> <html:messages id="msg" message="true"> <bean:write name="msg"/> <br> </html:messages> http://localhost:8000/err1/mer.do ---ams-1-->0 ---ams-2-->3 List of Error Messages Error Message one in fr Error Message two in fr Select the language English (United States) [en-US] in the internet explorer. http://localhost:8000/err1/mer.do ---ams-1-->0 ---ams-2-->3 List of Error Messages Error Message one Error Message two To generate the messages that are stored inside ActionMessages object, we can use the code shown above. Message tag is deal with ActionError & ActionErrors, ActionMessage & ActionMessages. This is the advantage of message tag. SQL> create table product (pid number(4) primary key, pname varchar(10), price number(10,2)); Table created. SQL> desc product Name Null? Type ----------------------------------------- -------- ---------------------------PID NOT NULL NUMBER(4) PNAME VARCHAR2(10) PRICE NUMBER(10,2) SQL> commit; Commit complete. SQL> select * from product; no rows selected

SUDHEER REDDY

23 POTHURAI Strut forms: Procedure for dealing with the forms in a struts based application: Step 1: - We must decide about the name of the form, the names of the fields in the forms, the validation rules for validating the data provided in the fields. Product Id: Product Name: Price: prodId prodName prodPrice

Form Name: NewProdForm Validation rules: 1) prodId is required 2) prodId must be an Integer 3) prodName is required 4) prodPrice is required 5) prodPrice must be float Step 2: - Provide a form bean class A sub class of ActionForm class is called as a form bean class. ActionForm . reset(..) validate(..) extends NewProdFB extends SomeOtherFB

import javax.servlet.http.*; import org.apache.struts.action.*; public class NewProdFB extends ActionForm { public void NewProdFB( ) { System.out.println("----NewProdFB created----"); } private String prodId; private String prodName; private String prodPrice; // getters & setters public void setProdId(String prodId) { SUDHEER REDDY

24 POTHURAI System.out.println("----setProdId---->"+prodId); this.prodId=prodId; } public String getProdId( ) { System.out.println("----getProdId---->"+this.prodId); return this.prodId; } public void setProdName(String prodName) { System.out.println("----setProdName---->"+prodName); this.prodName=prodName; } public String getProdName( ) { System.out.println("----getProdName---->"+this.prodName); return this.prodName; } public void setProdPrice(String prodPrice) { System.out.println("----setProdPrice---->"+prodPrice); this.prodPrice=prodPrice; } public String getProdPrice( ) { System.out.println("----getProdPrice---->"+this.prodPrice); return this.prodPrice; } // reset method public void reset(ActionMapping mapping, HttpServletRequest request) { this.prodId="100"; this.prodName="xyz"; this.prodPrice="100.01"; } // validate method public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { ActionErrors aes=new ActionErrors( ); System.out.println("---Size--1-->"+aes.size( )); if((this.prodId==null) || (this.prodId.equals(""))) { ActionError ae=new ActionError("prodId.req"); aes.add("prodId",ae); } else SUDHEER REDDY

25 POTHURAI { try { Integer.parseInt(this.prodId); } catch(Exception e) { ActionError ae=new ActionError("prod.not.int"); aes.add("prodId",ae); } } if((this.prodName==null) || (this.prodName.equals(""))) { ActionError ae=new ActionError("prodName.req"); aes.add("prodName",ae); } if((this.prodPrice==null) || (this.prodPrice.equals(""))) { ActionError ae=new ActionError("prodPrice.req"); aes.add("prodPrice",ae); } else { try { Float.parseFloat(this.prodPrice); } catch(Exception e) { ActionError ae=new ActionError("prod.not.float"); aes.add("prodPrice",ae); } } System.out.println("---Size--2-->"+aes.size( )); return aes; } } D:\Pskr\Struts>javac SPDAction.java Note: - As part of the reset( ) method code must be provided for setting the default values of various fields of the form. As part of the validate( ) method we must provide the code to check whether the data provided by the user is valid or not. Step 3: - Provide the action class import javax.servlet.http.*; import org.apache.struts.action.*; SUDHEER REDDY

26 POTHURAI import java.sql.*; public class SPDAction extends Action { public SPDAction( ) { System.out.println("----SPDAction created----"); } public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { NewProdFB fb=(NewProdFB)form; // code to strore data in DB String pid=fb.getProdId( ); String pname=fb.getProdName( ); String price=fb.getProdPrice( ); // code to connect DB Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con=DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger"); String vsql="insert into product values(?,?,?)"; PreparedStatement pstmt=con.prepareStatement(vsql); pstmt.setString(1,pid); pstmt.setString(2,pname); pstmt.setString(3,price); pstmt.executeUpdate( ); con.close( ); return mapping.findForward("pds"); } } D:\Pskr\Struts>javac SPDAction.java Step 4: - Provide a JSP that generates the input form <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("-----npform.jsp------"); %> <html:html locale="true"> <head> <title> New Product Data </title> </head> <body> <html:errors /> <html:form action="/spd.do"> Prod Id : <html:text property="prodId"/> <br> Prod Name : <html:text property="prodName"/> <br> Price : <html:text property="prodPrice"/> <br> <html:submit property="submit" value="store"/> <br> SUDHEER REDDY

27 POTHURAI </html:form> </body> </html:html> Step 5: - Provide the information about form bean & the action in struts-config.xml <form-beans> <form-bean name="NewProdForm" type="NewProdFB"/> </form-beans> <action-mappings> <action name="NewProdForm" input="/npform.jsp" path="/spd" validate="true" scope="request" type="SPDAction"> <forward name="pds" path="/pds.jsp"/> </action> </action-mappings> Step 6: - Provide the pds.jsp <% System.out.println("-- executing pds.jsp--"); %> data stored into db Step 7: - Provide the information about errors in properties file prodId.req=prodId is must be required prod.not.int=prodId is must be an integer prodName.req=prodName is must be required prodPrice.req=prodPrice is must be required prod.not.float=prodPriceId is must be an float http://localhost:8000/form/npform.jsp ----getProdId---->100 ----getProdName---->xyz ----getProdPrice---->100.01 Prod Id : Prod Name : Default values Price : Prod Id : Prod Name : Price : Click ----setProdId---->abc ----setProdName----> ----setProdPrice---->xyz ---Size--1-->0 ---Size--2-->3 ----npform.jsp-------getProdId---->abc SUDHEER REDDY

28 POTHURAI ----getProdName----> ----getProdPrice---->xyz


prodId is must be an integer prodName is must be required prodPriceId is must be an float

Prod Id : Prod Name : Price : Click ----setProdId----> ----setProdName---->abc ----setProdPrice----> ---Size--1-->0 ---Size--2-->2 ----npform.jsp-------getProdId----> ----getProdName---->abc ----getProdPrice---->

prodId is must be required prodPrice is must be required

Prod Id : Prod Name : Price : Click ----setProdId---->34 ----setProdName---->abc ----setProdPrice---->1234 ---Size--1-->0 ---Size--2-->0 ----SPDAction created-------getProdId---->34 ----getProdName---->abc ----getProdPrice---->1234 -- executing pds.jsp-data stored into db SQL> select * from product; PID PNAME PRICE --------------- -------------------- ----------------34 abc 1234 <html:html locale="true"> ---------<br> </html:html> SUDHEER REDDY

29 POTHURAI When the html tag of struts-html tag libraries is evaluated, its generates the html tag shown below <html lang="fr"> ---------<br> </html> <html:form action="/spd.do"> </html:form> When the above form tag is evaluated the following steps will be performed. 1) The name of the form bean class will be obtained. 2) If required the object will be created using the form bean class, the reset( ) method will be called. The form bean object will be stored either in the session or in the request. 3) Generates the form tag as shown below. <form name="NewProdForm" method="post" action="/form/spd.do"> </form> <html:text property="prodId"/> When the above text tag is evaluated the following steps will be carried out. 1) getProdId( ) method will be executed on the form bean object. 2) Generates the input tag as shown below. <input type="text" name="prodId" value="100"> Value returned by getProdId( ) method <html:submit property="submit" value="store"/> When the above tag is evaluated, its generates the html tag shown below <input type="submit" name="submit" value="store"> <% System.out.println("----eh.jsp----"); %> Please read the code once again. Provide the information in struts-config.xml <action name="NewProdForm" input="/eh.jsp" path="/spd" validate="true" scope="request" type="SPDAction"> http://localhost:8000/form/npform.jsp Prod Id : Prod Name : Price : Click ----eh.jsp---Please read the code once again. When we enter the wrong values in the fields and click the store button, eh.jsp is executed (specified in input attribute). When we enter the correct values in the fields and click the store button, SPDAction is executed (specified in type attribute). If scope is set to request (in action tag of struts-config.xml), Struts code places the form bean in the request object. If scope is set to session, form bean will be stored inside the session object. SUDHEER REDDY

30 POTHURAI If validate is set to true, Struts code calls the validate( ) method & the validations will be carried out in the server. This is called as server side validations. Server side validations put more burdens on the server. To reduce burdens on the server we can use java script to validate the data in the client. http://localhost:8000/form/spd.do Prod Id : Prod Name : Price : Click ----setProdId----> ----setProdName----> ----setProdPrice----> ---Size--1-->0 ---Size--2-->3 ----eh.jsp--- When we can use client side validations, we can switch off the server side validations. For this we can set validate="false"; http://localhost:8000/form/spd.do Prod Id : Prod Name : Price : Click ----setProdId----> ----setProdName----> ----setProdPrice----> ----SPDAction created--- In majority of cases client side validations provides bettor performance. In some of the cases we may need to transfer lot of data as part of the java script to take care of validations in the client. Transferring more amounts of data reduces the performance. In this kind of cases we can prefer server side validations. Capture the data provided by the user

not valid

Is data valid?

valid

Re display the form with errors

Process the data according to the business requirements.

SUDHEER REDDY

31 POTHURAI The above flow chart shows the steps that are typically performed by an application while dealing with a form. The frame works like struts, springs supports the same set of steps. Struts capture the data. Creates a form bean (if required) object, calls reset, and stores FB in request / session. Calls setters on FB to store the capture data in data

What is the value of validate? true Struts calls validate method on FB object

false

yes

Any errors reported by the validate method?

no

Struts forward the request to the resource specified in input atrribute ActionForm reset validate . extends DynaActionForm set (..) get(.) extends

Struts calls execute ( ) method on action object for processing the data

SUDHEER REDDY

32 POTHURAI OurOwnFB We need to provide getters & setters SQL> create table employee(uname varchar(15),pwd varchar(10),age number(3), email varchar(25)); Table created. SQL> select * from employee; no rows selected Procedure for using DynaActionForm to deal (handle) a form: Step 1: - We must decide about the name of the form, the names of the fields in the form and the validations rules that must be applied on various fields of the form. User Name : Password : Age : Email : userName pwd age email

Form name: UserRegForm Validations: 1) userName is required. 2) pwd is required. 3) min length of username must be 5 chars. Step 2: - Create the form bean class as a sub class of DynaActionForm class import javax.servlet.http.*; import org.apache.struts.action.*; public class DUserRegFB extends DynaActionForm { public void reset(ActionMapping mapping,HttpServletRequest request) { System.out.println("----reset----"); set("userName","your name"); set("pwd",""); set("age","21"); set("email",null); } public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) { System.out.println("----validate----"); String userName,pwd; userName=(String)get("userName"); pwd=(String)get("pwd"); SUDHEER REDDY

33 POTHURAI ActionErrors aes=new ActionErrors( ); if(userName==null || userName.equals("")) { ActionError ae=new ActionError("uname.req"); aes.add("userName",ae); } else { if(userName.length( )<5) { ActionError ae=new ActionError("uname.ml.err"); aes.add("userName",ae); } } if(pwd==null || pwd.equals("")) { ActionError ae=new ActionError("pwd.req"); aes.add("pwd",ae); } return aes; } } D:\Pskr\Struts>set CLASSPATH=.;struts.jar;servlet-api.jar;commons-beanutils.jar D:\Pskr\Struts>javac DUserRegFB.java Step 3: - Provide the information about form bean in struts-config.xml <form-beans> <form-bean name="UserRegForm" type="DUserRegFB"> <form-property name="userName" type="java.lang.String"/> <form-property name="pwd" type="java.lang.String"/> <form-property name="age" type="java.lang.String"/> <form-property name="email" type="java.lang.String"/> </form-bean> </form-beans> Step 4: - Provide the action class RUAction import javax.servlet.http.*; import org.apache.struts.action.*; import java.sql.*; public class RUAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----RUAction.execute----"); SUDHEER REDDY

34 POTHURAI DUserRegFB fb=(DUserRegFB)form; String vuname=(String)fb.get("userName"); String vpwd=(String)fb.get("pwd"); String vage=(String)fb.get("age"); String vemail=(String)fb.get("email"); Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con=DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger"); String vsql="insert into employee values(?,?,?,?)"; PreparedStatement pstmt=con.prepareStatement(vsql); pstmt.setString(1,vuname); pstmt.setString(2,vpwd); pstmt.setString(3,vage); pstmt.setString(4,vemail); pstmt.executeUpdate( ); con.close( ); return mapping.findForward("userregd"); } } D:\Pskr\Struts>javac RUAction.java Step 5: - Provide the JSP that generates the input form. <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("----urform.jsp----"); %> <html:html locale="true"> <head> <title> Register Data </title> </head> <body> <html:errors /> <html:form action="/ur.do"> User Name : <html:text property="userName"/> <br> Password : <html:password property="pwd"/> <br> Age : <html:text property="age"/> <br> Email : <html:text property="email"/> <br> <html:submit property="submit" value="register"/> <br> </html:form> </body> </html:html> Step 6: - Provide the information about ActionMapping in struts-config.xml <action-mappings>

SUDHEER REDDY

35 POTHURAI <action name="UserRegForm" input="/urform.jsp" path="/ur" validate="true" scope="request" type="RUAction"> <forward name="userregd" path="/ur.jsp"/> </action> </action-mappings> Step 7: - Provide the ur.jsp <% System.out.println("-- executing ur.jsp--"); %> user info registered Step 8: - Provide the information about errors in properties file uname.req=user name must be required uname.ml.err=minimum length of user name must be 5 characters pwd.req=password must be required http://localhost:8000/daform/urform.jsp ----urform.jsp-------reset---User Name : Password : Age : Email : User Name : Password : Age : Email : Click ----reset-------validate-------urform.jsp---

user name must be required password must be required

User Name : Password : Age : Email : Click ----reset-------validate-------urform.jsp---

minimum length of user name must be 5 characters

SUDHEER REDDY

36 POTHURAI User Name : Password : Age : Email : Click ----reset-------validate-------RUAction.execute----- executing ur.jsp-user info registered SQL> select * from employee; UNAME PWD AGE EMAIL --------------- ---------- ---------- ---------------------------abcde Sunil 25 sudheer_1620@yahoo.com Spell checker Plug-in OurNp A plug-in is additional software that is used to enhance the capabilities of the existing software. Any one can develop a plug-in for struts frame work. As part of struts 1.1 to standard plug-ins are provided. 1) Struts validator plug-in 2) Struts tiles plug-in The information about the plug-in must be provided in struts-config.xml using the plugin tag <plug-in className="org.apache.struts.validator.ValidatorPlugIn"> ------------</plug-in> ValidatorPlugIn uses the information available in the files validator-rules.xml, validation.xml. DynaValidatorForm provides the feature available as part of DynaActionForm & this class will be able to take care of the validations automatically. SQL> create table students(sid number(8),sname varchar(15),fname varchar(15), addr varchar(20),age number(3)); Table created. SQL> select * from students; no rows selected Procedure for implementing the application using DynaValidatorForm: -

SUDHEER REDDY

37 POTHURAI Step 1: - We must decide about the name of the form, the names of the fields in the form and the validations rules that must be applied on various fields of the form. Student Id: Student Name: Father Name: Address : Age: studId studName fatherName addr age

Form name: NewStudForm Validation rules: 1) studId is required. 2) studName is required. 3) age is required. 4) age must be between 15 & 45. 5) addr is required Step 2: - Create the form bean class as a sub class of DynaActionForm class. import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.validator.*; public class DVStudFB extends DynaValidatorForm { public void reset(ActionMapping mapping,HttpServletRequest request) { System.out.println("----reset----"); set("age",new java.lang.Integer(21)); } } D:\Pskr\Struts>set CLASSPATH=.;struts.jar;servlet-api.jar;commons-beanutils.jar D:\Pskr\Struts>javac DVStudFB.java Step 3: - Provide the information about the form bean in struts-config.xml <form-beans> <form-bean name="NewStudForm" type="DVStudFB"> <form-property name="studId" type="java.lang.String"/> <form-property name="studName" type="java.lang.String"/> <form-property name="fatherName" type="java.lang.String"/> <form-property name="addr" type="java.lang.String"/> <form-property name="age" type="java.lang.Integer"/> </form-bean> SUDHEER REDDY

38 POTHURAI </form-beans> Step 4: - Provide the action class import javax.servlet.http.*; import org.apache.struts.action.*; import java.sql.*; public class SSDAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----SSDAction.execute----"); DVStudFB fb=(DVStudFB)form; String vstudId=(String)fb.get("studId"); String vstudName=(String)fb.get("studName"); String vfatherName=(String)fb.get("fatherName"); String vaddr=(String)fb.get("addr"); String vage=(String)fb.get("age"); // code to store student's data in DB Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con=DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger"); String vsql="insert into students values(?,?,?,?,?)"; PreparedStatement pstmt=con.prepareStatement(vsql); pstmt.setString(1,vstudId); pstmt.setString(2,vstudName); pstmt.setString(3,vfatherName); pstmt.setString(4,vaddr); pstmt.setString(5,vage); pstmt.executeUpdate( ); con.close( ); return mapping.findForward("sds"); } } D:\Pskr\Struts>javac SSDAction.java Step 5: - Provide the JSP that generates the input form nsform.jsp <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("----nsform.jsp----"); %> <html:html locale="true"> <head> <title> Store Data </title> </head> <body> <html:errors /> <html:form action="/ssd.do"> Student Id: SUDHEER REDDY

39 POTHURAI <html:text property="studId"/> <br> Student Name: <html:text property="studName"/> <br> Father Name: <html:text property="fatherName"/> <br> Address : <html:text property="addr"/> <br> Age: <html:text property="age"/> <br> <html:submit property="submit" value="store"/> <br> </html:form> </body> </html:html> Step 6: - provide the information about the action in struts-config.xml <action-mappings> <action name="NewStudForm" input="/nsform.jsp" path="/ssd" validate="true" scope="request" type="SSDAction"> <forward name="sds" path="/sds.jsp"/> </action> </action-mappings> Step 7: - Provides the errors in properties file Address=----Address---Step 8: - Provide the sds.jsp <% System.out.println("-- executing ssd.jsp--"); %> Student's data stored Step 9: - Provide the information about the validations that has to be performed on various fields in the file validation.xml <formset> <form name="NewStudForm"> <field property="studId" depends="required"> <arg0 name="required" key="Student Id" resource="false"/> </field> <field property="studName" depends="required"> <arg0 name="required" key="Student Name" resource="false"/> </field> <field property="addr" depends="required"> <arg0 name="required" key="Address" resource="true"/> </field> <field property="age" depends="required,intRange"> <arg0 name="required" key="Age" resource="false"/> <arg0 name="intRange" key="Age" resource="false"/> <arg1 name="intRange" key="${var:min}" resource="false"/> SUDHEER REDDY

40 POTHURAI <arg2 name="intRange" key="${var:max}" resource="false"/> <var> <var-name>min</var-name> <var-value>15</var-value> </var> <var> <var-name>max</var-name> <var-value>45</var-value> </var> </field> </form> </formset> http://localhost:8000/dvaform/nsform.jsp ----nsform.jsp-------reset---Student Id: Student Name: Father Name: Address : Age: Student Id: Student Name: Father Name: Address : Age: Click ----reset-------nsform.jsp---

Student Id is required. Student Name is required. ----Address---- is required. Age is not in the range 15 through 45.

Student Id: Student Name: Father Name: Address : Age: Click ----reset-------SSDAction.execute----- executing ssd.jsp-Student's data stored SQL> select * from students; SID SNAME FNAME

ADDR

AGE SUDHEER REDDY

41 POTHURAI ---------- --------------- --------------- ----------------------- ------------630130 sudheer kesav nrp 24 pmsg.one=copying {0} to {1} pmsg.two=Hello {0} param0/ arg0 param1/ arg1 MessageResources.properties

<%@ taglib uri="/tags/struts-bean" prefix="bean"%> <bean:message key="pmsg.one" /> <br> <bean:message key="pmsg.two" /> http://localhost:8000/dvaform/eh.jsp copying null to null Hello null <%@ taglib uri="/tags/struts-bean" prefix="bean"%> <bean:message key="pmsg.one" arg0="xxx.txt" arg1="yyy.txt"/> <br> <bean:message key="pmsg.one" arg0="abc.txt" arg1="xyz.txt"/> <br> <bean:message key="pmsg.two" arg0="Sudheer"/> http://localhost:8000/dvaform/eh.jsp copying xxx.txt to yyy.txt copying abc.txt to xyz.txt Hello Sudheer The validator required uses the error message errors.required={0} is required & the validator int range uses the error message errors.range={0} is not in the range {1} through {2}. Some of the validators use the variables. min, max are the variables used by the validators intRange, floatRange, doubleRange. We can configure the byte validator on a field as shown below <field property="age" depends="byte"> <arg0 name="byte" key="Age" resource="false"/> </field> minLength, maxLength validators can be configured as shown below <field property="studName" depends="required,minlength,maxlength"> <arg0 key="Student Name" resource="false"/> <arg1 name="minlength" key="${var:minlength}" resource="false"/> <arg1 name="maxlength" key="${var:maxlength}" resource="false"/> <var> <var-name>minlength</var-name> <var-value>5</var-value> </var> <var> <var-name>maxlength</var-name> <var-value>10</var-value> SUDHEER REDDY

42 POTHURAI </var> </field> Date validator supports 2 variables datePattern, datePatternStrict <field property="studId" depends="required,date"> <arg0 key="Student Id" resource="false"/> <var> <var-name>datePatternStrict</var-name> <var-value>dd/MM/yyyy</var-value> </var> </field> Date validator treats 1/01/2001 & 1/1/01 as valid values if we use datePattern. 1/01/2001 & 1/1/01 is considered as invalid when we configured the date validator with the variable datePatternStrict. http://localhost:8000/dvaform/form.jsp Student Id: Student Name: Age: Click

Student Id is not a date. Student Name can not be less than 5 characters. Age must be a byte.

Student Id: Student Name: Age: Click

Student Name can not be greater than 10 characters.

Student Id: Student Name: Age: Click Data stored Mask validator uses the variable with the name mask. The value we provide for this variable is called as a regular expression. <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("----form.jsp----"); %> <html:html locale="true"> <head> <title> Store Id </title> </head> <body> SUDHEER REDDY

43 POTHURAI <html:errors /> <html:form action="/ssd.do"> Student Id: <html:text property="studId"/> <br> <html:submit property="submit" value="store"/> <br> </html:form> </body> </html:html> <formset> <form name="NewStudForm"> <field property="studId" depends="required,mask"> <arg0 key="Student Id" resource="false"/> <var> <var-name>mask</var-name> <var-value>xyz</var-value> </var> Regular expression </field> </form> </formset> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is required. Click

Student Id:

Student Id is invalid

Student Id: Click Data stored The regular expression xyz matches with any string that contains xyz in a sequence. xyz, aaxyz, xyzbb, wwwxyzmm matches with the regular expression xyz. <var-value>^xyz$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid Click Data stored

Student Id:

SUDHEER REDDY

44 POTHURAI The above regular expression accepts xyz only. Here ^ means starts with, $ means ends with. <var-value>^x[a-zA-Z0-9]z$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid

Student Id: Click Data stored Student Id: Click Data stored Student Id: Click Data stored The above regular expression allows any character between a to z, A to Z, 0 to 9. <var-value>^x(a|f|m)z$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid

Student Id: Click Data stored Student Id: Click Data stored The above regular expression allows a or f or m as second char in the input. <var-value>^[0-9][0-9][0-9]( |-)[0-9][0-9][0-9]$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click Data stored Student Id: Click Data stored We can use ^[0-9][0-9][0-9]( |-)[0-9][0-9][0-9]$ as a regular expression to accept the pin code as shown below. 500 007, 500-007, 100-001 etc.

SUDHEER REDDY

45 POTHURAI <var-value>^[0-9]{11}$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid

Student Id: Click Data stored The above regular expression accepts exactly 11 digits. <var-value>^[0-9]{10,12}$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid

Student Id: Click Data stored The above regular expression accepts minimum 10 digits, maximum 12 digits. <var-value>^[0-9]{5,}$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid

Student Id: Click Data stored The above regular expression accepts minimum 5 digits, maximum no limit. <var-value>^xa?z$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid Click Data stored

Student Id:

SUDHEER REDDY

46 POTHURAI Student Id: Click Data stored Here ? means zero or one. + ----> one are more * ----> zero are more <var-value>^x\d\Dz$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click

Student Id is invalid

Student Id: Click Data stored \d ----> allow digit. \D ----> allows anything other than a digit. \s ----> allows white space. \S ----> allows anything other than a white space. \w ----> allow word chars. \W ----> allows anything other than a word chars. . ----> matches with anything other than new line. Note: - Alphabets, digits, underscore( _ ) are called as a word characters. To remove a special meaning of meta characters a slash(\) can be used before the character. <var-value>^[A-Z]\.[A-Z][a-z]{2,10}$</var-value> http://localhost:8000/dvaform/form.jsp Student Id: Click Data stored Student Id: Click Data stored Struts validator plug-in will be able to generate the java script to validate the inputs in the clients. For generating the java script we must used the java script tag of struts-html tag library. <html:javascript formName="NewStudForm"/> The above tag sends a java script to the browser. This java script contains a function with the name validateNewStudForm. But this function is not executed automatically. We must provide the code to call this function when user submits the form. For this we can provide the code as shown below. <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("----nsform.jsp----"); %> SUDHEER REDDY

47 POTHURAI <html:html locale="true"> <head> <title> Register Data </title> </head> <body> <html:javascript formName="NewStudForm"/> <html:errors /> <html:form action="/ssd.do" onsubmit="return validateNewStudForm(this);"> Student Id: <html:text property="studId"/> <br> Student Name: <html:text property="studName"/> <br> Father Name: <html:text property="fatherName"/> <br> Address : <html:text property="addr"/> <br> Age: <html:text property="age"/> <br> <html:submit property="submit" value="store"/> <br> </html:form> </body> </html:html> <action-mappings> <action name="NewStudForm" input="/nsform.jsp" path="/ssd" validate="false" scope="request" type="SSDAction"> <forward name="sds" path="/sds.jsp"/> </action> </action-mappings> SQL> select * from students; no rows selected http://localhost:8000/dvaform/nsform.jsp Student Id: Student Name: Father Name: Address : Age: Click

SUDHEER REDDY

48 POTHURAI Student Id: Student Name: Father Name: Address : Age: Click

Student Id: Student Name: Father Name: Address : Age: Click Student's data stored SQL> select * from students; SID SNAME FNAME ADDR AGE ----------------- ------------- --------------------- ------------------ -----------------630130 Sunil Kesav Anantapur 25 How to take care of validations that can not be carried out by struts? A) SQL> create table users(uname varchar(15), pone varchar(10), ptwo varchar(10)); Table created. SQL> select * from users; no rows selected Step 1: UserName: userName Password: pwdOne re-type Password: pwdTwo

Form name: NewUserAccForm Validations: 1) userName is required. 2) pwdOne is required. 3) pwdTwo is required. 4) pwdOne must be same as pwdTwo. Assumption: - 4th validation can not be carried out by struts.

SUDHEER REDDY

49 POTHURAI Step2: - Create the form bean class as a sub class of DynaValidatorForm class import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.validator.*; public class DVNUsrFB extends DynaValidatorForm { public void reset(ActionMapping mapping,HttpServletRequest request) { set("userName",""); set("pwdOne",""); set("pwdTwo",""); } public ActionErrors validate(ActionMapping mapping,HttpServletRequest request) { ActionErrors aes=super.validate(mapping,request); System.out.println("---aes--1-->"+aes.size( )); String vpwdOne=(String)get("pwdOne"); String vpwdTwo=(String)get("pwdTwo"); if(!vpwdOne.equals(vpwdTwo)) { aes.add("pwdOne",new ActionError("pwds.not.equals")); } System.out.println("---aes--2-->"+aes.size( )); return aes; } } D:\Pskr\Struts>javac DVNUsrFB.java The validate( ) method in the super class DynaValidatorForm takes care of validations that are specified in validation.xml. Step3: - Provide the information about the form bean in struts-config.xml <form-beans> <form-bean name="NewUserAccForm" type="DVNUsrFB"> <form-property name="userName" type="java.lang.String"/> <form-property name="pwdOne" type="java.lang.String"/> <form-property name="pwdTwo" type="java.lang.String"/> </form-bean> </form-beans> Step4: - Provides the errors in properties file pwds.not.equals=Passwords must be same Step5: - Provide the action class SUDHEER REDDY

50 POTHURAI import javax.servlet.http.*; import org.apache.struts.action.*; import java.sql.*; public class CUAAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----CUAAction.execute----"); DVNUsrFB fb=(DVNUsrFB)form; String vuserName=(String)fb.get("userName"); String vpwdOne=(String)fb.get("pwdOne"); String vpwdTwo=(String)fb.get("pwdTwo"); // code to store student's data in DB Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con=DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger"); String vsql="insert into users values(?,?,?)"; PreparedStatement pstmt=con.prepareStatement(vsql); pstmt.setString(1,vuserName); pstmt.setString(2,vpwdOne); pstmt.setString(3,vpwdTwo); pstmt.executeUpdate( ); con.close( ); return mapping.findForward("uacreated"); } } D:\Pskr\Struts>javac CUAAction.java Step6: - Provide the JSP that generates the input form nuform.jsp <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("----nuform.jsp----"); %> <html:html locale="true"> <head> <title> User Created </title> </head> <body> <html:errors /> <html:form action="/cua.do"> UserName: <html:text property="userName"/> <br> Password: <html:password property="pwdOne"/> <br> re-type Password: <html:password property="pwdTwo"/> <br> <html:submit property="submit" value="Create"/> <br> </html:form> SUDHEER REDDY

51 POTHURAI </body> </html:html> Step7: - Provide the information about the action in struts-config.xml <action-mappings> <action name="NewUserAccForm" input="/nuform.jsp" path="/cua" validate="true" scope="request" type="CUAAction"> <forward name="uacreated" path="/uac.jsp"/> </action> </action-mappings> Step 8: - Provide the uac.jsp <% System.out.println("-- executing uac.jsp--"); %> User account stored in db Step 9: - Provide the information about the validations that has to be performed on various fields in the file validation.xml <formset> <form name="NewUserAccForm"> <field property="userName" depends="required"> <arg0 key="User Name" resource="false"/> </field> <field property="pwdOne" depends="required"> <arg0 key="Password One" resource="false"/> </field> <field property="pwdTwo" depends="required"> <arg0 key="Password Two" resource="false"/> </field> </form> </formset> http://localhost:8000/cncbs/nuform.jsp ----nuform.jsp---UserName: Password: re-type Password: Click ---aes--1-->3 ---aes--2-->3 ----nuform.jsp---

User Name is required. Password One is required. Password Two is required.

UserName: Password: SUDHEER REDDY

52 POTHURAI re-type Password: Click ---aes--1-->0 ---aes--2-->1 ----nuform.jsp---

Passwords must be same

UserName: Password: re-type Password: Click ---aes--1-->0 ---aes--2-->0 ----CUAAction.execute----- executing uac.jsp-User account stored in db SQL> select * from users; UNAME PONE PTWO ----------------- ------------- ----------sudheer sunil sunil To take care of the validations that can not be carried out by the java script generated by <html:javascript ----- > tag, we must provide our own java script function. In this function code must be provided to call the java script function generated by struts & the code to take care of additional validations. Action Chaining: - Multiple actions can be used to process a single request. All these actions are considered to be part of an action chain. import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionOne extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----ActionOne:execute----"); // Code to perform task one return mapping.findForward("fone"); } } D:\Pskr\Struts>set CLASSPATH=.;commons-beanutils.jar;servlet-api.jar;struts.jar; D:\Pskr\Struts>javac ActionOne.java import javax.servlet.http.*; import org.apache.struts.action.*; SUDHEER REDDY

53 POTHURAI public class ActionTwo extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----ActionTwo:execute----"); // Code to perform task Two return mapping.findForward("ftwo"); } } D:\Pskr\Struts>javac ActionTwo.java op genarated by dispop.jsp <action-mappings> <action path="/aone" type="ActionOne"> <forward name="fone" path="/atwo.do"/> </action> <action path="/atwo" type="ActionTwo"> <forward name="ftwo" path="/dispop.jsp"/> </action> </action-mappings> http://localhost:8000/achain/aone.do ----ActionOne:execute-------ActionTwo:execute---op genarated by dispop.jsp

/aone.do
Action servlet

ActionOne Browser

ActionTwo dispop.jsp

Server Note: - When the browser sends the request using /aone.do, the struts code executes ActionOne, ActionTwo & then it forwards the request to dispop.jsp. in this case a single request is processed by multiple actions (ActionOne, ActionTwo). What is the difference between global forward & local forward ? SUDHEER REDDY

54 POTHURAI A) import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionOne extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----ActionOne:execute----"); // Code to perform task one return mapping.findForward("fwd"); } } D:\Pskr\Struts>javac ActionOne.java import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionTwo extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { System.out.println("----ActionTwo:execute----"); // Code to perform task Two return mapping.findForward("fwd"); } } D:\Pskr\Struts>javac ActionTwo.java op genarated by dispop.jsp <action-mappings> <action path="/aone" type="ActionOne"> <forward name="fwd" path="/dispop.jsp"/> </action> <action path="/atwo" type="ActionTwo"> <forward name="fwd" path="/dispop.jsp"/> </action> </action-mappings> http://localhost:8000/achain/aone.do ----ActionOne:execute---op genarated by dispop.jsp http://localhost:8000/achain/atwo.do ----ActionTwo:execute---op genarated by dispop.jsp

local forward

A forward that is provided as part of the action tag is called as a local forward & it can be used only by that action. SUDHEER REDDY

55 POTHURAI In the above configuration the information about the same forward is provided twice. We can avoid this by using global forwards. <global-forwards> <forward name="fwd" path="/dispop.jsp"/> </global-forwards> <action-mappings> <action path="/aone" type="ActionOne"> </action> <action path="/atwo" type="ActionTwo"> </action> </action-mappings> http://localhost:8000/achain/aone.do ----ActionOne:execute---op genarated by dispop.jsp http://localhost:8000/achain/atwo.do ----ActionTwo:execute---op genarated by dispop.jsp global forward

A forward provided inside global-forwards tag is called as a global forward & it can be used by any of the actions that are configured in struts-config.xml. If the local forward & global forward is available then struts uses local forward. We can use try, catch blocks to deal with the exceptions. But in struts we can use declarative exception handling mechanism to deal with the exceptions. import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionOne extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { Class.forName("xxx"); System.out.println("-- class loaded --"); return mapping.findForward("fwd"); } } D:\Pskr\Struts>javac ActionOne.java Note: - The code shown above throws java.lang.ClassNotFoundException. import javax.servlet.http.*; import org.apache.struts.action.*; public class ActionTwo extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception SUDHEER REDDY

56 POTHURAI { java.io.FileInputStream fis=new java.io.FileInputStream("yyy.txt"); System.out.println("-- file opend --"); return mapping.findForward("fwd"); } } D:\Pskr\Struts>javac ActionTwo.java Note: - The code shown above throws java.lang.FileNotFoundException. cls.err=Class is not available file.err=File is not available <% System.out.println("-- executing ehone.jsp --"); %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <html:errors /> output of ehone.jsp <% System.out.println("-- executing ehtwo.jsp --"); %> <%@ taglib uri="/tags/struts-html" prefix="html" %> <html:errors /> output of ehtwo.jsp op genarated by dispop.jsp We can provide the information about what must be done by struts when an exception is thrown as shown below. <global-exceptions> <exception key="file.err" type="java.io.FileNotFoundException" path="/ehone.jsp"/> <exception key="cls.err" type="java.lang.ClassNotFoundException" path="/ehtwo.jsp"/> </global-exceptions> <global-forwards> <forward name="fwd" path="/dispop.jsp"/> </global-forwards> <action-mappings> <action path="/aone" type="ActionOne"> </action> <action path="/atwo" type="ActionTwo"> </action> </action-mappings> http://localhost:8000/cferr/aone.do -- executing ehtwo.jsp - Class is not available output of ehtwo.jsp http://localhost:8000/cferr/atwo.do -- executing ehone.jsp -SUDHEER REDDY

57 POTHURAI File is not available

output of ehone.jsp When java.io.FileNotFoundException is thrown, struts add an error with the key file.err & it forwards the request to ehone.jsp. gen.err=failed due to error, contact admin <global-exceptions> <exception key="gen.err" type="java.lang.Exception" path="/ehone.jsp"/> </global-exceptions> http://localhost:8000/cferr/aone.do -- executing ehone.jsp -

failed due to error, contact admin

output of ehone.jsp http://localhost:8000/cferr/atwo.do -- executing ehone.jsp -

failed due to error, contact admin

output of ehone.jsp When java.lang.ClassNotFoundException is thrown struts will try to find the information about ClassNotFoundException in the exception tags. In the above configuration this information is not available. In this case struts uses the information about java.lang.Exception as it is the super class of ClassNotFoundException . As part of struts a set of standard actions like org.apache.struts.actions.ForwardAction, org.apache.struts.actions.IncludeAction, org.apache.struts.actions.SwitchAction, org.apache.struts.actions.DispatchAction etc are provided. public class OAAction extends Action { // code for opening account (5 lines) } public class CAAction extends Action { // code for closing account (3 lines) } public class GADAction extends Action { // code for getting account info (4 lines) } public class UAAction extends Action { // code for updating account (5 lines) }

SUDHEER REDDY

58 POTHURAI The above four classes performs related actions and we have very less amount of code in these classes. Instead of providing multiple classes like this, we can provide a single class to perform related actions using DispatchAction. import javax.servlet.http.*; import org.apache.struts.actions.*; import org.apache.struts.action.*; public class MultiAction extends DispatchAction { public ActionForward openAcc(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { // Code to open an account return mapping.findForward("ao"); } public ActionForward closeAcc(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception { // Code to closing an account return mapping.findForward("ac"); } } D:\Pskr\Struts>javac MultiAction.java To take of the actions we must provide multiple methods like openAcc, closeAcc. The parameter types & the return type of these methods must be same as that of execute method. Output generated by ao.jsp Output generated by ac.jsp As part of struts-config.xml we must provide the configuration of the action as shown below. <action-mappings> <action path="/ma" type="MultiAction" parameter="mname"> <forward name="ao" path="/ao.jsp"/> <forward name="ac" path="/ac.jsp"/> </action> </action-mappings> The method openAcc will be executed when the client sends the request using the URL shown below http://localhost:8000/mact/ma.do?mname=openAcc Output generated by ao.jsp The method closeAcc will be executed when the client sends the request using the URL shown below http://localhost:8000/mact/ma.do?mname=closeAcc Output generated by ac.jsp SUDHEER REDDY

59 POTHURAI The execute method available in DispatchAction class takes care of calling the methods like openAcc, closeAcc. In case of a big project there will be more number of beans & Action classes. If we provide the information about to many numbers of form beans & Actions in a single file, the configuration file will become unmanageable. To avoid the problems started about we can use multiple configurations files. For this we must divide the project in to multiple modules & use one configuration file every module. Module name Config file name 1) struts-config.xml 2) modone sc-xxx.xml 3) modtwo sc-yyy.xml Module without name We must provide the information about the names of the modules & the configuration files in web.xml. <web-app> <servlet> <servlet-name>action</servlet-name> <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> <init-param> <param-name>config</param-name> <param-value>/WEB-INF/struts-config.xml</param-value> </init-param> <init-param> <param-name>config/modone</param-name> <param-value>/WEB-INF/sc-xxx.xml</param-value> </init-param> <init-param> <param-name>config/modtwo</param-name> <param-value>/WEB-INF/sc-yyy.xml</param-value> </init-param> </servlet> --------------</web-inf> In the WEB-ROOT directory we must create the directories with the names modone, modtwo. We must place the Resources (html files, JSP) of modone module in modone directory. <% System.out.println("-- urform.jsp --"); %> Output generated by urform.jsp

SUDHEER REDDY

60 POTHURAI The information about the form beans, Actions of modone must be provided in scxxx.xml. If we use the URL http://localhost:8000/bproj/modone/urform.jsp for generating the form that is part of modone. It will fail as struts will work with the module without name (default module) by default. To solve this problem we must configure switch action in struts-config.xml as shown below. <action-mappings> <action path="/sm" type="org.apache.struts.actions.SwitchAction"/> </action-mappings> SwitchAction takes the responsibility of switching from one module to another module. SwitchAction uses two parameters (prefix, page). For accessing urform.jsp available in modone, we can use the following URL http://localhost:8000/bproj/sm.do?prefix=/modone&page=/urform.jsp -- urform.jsp -Output generated by urform.jsp <% System.out.println("-- one.jsp --"); %> output generated by one.jsp <% System.out.println("-- two.jsp --"); %> output generated by two.jsp http://localhost:8000/bproj/one.jsp -- one.jsp -output generated by one.jsp http://localhost:8000/bproj/two.jsp -- two.jsp -output generated by two.jsp (*.do) action /one.jsp

/two.jsp one.jsp Client

two,jsp Server

SUDHEER REDDY

61 POTHURAI When the browser sends the request for one.jsp, the container executes one.jsp directly. In this case the struts code available in action servlet will not be executed. Some of the tags that are part of struts tag libraries may not work in this case. We can configure the ForwardAction as shown below <action-mappings> <action path="/xxx" parameter="/one.jsp" type="org.apache.struts.actions.ForwardAction"/> <action path="/yyy" parameter="/two.jsp" type="org.apache.struts.actions.ForwardAction"/> </action-mappings> http://localhost:8000/bproj/xxx.do -- one.jsp -output generated by one.jsp http://localhost:8000/bproj/yyy.do -- two.jsp -output generated by two.jsp (*.do) action /one.jsp

/two.jsp Client ForwardAction one.jsp two,jsp

Server When the browser sends the request using /xxx.do the following tasks will be carried out in the web container: 1) Web container starts the execution of Action Servlet. 2) Action Servlet will start executing the ForwardAction 3) ForwardAction uses the value of parameter (/one.jsp). 4) The request will be forwarded to one.jsp. In this case before executing one.jsp web container executes struts code available in struts-config.xml. SQL> create number(10,2)); Table created. table accounts(aid number(3), cname varchar(10), balance

SQL> insert into accounts values(1,'cone',10000); 1 row created. SUDHEER REDDY

62 POTHURAI SQL> insert into accounts values(2,'ctwo',20000); 1 row created. SQL> select * from accounts; AID CNAME BALANCE -------------- --------------- -------------1 cone 10000 2 ctwo 20000 Note: - Struts framework is based on MVC architecture. MVC design pattern Action Servlet Action Form Bean

B R O W S E R

1 Request

(Controller) Servlet 3 2 Instantiate

5 Response

(View) JSP

4 EIS

Browser

(Model) Java Bean Servlet Container

Account One: Account Two: Amount:

accone acctwo amount

Form Name: - FTForm Validations: - All the fields are required. In the carrier application, we are provided the business logic as part of the Action classes. This approach is not recommends, that we must use the model classes for the implementation of the business logic. import java.sql.*; public class FTManager { SUDHEER REDDY

63 POTHURAI public void transferFunds(int accone, int acctwo, float amount)throws Exception { Class.forName("oracle.jdbc.driver.OracleDriver"); Connection con=DriverManager.getConnection ("jdbc:oracle:thin:@localhost:1521:xe","scott","tiger"); String vsql1="select balance from accounts where aid="+accone; Statement stmt=con.createStatement( ); ResultSet rs=stmt.executeQuery(vsql1); rs.next( ); float bal=rs.getFloat("balance"); if(bal<amount) { throw new Exception("Funds not available"); } String vsql2="update accounts set balance=balance-"+amount+" where aid="+accone; String vsql3="update accounts set balance=balance+"+amount+" where aid="+acctwo; stmt.executeUpdate(vsql2); stmt.executeUpdate(vsql3); // code to send SMS to the customer } } D:\Pskr\Struts>set CLASSPATH=.;ojdbc14.jar D:\Pskr\Struts>javac FTManager.java Note: - In the above model class we have not use anything related to Servlet API, Struts API. This class is not dependent upon struts, servlet API & this class will work without these APIs import java.awt.*; import java.awt.event.*; public class GuiApp extends Frame implements ActionListener { private TextField tfaccone; private TextField tfacctwo; private TextField tfamount; private Button btransfer; public GuiApp( ) { tfaccone=new TextField("Acc No One Here"); tfacctwo=new TextField("Acc No two Here"); tfamount=new TextField("Amount Here"); btransfer=new Button("Transfer"); btransfer.addActionListener(this); setLayout(new FlowLayout( )); add(tfaccone); SUDHEER REDDY

64 POTHURAI add(tfacctwo); add(tfamount); add(btransfer); } public void actionPerformed(ActionEvent ae) { try { String vaccone=tfaccone.getText( ); String vacctwo=tfacctwo.getText( ); String vamount=tfamount.getText( ); FTManager ftm=new FTManager( ); ftm.transferFunds(Integer.parseInt(vaccone),Integer.parseInt(vacctwo), Float.parseFloat(vamount)); } catch(Exception e) { System.out.println(e); } } public static void main(String a[ ]) throws Exception { GuiApp win=new GuiApp( ); win.pack( ); win.show( ); } } D:\Pskr\Struts>javac GuiApp.java D:\Pskr\Struts>java GuiApp

java.lang.Exception: Funds not available

SQL> select * from accounts; AID CNAME BALANCE SUDHEER REDDY

65 POTHURAI ------------- ------------- --------------1 cone 7500 2 ctwo 22500 The above model class FTManager can be used as part of a GUI application, a web application developed using struts, a web application developed without using struts, applets etc. import javax.servlet.http.*; import org.apache.struts.action.*; import org.apache.struts.validator.*; public class FTInfoFB extends DynaValidatorForm { public void reset(ActionMapping mapping,HttpServletRequest request) { System.out.println("----reset----"); set("accone","0"); set("acctwo","0"); set("amount","0.0"); } } D:\Pskr\Struts>set CLASSPATH=.;struts.jar;servlet-api.jar;ojdbc14.jar;commonsbeanutils.jar D:\Pskr\Struts>javac FTInfoFB.java Note: - The form bean classes depends upon the struts API & servlet API. import javax.servlet.http.*; import org.apache.struts.action.*; import java.sql.*; public class FTAction extends Action { public ActionForward execute(ActionMapping mapping,ActionForm form, HttpServletRequest request,HttpServletResponse response)throws Exception { System.out.println("----FTAction.execute----"); FTInfoFB fb=(FTInfoFB)form; String vaccone=(String)fb.get("accone"); String vacctwo=(String)fb.get("acctwo"); String vamount=(String)fb.get("amount"); FTManager ftm=new FTManager( ); ftm.transferFunds(Integer.parseInt(vaccone),Integer.parseInt(vacctwo), Float.parseFloat(vamount)); return mapping.findForward("ftsuc"); } } D:\Pskr\Struts>javac FTAction.java Note: - The above Action class depends upon the struts API & servlet API.

SUDHEER REDDY

66 POTHURAI Can we provide business logic as part of the form bean classes & action classes? A) Its not recommended providing the business logic in the action class & in the form bean class. We can use these classes only as part of the struts based applications. If the business logic is implemented in a separate set of classes called as model classes then we can use the model classes as part of different kinds of applications like web applications, GUI applications etc. <%@ taglib uri="/tags/struts-html" prefix="html"%> <% System.out.println("----ftform.jsp----"); %> <html:html locale="true"> <head> <title> Transfer amount </title> </head> <body> <html:errors /> <html:form action="/ftAction.do"> <b>Account One :</b> <html:text property="accone"/> <br> <b>Account Two :</b> <html:text property="acctwo"/> <br> <b>Amount :</b> <html:text property="amount"/> <br> <html:submit property="submit" value="Transferr"/> <br> </html:form> </body> </html:html> <% System.out.println("----fts.jsp----"); %> Amount transfer successfully <form-beans> <form-bean name="FTForm" type="FTInfoFB"> <form-property name="accone" type="java.lang.String"/> <form-property name="acctwo" type="java.lang.String"/> <form-property name="amount" type="java.lang.String"/> </form-bean> </form-beans> <action-mappings> <action name="FTForm" type="FTAction" input="/ftform.jsp" path="/ftAction" validate="true" scope="request"> <forward name="ftsuc" path="/fts.jsp"/> </action> </action-mappings> <formset> <form name="FTform"> <field property="accone" depends="required"> <arg0 key="Account One" resource="false"/> </field> SUDHEER REDDY

67 POTHURAI <field property="acctwo" depends="required"> <arg0 key="Account Two" resource="false"/> </field> <field property="amount" depends="required"> <arg0 key="Amount" resource="false"/> </field> </form> </formset> http://localhost:8000/ftapp/ftform.jsp ----ftform.jsp-------reset---Account One : Account Two : Amount : Click ----reset-------FTAction.execute-------fts.jsp---Amount transfer successfully SQL> select * from accounts; AID CNAME BALANCE --------------- ------------ ----------------1 cone 4500 2 ctwo 25500 1) Struts is based on MVC architecture. In the above application ftform.jsp & fts.jsp acts as a View Component. 2) FTManager contains the business logic and it acts as the Model Component. 3) The code in Action servlet, form bean, Action is responsible for deciding about how the application as to react when the user interacts with the application. These 3 are considered to be part of Controller Component. DAO design pattern: - (data Access object). 1) For accessing the data available in the database, we can use the APIs like JDBC, Top Link, JDO (Java Data Objects), JPA (Java Persistence API) erc. 2) Companies will constantly change the API/technology for accessing the data in the databases. Ex: - A project developed by a company using JDBC API in 2004, may change the data access code using Hibernate API in 2008. If we provide the code to access the data base + the code that need not access the database together as part of the model classes for the implementation of business logic then modifying the data access logic using another API will be difficult. To solve this problem we can use DAO design pattern. SQL> select * from accounts; AID CNAME BALANCE --------------- ------------ ----------------1 cone 8000 SUDHEER REDDY

68 POTHURAI 2 ctwo 22000 public class Account { private long aid; private String cname; private float balance; // setters & getters supporting aid, cname, balance properties. } /* Account a=new Account( ); // get the data from Accounts table & put the data in Account object a.setAid(10); a.setCname(chun); a.setBalance(13000); AccountsDAO adao=new AccountsDAO( ); */ We can use an Account object to represent the data of 1 row available in accounts table. DAO class contains the code to access the data available in the database. Ex: - /* class developed in 2004 */ public AccountsDAO { public void save(Account acc) { // jdbc code to store a record in accounts table. } public Account getAccount(long id) { /* jdbc code to get a record from accounts table & load the data in Account object */ return acc; } public Vector getAccounts( ) { // jdbc code to get the records from accounts table } public void delete(Account a) { // jdbc code to remove record from accounts table } public void update(Account a) { // jdbc code to modify the record in accounts table. } } SUDHEER REDDY

69 POTHURAI Like AccountsDAO several DAO classes will be provided in the project. We can implement FTManager without using data access code directly as shown below. /* class developed in 2004 */ public class FTManager { public void transferFunds(int accone, int acctwo, float amount) throws Exception { AccountsDAO adao=new AccountsDAO( ); Account a1=adao.getAccount(accone); Account a2=adao.getAccount(acctwo); if(a1.getBalance( )<amount) { // throw Eception } a1.setBalance(a1.getBalance( )-amount); a2.setBalance(a2.getBalance( )+amount); adao.update(a1); adao.update(a2); // code to send SMS to the customer } } In the above class there in no JDBC code. Model Classes (Business logic)

DAO Classes (Data access logic)

Data Base If we need to use Hibernate in place of jdbc then we need not change the model classes. In this case we need to modify the data access code available in DAO classes. Switching from one data access technology to another data access technology will be easy if we use DAO design pattern. TilesPlugin: - TilesPlugin simplifies the development of a web application with consistent views (similar look for all the pages viewed by the user of the application). TilesPlugin uses the definitions available in tiles-defs.xml. In order to use the Tiles plug-In, we must first decide about the layout of the page.

SUDHEER REDDY

70 POTHURAI

CLogo

Menu Options (links)

TopTile

Context according to the Menu Option Chosen by the user Copyright Notice. Layout One CLogo Menu Options (links)

MiddleTile

BottomTile

TopTile Right MiddleTile

Left Middle Tile

Sub Menu Options

Context according to the Menu Option Chosen by the user

Copyright Notice

BottomTile

Layout Two Once the Layout is decided, a jsp must be provided according to the Layout using the tags that are part of struts-tiles tag libraries. <%@ taglib uri="/tags/struts-tiles" prefix="tiles" %> <html> <head> <title> <tiles:getAsString name="title"/> </title> </head> <body bgcolor="#cccc99"> <table> <tr> <td> <tiles:insert attribute="TopTile"/> </td> </tr> <tr> <td> <tiles:insert attribute="MiddleTile"/> </td> </tr> <tr> <td> <tiles:insert attribute="BottomTile"/> </td> </tr> </table> </body> </html> SUDHEER REDDY

71 POTHURAI In the above JSP title, TopTile, MiddleTile & BottomTile are called as the Components. Once the Layout is created, the same layout can be used for generating all the views. <%@ taglib uri="/tags/struts-tiles" prefix="tiles" %> <tiles:insert page="layout.jsp"> <tiles:put name="title" value="products"/> <tiles:put name="TopTile" value="header.jsp"/> <tiles:put name="MiddleTile" value=" productsbody.jsp "/> <tiles:put name="BottomTile" value=" footer.jsp "/> </tiles:insert> Definitions improve the flexibility of the application. <tiles-definitions> <definition name="ourdef" path="/layout.jsp"> <put name="title" value="products"/> <put name="TopTile" value="/header.jsp"/> <put name="MiddleTile" value="/productsbody.jsp"/> <put name="BottomTile" value="/footer.jsp"/> </definition> </tiles-definitions> products.jsp can be re-written using the definition as shown below <%@ taglib uri="/tags/struts-tiles" prefix="tiles" %> <tiles:insert definition="ourdef"> </tiles:insert>

SUDHEER REDDY

72 POTHURAI <%@ taglib uri="/tags/struts-tiles" prefix="tiles" %> <tiles:insert definition="ourdef"> <tiles:put name="title" value="services"/> <tiles:put name="MiddleTile" value="servicesbody.jsp"/> </tiles:insert> Note: - The values of title, MiddleTile provide using the put tags in the above JSP overrides the values provide in the definition (tiles-def.xml).

SUDHEER REDDY