Pages

October 01, 2016

Struts Interview Questions and Answers..

What are the advantages of Struts?
  • Struts follow MVC framework. So the JSP, Java and Action classes are organized and easily maintainable.
  • Centralized File-Based Configuration. Struts values/mapping are represented in XML or property files. This loose coupling means that many changes can be made without modifying or recompiling Java code, and that wholesale changes can be made by editing a single file. This approach also lets Java and Web developers focus on their specific tasks (implementing business logic, presenting certain values to clients, etc.) without needing to know about the overall system layout.
  • Struts provides a set of custom JSP tags that let you easily output the properties of JavaBeans components.
  • Form Field Validation. Struts has a robust, extensible validator that can be used to uniformly validate your form fields. This validation can be performed on the server (in Java), or both on the server and on the client (in JavaScript).
What is Struts2?
Struts2 is popular and mature web application framework based on the MVC design pattern. Struts2 is not just the next version of Struts 1, but it is a complete rewrite of the Struts architecture. It’s highly improved from Struts1 and that makes it more flexible, easy to use and extend. The core components of Struts2 are Action, Interceptors, Value Stack / OGNL, Results / Result types and View technologies.

What are the differences between Struts1 and Struts2?
1). Struts1 action classes are forced to extend an Abstract Class org.apache.struts.action.Action and implement execute() method which returns ActionForward and accept HttpServletRequest and HttpServletResponse, that makes it not extendable.

Struts2 action classes are flexible, we can create them by implementing Action interface, extending ActionSupport class or just by having execute() method.  Any POJO object with a execute signature can be used as an Struts 2 Action object. Also execute() method returns String rather than returning ActionForward object.(when you are implementing Action interface, you need to override execute() method and when youa re extending ActionSupport class, you will not be forced to override any method and you can method with any other name.)

2). Struts1 APIs are tightly coupled with Servlet API and Request and Response objects are passed to action classes execute() method.

Struts2 API is loosely coupled with Servlet API and automatically maps the form bean data to action class java bean properties that we mostly use. If however we need reference to Servlet API classes, there are Aware interfaces for that.

3). Struts1 Action Classes are Singleton and are not thread safe, that makes extra care on developer side to avoid any side effects because of multithreading as there is only one instance of a class to handle all requests for that Action. The singleton strategy places restrictions on what can be done with Struts 1 Actions and requires extra care to develop. Action resources must be thread-safe or synchronized.

Struts2 action classes gets instantiated per request, so there is no multithreading and makes them thread safe.

4). Struts1 action classes are hard to test because of Servlet API coupling.

Struts2 Action classes are like normal java classes and we can test them easily by instantiating them and setting their properties.

5). Struts1 requires us to create ActionForm classes to hold request params and we need to configure it in the struts configuration file.

Struts2 request params mapping is done on the fly and all we need is to have java bean properties in action classes or implement ModelDriven interface to provide the java bean class name to be used for mapping.

6). Struts1 supports validation through manual validate() method.

Struts2 support both manual validation as well as Validation framework integration.

7). Struts1 uses standard JSP technology for providing bean values to JSP pages for views.

Struts2 uses ValueStack to store request params and attributes and we can use OGNL and Struts2 tags to access them.

What are the steps to migrate a web application written with Struts 1 to Struts 2?
  • Moving ActionForms of Struts1 to POJO properties of Struts 2.
  • Converting Struts1 struts-config.xml to struts.xml of Struts2.
  • Rewriting the Struts action classes for Struts
 Life cycle of a request in Struts2 application?
  • User sends a request to the server for requesting for some resource (i.e pages).
  • The FilterDispatcher looks at the request and then determines the appropriate Action.
  • Configured interceptors functionalities applies such as validation, file upload etc.
  • Selected action is executed to perform the requested operation.
  • Again, configured interceptors are applied to do any post-processing if required.
  • Finally the result is prepared by the view and returns the result to the user.

What are different ways to create Action classes in Struts2?
  • By implementing Action interface
  • Using Struts2 @Action annotation
  • By extending ActionSupport class
  • Any normal java class with execute() method returning String can be configured as Action class. 
What is the difference in using Action interface and ActionSupport class for our action classes, which one you would prefer?
We can implement Action interface to create our action classes. This interface has a single method execute() that we need to implement. The only benefit of using this interface is that it contains some constants that we can use for result pages, these constants are SUCCESS, ERROR, NONE, INPUT and LOGIN.

