<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title><![CDATA[Latest topics for the forum "Mentawai Architecture"]]></title>
		<link>http://book.mentaframework.org/forums/show/3.page</link>
		<description><![CDATA[The newest discussed topics in the forum "Mentawai Architecture"]]></description>
		<generator>JForum - http://www.jforum.net</generator>
			<item>
				<title>Conclusion</title>
				<description><![CDATA[ In this chapter we discussed about the Mentawai architecture and its main interfaces like [i]Action, Input, Output, Context, Filter, Consequence[/i], etc. You learned how filters work and how to create your own filters. You also learned about inner actions and how to configure your actions inside the application manager. You were also introduced to the Mentawai Debug Mode, that can show you everything that is happening under the hood inside the action invocation chain.<br /> <br /> You also saw the main consequences of any web application: Forward and Redirect. You were also introduced to the Chain, Stream and Ajax consequences.<br /> <br /> Now it is time to dive into the many Mentawai features. Remember that one of the goals of the Mentawai framework is to abstract all the repetitive tasks of any web project. Stuff like Validation, Authentication, Form Handling, Sending Email, etc. are boring and repetitive, so the framework has to offer you a very simple and intuitive way of dealing with that. With Mentawai you should never waste time re-inventing the wheel. It tries to do all the boring work for you so you can have fun getting your project done and making your boss happy.]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/21/22.page</guid>
				<link>http://book.mentaframework.org/posts/preList/21/22.page</link>
				<pubDate><![CDATA[Mon, 14 Jan 2008 09:42:08]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Consequences (Forward, Redirect, Chain, Stream, etc.)</title>
				<description><![CDATA[ [color=blue][size=18][b]Forwarding to JSP pages[/b][/size][/color]<br /> <br /> The basic and most common consequence you will use in your web projects is the [b]Forward[/b]. In Mentawai, this is the [i]org.mentawai.core.Forward[/i] class, which implements the [i]org.mentawai.core.Consequence[/i] interface. The interesting aspects about a forward are listed below:<br /> <br /> :arrow: A forward always happens in the server-side, in other words, the client (the browser) does not realize that a forward is happening. For example, if you make a call to the action http://www.mysite.com/Hello.mtw and the result of the action [i]Hello.class[/i] is a forward to /hello.jsp, [b]the location in the address bar of your browser will not change[/b] to /hello.jsp. That's because the forward is really happening on the server-side. No other request is needed from the browser. The request is passed over to the JSP page and the result is returned in the same request that asked for the [i]Hello [/i]action. This is exactly the opposite of what happens when you do a Redirect.<br /> <br /> :arrow: A forward will always pass the action and all its contexts ([i]Input[/i], [i]Output[/i], [i]Session[/i], [i]Cookies[/i], etc.) to the JSP page. When you do a forward, the results of the action execution are made available to the JSP page. This is the opposite of what happens when you do a Redirect. When you do a redirect, a new request is done by the browser to a new action or JSP page. All the previous action information before the redirect is discarded.<br /> <br /> The classic scenario is: <br /> <ul>WebRequest    ---------&gt;    Action generates some results    ----------&gt;    Forward to JSP to display the results</ul><br /> For example for the simple action below you can configure some forwards:<br /> <br /> [code]<br /> public class HelloAction extends BaseAction {<br /> <br />     public String sayHi() {<br />  <br />         output.setValue("message", "Hi there!");<br /> <br />         return SUCCESS;<br />     }<br /> <br />     public String sayHello() {<br />  <br />         output.setValue("message", "Hello there!");<br /> <br />         return SUCCESS;<br />     }<br /> }<br /> [/code]<br /> <br /> Inside the application manager:<br /> <br /> [code]<br /> <br /> public void loadAction() {<br /> <br />     action(HelloAction.class)<br />         .on(SUCCESS, "sayHi", new Forward("/hi.jsp"))<br />         .on(SUCCESS, "sayHello", fwd("/hello.jsp"));<br /> <br />     // OR<br /> <br />     ActionConfig ac = new ActionConfig(HelloAction.class);<br />     ac.addConsequence(SUCCESS, "sayHi", new Forward("/hi.jsp"));<br />     ac.addConsequence(SUCCESS, "sayHello", fwd("hello.jsp"));<br />     addActionConfig(ac);  <br />   <br /> }<br /> [/code]<br /> <br /> Just keep in mind that whenever you want the [b]action information to be displayed in the JSP page[/b] you will most likely want a [b]Forward[/b] consequence. Another point to keep in mind is that if the user hits the [i]Reload [/i]button in the browser, the whole action is executed again.<br /> <br /> <br /> [color=blue][size=18][b]Redirecting to a new URL[/b][/size][/color]<br /> <br /> In Mentawai, the Redirect consequence is implemented by the core class [i]org.mentawai.core.Redirect[/i], which implements the core interface [i]org.mentawai.core.Consequence[/i]. When you issue a Redirect consequence, you are really telling the browser: "[i]Hey! Please do another web request to the this URL here![/i]". As a result, the URL location in the address bar of the browser will change to the redirect URL and all the information about the action that performed the redirect will be discarded.<br /> <br /> Contrary to the Forward, a Redirect happens in the client-side, in other words, it is the browser that performs another web request to the JSP page or action. You could use a redirect, for example, when you want to avoid having the user accidentally hitting the [i]reload [/i]button and executing the action again.<br /> <br /> There are many ways to a redirect in Mentawai. Below I will explain each one:<br /> <br /> :arrow: [b][color=blue]Regular redirect[/color][/b]<br /> <br /> This is the redirect you will be using 99% of the time and it is [b]always related to the [i]context path [/i]of your web application[/b]. The [i]context path[/i] is the directory where your application is located inside the Tomcat [i]webapps [/i]directory. It is what allows the same Tomcat to run a bunch of different web applications together and independently.<br /> <br /> Below are some examples:<br /> [code]<br />     on(SUCCESS, redir("/congrats.jsp"));<br /> <br />     addConsequence(JSP, new Redirect("/user/users.jsp"));<br /> [/code]<br /> The first redirect will tell the browser to perform another web request to the following URL:<br /> <br /> http://www.mysite.com/DVDStore/congrats.jsp<br /> <br /> The second redirect will tell the browser to perform another web request to the following URL:<br /> <br /> http://www.mysite.com/DVDStore/user/users.jsp<br /> <br /> This is assuming that your context path is "DVDStore". If your context path was the [i]ROOT context path[/i], which is the [i]ROOT [/i]directory inside the Tomcat [i]webapps [/i]directory, your redirect URLs would be:<br /> <br /> http://www.mysite.com/congrats.jsp<br /> <br /> http://www.mysite.com/user/users.jsp<br /> <br /> <br /> :arrow: [b][color=blue]Redirect relative to the web server[/color][/b]<br /> <br /> You can use this redirect when you want to perform a redirect [b]to another web application running in the same web server[/b]. For example:<br /> [code]<br />     on(SUCESS, redir("//BookStore/showBooks.mtw"));<br /> <br />     on(JSP, redir("//index.jsp"));<br /> [/code]<br /> When you start the redirect with a double slash ("//"), you are just saying: "Hey, I don't want to be relative to the context path!" Therefore, even if you context path is "DVDStore", the resulting redirect URLs for the examples above will be:<br /> <br /> http://www.mysite.com/BookStore/showBooks.mtw<br /> <br /> http://www.mysite.com/index.jsp<br /> <br /> This type of redirect is rare. It is only needed when you are running two different applications in the same servlet container that are somehow related to each other.<br /> <br /> <br /> :arrow: [b][color=blue]Redirect with dynamic parameters[/color][/b]<br /> <br /> Sometimes you want to perform a redirect, but you will only know the parameters of the URL at runtime. For example, you want to redirect the browser to the action that shows all the books for a certain category. This could be something like:<br /> <br /> http://www.mysite.com/BookStore/Book.show.mtw?cat=&lt;CATEGORY_ID&gt;<br /> <br /> To setup this redirect with a dynamic parameter, you can do this:<br /> [code]<br />     .on(SUCCESS, redir("/Book.show.mtw", true));<br /> [/code]<br /> The true above indicates that this is a redirect with dynamic parameters that will come from the action output. So our action will just do something like this:<br /> [code]<br /> public class BookAction extends BaseAction {<br /> <br />     public String add() {<br /> <br />         // add a new book to the database somehow...<br /> <br />         output.setValue("cat", book.getCategory());<br /> <br />         return SUCCESS;<br />     }<br /> }<br /> [/code]<br /> Assuming that book.getCategory() returns 43, the resulting URL would be:<br /> <br /> http://www.mysite.com/BookStore/Bood.show.mtw?cat=43<br /> <br /> Note that all the values from the action output will be added as parameters to the redirect URL.<br /> <br /> <br /> :arrow: [b][color=blue]Redirect to a dynamic URL[/color][/b]<br /> <br /> Sometimes you will not even know the URL you want to redirect to. This is rare, but can happen, for example, when you want to redirect your user to a URL saved in a database. Here is how it works:<br /> [code]<br />     on(SUCCESS, redir());<br />   <br />     on(JSP, new Redirect());<br /> [/code]<br /> When you create a redirect using the constructor with empty parameters (or make use of the helper method redir() with empty parameters), the redirect will expect the URL to come from the action output. Here is an example of an action:<br /> [code]<br /> public class BookmarkAction extends BaseAction {<br /> <br />     public String go() {<br /> <br />         // get the URL from the database<br /> <br />         String url = "http://www.mentaframework.org";<br /> <br />         output.setValue(Redirect.REDIRURL_PARAM, url);<br />     }<br /> }<br /> [/code]<br /> Note that you are using the REDIRURL_PARAM from the Redirect consequence to place the dynamic URL inside the action output. You may have other values inside the action output and that's how the redirect class knows how to find the dynamic URL.<br /> <br /> <br /> Last but not least about the Redirect consequence:<br /> <br /> :arrow: If you redirect contains the string "://" inside it, it is assumed that you want to do a redirect to a absolute address. Examples:<br /> [code]<br />     on(SUCCESS, redir("http://www.cnn.com"));<br /> <br />     on(FTP, redir("https://www.safe.com"));<br /> [/code]<br /> The redirect understands that the above redirect are all absolute URLs, not relative to anything.<br /> <br /> :arrow: There are no redirects relative to the request<br /> <br /> This is on purpose. If you try to do something like [i]on(SUCCESS, redir("[b]loosepage.jsp[/b]"))[/i], Mentawai will automatically assume that you meant [i]on(SUCCESS, redir("[b]/loosepage.jsp[/b]"))[/i]. Redirects relative to the request are not needed and only introduce confusion.<br /> <br /> :arrow: You can also use a dynamic URL with dynamic parameters. Below is how to configure this redirect in the application manager:<br /> [code]<br />     on(SUCCESS, redir(true));<br /> <br />     on(SUCCESS, new Redirect(true));<br /> [/code]<br /> :arrow: Dynamic parameters will be automatically encoded. Dynamic URLs will not be encoded, in other words, if they have any hardcoded parameter it is assumed that it is already encoded.<br /> <br /> <br /> [color=blue][size=18][b]Chaining actions[/b][/size][/color]<br /> <br /> For a single web request you can chain different actions in the server-side before invoking a consequence that will return a result to the browser. For example you can have a request handled by action A chained to action B chained to action C and then action C returns a result that will invoke a consequence. You should note that like a forward, chaining actions happens in the server-side. Below is an example of how to configure a chain consequence:<br /> [code]<br /> @Override<br /> public void loadActions() {<br /> 		<br />     ActionConfig helloAction = new ActionConfig(HelloAction.class, "hello");<br /> 	ac2.addConsequence(SUCCESS, new Forward("/show.jsp"));<br /> 	addActionConfig(helloAction);<br /> 		<br /> 	ActionConfig ac = new ActionConfig(HiAction.class, "hi");<br /> 	ac.addConsequence(SUCCESS, new Chain(helloAction));<br /> 	addActionConfig(ac);<br /> }<br /> [/code]<br /> Or you can use the less verbose style:<br /> [code]<br /> @Override<br /> public void loadActions() {<br /> 		<br />     ActionConfig helloAction = action(HelloAction.class, "hello")<br /> 	    .on(SUCCESS, fwd("/show.jsp"));<br /> 		<br />     action(HiAction.class, "hi")<br /> 	    on(SUCCESS, chain(helloAction));<br /> }<br /> [/code]<br /> Before you configure any chain consequence, you must understand that [b]action chaining is rare and in most cases there is no need for you to make use of it[/b]. Let's take a classic example where you have an action that adds an user and another action that lists all the users. You may get tempted to do a chain like:<br /> [code]<br /> ActionConfig showAction = action(User.class, "show")<br />     .on(SUCESS, fwd("/show.jsp"));<br />     <br /> action(User.class, "add")<br />     .on(SHOW, chain(showAction))<br />     .on(ERROR, fwd("/addUser.jsp"));<br /> [/code]<br /> Although definitely not a sin, this could have been done much better with a redirect consequence:<br /> [code]<br /> action(User.class, "show")<br />     .on(SUCESS, fwd("/show.jsp"));<br />     <br /> action(User.class, "add")<br />     .on(SHOW, redir("/User.show.mtw", true) // true = dynamic parameters<br />     .on(ERROR, fwd("/addUser.jsp"));<br /> [/code]<br /> So now after the [i]add[/i] inner action is done, it will redirect (not chain) to the show inner action. <u>If the user hits the reload button, only the show inner action will be executed again, and not the whole chain.</u> Note that we are supporting dynamic parameters for the redirect, that's because we may need to add some parameters to the URL before redirecting, for example:<br /> <br /> http://www.mysite.com/User.add.mtw?category=34<br /> <br /> As we saw in the previous chapter about redirect, these parameters will come from the action output.<br /> <br /> To conclude, here is what you should keep in mind when using a chain consequence:<br /> <br /> :arrow: Think if you don't really want a redirect to an action instead of a chain. The question you should ask yourself is: [i]Do you want to execute everything again if the user press the reload button?[/i]<br /> <br /> :arrow: When two actions are chained, the input and output of the first are passed to the second.<br /> <br /> :arrow: Each action will be executed with its own set of filters. If we have a global filter, then it will be executed twice, one time for each action.<br /> <br /> :arrow: You can also pass an inner action to the chain controller: <br /> [code] <br /> ac.addConsequence(SHOW, new Chain(helloAction, "hello"));<br /> <br /> on(SHOW, chain(helloAction, "hello"));<br /> [/code]<br /> <br /> [color=blue][size=18][b]Other consequences[/b][/size][/color]<br /> <br /> Mentawai comes with other consequences and you can also code your own consequences. For example, to return an image or a binary file you can use the [i]StreamConsequence[/i]:<br /> <br /> In the action:<br /> [code]<br /> public class ImageAction extends BaseAction {<br />     <br />     public String execute() {<br />         <br />         byte[] image = getImageBytesSomehow();<br />         <br />         output.setValue(StreamConsequence.STREAM_KEY, image);<br />         output.setValue(StreamConsequence.CONTENT_LENGTH_KEY, image.length);<br />         <br />         return SUCCESS;<br />     }<br /> }<br /> [/code]<br /> In the [i]ApplicationManager[/i]:<br /> [code]<br /> public void loadActions() {<br />     <br />     action(ImageAction.class)<br />         .on(SUCCESS, stream("image/jpg"));<br />         <br />     // or<br />     <br />     ActionConfig ac = new ActionConfig(ImageAction.class);<br />     ac.addConsequence(SUCCESS, new StreamConsequence("image/jpg"));<br />     addActionConfig(ac);<br /> }<br /> [/code]<br /> You can place a byte array or a [i]InputStream [/i]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:<br /> [code]<br /> public class PDFAction extends BaseAction {<br />     <br />     public String execute() {<br />         <br />         FileInputStream fis = new FileInputStream("review.pdf");<br />         <br />         output.setValue(StreamConsequence.STREAM_KEY, fis);<br />         output.setValue(StreamConsequence.FILENAME_KEY, "review.pdf");<br />         // InpuStream has no size...<br />         <br />         return SUCCESS;<br />     }<br /> }<br /> [/code]<br /> An in the ApplicationManager:<br /> [code]<br /> public void loadActions() {<br />     <br />     action(PDFAction.class)<br />         .on(SUCCESS, stream("application/pdf"));<br />         <br />     // or<br />     <br />     ActionConfig ac = new ActionConfig(PDFAction.class);<br />     ac.addConsequence(SUCCESS, new StreamConsequence("application/pdf"));<br />     addActionConfig(ac);<br /> }<br /> [/code]<br /> For Ajax, you can use the [i]AjaxConsequence [/i]that uses a renderer to format the action response into an ajax response (JSON, XML, etc.)<br /> <br /> Action:<br /> [code]<br /> public class TestAction extends BaseAction {<br /> <br /> 	public String autoCompleter() {<br /> <br /> 		String sourceInput = input.getStringValue("sourceInput");<br /> <br /> 		Map&lt;Integer, String&gt; map = new LinkedHashMap&lt;Integer, String&gt;();<br /> <br /> 		if(sourceInput.startsWith("a")) {<br /> <br /> 			map.put(1, "a. Somebody with id 1");<br /> 			map.put(2, "a. Somebody with id 2");<br /> 			map.put(3, "a. Somebody with id 3");<br /> <br /> 		} else if(sourceInput.startsWith("b")) {<br /> <br /> 			map.put(4, "b. Somebody with id 4");<br /> 			map.put(5, "b. Somebody with id 5");<br /> 			map.put(6, "b. Somebody with id 6");<br /> <br /> 		} else {<br /> <br /> 			map.put(7, "*. Somebody with id 7");<br /> 			map.put(8, "*. Somebody with id 8");<br /> 			map.put(9, "*. Somebody with id 9");<br /> 		}<br /> <br /> 		output.setValue(AjaxConsequence.KEY, map);<br /> 		<br /> 		return SUCCESS;<br /> 	}<br /> <br /> }<br /> [/code]<br /> ApplicationManager:<br /> [code]<br /> public void loadActions() {<br /> <br />       action(TestAction.class, "autoCompleter")<br />           .on(SUCCESS, new AjaxConsequence(new JSONGenericRenderer()));<br /> <br />      // or<br /> <br />       action(TestAction.class, "autoCompleter")<br />           .on(SUCCESS, ajax(new JSONGenericRenderer()));<br /> <br /> }<br /> [/code]]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/20/21.page</guid>
				<link>http://book.mentaframework.org/posts/preList/20/21.page</link>
				<pubDate><![CDATA[Mon, 14 Jan 2008 09:31:52]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Setting up actions</title>
				<description><![CDATA[ This chapter is important because it will show you all the ways you can use to setup your actions in the application manager. If you decide not to configure anything, then Mentawai will use its conventions, for example a request to http://www.mysite.com/HelloAction.hello.mtw will call the hello() method of the HelloAction class. The default consequence for the action will be a forward to the /HelloAction/hello.jsp.<br /> <br /> As we have discussed in earlier chapters, sometimes there is no way out and you have to configure your actions. This chapter will show you how to do it.<br /> <br /> [code]<br /> <br /> public class ApplicationManager extends org.mentawai.core.ApplicationManager {<br /> <br />     @Override<br />     public void loadActions() {<br />         <br />         // More verbose style...<br />         <br />         addGlobalFilter(new AuthenticationFilter());<br /> <br />         addGlobalConsequence(LOGIN, new Redirect("/login.jsp"));<br />         <br />         ActionConfig ac = new ActionConfig("/User", UserAction.class);<br />         ac.addFilter(new VOFilter("user", User.class);<br />         ac.addConsequence(SUCCESS, new Forward("/ok.jsp"));<br />         ac.addConsequence(JSP, new Redirect("/users.jsp"));<br />         <br />         addActionConfig(ac);<br />         <br />         // Less verbose style...<br />         <br />         filter(new AuthenticationFIlter());<br />         <br />         on(LOGIN, redir("/login.jsp"));<br />         <br />         action("/User", UserAction.class)<br />             .filter(new VOFilter("user", User.class))<br />             .on(SUCCESS, fwd("/ok.jsp"))<br />             .on(JSP, redir("/users.jsp"));<br />     }<br /> <br /> [/code]<br /> <br /> Note that we are adding a global filter that will be applied to all actions. We are also adding a filter specific to the action ([i]VOFilter[/i]). Two consequences (one for [i]JSP [/i]and one for [i]SUCCESS[/i]) and a global consequence for the result [i]LOGIN[/i] are being added as well.<br /> <br /> No inner action was specified, so by default this configuration will be considered for all inner actions inside UserAction.class. The following actions will be executed with the filters and consequences configured above:<br /> <br /> http://www.mysite.com/User.mtw<br /> http://www.mysite.com/User.add.mtw<br /> http://www.mysite.com/User.del.mtw<br /> <br /> Basically all inner actions inside the [i]UserAction [/i]class will have the configuration specified for the [i]UserAction[/i] class. Now let's get more specific.<br /> <br /> You can add consequences and filters specific for a single inner action. Let's add a filter and a consequence specific for the [i]add [/i]inner action, in other words, for requests to http://www.mysite.com/User.add.mtw:<br /> <br /> [code]<br />     @Override<br />     public void loadActions() {<br />         <br />         // More verbose style...<br />         <br />         addGlobalFilter(new AuthenticationFilter());<br /> <br />         addGlobalConsequence(LOGIN, new Redirect("/login.jsp"));<br />         <br />         ActionConfig ac = new ActionConfig("/User", UserAction.class);<br />         ac.addFilter(new VOFilter("user", User.class);<br />         ac.addConsequence(SUCCESS, new Forward("/ok.jsp"));<br />         ac.addConsequence(JSP, new Redirect("/users.jsp"));<br />         <br />         ac.addFilter(new AuthorizationFilter(new Permission("add")), "add");<br />         ac.addConsequence(SUCCESS, "add", new Forward("/add.jsp"));<br />         <br />         addActionConfig(ac);<br />         <br />         // Less verbose style...<br />         <br />         filter(new AuthenticationFIlter());<br />         <br />         on(LOGIN, redir("/login.jsp"));<br />         <br />         action("/User", UserAction.class)<br />             .filter(new VOFilter("user", User.class))<br />             .on(SUCCESS, fwd("/ok.jsp"))<br />             .on(JSP, redir("/users.jsp"))<br />             <br />             .filter(new AuthorizationFilter(new Permission("add")), "add")<br />             .on(SUCESS, "add", fwd("/add.jsp"));<br />     }<br /> [/code]<br /> <br /> So for our example, we will have the following filters being executed, in the following order:<br /> <br /> AuthenticationFilter -&gt; VOFilter -&gt; AuthorizationFilter -&gt; UserAction.add<br /> <br /> Note that global filters are always executed first, then comes the action specific filters, then comes the inner action specific filters.<br /> <br /> For consequences, the rule is simple:<br /> <br /> First try to get a consequence specific to the inner action. If not found, try to get a consequence specific to the action. If not found, try to get a global consequence. If still not found, go by the Mentawai conventions: forward to /User/add.jsp.<br /> <br /> You can get even more specific creating a whole [i]ActionConfig [/i]object just for the inner action you want to configure. The filters and consequences you define will be applied only for the inner action specified in the action config. Below is an example:<br /> <br /> [code]<br /> <br /> // More verbose style...<br /> <br /> ActionConfig ac = new ActionConfig("/User", UserAction.class, "add");<br /> <br /> ac.addFilter(new AuthorizationFilter(new Permission("add")));<br /> <br /> ac.addConsequence(SUCCESS, new Forward("/add.jsp"));<br /> <br /> // Less verbose style...<br /> <br /> action("/User", UserAction.class, "add")<br />     .filter(new AuthorizationFilter(new Permission("add")))<br />     .on(SUCCESS, fwd("/add.jsp"));<br /> [/code]<br /> <br /> You can play with the order of the filters with some methods like [i]ActionConfig.addFilterFirst()[/i], that will add a filter to be executed BEFORE the global filters. You can also make your action implement the [i]GlobalFilterFree [/i]interface, to signal to the controller that it does not want any global filters. And you can also add a global filter that will be executed LAST, in other words, after all other filters have been executed. This will be rare cases, when for some very particular scenario you need to take more control in the invocation chain of filters.<br /> <br /> Below are some examples of these rare methods:<br /> <br /> [code]<br /> <br /> // More verbose style...<br /> <br /> ac.addFilterFirst(new TheFirstFilter()); // before global filters<br /> <br /> addGlobalFilter(new TheLastFilter(), true); // true = LAST<br /> <br /> // Less verbose style...<br /> <br />     .filterFirst(new TheFirstFilter()) // before global filters...<br /> <br /> filterLast(new TheLastFilter()); // after all other filters...<br /> <br /> [/code]<br /> <br /> [code]<br /> <br /> <br /> public class UserAction extends BaseAction implements GlobalFilterFree {<br />     <br />     public String add() {<br />         <br />         // ...<br />     }<br />     <br />     public String execute() {<br />         <br />         // ...<br />     }<br />     <br />     public boolean isGlobalFilterFree(String innerAction) {<br />         <br />         if (innerActoin != null && innerAction.equals("add")) {<br />             <br />             return true;<br />         }<br />         <br />         return false;<br />     }<br /> }<br /> [/code]<br /> ]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/14/15.page</guid>
				<link>http://book.mentaframework.org/posts/preList/14/15.page</link>
				<pubDate><![CDATA[Sat, 5 Jan 2008 16:27:24]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Inner Actions</title>
				<description><![CDATA[ In Mentawai an action is a piece of code that gets executed when the Mentawai controller receives a HTTP request from the browser. As we have seen before, this can be a class that extends [i]BaseAction[/i], a class that implements [i]Action [/i]or any regular POJO ([i]Plain Old Java Object[/i]).<br /> <br /> By default, if you make a request to http://www.mysite.com/HelloAction.hello.mtw, the controller understands that you want to call the [i]hello()[/i] method of the [i]HelloAction [/i]class. You can also omit the method part, like in http://www.mysite.com/HelloAction.mtw and the controller assumes that you want to call the method [i]execute()[/i] from the [i]HelloAction [/i]class.<br /> <br /> Mentawai uses the term [i]inner action[/i] for the [i]hello()[/i] method. An action class such as [i]HelloAction.java[/i] can have many [i]inner actions[/i] inside it. These [i]inner actions[/i] are nothing more than the instance methods of the action class.<br /> <br /> For example, we may have an action class like this:<br /> <br /> [code]<br /> public class LoginAction extends BaseAction {<br /> <br />     public String execute() {<br /> <br />         // do something here...<br /> <br />         return SUCCESS;<br />     }<br /> }<br /> [/code]<br /> <br /> We say that the LoginAction has no inner actions. The LoginAction class is the action itself, in other words, you can call it with the following URL:<br /> <br /> http://www.mysite.com/LoginAction.mtw<br /> <br /> You can also call it like this, although it would not make much sense:<br /> <br /> http://www.mysite.com/LoginAction.execute.mtw<br /> <br /> Now we can add a new method to the LoginAction, in other words, we are adding an [i]inner action[/i] to the LoginAction class.<br /> <br /> [code]<br /> public class LoginAction extends BaseAction {<br /> <br />     public String execute() {<br /> <br />         // do something here...<br /> <br />         return SUCCESS;<br />     }<br /> <br />     public String sayHello() {<br /> <br />         output.setValue("hello", "Saying hi!");<br /> <br />         return SUCCESS;<br />     }<br /> }<br /> [/code]<br /> <br /> An now to call the inner action sayHello you would use the following URL:<br /> <br /> http://www.mentaframework.org/HelloAction.sayHello.mtw<br /> <br /> It is important to understand the inner action concept because some methods take a String as the [i]innerAction[/i] parameter. For example, we can make our action implement the Validatable interface, to setup some validation code:<br /> <br /> [code]<br /> public class LoginAction extends BaseAction implements Validatable {<br /> <br />     public String execute() {<br /> <br />         // do something here...<br /> <br />         return SUCCESS;<br />     }<br /> <br />     public String sayHello() {<br /> <br />         output.setValue("hello", "Saying hi!");<br /> <br />         return SUCCESS;<br />     }<br /> <br />     public void prepareValidator(Validator val, String innerAction) {<br /> <br />         if (innerAction == null) {<br /> <br />             // set up the validation for the execute method<br /> <br />         } else if (innerAction.equals("sayHello")) {<br /> <br />             // set up the validation for the sayHello method...<br /> <br />         }<br />     }<br /> }<br /> [/code]<br /> <br /> Note that for the execute method, we consider that there is no inner action, so the [i]innerAction [/i]is null and not "execute". The [i]execute()[/i] method is kind of the natural method of an action class, in other words, it is the method that gets executed when no inner action is specified in the request URL.<br /> <br /> The only way to get the [i]innerAction [/i] parameter to be equal to "execute" is to call the action with the following URL: http://www.mysite.com/HelloAction.execute.mtw, which does not make much sense. If you want to call the "execute" method, you should make a request like: http://www.mysite.com/HelloAction.mtw, and the [i]innerAction [/i]will be null.<br /> <br /> ]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/13/13.page</guid>
				<link>http://book.mentaframework.org/posts/preList/13/13.page</link>
				<pubDate><![CDATA[Fri, 4 Jan 2008 19:42:11]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Debug Mode</title>
				<description><![CDATA[ <br /> The Mentawai Debug Mode is an useful feature that lets you know and see what is happening when your action, together with all its filters, gets executed. As we saw in the previous chapter, a filter can alter the action input and output before and after the action gets executed. Wouldn't it be great to see all the filters that are being executed before the action as well as how the input and output look like after each step? That's exactly what the Mentawai Debug Mode will do for you. You can even choose to show the debug information at the bottom of your JSP page or inside your HTML code as a HTML comment. Here is how you set up and turn on the debug mode.<br /> <br /> First you need to configure the [i]DebugServletFilter [/i]as a servlet filter. This is a servlet filter (from the Servlet API) and not a Mentawai Filter, so we need to get inside the [i]web.xml[/i] file. Luckily all you have to do is paste some XML code inside this file. Below is the [i]web.xml[/i] file from the example in the previous chapter:<br /> <br /> [code]<br /> &lt;!-- The Mentawai controller --&gt;<br /> &lt;web-app&gt;<br /> 	&lt;servlet&gt;<br /> 	    &lt;servlet-name&gt;Controller&lt;/servlet-name&gt;<br /> 	    &lt;servlet-class&gt;org.mentawai.core.Controller&lt;/servlet-class&gt;<br /> 	    &lt;init-param&gt;<br /> 	        &lt;param-name&gt;applicationManager&lt;/param-name&gt;<br /> 	        &lt;param-value&gt;examples.helloworld.ApplicationManager&lt;/param-value&gt;<br /> 	    &lt;/init-param&gt;    <br /> 	    &lt;load-on-startup&gt;1&lt;/load-on-startup&gt;		<br /> 	&lt;/servlet&gt;<br /> 	<br /> 	&lt;!-- You must choose an extension to indicate a mentawai action --&gt;<br /> 	&lt;servlet-mapping&gt;<br /> 		&lt;servlet-name&gt;Controller&lt;/servlet-name&gt;<br /> 		&lt;url-pattern&gt;*.mtw&lt;/url-pattern&gt;<br /> 	&lt;/servlet-mapping&gt;<br /> 	<br />         &lt;!-- BEGIN XML BLOCK FOR DEBUG MODE --&gt;<br /> <br /> 	&lt;filter&gt;<br /> 	    &lt;filter-name&gt;DebugFilter&lt;/filter-name&gt;<br /> 	    &lt;filter-class&gt;<br /> 	        org.mentawai.util.DebugServletFilter<br /> 	    &lt;/filter-class&gt;<br /> 	&lt;/filter&gt;<br /> 	<br /> 	&lt;filter-mapping&gt;<br /> 	    &lt;filter-name&gt;DebugFilter&lt;/filter-name&gt;<br /> 	    &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;<br /> 	    &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt; <br /> 	    &lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;    <br /> 	    &lt;dispatcher&gt;INCLUDE&lt;/dispatcher&gt;    <br /> 	    &lt;dispatcher&gt;ERROR&lt;/dispatcher&gt;    <br /> 	&lt;/filter-mapping&gt;<br /> <br />         &lt;!-- END XML BLOCK FOR DEBUG MODE --&gt;<br /> <br /> &lt;/web-app&gt;<br /> [/code]<br /> <br /> After you setup the [i]DebugServletFilter [/i]inside the [i]web.xml[/i] file, all you have to do is turn it on in your application manager:<br /> <br /> [code]<br />    @Override<br />    public void init(Context application) {<br />       <br />       setDebugMode(true);<br />       <br />       Map&lt;String, Object&gt; cache = new HashMap&lt;String, Object&gt;();<br />       <br />       application.setAttribute("cache", cache);<br />    }<br /> [/code]<br /> <br /> This will make the debug text appears in the bottom of your HTML pages. Not something that you would want in a production site, for example. So you can also output the debug mode as a comment inside your HTML page:<br /> <br /> [code]<br /> setDebugMode(true, true); // the second parameter is saying that we want the debug mode to appear as a comment inside the HTML page...<br /> [/code]<br /> <br /> Run your application again and now you will see the debug information of your actions. For the web site http://www.secretcrushonline.com I see the following:<br /> <br /> <br /> - - - - - - - - - - - - - - - -  Mentawai DEBUG - - - - - - - - - - - - - - - - <br /> <br /> <br /> ActionName = CupidoAction<br /> InnerAction = answerArrow<br /> ActionClass = com.amorsecreto.action.CupidoAction<br /> Browser Locale = en_US<br /> Action Locale = pt_BR<br /> Default Locale = pt_BR<br />  <br /> <br /> Input:<br /> <br /> 	 empty <br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />  Filter = org.mentawai.filter.AuthenticationFilter@145eca6 <br /> <br /> <br /> Input:<br /> <br /> 	 empty <br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />  Filter = org.mentawai.filter.ValidatorFilter@1b3c169 <br /> <br /> <br /> Input:<br /> <br /> 	 empty <br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br /> Filter = org.mentawai.filter.ConnectionFilter@108fbd4 <br /> <br /> <br /> Input:<br /> <br /> 	 empty <br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />  Filter = IoCFilter <br /> <br /> <br /> Input:<br /> <br /> 	 empty <br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />  Filter = DIFilter: tryField=true <br /> <br /> <br /> Input:<br /> <br /> 	 empty <br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />  Filter = org.mentawai.filter.InjectionFilter@dcc20c <br /> <br /> <br /> Input:<br /> <br /> 	conn = com.mchange.v2.c3p0.impl.NewProxyConnection@efa9fb<br /> 	loc = pt_BR<br /> 	userDAO = com.amorsecreto.dao.mysql.MySQLUserDAO@179fb8d<br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />   Action = answerArrow()  <br /> <br /> Input:<br /> <br /> 	conn = com.mchange.v2.c3p0.impl.NewProxyConnection@efa9fb<br /> 	loc = pt_BR<br /> 	userDAO = com.amorsecreto.dao.mysql.MySQLUserDAO@179fb8d<br /> <br /> Output:<br /> <br /> 	 empty <br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br />  Result = jsp <br /> <br />  Consequence = Forward to /answerArrow.jsp <br /> <br /> Total Time = 1ms<br /> <br /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <br /> <br /> <br /> <br /> Mentawai Web Framework - Version:1.11 Build:20070911<br /> <br /> <br /> <br /> <br /> <br /> ]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/12/12.page</guid>
				<link>http://book.mentaframework.org/posts/preList/12/12.page</link>
				<pubDate><![CDATA[Fri, 4 Jan 2008 19:10:02]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Filters</title>
				<description><![CDATA[ Filters are the building blocks of Mentawai through which all the main feature of the framework are implemented. A filter [i]wraps[/i] or [i]intercepts[/i] an action so that it can change everything about the action before it is actually executed. A filter always gets executed before the action, but as we will see in a moment it can also modify the action after it has been executed. For a single action you will usually have a stack of filters ([i]InvocationChain[/i]) being executed before the action. You can define global filters that will be applied on all actions or you can define action specific filters that will be applied only on that action. Filters are powerful, simple and flexible. They favor the [url="http://en.wikipedia.org/wiki/Separation_of_Concerns"][b]Separation of Concerns[/b][/url] pattern, allowing your action to [b]do one thing and do it right[/b]! For example, there is no need for your action code to get convoluted with validation code, file upload code, connection pooling code, etc. This can and should be abstracted outside your action through filters.<br /> <br /> Mentawai comes with many ready-to-use filters, but you should understand how they work and how to build your own filters. Building filters are very simple and you should have this weapon ready to kill unnecessary complexity in your code. Let's start coding some filters.<br /> <br /> A filter that gets a Map from the application and places it in the action input:<br /> <br /> [code]<br /> <br /> import org.mentawai.core.*;<br /> <br /> import java.util.*;<br /> <br /> public class CacheFilter implements Filter {<br />     <br />     private static final String KEY = "cache";<br />     <br />     public String filter(InvocationChain chain) throws Exception {<br />         <br />         Action action = chain.getAction();<br />         <br />         Context application = action.getApplication();<br />         <br />         Map&lt;String, Object&gt; cache = (Map&lt;String, Object&gt;) application.getAttribute(KEY);<br />         <br />         if (cache != null) {<br />             <br />             Input input = action.getInput();<br />             <br />             input.setValue(KEY, cache);<br />             <br />         }<br />         <br />         return chain.invoke(); // next filter or the action<br />     }<br /> <br />     public void destroy() { }<br /> }<br /> <br /> <br /> <br /> [/code]<br /> <br /> This was a somewhat unrealistic example as your action can just access the application context and get the cache map itself. However it is useful to understand the basic functionality of filters.<br /> <br /> Through the [i]InvocationChain[/i] object passed as a parameter to the filter you can get the action before it has been executed. Having the action, you can now access its Input, Output and contexts such as the Application context. After the filter is done, it should call [i]chain.invoke()[/i] unless it wants to halt the action execution. The invoke method will call the next filter in the filter stack or the action if there are no more filters in the stack. It returns the action result (String) which will be in turn returned by the filter.  <br /> <br /> There will be cases when you do want to block the access to the action, for example when you are using an authentication filter. An authentication filter may look like the filter below:<br /> <br /> [code]<br /> import org.mentawai.core.*;<br /> <br /> public class AuthenticationFilter implements Filter {<br />     <br />     public static final String LOGIN = "login";<br />     <br />     public String filter(InvocationChain chain) throws Exception {<br />  <br />         Action action = chain.getAction();       <br />         <br />         Context session = action.getSession();<br />         <br />         if (session.hasAttribute("user")) {<br />             <br />             return chain.invoke();<br />             <br />         }<br />         <br />         return LOGIN;<br />     }<br />     <br />     public void destroy() { }<br /> }<br /> [/code]<br /> <br /> In the filter above we are checking if the use is logged in the system, before allowing the action to be executed. If we find an object in the session for the key "user" we assume that the user is logged and call invoke(). If the user is not logged than we return the result LOGIN which may redirect the browser to a login page.<br /> <br /> A filter can modify the action before and also after the action has been executed. Check the example below which calculates the total time the action has taken to execute:<br /> <br /> [code]<br /> import org.mentawai.core.*;<br /> <br /> import java.util.Date;<br /> <br /> public class TimerFilter implements Filter {<br />     <br />     public String filter(InvocationChain chain) throws Exception {<br />         <br />         Action action = chain.getAction();<br />         <br />         Output output = action.getOutput();<br />         <br />         output.setValue("timeBefore", new Date()); // before the action execution...<br />         <br />         long now = System.currentTimeMillis();<br />         <br />         String result = chain.invoke();<br />         <br />         long totalTime = System.currentTimeMillis() - now;<br />         <br />         output.setValue("timeAfter", new Date()); // after the action execution...<br />         <br />         output.setValue("totalTime", totalTime);<br />         <br />         return result;<br />     }<br /> <br />     public void destroy() { }<br /> <br /> }<br /> [/code]<br /> <br /> Note how we are modifying the action output before and after the action has been executed. Another possibility is to use the AfterConsequenceFilter, which inherits from the Filter interface, to perform some task after the consequence has been executed. Let's change our TimerFilter to compute the time it takes for the consequence to execute:<br /> <br /> [code]<br /> package examples.helloworld.filter;<br /> <br /> import org.mentawai.core.*;<br /> <br /> import java.util.Date;<br /> <br /> public class TimerFilter implements AfterConsequenceFilter {<br />     <br />     public String filter(InvocationChain chain) throws Exception {<br />         <br />         Action action = chain.getAction();<br />         <br />         Output output = action.getOutput();<br />         <br />         output.setValue("timeBefore", new Date().toString()); // before the action execution...<br />         <br />         long now = System.currentTimeMillis();<br />         <br />         String result = chain.invoke();<br />         <br />         long totalTime = System.currentTimeMillis() - now;<br />         <br />         output.setValue("timeAfter", new Date().toString()); // after the action execution...<br />         <br />         output.setValue("totalTime", totalTime);<br />         <br />         // save the initial time for the consequence here...<br />         <br />         Input input = action.getInput();<br />         <br />         input.setValue("initialTime", System.currentTimeMillis());<br />         <br />         return result;<br />     }<br />     <br />     public void afterConsequence(Action action, Consequence c, boolean conseqExecuted, boolean actionExecuted, String result) {<br />         <br />         if (!conseqExecuted) {<br />             <br />             System.out.println("There was an error executing the consequence!");<br />             <br />         } else {<br />             <br />             Input input = action.getInput();<br />         <br />             Long initialTime = (Long) input.getValue("initialTime");<br />             <br />             long totalTime = System.currentTimeMillis() - initialTime.longValue();<br />             <br />             System.out.println("The total time for the consequence was: " + totalTime);<br />         }<br />     }<br />     <br />     public void destroy() { }<br /> }<br /> [/code]<br /> <br /> Why didn't we place the total consequence time in the action output as well, so that we could show it in the JSP page? That's because after the consequence is executed the JSP page is history. The page was already processed so placing new things in the action output will not do us any good. That's why we chose to use the System.out to display the total consequence time.<br /> <br /> The [i]AfterConsequenceFilter [/i]is useful for example for the [i]HibernateFilter [/i]so that the hibernate session is closed only after the view layer has been processed and any lazy loading has been done.<br /> <br /> Filters can do many other things as we will see in later chapters. It can do input validation, handle exceptions, open transactions, inversion of control, etc. Filters prepare everything for the action, so that when it is time for the action to get executed, everything is ready, organized and beautiful.<br /> <br /> Below is an example of an ApplicationManager that is using the CacheFilter and the TimerFilter described above. You can also download by [url="http://www.mentaframework.org/mentainaction/HelloMentawai/HelloWorld3.war"]clicking here[/url] an application that makes use of both filters. Run this application and you will be surprised by the [b][color=blue]Mentawai Debug Mode[/color][/b], which is our next topic.<br /> <br /> [code]<br /> package examples.helloworld;<br /> <br /> import java.util.HashMap;<br /> import java.util.Map;<br /> <br /> import org.mentawai.core.Context;<br /> <br /> import examples.helloworld.action.HelloMenta;<br /> import examples.helloworld.filter.CacheFilter;<br /> import examples.helloworld.filter.TimerFilter;<br /> <br /> public class ApplicationManager extends org.mentawai.core.ApplicationManager {<br />    <br />    @Override<br />    public void init(Context application) {<br /> <br />       setDebugMode(true);<br />       <br />       Map&lt;String, Object&gt; cache = new HashMap&lt;String, Object&gt;();<br />       <br />       application.setAttribute("cache", cache);<br />    }<br /> 	<br /> 	@Override<br /> 	public void loadActions() {<br />       <br />       addGlobalFilter(new TimerFilter());<br />       <br />       addGlobalFilter(new CacheFilter());<br /> 		<br /> 		action(HelloMenta.class)<br /> 			.on(ERROR,   redir("/index.jsp"));<br /> 		<br /> 	}<br /> }<br /> [/code]<br /> ]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/11/11.page</guid>
				<link>http://book.mentaframework.org/posts/preList/11/11.page</link>
				<pubDate><![CDATA[Thu, 27 Dec 2007 14:43:43]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>The big picture</title>
				<description><![CDATA[ Mentawai has a very simple architecture following the KISS principle. The framework is all based on interfaces so it is extremely flexible. The basic concept is the notion of an [b]Action[/b] that executes some task. An action has an [b]Input [/b]and an [b]Output[/b]. All the information from the web request is contained in the action input. The results produced by an action are placed in the action output so that it can be displayed in the view layer (JSP page, velocity, etc.). An action also has access to [b]Context[/b]s such as Session, Application and Cookies. After the execution, an action should return a [b]Result[/b]. For each result you can configure a [b]Consequence [/b]such as Forward, Redirect and Chain.<br /> <br /> The core interfaces of the Mentawai framework are listed below with a brief explanation:<br /> <br /> (Click in the interface to see its javadoc)<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/Action.html"][b][i]org.mentawai.core.Action:[/i][/b][/url] It just has setters and getters for the Input, Output, Session, Application, Cookies and Locale. It also defines some standard Results like SUCCESS, ERROR, INDEX, etc. The default implementation is [url="http://www.mentaframework.org/api/org/mentawai/core/BaseAction.html"]BaseAction[/url].<br /> <br /> [code]<br /> <br /> Input input = action.getInput();<br /> <br /> Locale loc = action.getLocale();<br /> <br /> [/code]<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/Input.html"][b][i]org.mentawai.core.Input:[/i][/b][/url] It provides methods to get values from the input as Object, int, float, double, boolean, etc. It performs the necessary conversions and also have versions that return a default value. It also has methods to return properties of a request (through reflection) and headers of a request. You can also use the method keys() to list all keys in the action input. The default implementation is [url="http://www.mentaframework.org/api/org/mentawai/core/RequestInput.html"]RequestInput[/url]. Below are some examples:<br /> <br /> [code]<br /> <br /> // get a String from the this input...<br /> String username = input.getStringValue("username");<br /> <br /> // get the code as an int or return 100 if it is not present in the input...<br /> int code = input.getIntValue("code", 100);<br /> <br /> // get a boolean from the input...<br /> boolean accepted = input.getBooleanValue("accepted", false);<br /> <br /> // checkbox: get an array of all values with they key "interest"<br /> int[] interestsAsInt = input.getIntValues("interest");<br /> String[] interestsAsString = input.getValues("interest");<br /> <br /> // get any object in the action input<br /> MyObject obj = (MyObject) input.getValue("myObject");<br /> <br /> // list all keys and values<br /> Iterator&lt;String&gt; iter = input.keys();<br /> <br /> while(iter.hasNext()) {<br /> <br />     String key = iter.next();<br /> <br />     Object value = input.getValue(key);<br /> <br />     System.out.println("Key: " + key + " / Value: " + value.toString());<br /> }<br /> <br /> // check if input has a value for the given key<br /> boolean hasKey = input.hasValue("code");<br /> <br /> // get a header from this input<br /> String agent = input.getHeader("User-Agent");<br /> <br /> // get a property from this input<br /> String ip = input.getProperty("remoteAddr"); // IP of the request...<br /> <br /> [/code]<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/Output.html"][b][i]org.mentawai.core.Output:[/i][/b][/url] It behaves pretty much like a Map&lt;String, Object&gt; where you can place values by a String key. You can also check if it is empty with the isEmpty() method and get all the keys with the keys() method. The default implementation is [url="http://www.mentaframework.org/api/org/mentawai/core/RequestOutput.html"]ResponseOutput[/url]. Below are some examples:<br /> <br /> [code]<br /> <br /> output.setValue("username", username);<br /> <br /> output.setValue("user", user);<br /> <br /> boolean isEmpty = output.isEmpty();<br /> <br /> // list all keys and values<br /> Iterator&lt;String&gt; iter = output.keys();<br /> <br /> while(iter.hasNext()) {<br /> <br />     String key = iter.next();<br /> <br />     Object value = output.getValue(key);<br /> <br />     System.out.println("Key: " + key + " / Value: " + value.toString());<br /> }<br /> [/code]<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/Context.html"][b][i]org.mentawai.core.Context:[/i][/b][/url] It behaves pretty much like a web application context where you can set attributes by name. A context also supports the reset() method (optional) and the keys() method. Some of its implementations are the [url="http://www.mentaframework.org/api/org/mentawai/core/SessionContext.html"]SessionContext[/url], [url="http://www.mentaframework.org/api/org/mentawai/core/ApplicationContext.html"]ApplicationContext[/url] and [url="http://www.mentaframework.org/api/org/mentawai/core/CookieContext.html"]CookieContext[/url]. Below are some examples:<br /> <br /> [code]<br /> <br /> Context session = action.getSession();<br /> <br /> session.setAttribute("user", user);<br /> <br /> // reset the session<br /> session.reset();<br /> <br /> Context application = action.getApplication();<br /> <br /> Collection&lt;User&gt; users = (Collection&lt;User&gt;) application.getAttribute("users");<br /> <br /> application.reset(); // throws UnsupportedOperationException<br /> <br /> Context cookie = action.getCookies();<br /> <br /> // add a cookie<br /> cookie.setAttribute("username", username);<br /> <br /> // remove a cookie<br /> cookie.removeAttribute("username");<br /> <br /> cookie.reset(); // throws UnsupportedOperationException<br /> [/code]<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/Consequence.html"][b][i]org.mentawai.core.Consequence:[/i][/b][/url] A consequence is executed after the action has executed and returned a result. A consequence is an interface that has only the execute() method that receives the action, the HttpServletRequest and the HttpServletResponse. The main consequences implemented by the framework are: [url="http://www.mentaframework.org/api/org/mentawai/core/Forward.html"]Forward[/url] (forwards to a JSP page), [url="http://www.mentaframework.org/api/org/mentawai/core/Redirect.html"]Redirect[/url] (redirects to a JSP), [url="http://www.mentaframework.org/api/org/mentawai/core/Chain.html"]Chain[/url] (chains the action with another action) and [url="http://www.mentaframework.org/api/org/mentawai/core/StreamConsequence.html"]StreamConsequence[/url] (returns a byte stream through the HttpServletResponse). You can implement your own consequences as well.<br /> <br /> [code]<br /> <br /> ActionConfig ac = new ActionConfig(UserAction.class);<br /> ac.addConsequence(SUCCESS, new Forward("/user.jsp"));<br /> ac.addConsequence(ERROR, new Forward("/error.jsp"));<br /> addActionConfig(ac);<br /> <br /> // ou<br /> <br /> action(UserAction.class)<br />     .on(SUCCESS, fwd("/user.jsp"))<br />     .on(ERROR, fwd("/error.jsp"));<br /> [/code]<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/Filter.html"][b][i]org.mentawai.core.Filter:[/i][/b][/url] A filter is the main building block of the framework. We will talk more about filters in the next chapter, but for now you should know that it is an interface with two methods: destroy() for cleanup and filter() that receives an [url="http://www.mentaframework.org/api/org/mentawai/core/InvocationChain.html"]InvocationChain[/url] as a parameter and returns a result. The signature of the filter() method is:<br /> <br /> [code]<br /> public String filter(InvocationChain chain) throws Exception;<br /> [/code]<br /> <br /> [url="http://www.mentaframework.org/api/org/mentawai/core/AfterConsequenceFilter.html"][b][i]org.mentawai.core.AfterConsequenceFilter:[/i][/b][/url] This interface inherits from the Filter interface to add an extra method that is executed after the Consequence of the action is executed. The method signature is:<br /> <br /> [code]<br /> public void afterConsequence(Action action, Consequence c, boolean conseqExecuted, boolean actionExecuted, String result);<br /> [/code]<br /> <br /> The big picture is more or less like this:<br /> <br /> [img]http://www.mentaframework.org/mentainaction/MentaArch.jpg[/img]<br /> <br /> You don't need to fully understand the Mentawai architecture to start building web applications with it. However it does not hurt to have a good foundation and to really understand how things are working under the hood.<br /> <br /> ]]></description>
				<guid isPermaLink="true">http://book.mentaframework.org/posts/preList/10/10.page</guid>
				<link>http://book.mentaframework.org/posts/preList/10/10.page</link>
				<pubDate><![CDATA[Thu, 27 Dec 2007 09:45:01]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
	</channel>
</rss>