Last Updates | Login      

Turning any method from any POJO into an action (POJO Actions)

With Mentawai you can use any java class (POJO) as an action. You can also call any method without any restriction. Check the examples below:


In the application manager you just register the POJO action as you would register any other action:


The action input parameters will be sorted in alphabetical order. However, if you want to explicit determine what values will be used as the method parameters, you can setup a MethodParamFilter. For example, let's say you have the following request:

http://www.mysite.com/HelloPojo.mtw?a=23&a=3&b=5&x=9&y=4

If you want to make sure the method addTwoNumbers take the action input values x and y, and not a and b, which is the default because a and b come first in alphabetical order, then all you have to do inside your application manager is:


Accessing the action context from a POJO action

With Mentawai you can code simple POJO actions that have ZERO coupling with the framework.

The action context I am talking about is: Application, Session, Input, Output, Cookies, Locale, Headers, Method (POST or GET), Messages, Errors and Field Errors. For each one of these, there is a filter that you can use to inject a corresponding value or data structure inside your model.

Here is an example of all these filters:


Now, inside you POJO action, you can do this:


Feel free to add all these filters to your application, even if your actions do not need all of them. That's because these filters are all PULL filters, in other words, the objects are instantiated and injected if and only if the Actions have them as properties.

Another option is to use the ActionContextFilter that can place a single Map with everything. Take a look:


Now inside your action you can do:


Note that your action is completely decoupled from any framework class.

Using search-engine-friendly URLs

You can use the org.mentawai.core.PrettyURLController instead of the org.mentawai.core.Controller.

Instead of having:

http://www.mysite.com/MyContext/Topic.show.mtw?id=233&title=Welcome+to+Mentawai

http://www.mysite.com/MyContext/Topic.mtw?id=233&title=Welcome+to+Mentawai

You can have:

http://www.mysite.com/MyContext/mtw/Topic.show/233/Welcome-to-Mentawai

http://www.mysite.com/MyContext/mtw/Topic/233/Welcome-to-Mentawai

Note that you are losing the parameter names and that now you have mtw/ in front of every action URL.

The mtw/ is necessary so that you can correctly map the request to the controller in the web.xml file. Notice that we are using the PrettyURLController in the web.xml file:

OBS: If you don't want to have the mtw prefix you can map your actions some other way, like for example /Users/*.


Keep in mind that the parameters will be placed in the action input with the names "0", "1", "2", etc. So to get the parameters you should do:


Last but not least, you can use the PrettyURLParamFilter to give names to the parameters:


With the PrettyURLParamFilter, you can make any web application use the PrettyURLController without the need to change/migrate any action code.

