Mentawai Web Framework

Mensagens Dinâmicas

As mensagens dinâmicas são algo como:

  • "Seu perfil foi atualizado com sucesso!"
  • "Houve um erro ao tentar salvar seu perfil!"
  • "O email informado é inválido!"
  • "Por favor, preencha os campos abaixo:"
  • etc.

O Mentawai suporta mensagens dinâmicas facilmente, como você pode ver no exemplo abaixo. Você pode também clicar aqui para baixar um arquivo WAR com uma aplicação simples que mostra o uso de mensagens dinâmicas no Mentawai.

Um exemplo de uma ação que suporta mensagens dinâmicas:

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;
	}
	
}
	

Os métodos addMessage() e addError() são fornecidos pela BaseAction e podem ser usados para adicionar mensagens e erros a uma ação (action). Você define uma mensagen com um número ou string que será usado como chave para a mensagem no arquivo i18n.

Por padrão, o Mentawai procura pelo arquivo i18n de mensagens no diretório /messages da pasta raiz da sua aplicação web. Também por padrão, o arquivo i18n tem o mesmo nome da classe da action. Então para o exemplo acima, as mensagens estarão em um arquivo /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!
	

Mensagens não-localizadas

Você também pode criar mensagens não-localizadas, caso você não queira trabalhar com internacionalização. Para isso, basta apenas escrever a própria mensagem no lugar da chave da mensagem. Isso é possível porque o Mentawai mostrará a chave se ela não puder ser encontrada no arquivo i18n ou mesmo se o arquvio i18n não exitir. Veja o exemplo abaixo:

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;
	}
	
}
	

Usando o master

Caso você prefira manter todas as suas mensagens de erro em um arquivo apenas (arquivo master), você pode ativar essa opção através do método abaixo. Uma vez ativada, essa opção fará com que todas as mensagens internacionalizadas sejam buscadas dentro do arquivo /i18n/master_loc.i18n, onde loc é o locale (idioma, ex: pt_BR) do arquivo em questão.

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

Você também pode alterar a localização do arquivo master usando o método abaixo:

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

Mais Controle

O Mentawai procura por mensagens em um MessageContext. Esta classe encapsula um arquivo i18n com as mensagens definidas para cada locale. O Mentawai já vem com duas implementações úteis de um MessageContext

  • ClassMessageContext: usa o nome da classe para encontrar o arquivo i18n. Então, se você passar como parâmetro a classe HelloMentawai.class, o context irá procurar pelo arquivo HelloMentawai_loc.i18n, onde loc é o locale (idioma) do arquivo em questão. (note que pacote da classe não é levado em consideração!)


  • FileMessageContext: permite você especificar o nome exato do arquivo i18n. (veja a documentação API para mais detalhes)

Por padrão, um MessageContext usa o diretório /messages na pasta raiz para procurar por arquivos i18n. Para mudar esse diretório, você pode usar um construtor especial das classes ClassMessageContext e FileMessageContext que permite que você defina este diretório. (consulte a documentação API para mais detalhes)

É importante notar que, caso você julgue necessário, o que achamos não ser o caso aqui, nada impede que você estenda estas classes para criar seu próprio MessageContext. O Mentawai fornece uma classe base AbstractMessageContext para facilitar esse trabalho.

Veja um exemplo de uma action que define seu MessageContext:

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

Estamos suportando dois locales em nossos arquivos i18n: pt_BR e en_US, então, devemos informar isso no nosso ApplicationManager: (veja a seção Internacionalização para mais detalhes)

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"));
	}
}
	

A Camada View

Para mostrar essas mensagens na camada view, você pode usar algumas tags úteis do Mentawai:

O arquivo username.jsp com suporte a uma mensagem de erro:

<%@ 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>	
	

O arquivo hello.jsp com suporte a uma mensagem de sucesso:

<%@ 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>
	

As tags <mtw:hasMessage> e <mtw:hasError> são tags condicionais, em outras palavras, elas apenas mostram o conteúdo de seu body se a condicional for verdadeira. Com o Mentawai é muito simples criar suas próprias tags condicionais, bastando para tal estender a classe org.mentawai.tag.util.ConditionalTag.


Campos de Erro

Algumas mensagens de erro da sua aplicação web podem estar associadas com um campo de formulário. Em um formulário HTML, é interessante mostrar uma mensagem de erro próxima ao campo ao qual a mensagem se refere. Assim, a classe BaseAction tem um método especial addError() que aceita um nome de campo como parâmetro.

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

Então você pode usar a tag <mtw:error /> com um atributo de campo para buscar um erro de campo.

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

Novas tags na versão 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>