Struts 1.2 offers cool new features

by Bill Siggelkow

Related link: http://struts.apache.org



Now is a great time to be developing with Struts. With the recent release of version 1.2.4, now more than ever Struts provides a solid platform for developing complex Java web applications. While working on the upcoming Jakarta Struts Cookbook, I have come to appreciate a number of the innovative new features in Struts 1.2.


The move from Struts 1.0 to Struts 1.1 was a major shift. Struts 1.2 solidifies the Struts 1.1 platform and adds a number of additional features designed at empowering the Struts developer. Here are a couple of the features that I especially like in Struts 1.2.

Valid When


The Struts Validator introduced the ability to perform some types cross-field using the requiredif pluggable Validator. If you have ever used requiredif, you know what a pain it is. It is extremely verbose to code up the relationships in XML and, even then, you're still limited in how you compare different fields to each other; basically indicating that one field must be supplied if another field is empty (or not). The validwhen validator makes these rules easier to code – you use a simple expression language – and even easier to code up specific validations (e.g. checking if two fields have the same value) that were not even possible with requiredif. One knock against the validwhen rule (which also applies to requiredif) is that it does not support client-side (i.e. JavaScript-based) validation. Personally, I prefer server-side validations for the control offered, so this is not a major issue.

Wildcard Mappings


Wildcard mappings allow you to define a generic set of mappings that can be used across all actions that follow a common workflow pattern and naming convention. On numerous occasions people have complained on the struts-user list that they have to write so many repetitive action mappings; that all essentially implement the same workflow. A typical workflow might be:

  1. prepare the form for viewing
  2. display the form on a JSP
  3. submit the form to an action that saves the data
  4. display a success page

Good developers will use common naming conventions that across-the-board so it's easy for other developers to know what purpose the actions serve. Wildcard mappings allow you to codify the common pattern and naming convention. For example, here's a set of action mappings that use wildcards:

<action
path="/Edit*"
type="com.oreilly.strutsckbk.ch07.Edit{1}Action"
name="{1}Form"
scope="request"
validate="false">
>forward
name="success"
path="/edit_{1}.jsp"/<
</action>

<action
path="/Save*"
type="com.oreilly.strutsckbk.ch07.Save{1}Action"
name="{1}Form"
scope="request"
validate="true"
input="edit_{1}.jsp">
<forward
name="success"
path="/saved_{1}.jsp"/>
</action>

Now you when I have an action path like http://com.oreilly.struts/myapp/EditUser.do, the Struts RequestProcessor matches the wildcarded mapping to the URL; the {1} represents the text that matches the wildcard (*) (similar to a capture group in a regular expression). So you end up with the following "virtual" mapping:

<action
path="/EditUser"
type="com.oreilly.strutsckbk.ch07.EditUserAction"
name="UserForm"
scope="request"
validate="false">
>forward
name="success"
path="/edit_User.jsp"/<
</action>

<action
path="/SaveUser"
type="com.oreilly.strutsckbk.ch07.SaveUserAction"
name="UserForm"
scope="request"
validate="true"
input="edit_User.jsp">
<forward
name="success"
path="/saved_User.jsp"/>
</action>


This is a powerful feature; promoting both reuse as well as naming standards across your application.


These are just a couple of new features that Struts 1.2 offers. Check the release notes as well as the Struts User's Guide for more details. In general, I think you will find that you will want to use Struts 1.2 for new development. For existing Struts 1.1 applications, if you have to add new features to your application, then it might be a good time to go ahead upgrade to Struts 1.2.


