- Struts uses the ActionErrors instance returned by validate() to display the error messages on the redisplayed form.
- ActionErrors (note the plural) is very much like a HashMap, and it is used to store error messages, indexed by error keys. The error message is not a String, but an instance of ActionMessage.
- ActionMessages are added to an ActionErrors instance using the add() function:
- public void add(String key, ActionMessage message)
- eg. new ActionMessage("reg.error.password.mismatch")
- For one thing, it’s obvious that we’re not passing in the actual error message! Instead, we’re passing in a key to an error message, stored in a properties file accessible to Struts.
- Properties files are just text files, which contain key/value pairs. In this case, the key is reg.error.password.mismatch, and the value might be The passwords you keyed in don't match!.
- # Properties file for Registration webapp
- # Error messages: reg.error.userid.missing=The user id is missing.
- reg.error.userid.exists = The user id exists. Choose another.
- reg.error.userid.bad = Use only alphanumerics for the userid.
- reg.error.password.mismatch = The passwords you keyed in don't match! reg.error.password.long = The password is too long!
- reg.error.password.short = The password is too short!
- The string argument of the ActionMessage constructor must be a key on a properties file.
- This might seem restrictive, but there’s a very good reason for this. This is how Struts makes it easy to localize an application.
- For example, if you wanted a German version of the Registration webapp, all you’d have to do would be hand over this properties file (registration.properties) for translation. You’d save the translated version as registration_de.properties, and bundle it with your webapp.
- German users would see the German version of the Registration webapp and everyone else would see the default English version. Localizing a webapp was never so easy!
Struts Examples | Struts Tutorials | Struts Links
Blog Archive
-
▼
2009
(17)
-
▼
April
(16)
- Use of ActionErrors in struts
- Anatomy of ActionForm
- Life Cycle of Struts Request
- Struts and MVC
- 10 Tips: How to Optimise Your Website in a Web 2.0...
- Struts or JSF? Struts and JSF?
- processNoCache() : Disables Back Button of All Bro...
- struts flow
- differences between bean:message and bean:write
- validate() and reset() methods
- validator-rules.xml and validation.xml files
- Struts - DynaForm validation
- What is difference between ActionForm and DynaActi...
- Creating Your own RequestProcessor
- Is Struts Thread Safe ?
- RequestProcessor in struts and how it works
-
▼
April
(16)
Tuesday, April 7, 2009
Use of ActionErrors in struts
Anatomy of ActionForm
org.apache.struts.action.ActionForm
Struts requires you to associate each form displayed to the user with your subclass of ActionForm.
Your subclass of ActionForm does two things:
- It holds all form data: Your subclass of ActionForm must have getters and setters corresponding to each property of the form.
- It performs simple validation: Your subclass must override the validate() function, if you want to perform any simple checks.
When a user submits a form, Struts populates the associated ActionForm subclass with the data, then calls validate() to perform any simple validations required. This function looks like this:
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request)
ActionErrors, which is validate()’s return value, is essentially like a HashMap to store error messages by key.
- If validate() returns a null value (or an empty ActionErrors instance), the validation passes.
- If validate() returns a non-empty ActionErrors instance, the validation fails, and Struts redisplays the form to the user along with any error messages.
Monday, April 6, 2009
Life Cycle of Struts Request
With servlet technology all such processing is done by servlets, Servlets are just Java objects, usually your subclasses of HttpServlet.
Even JSP pages are converted at runtime into servlet classes—actual .java source files. These autogenerated Java source files are later compiled.
Since Struts is built on servlet technology, it is no exception to this rule.
All submissions of form data to a Struts application are intercepted by a single “master” servlet, an instance of ActionServlet, which is a part of Struts.
This master servlet is responsible for delegating the actual work of your application to your subclasses of ActionForm and Action.
ActionServlet and its helper classed are responsible for many other behind- the-scenes things like pooling Action subclasses for efficiency, reading configuration data, or initializing Struts extensions called plug-ins. These activities are invisible to Struts developers, and are one good reason why Struts is so easy to use. You don’t have to know how the clock works to tell the time!
The incoming form data is processed in stages:
- Data transfer: Form data is transferred to your ActionForm subclass.
- Simple validation: The form data in this subclass is passed through simple validation. If simple validation fails, then the user is automatically presented with the form with the error messages detailing the errors. This is a typical scenario, but the details would depend on how you configured Struts.
- Further processing: Form data is next sent to your Action subclass for complex vali- dation and the processing of business logic.
- Your Action subclass also specifies the “next” page to be displayed, and this ends the processing of a single request.
Struts and MVC
- Model: Code to control data access and persistence
- View: Code to handle how data is presented to the user
- Controller: Code to handle data flow and transformation between Model and View
With Struts, Controller code falls into three broad categories:
- (1)
- Simple validations are performed by your subclasses of the Struts base class called ActionForm. eg.Checks for password length or email address format are examples of this. Struts greatly simplifies validation with the Validator framework.
- (2)
- Complex validations and business logic are done in your subclasses of the Struts base class called Action. The check for the duplicate user ID for the Registration webapp is an example of complex validation. An example of business logic is calcu- lating the total amount due after a purchase in a shopping cart webapp.
- (3)
- Flow control is also decided by your Action subclasses, restricted to paths declared in the Struts configuration file called struts-config.xml.
10 Tips: How to Optimise Your Website in a Web 2.0 World
10 Tips: How to Optimise Your Website in a Web 2.0 World
Struts or JSF? Struts and JSF?
Introduction
It should come as no surprise that the most frequent questions I get asked center around the issue of which of these two web tier technologies an organization or individual developer should consider using. It makes sense to ask me, because I was the original creator of the Struts Framework, and was the co-specification lead for JavaServer Faces 1.0 (JSF).
Usually, the question is framed as an or issue, based on an understanding that the two technologies are mutually exclusive. That turns out not to be the case, but it can still be difficult to determine what to do. This blog entry provides my current advice on the subject -- but, to understand it better, it's worth briefly reviewing the development and focus of the two technologies.
The story is a little long compared to typical blog entries; if you want to cut to the chase and see my advice, scroll down to the section entitled The Bottom Line, below.
Struts
Struts grew out of a personal need (open source developers often call this scratching your own itch) to support the development of an application that I was responsible for, prior to joining Sun in 2000. My task was to take a US-centric application to Europe, initially in four languages, and make it available (among other delivery channels) on the web. At the time, there was lots of discussion about appropriate architectures for on the JSP-INTEREST mailing list at java.sun.com, but there were few available implementations. Therefore, I set out to create an application framework for my own use, particularly focused on some key functional areas:
- An architecture based on the Model-View-Controller design patterns commonly seen in rich client applications, focusing on separation of concerns between presentation logic and business logic.
- A request processing lifecycle that is applied to all incomding HTTP requests, allowing the centralized management of common functionality like input form validation, and invoking business logic via a logical alias, rather than embedding knowledge of the business tier into a view tier component.
- Robust support for localizing the user interface of a web application.
- Since I was planning to use JSP for the view tier, a set of JSP custom tags that simplified the creation of user interfaces based on HTML forms.
The resulting framework served my needs quite well. As it became obvious that my needs were not unique, I began the process of open sourcing this idea of a web application framework at the Apache Software Foundation. What happened next was nothing short of extraordinary -- Struts quickly became the de facto standard web application architecture in the J2EE space (the number of significant Internet applications built with it is substantial, but is dwarfed by the number of intranet applications that use it), integrated into nearly all the major app servers and tools, supported by a rich ecosystem of knowledgeable proffesionals and skilled developers, backed by significant documentation in the form of books and articles, and the basis for a large user community centered around the Struts User mailing list (to subscribe, send an empty message to user-subscribe@struts.apache.org).
As Struts became a common starting point for developers new to the Java platform, an interesting phenomenom was occurring -- for many developers, the key perceived value of using Struts was assumed to be the JSP custom tags for HTML forms. While these tags are quite useful, they do not constitute a robust user interface component model, which has led to the need to create or integrate of third party tag libraries for more complex presentation requirements. To me, the core value has always been in the controller tier (the request processing lifecycle, and the features which this lifecycle has enabled, such as the additions of the Tiles framework for reusable look and feel, and the Validator Framework for client side and server side enforcement of form validation business rules). This perception, then, has led to some of the current confusion.
JavaServer Faces
After Struts was released, and was beginning to demonstrate its popularity, an increasing number of other frameworks and component implementations were becoming available. Indeed, at one point during the development of JSF, I had pointers to over 50 such technologies on a spreasheet being used to survey the market. While a large amount of innovation occurred, it was difficult to forsee the development of a common standard API for user interface components -- one that would enable the creation of a component marketplace where tools vendors could support one component API instead of 50, and where component developers could count on interoperation with many tools instead of one or two.
JSR-127 was introduced with the goal of solving this problem -- providing a common base level API for building user interface components for web applications, with the specific goals of being both accessible to developers writing applications by hand, but also easy to integrate into tools. In order to complete this JSR in any reasonable amount of time (and, if you wish to argue that we didn't achieve this goal, I won't disagree :-), we stayed strictly focused on the view tier. Controller tier functionality was considered out of scope, although to be of any practical use we had to provide hooks for basic things like instantiating objects on demand, as well as support for page navigation.
The focus on the view tier was clear from the feature list for JSF 1.0:
- Standard component API for user interface components, ranging from simple input fields to more complex tree controls and menus, to sophisticated scrollable tables which allowed both input and output. Components also support standard JavaBeans style events and event listeners.
- Decoupled rendering model, so that the same component could be rendered in different ways (for example, a command component used to submit a form might be rendered as either a button or a hyperlink).
- Request processing lifecycle focused on the handling of user interface events (such as the node of a tree control being expanded or contracted), coupled with support for data type conversions and component level validation rules.
- Utility technologies supporting the component APIs, including value binding and method binding expressions, managed beans (create on demand), and page navigation support.
JSF 1.0 was released in March 2004, followed by a maintenance release (1.1) in May, and is being rapidly adopted by tools vendors, component writers, and application developers alike. The beginnings of widespread adoption are clearly occurring, and any application which you are about to start should certainly evaluate JSF to see if it meets your needs. Besides the functional APIs described above, you will enjoy the availability of robust tools support from many vendors (shamless plug -- including the product I am currently an architect for, Sun Java Studio Creator).
The Bottom Line
But what about all those existing Struts applications? Are they going to get left out in the cold, or the developers forced to abandon their existing code and rewrite it? Nothing could be further from the truth.
The ideal scenario for existing Struts applications would be that we should be able to migrate, one page at a time (nobody has time to replace their entire UI in one fell swoop) to using JSF component tags -- either the standard ones shipped with JSF, or from any available third party component library -- to improve the richness of the user interface. And, because of the original MVC-based promise of separation of concerns, this migration should require little or no change in the back end functionality of the application (for Struts, that primarily means Action and ActionForm classes). Also, the migration should not eliminate the ability to use key Struts features like Tiles and the Validator Framework.
This scenario is, in fact, achieveable. In the Struts source repository is the Struts-Faces Integration Library, that achieves exactly this goal. It is currently available in nightly builds, but will shortly be released as a stand-alone add on library for Struts 1.1 or 1.2 based environments. The nightly builds include two versions of the canonical Struts example application, one using Tiles and one not, both using the Validator Framework.
If you have an existing Struts based application, then, I encourage you to evaluate a migration towards using JSF components instead of the original Struts HTML tags. Not only are the original tags effectively superceded by JSF, they are also not undergoing active development at the moment. You will find effectively equivalent functionality in JSF components already available, and much more sophisticated user interface components under development by many providers, for use in the future.
For new development, here's the best strategy for determining what to do:
- Evaluate the two technologies individually, to see if they satisfy your requirements.
- If one or the other technology is sufficient, go ahead and use it (it's easier to learn and use one technology rather than two where possible); keeping in mind, however, the caveats about Struts HTML tags mentioned above.
- If your requirements include unique features supported only by Struts (such as Tiles or client side validation support), feel free to use the two frameworks together.
The Future
It should be clear by now that there is overlap between Struts and JSF, particularly in the view tier. Over time, JSF will continue to evolve in the view tier area, and I'm going to be encouraging the Struts community to focus on value adds in the controller and model tiers. Thus, it will become more and more clear that there is room in many web application architectures for two frameworks, each focused on their own tiers, cooperating to meet overall architectural requirements. The details of this, however, will be the subject of further discussions on the Struts developer mailing list, and (undoubtedly) future blog entries.
Thursday, April 2, 2009
processNoCache() : Disables Back Button of All Browsers
RequestProcessor as follows:
response.setHeader("Cache-Control", "no-cache");
With IE everything is fine. Hitting the back button works wonderfully and if
the previous request was a GET it would be "re GOTTEN" and if it was a
POST, it displays the "POST data has expired warning. U wanna resubmit?"
dialog.
However, for some other browsers, it doesn't quite work.
In Galeon and mozilla, regardless of whether the HTTP request was a POST
or a GET, hitting the back button shows the previous screen in its original
glory (not good).
I made a slight tweak and over-rode the processNoCache() method in
"my RequestProcessor" (which incidentally overrides TilesRP). Inside this
overriddent, I changed the Cache-Control setting to :
response.setHeader("Cache-Control", "no-cache,no-store,max-age=0");
This works fine.
struts flow
Struts Flow is a port of Cocoon’s Control Flow to Struts to allow complex workflow, like multi-form wizards, to be easily implemented using continuations-capable JavaScript. It provides the ability to describe the order of Web pages that have to be sent to the client, at any given point in time in an application.
The code is based on a proof-of-concept Dave Johnson put together to show how the Control Flow could be extracted from Cocoon. (Ref: http://struts.sourceforge.net/struts-flow/index.html )
differences between bean:message and bean:write
bean:message: This tag is used to output locale-specific text (from the properties files) from a MessageResources bundle.
bean:write: This tag is used to output property values from a bean.
validate() and reset() methods
- ActionForm class provides a validate() method hook that can be overridden by subclasses to perform validations on incoming form data.
- The validate() method hook gets called after a Form Bean has been populated with incoming form data.
- validate() method has return type ActionErrors
reset():
- ActionForm class has a reset() method that subclasses can override.
- The method is a hook that gets called before FormBean is populated with request data from an HTML form.
- Using this reset() method, all the form fields will be reset.i.e..Unchecking the check boxes, making the text fileds empty..etc
- public void reset() {}
validator-rules.xml and validation.xml files
Validator framework is used to validate the form data and you no need to write any code in your form bean for validations and storing the error messages.
Your Form Bean, extending one of the Validator’s Action Form subclasses, does the required validations.
If you do not use Validator, you need to handle the data validations in the validate() method of Form Bean objects, and also handle storing of error messages if validationis fails.
Two configuration files used by Validator are validation.xml and validator-rules.xml. In order to enable and use the Validator, plug-in should be added in sturts-config.xml
Struts - DynaForm validation
It is difficult to handle validator framework, if you are new Very Happy to struts.
I have also spent lot to time to learn it, so now finally I done it.
I will give you step by step of using dyna form validation. It is simple server side dynaform action validation or and client side validation with source code.
1. Open struts-config.xml file and do entries
2. Make validation.xml file in WEB-INF folder
3. Create validator-rules.xml in WEB-INF folder.
4. Create action class according to your requirement.
5. Create ApplicationResources.properties file in your package.
6. Last finally create a jsp file where you want to show your errors.
This example using struts 1.2 jars. So do little care of DTD tld standards. And version of it struts 1.1 use different and struts 1.3 use different one.
Wednesday, April 1, 2009
What is difference between ActionForm and DynaActionForm
The same process is repeated again and again when user creates a view.
DynaActionForm eliminates this burden and creates the form bean itself.
This way user dont have to write setters and getters.
DynaActionForm is specialized subclass of ActionForm that allows the creation of form beans with dynamic sets of properties, without requiring the developer to create a Java class for each type of form bean. DynaActionForm eliminates the need of FormBean class and now the form bean definition can be written into the struts-config.xml file. So, it makes the FormBean declarative and this helps the programmer to reduce the development time.
More Details
Creating Your own RequestProcessor
creating a custom RequestProcessor, we will change our sample application to implement these two business requirements:
- We want to create a
ContactImageActionclass that will generate images instead of a regular HTML page. - Before processing every request, we want to check that user is logged in by checking for
userNameattribute of the session. If that attribute is not found, we will redirect the user to the login page.
- Create your own
CustomRequestProcessorclass, which will extend theRequestProcessorclass, like this:
In the
public class CustomRequestProcessor
extends RequestProcessor {
protected boolean processPreprocess (
HttpServletRequest request,
HttpServletResponse response) {
HttpSession session = request.getSession(false);
//If user is trying to access login page
// then don't check
if( request.getServletPath().equals("/loginInput.do")
|| request.getServletPath().equals("/login.do") )
return true;
//Check if userName attribute is there is session.
//If so, it means user has allready logged in
if( session != null &&
session.getAttribute("userName") != null)
return true;
else{
try{
//If no redirect user to login Page
request.getRequestDispatcher
("/Login.jsp").forward(request,response);
}catch(Exception ex){
}
}
return false;
}
protected void processContent(HttpServletRequest request,
HttpServletResponse response) {
//Check if user is requesting ContactImageAction
// if yes then set image/gif as content type
if( request.getServletPath().equals("/contactimage.do")){
response.setContentType("image/gif");
return;
}
super.processContent(request, response);
}
}processPreprocessmethod of ourCustomRequestProcessorclass, we are
checking for theuserNameattribute of the session and if it's not found,
redirect the user to the login page.
For our requirement of generating images as output from theContactImageActionclass,
we have to override theprocessContentmethod and first check if the request is
for the/contactimagepath. If so, we set thecontentTypetoimage/gif; otherwise,
it'stext/html...More Details
Is Struts Thread Safe ?
- Struts is not only thread-safe but thread-depenedent.
- The response to a request is handled by light weight Action object, rather than an individual servlet.
- Struts instanciate each Action class once and allows other request to threaded through the orginal object.
- This core strategy conserves resources and provides the best posible throughput.
- A properyly-designed application will exploit this further by routing realated operations through a single action.