ActionSupport class is the default implementation of Action interface and it also implements interfaces related to Validation and i18n support. ActionSupport class implements Action, Validateable, ValidationAware, TextProvider and LocaleProvider interfaces. We can override validate() method of ActionSupport class to include field level validation login in our action classes.

Depending on the requirements, we can use any of the approaches to create struts 2 action classes, my favorite is ActionSupport class because it helps in writing validation and i18n logic easily in action classes.

How can we get Servlet API Request, Response, HttpSession etc Objects in action classes?
Struts2 action classes doesn’t provide direct access to Servlet API components such as Request, Response and Session. However sometimes we need these access in action classes such as checking HTTP method or setting cookies in response.

Thats why Struts2 API provides a bunch of *Aware interfaces that we can implement to access these objects. Struts2 API uses dependency injection to inject Servlet API components in action classes. Some of the important Aware interfaces are SessionAware, ApplicationAware, ServletRequestAware and ServletResponseAware.

What are Struts2 core components?
  • Action Classes
  • Interceptors
  • Result Pages, JSP of FreeMarker templates
  • ValueStack, OGNL and Tag Libraries
Name some useful annotations introduced in Struts2?
  • @Action to create action class
  • @Actions to configure single class for multiple actions
  • @Namespace and @Namespaces for creating different modules
  • @Result for result pages
  • @ResultPath for configuring result pages location 
What is the use of namespace in action mapping in Struts2?
Struts2 namespace configuration allows us to create modules easily. We can use namespace to separate our action classes based on their functionality, for example admin, user, customer etc.

What is the default location of result pages and how can we change it?
By default Struts2 looks for result pages in {WEBAPP-ROOT}/{Namespace}/ directory but sometimes we want to keep result pages in another location, we can provide struts.convention.result.path constant value in Struts2 configuration file to change the result pages location.

Another way is to use @ResultPath annotation in action classes to provide the result pages location.

In Struts 2, @ResultPath annotation is used to control where Struts 2 will find the the stored results or JSP pages. By default, it will find the result pages from the 'WEB-INF/content/' folder.

e,g:
1). A login action class, set to “/User” namespace, and redirect to the “pages/login.jsp” pages.
@Namespace("/User")
@Result(name="success",location="pages/login.jsp")
public class LoginAction extends ActionSupport{
}

When you access: http://localhost:8080/Struts2Test/User/login.action

Struts 2 will find the 'login.jsp' result page from the default location /Struts2Test/WEB-INF/content/User/pages/login.jsp

2) You can customize the ResultPath. If your JSP result pages are store in other location, you are allow to change it with @ResultPath annotation.

@Namespace("/User")
@ResultPath(value="/")
@Result(name="success",location="pages/login.jsp")
public class LoginAction extends ActionSupport{
}

When you access: http://localhost:8080/Struts2Test/User/login.action

Now the Struts 2 will find the 'login.jsp' result page from different location /Struts2Test/User/pages/login.jsp

3). You can also set global @ResultPath. The @ResultPath is only apply to the class level. To apply it globally, you can configure it in the struts.xml file.

< ?xml version="1.0" encoding="UTF-8" ? >
< !DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd" >
< struts >
    < constant name="struts.convention.result.path" value="/"/ >
< /struts >

Which class is the Front Controller in Struts2?
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter is the Front Controller class in Struts2 and every request processing starts from this class. Earlier versions of Struts2 uses org.apache.struts2.dispatcher.FilterDispatcher as Front Controller class.

What is the purpose of struts.xml in Struts2?

struts.xml is the configuration file in Struts2 framework. By default you can keep this file under the folder WEB-INF/classes. But you can change this location also by providing an entry in ContextParam in web.xml.This file can be used to override default settings for an application, for example struts.devMode = false and other settings which are defined in property file.

Who loads the struts.xml file in Struts2?
In Struts2 FilterServlet is the responsible class for loading struts.xml file as we deploy the application on the container. Unlike Servlet (as with Struts1) needs the load-on-start-up tag to load the front controller, a filter doesn't need to have load on start-up tag to be loaded as the application is deployed. As with servlet specification a filter is loaded/ executed as the application starts up.

How to use multiple struts config file in struts2?
We can break struts.xml file into multiple small files. At runtime there can be only one struts.xml for an application so other files have to be included in the default struts.xml file.

< struts >
      < include file="strutsfile1.xml"/ >
      < include file="strutsfile2.xml"/ >
 < /struts >


What is the purpose of constant tag in struts.xml?

