Mentawai Web Framework

Dynamic Messages

Dynamic Messages are something like:

  • "Your profile was successfuly updated!"
  • "There was an error trying to save your profile to the database"
  • "The email address you entered is invalid!"
  • "Please fill up the field below:"
  • etc.

Mentawai support localized dynamic messages in an easy way, as you will see in the example below. You can also click here to download a war file with a simple application that illustrates the use of dynamic messages with mentawai.

A simple example of an action that supports dynamic messages is below:

package examples.messages;

import java.util.*;

import org.mentawai.core.*;
import org.mentawai.message.*;

public class HelloMentawai extends BaseAction {
	
	private static final String USERNAME_MISSING_ERROR = "1"; // this can also be an int!
	private static final String CONGRATULATION_MSG = "2";
	
	public String execute() throws Exception {
		String username = input.getStringValue("username");
		if (username == null || username.trim().equals("")) {
			addError(USERNAME_MISSING_ERROR);
			return ERROR;
		}
		output.setValue("username", username.toUpperCase());
		addMessage(CONGRATULATION_MSG);
		return SUCCESS;
	}
	
}
	

The addMessage() and addError() methods are provided by BaseAction and can be used to add messages and errors to the action. You define a message with a string or integer that will be used as the key to the message in the i18n file.

By default, Mentawai looks for the messages's i18n file in the directory /messages from the document root. Also by default, the i18n file has the name of the action class. So for the above example, the messages are in the file /messages/HelloMentawai_loc.i18n:

############################################
# Messages for the action HelloMentawai    #
# file: /messages/HelloMentawai_en_US.i18n #
############################################

1 = The username field is blank!
2 = Congratulations my friend!
	

Non-Localized Messages

You can create non-localized messages if you don't want to deal with internationalization. To accomplish that, simply write your message in the message key. This is possible because mentawai will show the key if it cannot find the message in the i18n file and even if the i18n file does not exist. See the example below:

public class HelloMentawai2 extends BaseAction {
	
	private static final String USERNAME_MISSING_ERROR = "Username is missing!";
	private static final String CONGRATULATION_MSG = "Congratulations!";
	
	public String execute() throws Exception {
		String username = input.getStringValue("username");
		if (username == null || username.trim().equals("")) {
			addError(USERNAME_MISSING_ERROR);
			return ERROR;
		}
		output.setValue("username", username.toUpperCase());
		addMessage(CONGRATULATION_MSG);
		return SUCCESS;
	}
	
}
	

Using the master file

Instead of using one i18n file per action, you can fetch all localized messages from a single file called the master file. The master file by default is located on /i18n/master_loc.i18n.

public class ApplicationManager extends org.mentawai.core.ApplicationManager {
	
	public void init(Context application) {
		LocaleManager.setUserLocaleForEverything(true);
	}
}
	

You can also alter the location of the master file using the method below:

public class ApplicationManager extends org.mentawai.core.ApplicationManager {
	
    public void init(Context application) {
        LocaleManager.setUserLocaleForEverything(true);
        LocaleManager.setMaster("/mydir/mymaster");
    }
}
	

More Control

Mentawai looks for messages in an MessageContext. This class encapsulates an i18n file with the localized messages. Mentawai provides two useful implementations of a MessageContext:

  • ClassMessageContext: uses the name of the class to find the i18n file. So if you pass as a parameter the class HelloMentawai.class, the context will look for the file HelloMentawai_loc.i18n. (Note that it ignores the package prefix!)


  • FileMessageContext: allows you to specify the exact name of the i18n file. (Refer to the API documentation for more details)

By default, a MessageContext uses the /messages directory in the document root to look for i18n files. To change the directory, you can use the special constructor the allows you to define this directory. (Refer to the API documentation for more details)

It is important to note that nothing holds you from overriding these classes to create your own MessageContext. Mentawai provides a base AbstractMessageContext class to facilitate you in this job.

