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.











Saturday, 23 April 2011

Struts Class 5

Steps to understand the above Architecture:-
In the above Architecture we understand two phases.
Phase I:- The initialization phase:

         -> In this phase we understand Struts components initialization which commences with ActionServlet initialization
         -> In ActionServlet initialization the configuration files are read or looked. 
         -> Checks for ModuleCofigurations whether Modules are configured or not.
         -> If Modules are not configured , default module is taken.(in details about modules at later stages of our learning)

Note: Modules are configured in web.xml file using the init-param tags, for the default module the configuration is


                  <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
                  </init-param>                   


for module configuration

Ex:     <init-param>
        <param-name>config/[moduleName]</param-name>
        <param-value>/WEB-INF/module-config.xml</param-value>
        </init-param>



         ->The next step in the initialization process is module initialization.
         ->Here ModuleConfig object is prepared.
         ->This object consists of configuration file and a unique name(modulename).
         ->The next process is initialization of RequestProcessor where RequestProcessor is initiated  and injected with ActionServlet instance and ModuleConfig instance.
         ->Initialization of any PlugIns configured or any Frameworks plugged like tiles.

Note: ActionServletInstance and ModuleConfig instance are maintained in instance variables, for the further use.

Phase 2:

         -> Clients request initiates to ActionServlet
         -> In the process() behaviors of ActionServlet, navigation logic is implemented to locate the module. Module is located by matching the first part of the request with the module name configured.
         -> The next step in delegation i.e request is delegated by calling process() behaviors on the RequestProcessor instance.
         -> Request is given to the RequestProcessor where RequestProcessor performs various steps like

                 processMultiPart();(we discuss about this later)   
                 processPath(): Here navigation logic is implemented to locate the Action, where the request uri is matched with the path attribute value of the <action>tag.

              If the match is not found we get 404 ErrorCode if match is found.
            ->Checks whether the Action is instantiated or not.
            -> If the Action is not intantiated, instanciated the action where processActionCreate() behavior of RequestedProcessor is invoked.
            -> If instantiated fails, we get an ErrorCode 500


Note: In our application we need Action class and <action> tag ActionClass is an Wrapper between the request and the corresponding BussinessOperation.

      The ActionMapping object describe an Action object, meaning for every <action> tag an ActionMapping object is created where ActionMapping object is encapsulated with type,name,path,forward,exception... details of an Action.

Note: ActionMapping used in the Application represents the details to map the request to particular Action instance.
     
      -> After the Action is instantiated, process ActionPerform() is called, this results to invoke the execute(-,-,-,-) behavior.
      -> The execute(-,-,-,-) behavior may return null, if the response is generated in the Action.
      -> If the response is not generated in the Action, the execute(-,-,-,-) returns ActionForward to the RequestProcessor
(recall am.findForward("logical name")), this returns ActionForward Object).

Note: for every <forward>tag, this object is created which consists of name & path. 

         -processForwardConfig() behavours is invoked, results to forward or send Redirect to the respective path using RequestDispatcher's forward mechanism(recall of servlets). This results to display the respective view page.

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


In the previous example, to retrieve the client parameters we used the logic.

    req.getParameter("parameterName"); or we say this is the logic used to exchange the data between the view and Action but implemented this logic, results to issues like


                - Complexity 
                -Dependency to the Actions.










Wednesday, 20 April 2011

Struts Class 3


Struts 1.3.10:
So far discussion gave an idea what is the workflow of Struts and what Design Patterns are implemented. Before we use Struts w.r. to WebApplication development lets see few advantages of Struts.



  1. Presenting Dynamic web content to the web clients in a faster, simpler and easier manner.
  2. As it is built on top of Servlet & JSP specifications we can deploy the Struts applications in any web or application servers.
  3. Provides Infrastructures, so we take the advantage of Declarative Exception handling, Declarative validations and also Programmatic validations(at server side).
  4. As Struts is open source, customization is not a deal. Meaning we can have further UserExtensions.
  5. Helps in designing the view pages followed with implementing Composite view design pattern(i.e Struts with Tiles framework).
To understand in detail about Struts components and the work flow we directly commence by implementing an application.




Requirement is validating User name and password.





  • Write a Login.html
  • Write a web.xml
  • Write an Action Class? How?

     ->Your class should be sub type of      org.apache.struts.action.Action
     ->Override the execute() behavior which takes the following inputs
         -->ActionMapping
         -->ActionForm
         -->HttpServletRequest
         -->HttpServletResponse
         -->throws clause is throws "Exception"
     ->Output type of execute() behavior is ActionForward.


     ->Write a struts configuration file.
     ->Write a jsp document as a view page.
What is the Directory Structure to arrange the above?
As Struts is a web Application framework it uses the same directory structure that we used for Servlets and jsp.








      
     Login.Html





web.xml


<web-app>
    <servlet>
        <servlet-name> st1  </servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
   </servlet>
   <servlet-mapping>
        <servlet-name> st1  </servlet-name>
        <url-pattern>*.stech</url-pattern>
   </servlet-mapping>


</web-app>


LoginAction.java



import javax.servlet.http.*;
import org.apache.struts.action.*;


public class LoginAction extends Action{
    public ActionForward execute(ActionMapping am,ActionForm af, HttpServletRequest req, HttpServletResponse res)throws Exception{
    //retrive the client sent parameters
        String name=req.getParameter("uname");
        String pass=req.getParameter("pass");
        //now validate the username and password
        // not recommanded database logic in the Action
        //use controlflow statements
        if(name.equals("user1")&&pass.equals("pass1"))
            return am.findForward("success");
        return  am.findForward("failure");


    }//execute
}//Action class

struts-config.xml
<struts-config>
    <action-mappings>
        <action type="LoginAction" path="/login">
            <forward name="success" path="/welcome.jsp"/>
            <forward name="failure" path="/Login.html"/>
        </action> 
    </action-mappings>
</struts-config>

welcome.jsp:


Welcome to Java at:: <%=request.getParameter("uname")%>



^^^^^^^^^^^^^^^^^^^^^^^^^^^^
for classpath we need the following jars to compile the program.



servlet-api.jar
struts-core-1.3.8.jar

url:
localhost:2010/ex1/Login.html