The constant tag along with name and value attributes will be used to override properties defined in default.properties, like struts.devMode. Setting struts.devMode allows us to see more debug messages in the log file.

e.g
< constant name="struts.devMode" value="false" / >
< constant name="struts.custom.i18n.resources" value="ApplicationResources" / >


What is struts.devMode and why it is used?
struts.devMode is a key used in struts.properties file (Can also be configured in struts.xml file as), to represent whether the framework is running in development mode or production mode by setting true or false.

< constant name="struts.devMode" value="false" / >'If set to development mode, it gives the following benefits :
  • Resource bundle reload on every request; i.e. all localization properties file can be modified and the change will be reflected without restarting the server.
  • struts.xml or any configuration  files can be modified without restarting or redeploying the application
  • The error occurs in the application will be reported, as oppose to production mode.
  • Also remember that struts.devMode should be marked as false in production environment to reduce impact of performance. By default it is "false".
What is the purpose of action tag in struts.xml?
We define action tags corresponds to every URL we want to access and we define a class with execute() method which will be accessed whenever we will access corresponding URL.

Results determine what gets returned to the browser after an action is executed. The string returned from the action should be the name of a result. Results are configured per-action as above, or as a "global" result, available to every action in a package. Results have optional name and type attributes. The default name value is "success".

< action name="login" class="com.dachser.action.LoginAction" method="execute">
< result name="success" type="tiles" >/welcome.tiles< /result >
< result name="fail" type="tiles" >/error.tiles< /result >
< /action >


What is the purpose of form-beans tag in struts-config.xml in Struts1?
This is where you map your ActionForm subclass to a name. You use this name as an alias for your ActionForm throughout the rest of the struts-config.xml file, and even on your JSP pages.

What is the purpose of global-forwards tag in struts-config.xml?
This section maps a page on your webapp to a name. You can use this name to refer to the actual page. This avoids hardcoding URLs on your web pages.

What is the purpose of struts.properties in Struts2?

This configuration file provides a mechanism to change the default behavior of the framework. Actually all of the properties contained within the struts.properties configuration file can also be configured in the web.xml using the init-param, as well using the constant tag in the struts.xml configuration file. But if you like to keep the things separate and more struts specific then you can create this file under the folder WEB-INF/classes. The values configured in this file will override the default values configured in default.properties which is contained in the struts2-core-x.y.z.jar distribution.

 What is interceptor in Struts2?
Interceptors are the backbone of Struts2 Framework and are conceptually the same as servlet filters or the JDKs Proxy class.

In Struts 2, interceptor is used to perform operations such as validation, exception handling, internationalization, displaying intermediate result etc. They are responsible for most of the processing done by the framework, such as passing request params to action classes, making Servlet API request, response, session available to Action classes, validation, i18n support, etc.

ActionInvocation is responsible to incapsulate Action classes and interceptors and to fire them in order. The most important method for use in ActionInvocation is invoke() method that keeps track of the interceptor chain and invokes the next interceptor or action. This is one of the best example of Chain of Responsibility pattern in Java EE frameworks.

We can achieve the following using interceptors:
  • Providing preprocessing logic before the action is called.
  • Providing postprocessing logic after the action is called.
  • Catching exceptions so that alternate processing can be performed.

The advantage of interceptor is that they are Pluggable. If we need to remove any concern such as validation, exception handling, logging etc. from the application, we don't need to redeploy the application. We only need to remove the entry from the struts.xml file.

Name a few default interceptors of Struts 2?
#fileUpload : It provides support to file upload in struts 2.
< action name="fileupload" class="com.dachser.action.UploadAction" method="execute" >
< interceptor-ref name="fileUpload" >
< param name="maximumSize" > 12582912 < /param >
< param name="allowedTypes" >
application/pdf
< /param >


< result name="success" type="tiles" >/welcome.tiles< /result >
< result name="fail" type="tiles" >/error.tiles< /result >
< /action >

#token: It prevents duplication submission of request.
< interceptor-ref name="token"/ >
#tokenSession: It prevents duplication submission of request.
#checkbox: It is used to handle the check boxes in the form. By this, we can detect the unchecked checkboxes.
#createSession: It creates and HttpSession object if it doesn't exists.
#clearSession: It unbinds the HttpSession object.
#timer: It outputs the time needed to execute an action.
#params: com.opensymphony.xwork2.interceptor.ParametersInterceptor is responsible for mapping request parameters to action class Java Bean properties. This interceptor is part of basicStack and defaultStack interceptors stack.
#execAndWait: It is used for long running action classes, it sends an intermediate waiting page to the client and once the processing is finished, final response is returned to the client. This interceptor is defined in the struts-default package and implementation is present in ExecuteAndWaitInterceptor class.