An example of an action that defines its MessageContext is below:

public class HelloMentawai2 extends BaseAction {
	
	private static final MessageContext MSG_CONTEXT = new FileMessageContext("MyMessages.i18n", "msgDir");
	private static final int USERNAME_MISSING_ERROR = 1;
	private static final int CONGRATULATION_MSG = 2;
	
	public String execute() throws Exception {
		String username = input.getStringValue("username");
		if (username == null || username.trim().equals("")) {
			addError(USERNAME_MISSING_ERROR, MSG_CONTEXT);
			return ERROR;
		}
		output.setValue("username", username.toUpperCase());
		addMessage(CONGRATULATION_MSG, MSG_CONTEXT);
		return SUCCESS;
	}
	
}
	

Locales

We are supporting two locales in our i18n files: pt_BR and en_US, so we should specify that in our ApplicationManager: (refer to the section on Internationalization for more details)

public class ApplicationManager extends org.mentawai.core.ApplicationManager {
	
	public void loadActions() {
		ActionConfig ac = new ActionConfig("/HelloWorld", HelloMentawai.class);
		ac.addConsequence(HelloMentawai.SUCCESS, new Forward("/hello.jsp"));
		ac.addConsequence(HelloMentawai.ERROR, new Forward("/username.jsp"));
		addActionConfig(ac);
	}
	
	public void loadLocales() {
		LocaleManager.add(new Locale("pt", "BR"));
		LocaleManager.add(new Locale("en", "US"));
	}
}
	

The View Layer

To show these messages in the view layer, you can use some useful mentawai tags:

The username.jsp file with support for an error message:

<%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %>
<html>
<body>
<h1>Hello Metawai!</h1>
<mtw:hasError>
<h3><font color="red"><mtw:error /></font></h3>
</mtw:hasError>
<form action="HelloWorld.mtw" method="post">
Type your username: <input name="username" size="25" />
<input type="submit" value="Send Now!">
</form>
</body>
</html>	
	

The hello.jsp file with support for a success message:

<%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %>
<html>
<body>
<mtw:hasMessage>
<h4><mtw:message /></h4>
</mtw:hasMessage>
<h3>Hello <mtw:out value="username" /> from Mentawai!</h3>
</body>
</html>
	

The tags <mtw:hasMessage> and <mtw:hasError> are conditional tags, in other words, they only show their body content if the condition is true. Mentawai offers you some really easy base classes from where you can code your own conditional tags.


Field Errors

Some web application error messages may be associated with a form field. In a HTML form, it is nice to show an error message next to the form field it relates to. So the class BaseAction has a special addError() method that accepts a field name as a parameter.

	addError("username", USERNAME_MISSING_ERROR);
	
	// or if you are defining your own MessageContext
	addError("username", USERNAME_MISSING_ERROR, MSG_CONTEXT);
	

Then you can use the <mtw:error /> tag with a field attribute to look for a field error.

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

New Tags in vs.1.0.1

<!-- Gets the first message -->
<mtw:outMessage>
<h3><mtw:out /></h3>
</mtw:outMessage>
    
<!-- List all messages -->
<mtw:outMessages>
<mtw:loop>
<h3><mtw:out /></h3>
</mtw:loop>
</mtw:outMessages>
    
<!-- Gets the first non-field error -->
<mtw:outError>
<h4><mtw:out /></h4>
</mtw:outError>

<!-- Gets a field error -->
<mtw:outError field="username">
<h4><mtw:out /></h4>
</mtw:outError>

<!-- List all non-field errors -->
<mtw:outErrors>
<mtw:loop>
<h3><mtw:out /></h3>
</mtw:loop>
</mtw:outErrors>

<!-- List all field errors -->
<mtw:outFieldErrors>
<mtw:loop>
<h3><mtw:out /></h3>
</mtw:loop>
</mtw:outFieldErrors>