And also feel free to use the old URL format (http://www.mysite.com/UserAction.show.mtw?id=23&category=34) with the new controller. It will just work! Just make sure you keep the *.mtw configured in the web.xml.

Using conventions for the view layer

Mentawai, by default, supports the following convention for the view layer:


Because we did not define any consequence for the HelloAction, the consequence used by default will be a forward to /HelloAction/sayHello.jsp, no matter what result (SUCCESS, ERROR, etc.) the action returns.

You can also use more conventions to simplify the configuration above to:


The name of the action will the the name of the class (HelloAction) and you don't need to specify the method name (inner action) unless you want to create a configuration specific for that method.

And you don't even need to specify each and every action you will use in the application manager. Let's say your actions are distributed across the packages com.mysite.actions and com.mysite.actions.user, then you can just do this:


And last but not least, you can create your on conventions by implementing the ConsequenceProvider interface:


Then you can set it up in the application manager like this:


And don't forget you can always configure your actions by hand:


Automatic pagination through the PaginatorFilter

You may have an action that fetches a long list of objects from the database. So you will need to paginate this big collection. The PaginatorFilter will do this for you:

Action:


And in the ApplicationManager:


The default number of items per page is 20 and the default page parameter (http://www.mysite.com.br/UserAction.listAll.mtw?p=3) is "p". You can change that using a different PaginatorFilter constructor:


Now in your JSP you can just display your page with the pagination details:


Turning FORM data into POJOs and POJOs into FORM data

Let's say you have a HTML form sending username, email, password, age, etc. and you want to build a User object out of these form parameters. Just use the VOFilter and all the values from the action input will be used to create a new User object.

In the ApplicationManager:


That's it! Mentawai tries the best it can to convert and inject all the values in the action input inside a new User object. Then inside your action you can just do:


Or if you don't want to use the VOFilter you can use the input.getObject method. This method also allows you to pass an already created User object.


Now to turn a POJO into FORM data you can use the OVFilter, that does the opposite of the VOFilter: It gets all properties from a POJO and place them in the action output so they can be easily displayed inside an HTML FORM.

In the ApplicationManager:


The POJO will come from the action output with the key "user". Then all its properties will be extracted and placed in the action output.

In your JSP page, just use the Mentawai form tags so that the values will appear automatically for you to edit:


Actually you don't need the OVFilter. If you only have the User object in the action output, you can use the mtw:bean tag to place a bean in the page context:


Another way to do the same thing is:


Ajax List of Beans and Relationships

On MentaAjax 2.0 and above

Example with List of Beans and Relationships.

People class


Address class


Action:


ApplicationManager:


The int parameter on JSONGenericRenderer(1) , says to renderer that you want to load one relantionship.

JSP:


The line 17 is optional, if you dont specify the onSuccess method, the convention is to call a function with the same name of innerAction. In this axample the innerAction is TestAction.getListBean.mtw

Ajax update area

Action:


ApplicationManager:


JSP:


Global Lists

A global list is a list that does not change very often and is the same for all users in a web application.

Examples: list of genders, list of cities, list of age ranges, list of browsers, list of interests, list of month, etc.

A list can come from a file or from a database. Although not very recommended, you can also hardcode the list inside the your ApplicationManager.java.

Coming from a file in the default directory /lists: (genders_en_US.i18n)


That's it! Now you can use the mtw:select tag to display your list like this:


Or you can access your list through code:


When using internationalization, you will have a list for each locale (language). Let's add another file to the /lists directory: (genders_pt_BR.i18n)


The mtw:select tag will automatically pick the right list for you, depending on the user locale. Using code you could do this now:


When using the mtw:out tag, you can just pass the list to print a value from the list:


Assuming that user.getGender() returns an id from the list, Mentawai will pick up the element from the "genders" list from the user locale.

You can also load a list from the database in the ApplicationManager, for example:


Now if you don't have the locale column in your database and you want to load a single non-localized ListData, then you can just remove the locale column name from the constructor:


If you are lazy or if your list is so small that you don't care much, you can hardcode the list items inside the ApplicationManager:


If your list is localized, you can use the the LocalizedListData:


Action returning a binary content (image, pdf, etc.)

Just use the StreamConsequence.

In the action:


In the ApplicationManager:


You can place a byte array or a InputStream as the stream key in the action output. If for example the file is a PDF, you don't want to load everything in memory in a byte array:


An in the ApplicationManager:


Sending emails with a velocity template

First get the velocity-dep-1.4.jar file that comes with Mentawai in the lib directory and place it inside the WEB-INF/lib directory of your web application.

Now use the following code inside your action:


The default directory to look for letters is /letters and for each locale you create a directory, for example:


The correct file will be loaded depending on the user locale, and the attributes will be replaced by a velocity template. You hello.html file might look like this:


Your HTML file will be treated as a velocity template, so you can use any velocity feature you want inside it.

Sending simple emails

First get the mail.jar and activation.jar that comes in the Mentawai lib directory and place them in the WEB-INF/lib directory of your web application.

Set some default values in the ApplicationManager so that you don't need to set them each time you want to send an e-mail message. Of course you can always override the default values if you want to.


Now to send an email message you just do this:


Or you can send an HTML e-mail message:


Displaying application exceptions in a nice way

You can use the ExceptionFilter as a global filter for that. Just set it up in the front of all other filters, so it will trap any exceptions that happen after him:


After placing some info about the exception in the action output, the ExceptionFilter returns the EXCEPTION result. Therefore you should define a global consequence that will be a forward to the page designed to exception and perhaps a sorry message to the user:


Now in the error.jsp page, you can get the following values from the action output:


Validation through the Validatable interface

You can set the ValidatorFilter as a global filter so that all actions that implement the Validatable interface will be validated.


And the internationalized messages would be inside the /validation/MyAction_loc.i18n file, where loc is the locale (ex: MyAction_en_US.i18n). OBS: If you are using a master i18n file through LocaleManager.useMasterI18N(true), then your messages will be inside the /i18n/master_en_US.i18n.


Now if you don't want to put your messages in a separate file, then you can just hardcode your messages:


Now to display your message in the JSP, you can use the menta tag. You can choose from mtw:hasError and mtw:outError tag.


Note that this tags are conditional tags, in other words, nothing will be shown if there is no error for the field.

To add the ValidatorFilter as a global filter in the application manager you can just do that:


TIP: Use the Mentawai HTML form tags mtw:input, mtw:select, etc. so you don't have to worry about re-displaying the values that the user typed in case of validation error. We know you don't want to place a bunch of scriptlets in your JSPs to do this.

Validation through a separate filter


And the internationalized messages would be inside the /validation/HelloValidator_loc.i18n file, where loc is the locale (ex: HelloValidator_en_US.i18n). OBS: If you are using a master i18n file through LocaleManager.useMasterI18N(true), then your messages will be inside the /i18n/master_en_US.i18n.


Now if you don't want to put your messages in a separate file, then you can just hardcode your messages:


Now to display your message in the JSP, you can use the menta tag. You can choose from mtw:hasError and mtw:outError tag.


Note that this tags are conditional tags, in other words, nothing will be shown if there is no error for the field.

To add the HelloValidator as an action specific filter inside your application manager, you can just do this:


TIP: Use the Mentawai HTML form tags mtw:input, mtw:select, etc. so you don't have to worry about re-displaying the values that the user typed in case of validation error. We know you don't want to place a bunch of scriptlets in your JSPs to do this.