Which interceptor is responsible for mapping request parameters to action class Java Bean properties?
com.opensymphony.xwork2.interceptor.ParametersInterceptor interceptor is responsible for mapping request parameters to the Action class java bean properties. This interceptor is configured in struts-default package with name “params”. This interceptor is part of basicStack and defaultStack interceptors stack.

Which interceptor is responsible for i18n support?
com.opensymphony.xwork2.interceptor.I18nInterceptor interceptor is responsible for i18n support in Struts2 applications. This interceptor is configured in struts-default package with name “i18n” and it’s part of i18nStack and defaultStack.

How can you create your custom interceptor in Struts 2?
Creating a custom interceptor is easy, the interface that needs to be extended is the Interceptor interface.

How interceptor works in Struts 2?
Actual action will be executed using the interceptor by invocation.invoke() call. So you can do some pre-processing and some post-processing as per your requirement.

The framework itself starts the process by making the first call to the ActionInvocation object's invoke(). Each time invoke() is called, ActionInvocation consults its state and executes whichever interceptor comes next. When all of the configured interceptors have been invoked, the invoke() method will cause the action itself to be executed.

What is life cycle of an interceptor?
Interceptor interface defines three methods – init(), destroy() and intercept().

init and destroy are the life cycle methods of an interceptor. Interceptors are Singleton classes and Struts2 initialize a new thread to handle each request. init() method is called when interceptor instance is created and we can initialize any resources in this method. destroy() method is called when application is shutting down and we can release any resources in this method.

intercept() is the method called every time client request comes through the interceptor.

Which design pattern is implemented by Struts2 interceptors?
Struts2 interceptors are based on intercepting filters design pattern. The invocation of interceptors in interceptor stack closely resembles Chain of Responsibility design pattern.

What is an interceptor stack?
An interceptor stack helps us to group together multiple interceptors in a package for further use. struts-default package creates some of the mostly used interceptor stack - basicStack and defaultStack. We can create our own interceptor stack at the start of the package and then configure our action classes to use it.

What is struts-default package and what are it’s benefits?
struts-default is an abstract package that defines all the Struts2 interceptors and commonly used interceptor stack. It is advisable to extend this package while configuring our application package to avoid configuring interceptors again. This is provided to help developers by eliminating the trivial task of configuring interceptor and result pages in our application.

Are Interceptors and Filters different?
Apart from the fact that both Interceptors and filters are based on intercepting filter, there are few differences when it comes to Struts2.
  • Interceptors are based on Struts2, wher as Filters are based on Servlet Specification.
  • Interceptors executes for all the request qualifies for a front controller (A Servlet filter).And can be configured to execute additional interceptor for a particular action execution. Filters executes on the pattern matches on the request.
  • Methods in the Interceptors can be configured whether to execute or not by means of exclude methods or include methods. Filters have non configurable method calls.
Are Interceptors in Struts2 thread safe?
No. Unlike Struts2 action, Interceptors are shared between requests, so thread issues will come if not taken care of.

Does the order in which interceptors execute matters? If yes then why?
It depends on the type of Interceptors used. Some Interceptors are designed to be independent so the order doesn't matter, but some interceptors are totally dependent on the previous interceptor’s execution.

For example the validation and workflow interceptors, the validation interceptors checks if there is any error in the form being submitted to the action, then comes the workflow interceptor who checks if validation (occurred in the last) has any error, in presence of error it will not let the rest of the interceptors ( if any ) in the stack to execute. So this is very important that the validation interceptors execute first before the workflow.

On the other hand let’s say you wrote an interceptors who is doing the authentication and you have the user credential provided (by the time this executes) it doesn't matter where this interceptors is placed.

Which interceptor is responsible for setting action's JavaBean properties?
com.opensymphony.xwork2.interceptor.ParametersInterceptor is the interceptor class who sets the action's JavaBean properties from request.



What is Value Stack?
ValueStack is the storage area where the application data is stored by Struts2 for processing the client requests. The data is stored in ActionContext objects that use ThreadLocal to have values specific to the particular request thread.

