Friday, 29 April 2011

Struts Class 9



Recall the above example how flow goes?


->initialization
->RequestProcessing
->processPath()
->If action is located, check is performed whether there are any form processings.


How ?

  • If name attribute is configured in the <action> tag, then Performs form processing inside the behavior named processActionForm().
  • Here check is performed whether the formbean instance is available in the specified scope or not.
  • If form bean instance is available then calls reset() and resets the form bean instance. Then invokes the setXXX() and sets the new data into the form bean instance and places in its specified scope.
  • If the form bean instance is not available in the specified scope, creates a new form bean instance calls setXXX() and places the instance in the specified scope
  • After performing the above form processing as the validate attribute is true by default, validates the form fields if the validate(-,-) returns an empty ActionError or null, the request is given to Action. If the validate(-,-) returns ActionErrors object then displays the error messages in the same jsp page.
  • Once the request goes to the Action the remaining steps are same as 1st application.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


In the 2 & 3 examples we used form beans and identified its use, now in the application development we find an issue if number of formbean classes are written as it requires huge active memory space.
So here we wanted to reduce writing formbean classes.


How to overcome this?
The Struts framework supports the above requirement by providing us a Declarative Formbean or ready made formbean named 
org.apache.struts.DynaActionForm (a subtype of org.apache.struts.action.ActionForm).


How to use DynaActionForm with respect to Application development.


Step A):
^^^^^^^
Configure the DynaActionForm in the struts-config file using form beans tag.
Specify the form properties using the <form-property> tag a child tag to <form-bean>



<form-bean name="mybean" type="org.apache.struts.action.DynaActionForm">
<form-property name="uname" type="java.lang.String"/>
<form-property name="pass" type="java.lang.String"/>
</form-bean>







Step B)
^^^^^^^


Associating the DynaActionForm to the Action is same as we associated ActionForm with Action i.e using name attribute value.


Step C)
^^^^^^^


Retrieve the DynaActionForm bean in our Action




DynaActionForm daf=(DynaActionForm)af;
//use Object.get(<property>) behavior
vo.setUname((String)daf.get("uname"));
vo.setPass((String)daf.get("pass"));




Directory struture as shown in previous example.


***Delete the previous LoginActionForm.java 




Next requirement:-


How to validate DynaActionForm fields.


As DynaActionForm is configured Declaratively we have to validate its fields or properties also in a Declarative fashion.


To support Declarative validations in struts we commence our learning with Validation Framework.





  1. How to plug validation framework with struts framework?
  2. What validation framework provides?
  3. how to use validation framework for Action form bean and DynaActionForm beans?




















  



Struts Class 8



Now we have a requirement like we wanted to validate the form fields
How to validate?
By overriding the following behaviour 


ActionErrors validate(ActionMapping am,HttpServletrequest req)


Another requirement is our application should support i18n(Internationalization).


with respect to struts framework we are given with predefined bean tags 
<bean:message>






Do the modifications in the previous example


1. Login.jsp





<%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>
<html>
<body>
<html:form action="login.stech"><pre>
<bean:message key="uname"/><html:text property="uname"/>
<html:errors property="uname"/>
<bean:message key="pass"/><html:password property="pass"/>
<html:errors property="pass"/>
<html:submit>
<bean:message key="submit"/>
</html:submit>
</pre>
</html:form>
</body>
</html>





In LoginActionForm.java




package com.cg.struts.form;
import org.apache.struts.action.*;
import javax.servlet.http.*;
public class LoginActionForm extends ActionForm
{
public void setUname(String uname){this.uname=uname;}
public String getUname(){return this.uname;}
public void setPass(String pass){this.pass=pass;}
public String getPass(){return this.pass;}
public ActionErrors validate(ActionMapping am,HttpServletRequest req)
{
//first instantiate ActionErrors
ActionErrors ae=new ActionErrors();
//using control flow statements
if(getUname().equals(""))
{
//add to the ActionErrors
ae.add("uname",new ActionMessage("field.required","UserName"));
}
else if(getUname().length()<3)
{
ae.add("uname",new ActionMessage("minlengthrequired"));
}
if(getPass().equals(""))
{
ae.add("pass",new ActionMessage("passrequired"));
}
//check the size of ActionErrors object
if(ae.size()==0)
{
return null;
}
return ae;
}
String uname,pass;
};


