Context-Sensitive Error Messages

 < Day Day Up > 



If you have a form with a lot of properties and something goes wrong, you want to give the user more cues than just error messages at the top of the page. For example, you may want to turn the label red by field. You can do this by using logic:messagesPresent:

 <logic:messagesPresent property="userName">     <font size="4" color="red"> </logic:messagesPresent> <bean:message key="inputForm.userName"/>: <logic:messagesPresent property="userName">     </font> </logic:messagesPresent> <html:text property='userName' /> <br /> 

By specifying the property attribute as userName, we are checking to see whether there are any error messages for the userName property. If there are, we turn the font of the userName red. This snippet contains a lot of repetitive JSP code. You may want to either write a visual component with a Tile layout (see Chapter 13, "Using Tiles," to learn more) or write a custom tag. The following is a custom tag that does the job:

 package trivera.tags.html; import java.util.Iterator; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.BodyTagSupport; import org.apache.struts.Globals; import org.apache.struts.action.ActionErrors; import org.apache.struts.util.RequestUtils; import org.apache.struts.util.ResponseUtils; /**  *  * @jsp.tag name="redIfError"  *          body-content="JSP"  */ public class RedIfErrorTag extends BodyTagSupport {     private String property;     private boolean isError() throws JspException{         ActionErrors actionErrors =           RequestUtils.getActionErrors(pageContext,Globals.ERROR_KEY);         if (actionErrors == null){             return false;         }         Iterator iter = actionErrors.get(this.getProperty());         if (iter==null) return false;         if (iter.hasNext()==false)return false;         return true;     }     /** Getter for property property.      * @return Value of property property.      * @jsp.attribute required="false"      *                  rtexprvalue="false"      *                  description="The property attribute"      */     public String getProperty() {         return property;     }     /**      * @param string      */     public void setProperty(String string) {         property = string;     }     /* (non-Javadoc)      * @see javax.servlet.jsp.tagext.IterationTag#doAfterBody()      */     public int doAfterBody() throws JspException {         boolean wasErrors = isError();         StringBuffer buffer = new StringBuffer(50);         if (wasErrors){ //For real projects, use CSS             buffer.append("<font color=\"red\" size='4'>");         }         buffer.append(this.bodyContent.getString());         try{             this.bodyContent.clear();         }catch(Exception e){             throw new JspException(e);         }         if (wasErrors){             buffer.append("</font>");         }         ResponseUtils.writePrevious(pageContext, buffer.toString());         return SKIP_BODY;     } } 

Notice the liberal use of Struts utility classes. Now we can use that code as follows:

          <thtml:redIfError property="userName">          <bean:message key="inputForm.userName"/>:                </thtml:redIfError> 

start sidebar

In a future release of Struts, look for a tag called html:label. This tag is under development by Erik Hatcher, and will likely be in a future release of Struts. This tag also integrates with the Validator framework to find the labels. It is similar in concept to redIfError but more advanced. Erik's html:label uses CSS instead of <font>. Using CSS is a best practice.

end sidebar

So how did we know how to write this custom tag? Easy! Just look at the Struts source code for the tags that are most like the tag you want to write. Don't be afraid of the code!

Another thing you may want to do is put the message right next to the field. You can do that with <html:messages>:

 <html:text property='userName'/>  <html:messages  property='userName'>  <font color="red">  <%=message%> </font> </html:messages> 

The problem with this code is that you would have to type it out for each property in the form. Notice in Figure 21.2 how that code would put the image right by the field.

click to expand
Figure 21.2: The message appears next to the field.

You can write your own custom tag or Tile layout component that does a similar thing so that you don't have to repeat the code for each field:

 import java.util.Iterator; import javax.servlet.jsp.JspException; import org.apache.struts.Globals; import org.apache.struts.action.ActionError; import org.apache.struts.action.ActionErrors; import org.apache.struts.taglib.html.TextTag; import org.apache.struts.util.RequestUtils; import org.apache.struts.util.ResponseUtils; /**  *  * @jsp.tag name="text-ext"  *          body-content="JSP"  *  */ public class TextTagExt extends TextTag {     /*      */     public int doAfterBody() throws JspException {         ActionErrors actionErrors = (ActionErrors)                 pageContext.getRequest().getAttribute(Globals.ERROR_KEY);         if (actionErrors!=null){             Iterator iter = actionErrors.get(this.getProperty());             while (iter.hasNext()){                ActionError error = (ActionError) iter.next();                String key = error.getKey();                Object [] values = error.getValues();                String message = RequestUtils.                          message(pageContext, null, null, key, values);                ResponseUtils.write(pageContext,message + "   ");             }         }         return SKIP_BODY;     } } 

The previous tag subclasses the tag handler for form:text. It then uses RequestUtils.message to retrieve the message for the property out of the ressource bundle. To subclass TextTag, we had to study it so we could figure out where it could be extended. We find extending the customs tags makes them a bit fragile; the extentions points are not well documented and there is not much consistency of implementation from tag to tag. Therefore, to use the tag

 <thtml:text property="userName" /> 

without our custom tags, the following would turn the label red and put the error text by the field (where thtml is our own tag library):

 <logic:messagesPresent property="userName">     <font size="4" color="red"> </logic:messagesPresent> <bean:message key="inputForm.userName"/>: <logic:messagesPresent property="userName">     </font> </logic:messagesPresent>  <html:text property='userName'/>  <html:messages  property='userName'>  <font color="red">  <%=message%>  </font>  </html:messages>  <br /> By developing our own custom tags, we can rewrite the above as follows: <thtml:redIfError property="userName">            <bean:message key="inputForm.userName"/>: </thtml:redIfError> <thtml:text property="userName" /> 



 < Day Day Up > 



Professional Jakarta Struts
Professional Jakarta Struts (Programmer to Programmer)
ISBN: 0764544373
EAN: 2147483647
Year: 2003
Pages: 183

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net