The value stack is a set of several objects which keeps the following objects in the provided order:
  • Temporary Objects − There are various temporary objects which are created during execution of a page. For example the current iteration value for a collection being looped over in a JSP tag.
  • The Model Object − If you are using model objects in your struts application, the current model object is placed before the action on the value stack.
  • The Action Object − This will be the current action object which is being executed.
  • Named Objects − These objects include #application, #session, #request, #attr and #parameters and refer to the corresponding servlet scopes.
The value stack can be accessed via the tags provided for JSP, Velocity or Freemarker.

You can get valueStack object inside your action from ActionContext.getContext().getValueStack()

Once you have a ValueStack object, you can use following methods to manipulate that object:
1. Object findValue(String expr):Find a value by evaluating the given expression against the stack in the default search order.
2. CompoundRoot getRoot(): Get the CompoundRoot which holds the objects pushed onto the stack.
3. Object peek(): Get the object on the top of the stack without changing the stack.
4. Object pop(): Get the object on the top of the stack and remove it from the stack.
5. void push(Object o): Put this object onto the top of the stack.
6. void set(String key, Object o): Sets an object on the stack with the given key so it is retrievable by findValue(key,...)
7. void setDefaultType(Class defaultType): Sets the default type to convert to if no type is provided when getting a value.
8. void setValue(String expr, Object value):  Attempts to set a property on a bean in the stack with the given expression using the default search order.
9. int size(): Get the number of objects in the stack.

What is ActionContext?
The ActionContext is the context in which an Action is executed. Each context is basically a container of objects an action needs for execution like the session, parameters, locale, etc.

The values stored in the ActionContext are unique per thread (i.e. ThreadLocal). So we don't need to make our action thread safe. Struts2 will create a new ActionContext before the implementation of each Action, attributes on the same thread inside the ActionContext is the only, so that Action can be used in multiple threads.

We can get the reference of ActionContext by calling the getContext() method of ActionContext class. It is a static factory method.

ActionContext context = ActionContext.getContext();

How Struts2 ensure the thread safety of ActionContext?
Struts2 will create a new ActionContext before the implementation of each Action.

public class ActionContext implements Serializable {
static ThreadLocal actionContext = new ThreadLocal();
}

   
The ThreadLocal is also called the "thread local variables", it is each one using the variable threads provide a copy of a variable's value, so that each thread can be changed independently its own copy, the copy will not conflict with other threads.

Attributes are stored in the ActionContext data are stored in the ThreadLocal, and this property will only in the corresponding to the current request thread visible, so as to ensure that the data is thread safe.

What is ONGL?
The Object-Graph Navigation Language (OGNL) is very similar to the JSP Expression Language and is a powerful expression language that is used to reference and manipulate data on the ValueStack. OGNL also helps in data transfer and type conversion.

OGNL is based on a context and Struts builds an ActionContext map for use with OGNL. The ActionContext map consists of the following:
•    application - application scoped variables
•    session - session scoped variables
•    root / value stack - all your action variables are stored here
•    request - request scoped variables
•    parameters - request parameters
•    attributes - the attributes stored in page, request, session and application scope

OGNL is based on the idea of having a root or default object within the context. The properties of the default or root object can be referenced using the markup notation, which is the pound symbol.

Objects in the ActionContext are referred using the pound symbol, however, the objects in the value stack can be directly referenced
, for example if employee is a property of an action class then it can be referenced as follows:
< s:property value="name"/ > instead of < s:property value="#name"/ >
If you have an attribute in session called "login" you can retrieve it as follows:
< s:property value="#session.login"/ >

OGNL also supports dealing with collections - namely Map, List and Set. For example to display a dropdown list of colors, you could do:
< s:select name="color" list="{'red','yellow','green'}" / >

The OGNL expression is clever to interpret the "red","yellow","green" as colors and build a list based on that.

What is Struts 2 validation framework?
At Struts's core, we have the validation framework that assists the application to run the rules to perform validation before the action method is executed. Action class should extend the ActionSupport class, in order to get the validate method executed.

How Struts 2 validation works?
When the user presses the submit button, Struts 2 will automatically execute the validate method and if any of the if statements listed inside the method are true, Struts 2 will call its addFieldError method. If any errors have been added then Struts 2 will not proceed to call the execute method. Rather the Struts 2 framework will return input as the result of calling the action.

So when validation fails and Struts 2 returns input, the Struts 2 framework will redisplay the view file. Since we used Struts 2 form tags, Struts 2 will automatically add the error messages just above the form filed.

These error messages are the ones we specified in the addFieldError method call. The addFieldError method takes two arguments. The first is the form field name to which the error applies and the second is the error message to display above that form field.