3) Inside the classes folder Save the following file

ApplicationResources.properties


uname=UserName
pass=Password
submit=Login
field.required=Please give {0}
minlengthrequired=UserName should have min3 characters.
passrequired=You did not give password


4)In struts-config.xml file



<struts-config>
<form-beans>
<form-bean name="mybean" type="com.cg.struts.form.LoginActionForm"/>
</form-beans>
<action-mappings>
<action type="com.cg.struts.action.LoginAction" path="/login" name="mybean" input="/Login.jsp" validate="true">
<forward name="success" path="/Welcome.jsp"/>
<forward name="fail" path="/Login.jsp"/>
</action>
</action-mappings>
<message-resources parameter="ApplicationResources"/>
</struts-config>




Deploy this application in Tomcat web apps folder.










Struts Class 7

Application 2:


<!--Login.jsp-->



<%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<html>
<body>
<html:form action="login.stech">
UserName:<html:text property="uname"/><br/>
PassWord:<html:password property="pass"/><br/>
<html:submit value="login"/>
</html:form>
</body>
</html>




^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^




<!--web.xml-->



<web-app>
<servlet>
<servlet-name>st2</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>st2</servlet-name>
<url-pattern>*.stech</url-pattern>
</servlet-mapping>
</web-app>


^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^




//LoginActionForm.java


package com.cg.struts.form;
import org.apache.struts.action.*;
public class LoginActionForm extends ActionForm
{
public void setUname(String uname){this.uname=uname;}
public String getUname(){return this.uname;}
public void setPass(String pass){this.pass=pass;}
public String getPass(){return this.pass;}
String uname,pass;
};

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



//Loginvo
package com.cg.struts.vo;
public class Loginvo
{
public void setUname(String uname){this.uname=uname;}
public String getUname(){return this.uname;}
public void setPass(String pass){this.pass=pass;}
public String getPass(){return this.pass;}
String uname,pass;


};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~





//Integration Tier
//DBConstants.java


package com.cg.struts.dao;
public class DBConstants
{
public static final int Db_Type=DaoFactory.Oracle;
//similarly for other db's;


}




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



//DaoFactory.java


package com.cg.struts.dao;
public abstract class DaoFactory
{
public abstract LoginDaoInterface getLoginDao();
public static final int Oracle=1;
//similarly public static final int Sybase=2;
//public static final int MySql=3;
public static DaoFactory getDaoFactory(int whichDb)
{
switch(whichDb)
{
case Oracle: return new OracleDaoFactory();
//similarly for sybase and mysql
default: return null;
}
}
};


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~







//OracleDaoFactory.java


package com.cg.struts.dao;
import java.sql.*;
public class OracleDaoFactory extends DaoFactory
{
public static final String driver="oracle.jdbc.driver.OracleDriver";
public static final String url="jdbc:oracle:thin:@localhost:1521:XE";
public static Connection createConnection()
{
Connection con=null;
try{
Class.forName(driver);
con=DriverManager.getConnection(url,"system","tiger");
}catch(Exception e){e.printStackTrace();}
return con;
}
public LoginDaoInterface getLoginDao()
{
return new LoginDaoImpl();
}
};



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~




//LoginDaoInterface.java


