Last Updates | Login      

Choosing consequences for handling different outputs

Mentawai has the concept of Consequence, also known as Resolver in other frameworks like Spring MVC.

Basically, depending on the RESULT of an Action you can trigger the appropriate CONSEQUENCE.

The most common consequences are FORWARD to a JSP or REDIRECT to an URL:


Now we talk about consequences for other types of output:

1) AJAX consequence generating JSON:

Action:


Configuration:


2) Streaming binary (images, pdf or anything):

Action:


Configuration:


Easy internationalization (i18n)

OBS: Mentawai i18n files are auto-reloadable, in other words, from time to time the file is checked for modifications. If it was modified it is reloaded. That means you do NOT have to restart your web container each time you change some text inside your i18n file.

When the user is authenticated, you set his locale:


Then all you have to do is create a directory i18n and place one file per language in there. Example:

/i18n/master_en_US.i18n


/i18n/master_es_ES.i18n


Then in the JSP you can do:


To better organize your text file you can use prefixes. Example:

/i18n/master_en_US.i18n


/i18n/master_es_ES.i18n


Then in the JSP you do:


If you have a text that is global, for example, the title of all pages, you can skip the prefix by doing:

/i18n/master_en_US.i18n


/i18n/master_es_ES.i18n


An in the JSP:


And there is much more:

You can have localized texts inside your actions.

If the user is not logged, you can pick a locale based on browser request, cookie, etc.

You can use placeholders to help the designer:


You can configure what to do if the key is not found: show the default locale translation or show the key with exclamation marks around it so someone can spot the problem and fix it. (good for QA)

Authenticating your users

LoginAction.java: (extends BaseLoginAction from Mentawai)


Protecting the access to our actions by users not authenticated:

In the ApplicationManager.java:


If the user is not authenticated, the AuthenticationFilter will return LOGIN as the result and the redirect consequence to /login.jsp will be executed.

Protecting the access to our JSP pages by users not authenticated:


Same thing here: The browser will be redirected to the page configured for the LOGIN result if the user is not authenticated.

Some actions cannot be blocked, for example RegistrationAction, PasswordRecoveryAction, HelpAction, etc. They can implement the AuthenticationFree interface:


For the logout, just use the LogoutAction that comes with Mentawai. The user session object will be removed from the session and the session will be reset (invalidated):


Last but not least, you can use some Mentawai tags to make your job even easier:


Easy Authorization with groups

An authenticated user can belong to one or more groups. All you have to do is:


Now to protect access to an action you can do:


The AuthorizationFilter returns the result ACCESSDENIED if the current authenticated user does not belong to the admin group. Then a global consequence can redirect to a page or throw an exception.

And how to protect access to an JSP page

1) Blocking access to a page:


2) Block access to a portion of the page:


Mentawai also supports authorization by permissions. For more info see here: http://www.mentaframework.org/authorization.jsp

Easy Authentication

After checking username and password, in any way you want, you decide that your user is authenticated. So you do:


Now if you use the AuthenticationFilter as a global filter, all access to your actions will only be allowed if the user is authenticated, in other words, if you called the method above for the current session. If not the LOGIN result is returned and you can redirect for the login page.


Now, some actions need to bypass authentication. Example: the action for registration. All you have to do is implement te AuthenticationFree interface.


The LoginAction is another one that should not be authenticated. The org.mentawai.action.LoginAction implements AuthenticationFree as you might expect.

You blocked access to actions. Now it is time to block access to JSPs. You can use the simple tag:


That's it. Mentawai also supports redirect after login in a very simple way. See here: http://www.mentaframework.org/authentication.jsp

Dynamic/Ajax Combos with mtw:select tag

One recurrent problem is when you want to display a dynamic list, in other words, a list that depends on other field. One standard example is State and City where each State has its own list of Cities.

One possible approach to this problem is to add all 50 lists to ListManager, but that would not be a good solution because you would have to have a bunch of IFs in your JSP, like below:


This is awkward and will introduce other problems. For example when we first show the page and no state is selected, we must show an empty list.

Luckily there is a much better solution by using a Mentawai filter to create a dynamic list on the fly and place it in the action output. Remember that the mtw:select tag is smart enough to pick up lists straight from the action output, if it finds one.

Let's define the problem before we dive into the code. Below are the situations where we need to take action:

1) Empty form is being displayed to insert a new bean => List should be empty

2) Form is being redisplayed probably because of a validation error => List should be the same one when the used submitted the form, in other words, it should not lose its state when a validation error occurs.

3) Form is being used to EDIT a bean, in other words, a bean object was placed in the action output and a forward was performed to the JSP with the form => List should display the appropriate list corresponding to the bean State.

4) The user selected another State => List should be changed through Ajax (out of the scope of this recipe)

Here are the conditions for 1), 2) and 3):

1) Nothing is in the action input and nothing is in the action output => Form is being used to insert a bean and an empty list should be displayed.

2) The current State id is in the action input => A validation error occurred and you should use the State id to show the appropriate City list.

3) There is an object in the action output with a State id property => The object (bean) is being edited, so show the appropriate City list corresponding to this bean State id.

Below is a simple filter that I coded to address all these scenarios:


So now you can use a single mtw:select tag and your list will be filled appropriately according to the situation and the State id.


One last catch when setting the filter in the application manager: This filter should be executed *before* the ValidatorFilter which is a global filter that performs validation. That's because the ValidatorFilter aborts the execution chain if it finds an error and as we know global filters are executed before any action specific filter.

Luckily there is an easy way to place an action specific filter before all global filters. Just use the addFilterFirst() or filterFirst() method from ActionConfig.


In a web application project, you will probably have to code a filter like that for every dynamic list. To make this job easier, Mentawai 1.14 includes the org.mentawai.filter.DynamicListFilter that you can use to fast code these filters. See how we could have coded the filter above with this new abstract class:


Coding your application with no coupling (0%) with Mentawai

The Mentawai support for POJO actions, along with its powerful filters, allows you to code a web application totally decoupled from the Mentawai framework.

For a complete example, feel free to download both versions of the MyBooks application: (use the mybooks.sql file included in the zip to create your mybooks mysql database)

MyBooks-ACTION.zip - Action and Business Model are separated. Action is coupled to Mentawai. Business Model is not coupled.

MyBooks-POJO.zip - Action and Business Model are together in a single class totally decoupled from the Mentawai framework.

Take a look below:

ACTION version:

MyBooks-ACTION ApplicationManager.java


MyBooks-ACTION BookAction.java


MyBooks-ACTION BookService.java


Now the POJO version:

MyBooks-POJO ApplicationManager.java


MyBooks-POJO BookService.java