If you are writing validate() method in action class, then make sure that your action class extends the ActionSupport class, otherwise your validate method will not be executed. e.g

import com.opensymphony.xwork2.ActionSupport;
public class UserTestAction extends ActionSupport{
   private String name;
   //getter setters...
   public String execute()
   {
       return SUCCESS;
   }
   public void validate()
   {
      if (name == null || name.trim().equals(""))
      {
         addFieldError("name","The name is required");
         //Or
         //addActionError(getText("error.usernamerequired"));
      }
   }
}


As shown in the above example, the validation method checks whether the 'Name' field has a value or not. If no value has been supplied, we add a field error for the 'Name' field with a custom error message.

What is XML Based Validation in Struts2?
The second method of doing validation is by placing an xml file next to the action class. Struts2 XML based validation provides more options of validation like email validation, integer range validation, form validation field, expression validation, regex validation, required validation, requiredstring validation, stringlength validation and etc.


The advantage of having an xml file to store the configuration allows the separation of the validation from the application code. You could get a developer to write the code and a business analyst to create the validation xml files.

What should be the name of xml file used for validation in struts?

The xml file needs to be named '[action-class]'-validation.xml.

e.g
< validators >
    < field name="username" >
        < field-validator type="requiredstring" >
            < param name="trim" > true < /param >
            < message key="errors.required" / >
        < /field-validator >
    < /field >
< /validators >


What types of validations are available in xml based validation in struts2?
Following is the list of various types of field level and non-field level validation available in Struts2:
date validator,double validator,email validator,expression validator,int validator,regex validator,required validator,requiredstring validator,stringlength validator,url validator.

What is DispatchAction in Struts 1.x?
DispatchAction provides a mechanism for grouping a set of related functions into a single action, thus eliminating the need to create separate actions for each functions.

Step 1). In the below example class UserAction extends org.apache.struts.actions.DispatchAction and does not have an implementation of the execute() method. The DispatchAction uses the execute() method to manage delegating the request to the individual methods based on the incoming request parameter. For example if the incoming parameter is "method=update", then the update method will be invoked.

public class MyDispatchAction extends DispatchAction {
private final static String SUCCESS = "success";

public ActionForward add(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)
throws Exception {
UserForm userForm = (UserForm) form;
userForm.setMessage("add method.");
return mapping.findForward(SUCCESS);
}

public ActionForward update(ActionMapping mapping, ActionForm form,HttpServletRequest request, HttpServletResponse response)
throws Exception {
UserForm userForm = (UserForm) form;
userForm.setMessage("update method.");
return mapping.findForward(SUCCESS);
}

public ActionForward delete(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
UserForm userForm = (UserForm) form;
userForm.setMessage("delete method.");
return mapping.findForward(SUCCESS);
}
}


Step 2). Create an action mapping
<  action-mappings  >
<  action input="/index.jsp" parameter="method" name="UserForm" path="/
MyDispatchAction" scope="session" type="com.khs.MyDispatchAction"  >
<  forward name="success" path="/index.jsp" /  >
<  /action  >
<  /action-mappings  >


The request parameter name is specified using the parameter attribute, here its 'method'

Step 3).
...
.....
< script type="text/javascript" >
function callAdd()
{
document.forms[0].action = "MyDispatchAction.do?method=add"
document.forms[0].submit();
}
< /script >
...
....
< html:form action="MyDispatchAction"  >
...
< bean:write name="UserForm" property="message" / >
< html:submit value="Add" onclick="callAdd()" / >
< html:submit property="method" value="update" / >
< html:submit  property="method"  >delete< /html:submit >
...
< /html:form >


#When user clicks on 'add' button, request parameter 'method' is set to 'add'.
#For update and the delete button, the request parameter name specified in the action handler is 'method'. So this should be specified as the property name for the submit button. The name of the method to be invoked and the value of the button should be the same. So when the button is clicked the corresponding method in the UserAction will be called. The delete button shows an alternate way to specify the value of the button. The method name and the button name should be same. So we can't have an update button like this 'Update'.

What is LookupDispatchAction in Struts?
The LookupDispatchAction class extends org.apache.struts.actions.DispatchAction. It provides a mechanism for grouping a set of related functions into a single action, thus eliminating the need to create seperate actions for each functions.

Step 1)
. In the below example MyLookupDispatchAction, which extends LookupDispatchAction contains 3 methods for add, update and delete purpose. The signatures of these methods are similar to the execute method except the name.