package com.cg.struts.dao;
import com.cg.struts.vo.Loginvo;
public interface LoginDaoInterface
{
boolean validateUser(Loginvo vo);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



//LoginDaoImpl.java


package com.cg.struts.dao;
import java.sql.*;
import com.cg.struts.vo.Loginvo;
public class LoginDaoImpl implements LoginDaoInterface
{
Connection con=null;
PreparedStatement ps=null;
ResultSet rs=null;
public boolean validateUser(Loginvo vo)
{
String query="select * from check_db where uname=? and pass=?";
boolean status=false;
try{
con=OracleDaoFactory.createConnection();
ps=con.prepareStatement(query);
ps.setString(1,vo.getUname());
ps.setString(2,vo.getPass());
rs=ps.executeQuery();
while(rs.next())
{
status=true;
}
}catch(Exception e){}
return status;
}
};




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//Loginbo.java





//Business Object
package com.cg.struts.bo;
import com.cg.struts.vo.*;
import com.cg.struts.dao.*;
public class Loginbo
{
public static boolean validateUser(Loginvo vo)
{
//get the DaoFactory
DaoFactory oracleFactory=DaoFactory.getDaoFactory(DBConstants.Db_Type);
LoginDaoInterface dao=oracleFactory.getLoginDao();
return dao.validateUser(vo);
}
};




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



//LoginAction.java


package com.cg.struts.action;
import org.apache.struts.action.*;
import javax.servlet.http.*;
import com.cg.struts.vo.*;
import com.cg.struts.bo.*;
import com.cg.struts.form.*;
public class LoginAction extends Action
{
public ActionForward execute(ActionMapping am,ActionForm af,HttpServletRequest req,HttpServletResponse res)throws Exception
{
//instantiate vo
Loginvo vo=new Loginvo();
//instantiate ActionForward
ActionForward forward=new ActionForward();
LoginActionForm lf=(LoginActionForm)af;
vo.setUname(lf.getUname());
vo.setPass(lf.getPass());
boolean status=Loginbo.validateUser(vo);
String forwardString="success";
if(!status)
{
forwardString="fail";
}
forward=am.findForward(forwardString);
return (forward);
}
};


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<!--struts-config.xml-->

<struts-config>
<form-beans>
<form-bean name="mybean" type="com.cg.struts.form.LoginActionForm"/>
</form-beans>
<action-mappings>
<action type="com.cg.struts.action.LoginAction" path="/login" name="mybean">
<forward name="success" path="/welcome.jsp"/>
<forward name="fail" path="/Login.jsp"/>
</action>
</action-mappings>
</struts-config>




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~








Directory Structure for above application is 




create table and insert values into database using following commands.




sql> Create table check_db (uname varchar2(20), pass varchar2(20));


sql> insert into check_db values('user1','pass1');
sql> commit;




~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~





Struts Class 6

To overcome the above issues the Struts Framework has provided FormBean.


What is a FormBean?
        A Java bean with setter and getter behaviors, for each form a property, thereby implementing validation and reset() behaviors.


Why FormBean?
        -> To exchange data between the view and the Action.
        -> Proper mechanism implementing DTO(Data Transfer Object) design pattern.
        -> Provides implicit Data conversions.


How to use FormBean with respect to Struts Application Development.

  • Your class should be subtype of org.apache.struts.action.ActionForm.
  • Write setter and getter behaviors, for each form property.
  • Optionally, if required, override the validate(ActionMapping am, HttpServletRequest req) and reset() behaviors.
for ex:-


public class LoginForm extends org.apache.struts.action.ActionForm{


public void setUname(String uname){


this.uname=uname;
}


public String getUname(){


return this.uname;


}


String uname;
//similarly for password also
}//class 




How to configure Formbeans in the struts-config file?


<struts-config>
<form-beans>
<form-bean name="mybean" type="LoginForm"/>
</form-beans>
.....
....
....
</struts-config>








How to associate a Formbean to an Action?



<struts-config>
<form-beans>
<form-bean name="mybean" type="LoginForm"/>
</form-beans>
<action-mappings>
<action type="LoginAction" path="/login" name "mybean">


.....
....
</action-mappings>
</struts-config>


From the above configuration we understand that the formbean is associated to the action using the name attributes value.


How to use the form data in our Action Class?


public class LoginAction extends Action{
public ActionForward execute(ActionMapping am,ActionForm af, HttpServletRequest req, HttpServletResponse)throws Exception{


//get the FormBean type


LoginForm lf=(LoginForm)af;
// now use the getXXX() of LoginForm to retrieve the form data.
System.out.println(lf.getUname());
 }
}


The next requirement is, implementing Database Connectivity with respect to First Application and we go for using struts framework provided tag libraries to design the views.