Let me know of additional features in Struts 1.2 that you like (or don't like, for that matter).


22 Comments

paulwhite1
2005-01-05 14:19:43
validwhen is very limited
Validwhen appears very limited. For example I do not believe it can be used to implement the following. If it can I would love to be proved wrong with an example:


Suppose I have a checkbox and a textfield called startdate.


If checkbox is checked then validation must always succeed (i.e. startdate value is ignored)


If checkbox is not checked then
If date is null
then validation succeeds
If date not null
If date format OK then validation succeeds
If date format wrong then validat. fails

paulwhite1
2005-01-05 14:22:11
validwhen is very limited
Here is what I want (formatted)

If checkbox is checked then validation must always succeed (i.e. startdate value is ignored)


If checkbox is not checked then
If date is null
then validation succeeds
If date not null
If date format OK then validation succeeds
If date format wrong then validat. fails

BillSiggelkow
2005-01-06 05:58:19
validwhen is very limited
The key to this, Paul, is combining pluggable validators in the depends attribute. For your example, you would make the "date" field with 'depends="validwhen,date". The date formatting validation will only be applied when the date is a non-null value. The validwhen test only sets up the dependency with the checkbox field.
paulwhite1
2005-01-06 07:32:32
validwhen is very limited
I still don't believe it is possible to implement my logic. I don't see how validwhen gives me the flexibility that I need.
BillSiggelkow
2005-01-06 08:49:17
validwhen is very limited
Paul --
First my apologies for the someone short initial answer. I had not taken the initial time to actually attempt to implement your scenario. After doing so, I discovered that, in fact, I was unable to implement your scenario, verbatim, using validwhen. However, I would not say that valid when is "very limited". It's limited, yes, but is still more powerful than requiredif. In general, the validator does not provide a means of "skipping" a validation based on the value of another field. However, if the requirement was
The date field must be null if the checkbox is checked
then you could use validwhen. Here's how I implemented this close cousin of your scenario:

<field property="mychkbox" depends="validwhen">
<arg key="My checkbox" resource="false"/>
<var>
<var-name>test</var-name>
<var-value>(((*this* != null) and (mydate == null)) or (*this* == null))</var-value>
</var>
</field>
<field property="mydate" depends="date">
<arg key="My date" resource="false"/>
<var>
<var-name>datePattern</var-name>
<var-value>MM/dd/yyyy</var-value>
</var>
</field>

If you still need to implement your scenario verbatim than I suggest you use either a custom validator or code the validation in your ActionForm.
paulwhite1
2005-01-06 09:33:38
validwhen is very limited
Many thanks Bill,
you've confirmed what I suspected.
Paul
vmanjunath
2005-02-24 11:38:53
Validating a date field.
I have a situation where my form consists of 2 fields(not required) that need to be validated against each other - primaryGender and primaryDob. One is a 'gender' field and the other is a date of birth field. The gender field defaults to 'NA'. The valid values are 'F' and 'M'. If the user chooses a gender, then the date of birth field has to be a valid date and vice-versa. So, the validation succeeds only if both fileds have valid values or both are null. I am using 'validwhen' validator as follows:





test
((primaryDob == null)or(*this* != 'NA'))


But, I am getting this exception : [Servlet Error]-[org.apache.struts.validator.Resources: method getActionMessage(Ljavax/servlet/http/HttpServletRequest;Lorg/apache/commons/validator/ValidatorAction;Lorg/apache/commons/validator/Field;)Lorg/apache/struts/action/ActionMessage; not found]: java.lang.NoSuchMethodError: org.apache.struts.validator.Resources: method getActionMessage(Ljavax/servlet/http/HttpServletRequest;Lorg/apache/commons/validator/ValidatorAction;Lorg/apache/commons/validator/Field;)Lorg/apache/struts/action/ActionMessage; not found.


I am not sure if the value is being parsed properly. Is the problem with the date field or the boolean expression? How exactly does the validateValidWhen() method work in this case?


Thanks,
vmanjunath



BillSiggelkow
2005-02-24 12:28:35
Validating a date field.
Your problem is coming from a incorrect JAR -- make sure that you are using the latest commons validator Jar. There is nothing wrong with your actual validation rule and validwhen expression.
vmanjunath
2005-02-24 13:59:43
Validating a date field.
Hi Bill,


Thanks for a quick reply. I had the latest version of Commons Validator. But, as per your suggestion I did replace it with version 1.1.4.
I am still getting the same exception. Any suggestions? After validating the gender field, I am validating the date of birth field as follows :




datePattern
MM/dd/yyyy


Is that correct?


Thanks,
vmanjunath

BillSiggelkow
2005-02-24 19:12:44
Validating a date field.
Trust me -- its not your XML -- you may have an old "validator-rules.xml". A NoMethodFoundError means that some code is trying to call a method that does not exist. The old Resources class changed the method from getActionError to getActionMessage so there's some sort of problem there. You might want to try getting a fresh download of Struts.
vmanjunath
2005-02-28 11:41:32
Validating a date field.
Hi Bill,


Thanks so much for your time and valid suggestions. I did download Struts again and everything works fine.


vmanjunath

skul
2005-03-16 08:57:17
Validating a date field.
Hi,


I have a similar problem. Everything was working fine until few days back. The problem started this monday - I get:



java.lang.NoSuchMethodError: org.apache.commons.validator.ValidatorResources.getForm(Ljava/util/Locale;Ljava/lang/String;)Lorg/apache/commons/validator/Form;


I have the same jars, dtds, xml files as before, why would this suddenly change when nothing else has?


I am running Tomcat 4.1.31 with Apache 1.3 and struts 1.2.


Thank you for your time.

skul
2005-03-16 09:31:33
Validating a date field.
Hi,


I downloaded a fresh copy of validator and it works fine now. But I still cannot understand why this worked earlier and stopped working all of a sudden.


Thanks.

munichcafe
2005-06-18 04:07:58
name="{1}Form" does not work!
Wildcard mappings:


I tried the Wildcard Mappings, the name of the ActionForm must be concret, otherwise it does not work.


I checked the config.xml file in the struts-blank project, there you can not find Wildcard for ActionForm.

munichcafe
2005-06-18 04:14:42
Now it works!
I don't know why, but I retried and it works now.
arudra
2005-08-29 15:06:27
validator question
in my form i have tow fileds that hold dates( start and end dates).


how to specify validation rule to make sure end date is greater than start date.


depends="required,date">


datePattern
MM/dd/yyyy



depends="date,validwhen">


datePattern
MM/dd/yyyy

key="admin.setupprogram.endDate.invalid"
resource="true"/>

test
(*this* >= startDate)


my both start and end dates are strings holding dates(mm/dd/yyyy).


Thanks,




BillSiggelkow
2005-08-29 19:08:16
validator question
Because the two values are Strings they you need to be able to compare them as dates. I do not think that validwhen knows to perform date translation. The straightforward way to solve your problem is to hand-code the validation in your ActionForm's validate() method. Just be sure to call super.validate() to allow the Validator's validations to take place.
arudra
2005-08-30 07:18:34
validator question
Thx for the reply bill.


Yes, my basic question was whether vaidwhen can handle date translation. sothat i can avoid writing any code in the validate() method.


BillSiggelkow
2005-08-30 07:49:42
validator question
I dug a little deeper and by all indications validWhen does not do any date translation. If you need this functionality in more than one place and you want the convenience of the Validator consider righting your own pluggable Validator. It's not that hard .. in the Struts Cookbook, for example, I show how to write a validator that compares if two values are the same (of course, this could be done with validWhen) ...
arudra
2005-08-30 08:03:50
validator question
yes, thats seems like good idea. i'll try that. thanks for your help, Bill.
WayneR
2005-12-21 21:36:20
Tiles and tabbed panels
I have used the Jakarta Struts Cookbook often to resolve issues. Now I have run into a snag using the book. In chapter 14 Tabbed panels are explained. I have put the example into a tile definition and can display it on screen. Now for the fun bit. when I click the tabs I get null pointer exceptions. If I use the page outside of the tiles all works well. What could be the issue?
Regards
Wayne
BillSiggelkow
2005-12-22 05:13:07
Tiles and tabbed panels
Wayne, I have not run this example in a while. Perhaps you can derive some information from the stack trace?