For using LookupDispatchAction, the action class must provide an implementation of getKeyMethodMap() method. This method maps the methods in the action class to keys in the Struts resource bundle file. The next step is to create an action mapping for this action handler. The request parameter name is specified using the parameter attribute. Here the request parameter name is method.

public class MyLookupDispatchAction extends LookupDispatchAction {
private final static String SUCCESS = "success";
protected Map getKeyMethodMap() {
Map map = new HashMap();
map.put("UserForm.add", "add");
map.put("UserForm.update", "update");
map.put("UserForm.delete", "delete");
return map;
}

public ActionForward add(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
UserForm userForm = (UserForm) form;
userForm.setMessage("add method.");
return mapping.findForward(SUCCESS);
}

public ActionForward update(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
UserForm userForm = (UserForm) form;
userForm.setMessage("update method.");
return mapping.findForward(SUCCESS);
}

public ActionForward delete(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
UserForm userForm = (UserForm) form;
userForm.setMessage("delete method.");
return mapping.findForward(SUCCESS);
}
}

Step 2).
< action-mappings>
< action input="/index.jsp" parameter="method" name="UserForm" path="/MyLookupDispatchAction " scope="session" type="com.khs.MyLookupDispatchAction " >
< forward name="success" path="/index.jsp" / >
< /action>
< /action-mappings >

Step 3).
The getKeyMethodMap() method contains a HashMap. The names in the resource bundle file are the keys for this map and the corresponding values are the method names in the action class. For example the key value in the ApplicationResource.properties file is "UserForm.add" and the corresponding method name is "add" in the UserAction class. The main constraint in the DispatchAction is the method name in the action class and the button name in the jsp page should be the same. But here in LookupDispatchAction, we can have different names for the buttons and the methods.

In ApplicationResource.properties file each key is mapped to a value, that value represents the button name in the jsp page. In the getKeyMethodMap() method the same key is mapped to a different value, this value corresponds to the method name to be invoked in the action class.

------------------------------
ApplicationResource.properties
------------------------------
UserForm.add = Add
UserForm.update = Update
UserForm.delete = Delete


Here "Add", "Update" and "Delete" are the button names and "add", "update" and "delete" are the corresponding method names. If you want to change the name of the button at the later stage, you can easily do so by just changing the value in the ApplicationResource.properties file without making any changes to the jsp page.

What are the differences between DispatchAction and LookupDispatchAction in Struts Framework?
1). DispatchAction is the parent class of LookupDispatchAction.
2). DispatchAction provides a mechanism for grouping a set of related functions into asingle action, thus eliminating the need to create separate actions for each function.
Where as in LookupDispatchAction, an abstract Action that dispatches to the subclass mapped executes method. This is useful in cases where an HTML form has multiple submit buttons with the same name. The button name is specified by the parameter property of the corresponding ActionMapping.
3). If not using Internalization functionality then dispatch action is more useful.
Lookup Dispatch Action is useful when we are using Internalization functionality
4). DispatchAction selects the method to execute depending on the request parameter valuewhich is configured in the xml file.
LookupDispatchAction looks into the resource bundle file and find out the corresponding key name. We can map this key name to a method name by overriding the getKeyMethodMap() method.

What is DynaActionForm?
With DynaActionForm class pf Struts 1.x we can create a form bean dynamically and declaratively. It enables us to create a “virtual” form bean in Struts configuration file instead of create a real Java form bean class. e.g

< form-bean name="dynaProductForm" type="org.apache.struts.action.DynaProductActionForm" >
    < form-property name="productname" type="java.lang.String"/ >
< /form-bean >


Different between DynaActionForm and ActionForm:
  • DynaActionForm is not required to create a real Java class (just declare in Struts config file), but ActionForm does.
  • In DynaActionForm, form validation is implement in Action class, while ActionForm is implement inside its own class.
How validation is performed in struts 1.x application?
In struts validation is performed using validator framework, Validator Framework in Struts consist of two XML configuration files.
  • validator-rules.xml file: It declares the validation routines that should be plugged into the framework and provides logical names for each of the validations. The validator-rules.xml file also defines client-side JavaScript code for each validation routine. Validator can be configured to send this JavaScript code to the browser so that validations are performed on the client side as well as on the server side. 
  • validation.xml: defines which validation routines should be applied to which Form Beans.

To use Validator framework, we need to enable the Validator plug-in, configuring Validator’s two configuration files, and creating Form Beans that extend the ValidatorForm.

