No XML, please!

A small, flexible, and easy MVC Web framework with no XML

1 2 Page 2
Page 2 of 2

Best practices

Inside your actions, you should place only code related to your model layer, either through model beans or plain code. With filters, you can better separate the model layer that goes inside your action from authentication, validation, connection pooling, and any other logic that has nothing to do with your model. Filters are an elegant approach for keeping your model layer clean!

Validation

Validation is an important topic in any Web application that must guarantee only valid data is written to the database. Frameworks exist solely for this purpose, like Apache Commons Validator; however, they encourage the use of XML. Mentawai takes a different approach by using the classes org.mentawai.filter.ValidationFilter and org.mentawai.validator.Rule to obtain a similar result with plain Java code.

You should do validation for your actions through a filter. Your validation filter should inherit from org.mentawai.filter.ValidationFilter and override the initValidator() method to set up rules for each field, along with the error you want to show in case of a validation failure. Check the example below:

 

public class HelloWorldValidator extends ValidationFilter {

private static final int FIELD_REQUIRED_ERROR = 1; private static final int INVALID_USERNAME_LENGTH = 2; private static final int INVALID_AGE = 3; private static final int INVALID_PASSWORD_LENGTH = 4; private static final int PASSWORD_DOES_NOT_MATCH = 5; public void initValidator() { add("username", new RequiredFieldRule(), FIELD_REQUIRED_ERROR); add("username", new StringRule(6, 30), INVALID_USERNAME_LENGTH); add("age", new RequiredFieldRule(), FIELD_REQUIRED_ERROR);

add("age", new IntegerRule(18, 50), INVALID_AGE); add("password", new RequiredFieldRule(), FIELD_REQUIRED_ERROR); add("password", new StringRule(4, 20), INVALID_PASSWORD_LENGTH); add("password", new EqualRule("password", "passconf"), PASSWORD_DOES_NOT_MATCH); add("passconf", new RequiredFieldRule(), FIELD_REQUIRED_ERROR);

} }

Note that validation happens in a chain for each field. In the example above, the age field has two validation rules: RequiredFieldRule and IntegerRule. The second one executes only if the first one succeeds. You can add as many rules as you want for a single field.

By default, validation looks for error messages in the directory /validation, inside the document root. The i18n file inside this directory must have the same name of the validation filter, so, in our case, it is HelloWorldValidator_loc.i18n.

The contents for the file /validation/HelloWorldValidator_en_US.i18n appear below:

 

############################################### # Messages for the filter HelloWorldValidator # ###############################################

1 = Required field cannot be left blank 2 = Your username must be between %min% and %max% characters long. 3 = You must be %min% years old or older. 4 = Your password must be between %min% and %max% characters long. 5 = Passwords do not match.

What are %min% and %max% in the error messages? Each rule can place special tokens inside error messages by implementing the method getTokens(). These tokens replace the marker %token%. RequiredFieldRule and EqualRule have no tokens. StringRule and IntegerRule return the minimum and maximum values as tokens, so, if desired, you can show these values in the error messages.

A validation filter is totally decoupled from the action, so the same filter may be used to validate different actions. This avoids unnecessary code duplication and strives for better code maintenance.

Below is our ApplicationManager, which registers the validation filter for our action:

 

public class ApplicationManager extends org.mentawai.core.ApplicationManager {

public void loadActions() { ActionConfig ac = new ActionConfig("/HelloWorld", HelloWorld.class); ac.addConsequence(HelloWorld.SUCCESS, new Forward("/hello.jsp")); ac.addConsequence(HelloWorld.ERROR, new Forward("/form.jsp")); addActionConfig(ac); ac.addFilter(new HelloWorldValidator()); } public void loadLocales() { LocaleManager.add(new Locale("pt", "BR")); LocaleManager.add(new Locale("en", "US")); } }

Notice that we specify in the loadLocales() method the locales our application supports. If you don't do anything, Mentawai will have just one default locale: en_US. Therefore, it will expect to find at least *_en_US.i18n files. Since we are specifying two locales, you should have two files inside the validation directory: HelloWorldValidator_en_US.i18n and HelloWorldValidator_pt_BR.i18n. You can change your browser's default language to test these files.

In the view layer, we can use the handy <mtw:hasError> and <mtw:error field="" /> to display validation error messages. The contents of the form.jsp file appear below:

 

<%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %> <!-- Note: The form loses all data on each submission! Mentawai can solve this problem automatically for you through its HTML tags. --> <html> <body> <h1>Hello Validation!</h1> <form action="HelloWorld.mtw" method="post"> Your username: <input name="username" size="25" />

<mtw:hasError> <font color="red"><mtw:error field="username" /></font> </mtw:hasError>

<br>Your age: <input type="text" name="age" size="10" maxlength="3" />

<mtw:hasError> <font color="red"><mtw:error field="age" /></font> </mtw:hasError>

<br>Your password: <input type="password" name="password" size="25" />

<mtw:hasError> <font color="red"><mtw:error field="password" /></font> </mtw:hasError>

<br>Again please: <input type="password" name="passconf" size="25" />

<mtw:hasError> <font color="red"><mtw:error field="passconf" /></font> </mtw:hasError>

<input type="submit" value="Enviar"> </form> </body> </html>

Notice that the Mentawai tag <mtw:hasError> is conditional; in other words, it will only show its body contents if its conditional is true.

Refer to Resources to download the complete validation example as a war archive.

Creating more validation rules

When it comes to validation, you can create an unlimited number of validation rules. For example, you may need to have a CreditCardRule, a URLRule, an EmailRule (provided by Mentawai), or a PasswordRule. You can use one of the available Mentawai rules or create your own.

Creating your own rules in Mentawai is easy and just a matter of implementing the org.mentawai.validator.Rule interface. You can also use one of the abstract rules that come with Mentawai:

  • BasicRule: A simple rule to validate a single field (StringRule)
  • LocaleRule: A rule to validate a single field considering its locale (DateRule)
  • CrossRule: A rule to compare different fields in the same form for the validation (EqualRule)

Mentawai comes with a useful rule: org.mentawai.rule.RegexRule. With this rule, you can validate a field with a regular expression. Therefore, this rule should be subclassed to create more rules that can be performed with a regular expression. org.mentawai.rule.EmailRule is such an example. You should refer to the API documentation for more details on how to extend these classes.

Keeping the form data

You probably noticed that our form loses all its data after each submission, forcing the user to type everything again and resulting in a terrible experience for the user and also for the developer who must code a solution. However, through Mentawai's HTML tags, you can solve this problem without a single line of code. Just use the tags <mtw:input>, <mtw:select>, <mtw:checkboxes>, and <mtw:radiobuttons> to construct your HTML and the form will not lose its data anymore. These custom tags have the same attributes of normal HTML tags, so you should have no problems using them.

Conclusion

In this article, I have covered a small part of the Mentawai Web framework. You have been introduced to the framework's architecture and have seen how most of its features can be implemented as filters and, best of all, with no XML. We also examined the validation feature and saw how we can easily configure localized error messages in i18n files. With Mentawai, you don't have to deal with those boring XML files anymore. You can use the ApplicationManager class to achieve the same results with plain Java code.

Sergio Oliveira Jr. graduated from Case Western Reserve University with a degree in computer engineering in 1998. He has participated in many successful Web projects like Zipmail, Escola24horas, DatingPlace, and Gazzag. He is also the author of Lohis, a collaborative application in Java Media Framework with audio and video conferencing for distance learning, and of the open source projects Space4J and Mentawai. He can be found at GUJ discussing Java-related topics.

Learn more about this topic

1 2 Page 2
Page 2 of 2