In order to use Validator in our project we need to configure it in struts-config.xml file. For this add following code in your struts-config.xml file.

< plug-in className="org.apache.struts.validator.ValidatorPlugIn" >
    < set-property property="pathnames"
        value="/WEB-INF/validator-rules.xml,
                /WEB-INF/validation.xml" / >
< /plug-in >

Configuring validations in validation.xml

< form-validation >
< global >
    < constant >
    < constant-name >telephoneFormat< /constant-name >
    < constant-value >^\d{5,10}$< /constant-value >
    < /constant >
< /global >
< formset >
    < form name="EmployeeForm" >       
        < field property="age" depends="required, integer, intRange" >
            < arg0 key="label.age" / >
            < arg1 key="${var:min}" resource="false"/ >
            < arg2 key="${var:max}" resource="false"/ >
            < var >
                < var-name >min< /var-name >
                < var-value >1< /var-value >
            < /var >
            < var >
                < var-name >max< /var-name >
                < var-value >125< /var-value >
            < /var >
        < /field >
        < field property="telephone" depends="required, mask" >
            < arg key="label.telephone" / >
            < arg1 key="label.telephone" / >
            < var >
                < var-name >mask< /var-name >
                < var-value >${telephoneFormat}< /var-value >
            < /var >
        < /field >
        < field property="email" depends="email" >
            < arg0 key="label.email" / >
            < arg1 key="label.email" / >
        < /field >
    < /form >
< /formset >
< /form-validation >


In order to do form validation without Validator framework, we need to add validate() method of the form bean (for Struts 1.x).

How validation is performed in struts 2 application?
By default, the validation framework is included in Struts2 default stack and is “turned on”. That's why so we don’t have to do anything to use it, except creating validation rules in an XML file in a correct manner and putting it under same location as the action class. . Naming convention for validation xml in Staruts2:
< actionClass >-validation.xml
< actionClass >-< actionAlias >-validation.xml


Where actionClass is Java class name of the action, and actionAlias is name of the action element specified in struts.xml file. e.g:
LoginAction-validation.xml
LoginAction-doLogin-validation.xml

Inside this XML file we specify validation rules using validators. There are two types of validator in Struts2:
Field Validators: are used to perform validation checks on a single field. The field is declared in the action class or in a JavaBean associated with the action class. A field validator is declared using < field-validator > element. e.g:

< field name="email" >
    < field-validator type="email" >
        < message >You must enter a valid e-mail address< /message >
    < /field-validator >
< /field >


Non-Field Validators (or Plain Validators): are used to perform validation checks on a set of fields or none field at all. A non-field validator is declared using < validator > element. e.g:

< validator type="expression" >
    < param name="expression" >x > y< /param >
    < message >x must be greater than y, x = ${x}, y = ${y}< /message >
< /validator >



The attribute validate=”true” of the < s:form > tag specifies that the form validation will take place on the client side. e.g:   
< s:form action="doLogin" method="post" validate="true" >

Without specifying the attribute validate=”true”, Struts will perform validation checks on the server-side:

You can perform validations with annotations instead of XML. It’s very easy to use an annotation type to specify validation rule for a form’s field in Struts2, just by annotating setter method of the field in action class or in a JavaBean model class. e.g:

@RequiredStringValidator(message = "Please enter User Name.")
public void setUserName(String username) {
    this.username = username;
}


In the code snippet above, the setter method is annotated by the @RequiredStringValidator annotation which will ensure that the user doesn’t leave the field empty when submitting the form. The text message “Please enter your name.” will be shown in case validation fails.

@EmailValidator: Validated email address.
@IntRangeFieldValidator: Checks if entered number is in given range or not, we need to define min and max attribute.


Example of struts-config.xml of Struts 1.0
 < struts-config >
 < global-exceptions >
         < exception type="java.io.IOException" path="/pages/error.jsp" / >
 < /global-exceptions >
 < global-forwards >
   < forward name="sessionexpired" path="/sessionExpire.jsp"/ >
 < /global-forwards > 
 < form-beans >
     < form-bean name="helloWorldForm"
    type="com.mkyong.common.form.HelloWorldForm"/ >
 < /form-beans >

 < action-mappings >
     < action path="/helloWorld" type="com.scrutiny.action.HelloWorldAction"
        name="helloWorldForm" >
     < forward name="success" path="/HelloWorld.jsp"/ >
 < /action >
 < /action-mappings >
 < /struts-config >

-K Himaanshu Shuklaa..

No comments:

Post a Comment