<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
	<channel>
		<title><![CDATA[Latest posts for the topic "30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai"]]></title>
		<link>http://forum.mentaframework.org/posts/list/19.page</link>
		<description><![CDATA[Latest messages posted in the topic "30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai"]]></description>
		<generator>JForum - http://www.jforum.net</generator>
			<item>
				<title>30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ Iniciamos criando um novo projeto web (Tomcat Project) no eclipse, chamado MentaNews. Estamos utilizando o plugin sysdeo para projetos web integrados com o Tomcat dentro do Eclipse, e recomendamos a todos que utilizem esse excelente plugin.

Copiamos o jar do mentawai pra dentro do diretório WEB-INF/lib, não esquecendo de ir nas propriedades do projeto e adicionar esse jar no classpath do projeto.

Começamos criando nossa primeira action, que se chamará NewsAction.java e ficará no pacote org.mentanews.action:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
package org.mentanews.action;

import org.mentawai.core.BaseAction;

public class NewsAction extends BaseAction {
   
   public String test&#40;&#41; throws Exception {
      
      output.setValue&#40;"hello", "Hello MentaNews Application!"&#41;;
      
      return SUCCESS;
   }
}
</pre>
		</div>

Repare que adicionamos uma inner action <b>test</b> que apenas coloca uma mensagem no output da action e retorna SUCCESS. Mais informações sobre <b>Inner Action</b> podem ser obtidas <a href="http://www.mentaframework.org/inneraction.jsp" target="_new" rel="nofollow">aqui</a>.

Feito isso criamos o ApplicationManager da nossa aplicação, que ficará no pacote org.mentanews:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
package org.mentanews;

import org.mentanews.action.NewsAction;
import org.mentawai.coc.InnerActionConsequenceProvider;
import org.mentawai.core.Context;

public class ApplicationManager extends org.mentawai.core.ApplicationManager {
   
   @Override
   public void init&#40;Context application&#41; {

      /*
       * Convention Over Configuration that will provide a default consequence for all
       * inner actions when they return SUCCESS or ERROR.
       * 
       * Ex: When NewsAction.test.mtw returns SUCCESS or ERROR, it will FORWARD to:
       * 
       *     /news/test.jsp
       */
      setConsequenceProvider&#40;new InnerActionConsequenceProvider&#40;&#41;&#41;;
      
      setDebugMode&#40;true&#41;; // turn on debug mode...
      
   }
   
   public void loadActions&#40;&#41; {
      
      action&#40;NewsAction.class&#41;;

      // If not using InnerActionConsequenceProvider we would have to do:
     // .on&#40;SUCCESS, fwd&#40;"/news/test.jsp"&#41;&#41;;
   }
}
</pre>
		</div>

Inicialmente o nosso application manager está apenas ligando <a href="http://www.mentaframework.org/debugmode.jsp" target="_new" rel="nofollow">o modo debug do Mentawai</a> e setando o <i>InnerActionConsequenceProvider</i> como o nosso esquema de CoC (Convention over Configuration). Mais embaixo declaramos a nossa primeira action, através do método <i>action(NewsAction.class);</i>.

<font color='blue'>O que está acontecendo aqui?</font> Como não passamos nenhum nome quando declaramos a action NewsAction.class, o Mentawai assume que o nome será o mesmo nome da classe, ou seja, NewsAction. Como não definimos nenhuma consequencia para a action NewsAction.class (e poderíamos ter feito isso) o Mentawai através do <i>InnerActionConsequenceProvider</i> vai assumir que se a action retornar SUCCESS ou ERROR, ela deverá sofrer um forward para /news/NOMEDAINNERACTION.jsp. Abaixo temos alguns exemplos de como a <i>InnerActionConsequenceProvider</i> funciona:

/User.view.mtw = FORWARD para /user/view.jsp

/UserAction.view.mtw = FORWARD para /user/view.jsp

/UserAction.mtw = ERRO pois a <i>InnerActionConsequenceProvider</i> só funciona para Inner Actions como o nome já diz

<font color='blue'>Nota:</font> <i>Vc pode também implementar a interface ConsequenceProvider para criar o seu próprio esquema de Convention Over Configuration para a camada view.</i>

De acordo com o esquema acima, quando acessarmos NewsAction.test.mtw, o Mentawai assumirá a consequencia FORWARD para /news/test.jsp. Então vamos criar essa página test.jsp:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
&lt;%@ page contentType="text/html; charset=ISO-8859-1" %&gt; 
&lt;%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %&gt;
&lt;h1&gt;Hello MentaNews!&lt;/h1&gt;
&lt;h5&gt;&lt;mtw:out value="hello" /&gt;&lt;/h5&gt;
</pre>
		</div>

Nessa página estamos declarando a taglib do Mentawai (mtw) e estamos usando a tag mtw:out para imprimir o valor "hello" do output da action.

Feito isso, o último passo para colocarmos a nossa aplicação para rodar é definir o web.xml, que fica dentro de WEB-INF/.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
&lt;?xml version="1.0" encoding="ISO-8859-1"?&gt;

&lt;!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd"&gt;

&lt;web-app&gt;
	&lt;display-name&gt;MentaNews&lt;/display-name&gt;
	&lt;description&gt;&lt;/description&gt;

	&lt;servlet&gt;
        &lt;servlet-name&gt;Controller&lt;/servlet-name&gt;
        &lt;servlet-class&gt;org.mentawai.core.Controller&lt;/servlet-class&gt;
        &lt;init-param&gt;
    	    &lt;param-name&gt;applicationManager&lt;/param-name&gt;
        	&lt;param-value&gt;org.mentanews.ApplicationManager&lt;/param-value&gt;
	    &lt;/init-param&gt;    
		&lt;load-on-startup&gt;1&lt;/load-on-startup&gt;		
    &lt;/servlet&gt;

    &lt;!-- You must choose an extension to indicate a mentawai action --&gt;
    &lt;servlet-mapping&gt;
        &lt;servlet-name&gt;Controller&lt;/servlet-name&gt;
        &lt;url-pattern&gt;*.mtw&lt;/url-pattern&gt;
    &lt;/servlet-mapping&gt;
    
    &lt;filter&gt;
        &lt;filter-name&gt;DebugFilter&lt;/filter-name&gt;
        &lt;filter-class&gt;
            org.mentawai.util.DebugServletFilter
        &lt;/filter-class&gt;
    &lt;/filter&gt;
    
    &lt;filter-mapping&gt;
        &lt;filter-name&gt;DebugFilter&lt;/filter-name&gt;
        &lt;url-pattern&gt;*.jsp&lt;/url-pattern&gt;
        &lt;dispatcher&gt;REQUEST&lt;/dispatcher&gt; 
        &lt;dispatcher&gt;FORWARD&lt;/dispatcher&gt;    
        &lt;dispatcher&gt;INCLUDE&lt;/dispatcher&gt;    
        &lt;dispatcher&gt;ERROR&lt;/dispatcher&gt;    
    &lt;/filter-mapping&gt;

&lt;/web-app&gt;
</pre>
		</div>

O que estamos fazendo no web.xml é:

- Indicamos que será o controlador do Mentawai que tratará as requisições terminadas por *.mtw.

- Indicamos que o ApplicationManager que deverá ser usado é o org.mentanews.ApplicationManager.

- Fazemos as configurações necessárias para o modo debug do Mentawai, que é um filtro de servlet.

Agora a melhor parte: Colocamos o Tomcat para ordar e acessamos a URL http://localhost:8080/MentaNews/NewsAction.test.mtw. Você deverá ver o seguinte no seu browser:

<b>Hello MentaNews!</b>

Hello MentaNews Application!

(Debug do Mentawai omitido)


Agora que temos o básico da nossa aplicação rodando, vamos criar o esquema do banco-de-dados. No nosso exemplo estaremos utilizando o MySQL, mas nada impede vc de utilizar qualquer outro banco. Como veremos mais a frente, sua aplicação pode suportar N bancos-de-dados através de N implementações diferentes do seu repositório de dados (DAO ou Repository).

O esquema completo do banco de dados (para MySQL) pode ser baixado <a href="http://www.mentaframework.org/beta/mentanews.sql" target="_new" rel="nofollow">aqui</a>.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

|=========================| |===================|
|News                     | |Sections           |
|=========================| |===================|
|id                 pk int| |id           pk int|
|-------------------------| |-------------------|
|section               int| |name    varchar&#40;50&#41;|
|create_date      datetime| |===================|
|title        varchar&#40;200&#41;|
|body             longtext|
|=========================|

A tabela News possui inicialmente uma entrada com o id = 1.

A tabela Sections possui 4 entradas: &#40;1, Esportes&#41;, &#40;2, Economia&#41;, &#40;3, País&#41;, &#40;4, Política&#41;

Criamos também um usuário do mysql "mentanews" com a senha "mentanews" com acesso total ao database "mentanews".

grant all privileges on mentanews.* to mentanews@"%" identified by 'mentanews';

</pre>
		</div>

Nesse ponto precisamos de um pool de conexões com o banco-de-dados. Isso é básico de toda aplicação web. Logo vc pode ir aprender Commons DBCP, C3P0, configurar um XML do tomcat para fazer o pool de conexões funcionar e <font color='red'>voltar daqui a 1 hora, um dia ou um mês</font>. Ou vc pode deixar que o Mentawai resolva isso pra vc. O Mentawai já vem de fábrica com uma abstração de um pool de conexões (interface <i>org.mentawai.sql.ConnectionHandler</i>) dentro dele, e com implementações que utilizam por trás o DBCP e o C3P0, dois dos mais famosos pools de conexões do mercado. Então para por exemplo utilizar o C3P0 com sua aplicação, tudo que vc tem que fazer é:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

   public void loadActions&#40;&#41; {
      
      // create a C3P0 connection pool...
      ConnectionHandler connHandler = new C3P0ConnectionHandler&#40;"com.mysql.jdbc.Driver", "jdbc:mysql://localhost/mentanews?autoReconnect=true", "mentanews", "mentanews"&#41;;
      
      // create a global connection filter...
      filter&#40;new ConnectionFilter&#40;"conn", connHandler&#41;&#41;;
      
     ...
   }
</pre>
		</div>

Utilizamos o ConnectionFilter para disponibilizar uma connection para todas as actions da nossa aplicação quando, e apenas quando, uma connection for necessária. O ConnectionFilter se encarrega de obter a connection do pool de conexões e devolve-la para o pool quando a nossa action termina, sem que precisemos nos preocupar com isso. Mais informações sobre o ConnectionFilter pode ser obtido <a href="http://www.mentaframework.org/connfilter.jsp" target="_new" rel="nofollow">aqui</a>. <b>Não se esquecer de colocar o jar do C3P0 e do Mysql Connector (driver JDBC) dentro de WEB-INF/lib !</b> Esses jars vem junto com a <a href="http://www.mentaframework.org/mentawai-1.11.zip" target="_new" rel="nofollow">versão full do Mentawai</a>.

Para testarmos o nosso pool de conexões, vamos modificar a inner action test da nossa NewsAction:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   public String test&#40;&#41; throws Exception {
       
      Connection conn = &#40;Connection&#41; input.getValue&#40;"conn"&#41;;
      
      PreparedStatement stmt = conn.prepareStatement&#40;"select * from Sections limit 1"&#41;;
      
      ResultSet rset = stmt.executeQuery&#40;&#41;;
      
      if &#40;rset.next&#40;&#41;&#41; {
         
         output.setValue&#40;"hello", rset.getString&#40;1&#41; + ": " + rset.getString&#40;2&#41;&#41;;
      }
      
      rset.close&#40;&#41;;
      stmt.close&#40;&#41;;
       
      return SUCCESS;
   }
</pre>
		</div>

Estamos obtendo uma connection (através do ConnectionFilter) e fazendo uma simples query para testarmos nossa conexão com o banco. Acesse http://localhost:8080/MentaNews/News.test.mtw e vc deverá visualizar a primeira linha da tabela Sections sendo exibida pelo JSP test.jsp:

<b>Hello MentaNews!</b>

1: Esportes

Vamos seguir em frente e carregar agora uma lista de dados para as Sections. Uma aplicação web normalmente terá várias listas estáticas de dados como países, categorias, métodos de pagamento aceitos, sexo (masculino/feminino), etc. Essas listas serão normalmente exibidas dentro de uma combo box. Para carregar uma lista de dados do banco de dados com o Mentawai, tudo que vc tem que fazer no ApplicationManager é:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

      // load list...
      DBListData servicos = new DBListData&#40;"sections", "ID", "NAME", "SECTIONS", "NAME"&#41;;

      addList&#40;servicos, connHandler&#41;;
</pre>
		</div>

Feito isso vc tem uma lista estática carregada em memória que pode ser acessada de qualquer lugar da sua aplicação através do método <i>ListManager.getList("sections");</i> Como veremos mais adiante, também poderemos facilmente construir uma combo box de formulário HTML utilizando essa lista e as tags do Mentawai.

Note que para o construtor de DBListData estamos passando o nome da lista, o nome da coluna quem contém o id do elemento da lista, o nome da coluna que contém o nome do elemento da lista, o nome da tabela de onde virá essa lista e o campo pelo qual queremos ordenar nossa lista. Informações completas sobre as listas de dados do Mentawai podem ser obtidas <a href="http://www.mentaframework.org/lists.jsp" target="_new" rel="nofollow">aqui</a>.

Seguindo em frente, vamos falar agora sobre outro tópico importantíssimo para todo projeto web. ORM ou mapeamento dos seus objetos para dentro das tabelas do seu banco de dados.

Abaixo temos o código News.java para a nossa entidade News (Notícia), que deverá ser colocado em <i>org.mentanews.bean</i>.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

package org.mentanews.bean;

import java.util.Date;

public class News {
   
   private int id;
   private int section;
   private Date createDate;
   private String title;
   private String body;
   
   public News&#40;&#41; { }
   
   public News&#40;int id&#41; {
      
      this.id = id;
   }

   // setters and getters here &#40;omitted&#41; 

</pre>
		</div>

Nesse ponto vc pode parar, ir aprender Hibernate e <font color='red'>voltar daqui a um dia, uma semana ou um mês</font>. A outra opção é utilizar SQL puro via JDBC dentro dos seus <i>repositories</i> ou <i>DAOs</i>, ou ainda melhor: utilizar o MentaBeans para  te ajudar com suas queries e CRUDs (Create, Update, Delete) de beans. O MentaBeans é um facilitador para quem não sabe ou não quer usar uma ferramenta de ORM completa e/ou prefere utilizar JDBC puro em suas aplicações. 

Note que os <i>repositories</i> (ou DAOs, depende de como vc estiver arquitetando sua aplicação) servem exatamente para deixar sua aplicação aberta a qualquer outro banco-de-dados ou esquema de persistência. Se amanhã vc decidir utilizar Hibernate, iBatis, LDAP, arquivos textos, MS Access, tudo que vc terá que fazer é codificar uma nova implementação dos seus <i>repositories</i> ou <i>DAOs</i>.

Para manter as coisas simples estaremos utilizando o MentaBeans para a nossa aplicação. Para isso, tudo que temos que fazer é definir os BeanConfigs dentro do nosso ApplicationManager. (O Mentawai vem com o aplicativo helper <i>org.mentawai.tools.BeanConfig</i> para gerar automáticamente a configuração de um BeanConfig a partir de qualquer POJO). Note que não precisamos de XML ou Annotations para mapear os campos e que em nenhum momento estamos poluindo as nossas entidades com annotations. <b>O seu objeto News.java ficará totalmente independente do MentaBeans e do Mentawai.</b>

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   @Override
   public void loadBeans&#40;&#41; {
      
      bean&#40;News.class, "news"&#41;
         .pk&#40;"id", DBTypes.INTEGER&#41;
         .field&#40;"section", DBTypes.INTEGER&#41;
         .field&#40;"createDate", "create_date", DBTypes.TIMESTAMP&#41;
         .field&#40;"title", DBTypes.STRING&#41;
         .field&#40;"body", DBTypes.STRING&#41;;
   }
</pre>
		</div>

Feito isso partimos para o desenvolvimento dos nossos <i>repositories</i>:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
package org.mentanews.repository;

import java.util.List;

import org.mentanews.bean.News;

public interface NewsRepository {
   
   public News get&#40;int id&#41;;
   
   public void add&#40;News news&#41;;
   
   public void remove&#40;int id&#41;;
   
   public List&lt;News&gt; getLast&#40;int max&#41;;
   
   public List&lt;News&gt; getLastBySection&#40;int sectionId, int max&#41;;
   
}
</pre>
		</div>

Note que o nosso repositório é independente de qualquer implementação referente ao mecanismo de persistência que estaremos utilizando. O método getLast retorna as últimas notícias cadastradas, por ordem de cadastro e o método getLastBySection retorna as últimas notícias cadastradas naquela sessão, também ordenadas pela data de cadastro.

Agora vamos a implementação do nosso repositório para o MySQL utilizando o MentaBeans para facilitar a nossa vida. Repare que não é necessário escrever nenhum SQL para as operações mais simples de listagem e CRUD de beans:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
package org.mentanews.repository.mysql;

import java.sql.Connection;
import java.util.List;

import org.mentanews.bean.News;
import org.mentanews.repository.NewsRepository;
import org.mentawai.bean.jdbc.JdbcBeanSession;
import org.mentawai.bean.jdbc.MySQLBeanSession;

public class MySQLNewsRepository implements NewsRepository {
   
   protected Connection conn;
   
   protected JdbcBeanSession session; // mentabeans
   
   public void setConn&#40;Connection conn&#41; {
      
      this.conn = conn;
      
      this.session = new MySQLBeanSession&#40;conn&#41;;
   }
   
   public News get&#40;int id&#41; {
      
      News news = new News&#40;id&#41;;
      
      try {
      
         if &#40;session.load&#40;news&#41;&#41; {
            
            return news;
         }
      
      } catch&#40;Exception e&#41; {
         
         throw new RuntimeException&#40;e&#41;;
      }
      
      return null;
   }
   
   public void add&#40;News news&#41; {
      
      int id = news.getId&#40;&#41;;
      
      try {
      
         boolean exists = id &gt; 0;
         
         if &#40;exists&#41; {
            
            session.update&#40;news&#41;;
            
         } else {
            
            session.insert&#40;news&#41;;
         }
         
      } catch&#40;Exception e&#41; {
         
         throw new RuntimeException&#40;e&#41;;
      }
   }
   
   public void remove&#40;int id&#41; {
      
      News n = new News&#40;id&#41;;
      
      try {
         
         session.delete&#40;n&#41;;
         
      } catch&#40;Exception e&#41; {
         
         throw new RuntimeException&#40;e&#41;;
      }
   }
   
   public List&lt;News&gt; getLast&#40;int max&#41; {
      
      News n = new News&#40;&#41;;
      
      try {
      
         return session.loadList&#40;n, "create_date desc", max&#41;;
         
      } catch&#40;Exception e&#41; {
         
         throw new RuntimeException&#40;e&#41;;
      }
   }
   
   public List&lt;News&gt; getLastBySection&#40;int sectionId, int max&#41; {
      
      News n = new News&#40;&#41;;
      
      n.setSection&#40;sectionId&#41;;
      
      try {
         
         return session.loadList&#40;n, "create_date desc", max&#41;;
         
      } catch&#40;Exception e&#41; {
         
         throw new RuntimeException&#40;e&#41;;
      }
   }
  
}
</pre>
		</div>

As funções insert, update, load e delete do MentaBeans são bem auto-explicativas. As funções loadList recebem um bean que pode ter algumas propriedades preenchidas (ou nenhuma) e será a partir dessas propriedades que a lista será carregada. Logo se queremos carregar uma lista de News com a sectionId igual a alguma coisa, simplesmente construimos um bean com essa propriedade setada e passamos para o loadList. Note que o loadList tb suporta um número máximo para a lista retornada e ordenação (order by do SQL). Mais informações sobre o MentaBeans podem ser obtidas <a href="http://www.mentaframework.org/mentabean.jsp" target="_new" rel="nofollow">aqui</a>.

Partiremos agora para o próximo passo que é criar uma fachada ou <i>service</i> que será usado pelas nossas actions. Isso vai evitar que coloquemos a lógica do nosso negócio dentro das nossas actions. Abaixo temos o código para NewsService.java. Note que se amanhã vc precisar de acesso remote/distribuído ao seu sistema, vc vai transformar essa classe NewsService numa classe remota via xFire, RMI, EJB, etc.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
package org.mentanews.service;

import java.util.List;
import java.util.Date;

import org.mentanews.bean.News;
import org.mentanews.repository.NewsRepository;

public class NewsService {
   
   private static final int MAX = 20;
   
   private NewsRepository newsRepo;
   
   public News load&#40;int id&#41; {
      
      return newsRepo.get&#40;id&#41;;
   }
   
   public void delete&#40;int id&#41; {
      
      newsRepo.remove&#40;id&#41;;
   }
   
   public List&lt;News&gt; loadList&#40;&#41; {
      
      return newsRepo.getLast&#40;MAX&#41;;
   }
   
   public void create&#40;News news&#41; {
      
      news.setCreateDate&#40;new Date&#40;&#41;&#41;;
      
      newsRepo.add&#40;news&#41;;
      
   }
   
   public void update&#40;News news&#41; {
      
      newsRepo.add&#40;news&#41;;
   }
   
   public List&lt;News&gt; loadList&#40;int sectionId&#41; {
      
      return newsRepo.getLastBySection&#40;sectionId, MAX&#41;;
   }
}
</pre>
		</div>

Agora vamos codificar a nossa NewsAction que utilizará o NewsService para realizar as tarefas necessárias. Vamos começar com as inner actions <i>list</i> e <i>load</i>.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
package org.mentanews.action;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.List;

import org.mentanews.bean.News;
import org.mentanews.service.NewsService;
import org.mentawai.core.BaseAction;
import org.mentawai.filter.ModelDriven;
 
public class NewsAction extends BaseAction implements ModelDriven {
   
   private NewsService newsService = new NewsService&#40;&#41;;
   
   public Object getModel&#40;&#41; {
      
      return newsService;
   }
    
   public String test&#40;&#41; throws Exception {

        // omitted!
   }
   
   public String list&#40;&#41; throws Exception {
      
      int sectionId = input.getIntValue&#40;"sectionId"&#41;;
      
      List&lt;News&gt; list = null;
      
      if &#40;sectionId &gt; 0&#41; {
         
         list = newsService.loadList&#40;sectionId&#41;;
         
      } else {
         
         list = newsService.loadList&#40;&#41;;
      }
      
      output.setValue&#40;"list", list&#41;;
      
      return SUCCESS;
   }
   
   public String show&#40;&#41; throws Exception {
      
      int id = input.getIntValue&#40;"id"&#41;;
      
      if &#40;id &lt;= 0&#41; return ERROR;
      
      News news = newsService.load&#40;id&#41;;
      
      output.setValue&#40;"news", news&#41;;
      
      return SUCCESS;
   }
}
</pre>
		</div>

É importante notar aqui que estamos utilizando a interface ModelDriven, ou seja, quando utilizarmos o filtro global InjectionFilter, tudo será injetado diretamente em NewsService, que é o objeto retornado pelo método <i>getModel()</i> da interface ModelDriven. Essa opção de arquitetura é muito importante pois deixa a nossa action totalmente desacoplada do nosso modelo de negócios, ou seja, a nossa action usa o nosso modelo de negócios, que no caso aqui é o NewsService, ao invés de implementar o nosso modelo de negócio dentro dela (dentro da action).

Agora vamos partir para a questão do IoC (IoCFilter)  e do Auto-Wiring (que no Mentawai é feito pelo DIFilter). Nesse ponto vc pode parar, ir aprender Spring e voltar daqui <font color='red'>a um dia, uma semana ou um mês</font>. Ou vc pode utilizar o excelente suporte que o Mentawai oferece para IoC e Auto-Wiring. Enquanto muitos frameworks web deixam de lado esse importante tópico, o Mentawai oferece uma implementação bastante prática e poderosa através do seu IoCFilter e do DIFilter.

Começamos pelo IoC. Temos que dizer para a nossa aplicação que ela vai usar a implementação MySQLNewsRepository para o nosso NewsRepository:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   @Override
   public void loadActions&#40;&#41; {
      
      // create a C3P0 connection pool...
      ConnectionHandler connHandler = new C3P0ConnectionHandler&#40;"com.mysql.jdbc.Driver", 
            "jdbc:mysql://localhost/mentanews?autoReconnect=true", "mentanews", "mentanews"&#41;;
      
      // load list...
      DBListData servicos = new DBListData&#40;"sections", "ID", "NAME", "SECTIONS", "NAME"&#41;;
      addList&#40;servicos, connHandler&#41;;
      
      // create a global connection filter...
      filter&#40;new ConnectionFilter&#40;"conn", connHandler&#41;&#41;;
      
      // transform Mentawai in a IOC container...
      filter&#40;new IoCFilter&#40;&#41;&#41;;
      
      // we will be using MYSQL implementation of our NewsRepository
      ioc&#40;"newsRepo", MySQLNewsRepository.class&#41;;

      // ...
}
</pre>
		</div>

Note que se amanhã vc tiver uma outra implementação do seu NewsRepository (ex: OracleNewsRespository, HibernateNewsRepository, etc.) vc só terá que mudar isso no ApplicationManager e toda a sua aplicação passará a utilizar essa nova implementação. Outra vantagem é que o seu modelo de negócios ficou totalmente independente da sua aplicação. Se amanhã vc quiser testar o seu modelo de negócios vc pode, por exemplo, passar para ele uma implementação <i>dummy</i> (boba) que não vai a lugar nenhum e apenas retorna valores estáticos.

Vamos agora para o auto-wiring (DIFilter). Uma dependência clara que temos aqui é MySQLNewsRepository DEPENDE de java.sql.Connection (que virá automaticamente do nosso pool de conexões previamente setado). Então fazemos o seguinte no ApplicationManager:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   @Override
   public void loadActions&#40;&#41; {
      
      // create a C3P0 connection pool...
      ConnectionHandler connHandler = new C3P0ConnectionHandler&#40;"com.mysql.jdbc.Driver", 
            "jdbc:mysql://localhost/mentanews?autoReconnect=true", "mentanews", "mentanews"&#41;;
      
      // load list...
      DBListData servicos = new DBListData&#40;"sections", "ID", "NAME", "SECTIONS", "NAME"&#41;;
      addList&#40;servicos, connHandler&#41;;
      
      // create a global connection filter...
      filter&#40;new ConnectionFilter&#40;"conn", connHandler&#41;&#41;;
      
      // transform Mentawai in a IOC container...
      filter&#40;new IoCFilter&#40;&#41;&#41;;
      
      // we will be using MYSQL implementation of our NewsRepository
      ioc&#40;"newsRepo", MySQLNewsRepository.class&#41;;
      
      // auto-wiring
      filter&#40;new DIFilter&#40;&#41;&#41;;
      
      // Everything that depends &#40;needs&#41; on a Connection will receive one
      di&#40;"conn", Connection.class&#41;;

      // ...
}
</pre>
		</div>

Estamos dizendo aqui que "tudo que sair do input da action e precisar de uma <i>java.sql.Connection</i> <b>irá receber</b> uma connection", que por sua vez também sairá do input da action (que por sua vez sairá do pool de conexões previamente setado). Note que diferentemente do IoC, que trabalha com implementações, o auto-wiring trabalha com interfaces. O auto-wiring só se preocupa em <b>ligar</b> as coisas, sem se importar com o que elas são. Mais informações sobre o DIFilter podem ser obtidas <a href="http://www.mentaframework.org/depinj.jsp" target="_new" rel="nofollow">aqui</a>. Mais informações sobre o IoCFilter podem ser obtidos <a href="http://forum.mentaframework.org/posts/list/477.page" target="_new" rel="nofollow">aqui</a>.

Feito isso, vc configurou sua aplicação web para utilizar IoC com auto-wiring. Mas ainda falta um ponto importante que é o InjectionFilter.

O IoCFilter é encarregado de instanciar a implementação definida no application manager e <b>colocá-la no input da action</b>. O IoCFilter por si só, não injeta nada em lugar nenhum, apenas coloca uma instância no input da action. Para realizar a injeção, devemos utilizar o filtro global InjectionFilter. Como o InjectionFilter funciona? Ele olha a action e pega uma lista das propriedades da action. De posse dessa lista ele procura no input da action por esses valores e se encontrar injeta na action. A diferença é que estamos utilizando a interface <i>ModelDriven</i>, o que faz com que o InjectionFilter ao invés de procurar e injetar na action ele vai procurar e injetar diretamente no modelo retornado pelo método getModel().

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

       // ...

       // auto-wiring
       filter&#40;new DIFilter&#40;&#41;&#41;;
       
       // Everything that depends &#40;needs&#41; on a Connection will receive one
       di&#40;"conn", Connection.class&#41;;

       // injection
       filter&#40;new InjectionFilter&#40;&#41;&#41;;
</pre>
		</div>

Como estamos retornando NewsService no método getModel() da nossa action, então o que acontece é o seguinte:

ConnectionFilter cria uma Connection e coloca no input da action; IoCFilter cria um MySQLNewsRepository e coloca no input da action. O DiFilter se encarrega de injetar a connetion dentro de MySQLNewsService (dependencia / auto-wiring). O InjectionFilter detecta que o NewsService possui uma propriedade do tipo NewsRepository e com o nome newsRepo. InjectionFilter procura essa propriedade no input da action e injeta ela no NewsService. A cadeia de filtros chega na action e ela é executada, utilizando o NewsService para fazer o que ela precisa fazer.

É claro que vc poderia fazer todos os passos acima na mão, sem filtros, mas então vc não estaria utilizando IoC nem auto-wiring e a sua aplicação estaria cheia de acoplamentos fortes e não seria uma aplicação <i>loosely coupled</i> (fracamente acoplada).

Vamos partir agora o JSP que exibirá os resultados da nossa action. O nome do JSP, de acordo com nossa convenção proposta pelo InnerActionConsequenceProvider, deverá ser /news/list.jsp:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

&lt;%@ page contentType="text/html; charset=ISO-8859-1" %&gt; 
&lt;%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %&gt;

&lt;h1&gt;Hello MentaNews!&lt;/h1&gt;
&lt;table border="1" cellspacing="3" cellpading="3"&gt;
&lt;tr&gt;&lt;th&gt;ID&lt;/th&gt;&lt;th&gt;Section&lt;/th&gt;&lt;th&gt;Title&lt;/th&gt;&lt;th&gt;Date&lt;/th&gt;&lt;/tr&gt;
&lt;mtw:list value="list"&gt;
&lt;mtw:loop&gt;
&lt;tr&gt;
&lt;td&gt;&lt;mtw:out value="id" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;mtw:out value="section" list="sections" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;mtw:out value="title" /&gt;&lt;/td&gt;
&lt;td&gt;&lt;mtw:out value="createDate" /&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/mtw:loop&gt;
&lt;/mtw:list&gt;
&lt;/table&gt;

</pre>
		</div>

Veja como estamos utilizando as tags mtw:list e mtw:loop. A tag list procura pela lista no output da action e coloca ela no context da página (pageContext). A tag loop pega essa lista e faz um loop, colocando cada item da lista no contexto da página. O método mtw:out exibe as propriedades dos itens da lista.

O Mentawai oferece um conjunto bastante poderoso de tags para acelerar o desenvolvimento dos seus JSPs em muitas ordens de grandeza se comparado com JSTL. E vale notar que com o Mentawai vc pode também utilizar JSTL sem qualquer restrição, se assim vc preferir.

Agora vamos partir para inclusão e edição de uma notícia, o que nos dará a oportunidade de ver como a validação do Mentawai funciona. Começamos criando as actions para insert e update:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   public String add&#40;&#41; throws Exception {
      
      if &#40;isPost&#40;&#41;&#41; {
         
         // we are inserting...
         
         News news = input.getObject&#40;News.class&#41;;
         
         newsService.create&#40;news&#41;;

         list&#40;&#41;; // you can chain actions as well if you want...
         
         return LIST;
         
      } else {
         
         // we want to insert...
         
         return SUCCESS;
      }
   }
   
   public String edit&#40;&#41; throws Exception {
      
      if &#40;isPost&#40;&#41;&#41; {
         
         // we are updating...
         
         int id = input.getIntValue&#40;"id"&#41;;
         
         if &#40;id &lt;= 0&#41; return ERROR;
         
         News news = newsService.load&#40;id&#41;;
         
         if &#40;news == null&#41; return ERROR;
         
         news = input.getObject&#40;news&#41;; // update object with input values...
         
         newsService.update&#40;news&#41;;
         
         return LIST;
         
      } else {
         
         // we want to edit...
         
         int id = input.getIntValue&#40;"id"&#41;;
         
         if &#40;id &lt;= 0&#41; return ERROR;
         
         News news = newsService.load&#40;id&#41;;
         
         if &#40;news == null&#41; return ERROR;
         
         output.setValue&#40;"news", news&#41;;
         
         return SUCCESS;      
      }
   }
</pre>
		</div>

Estamos utilizando o método isPost() para saber se a requisição foi um POST ou um GET. Se for um POST significa que o formulário HTML de inclusão foi submetido via POST e estamos tentando inserir uma nova notícia. Se for um GET, significa que estamos apenas querendo ir para a página com o formulário de inclusão, que no caso será /news/add.jsp. Para o caso de uma inclusão, utilizamos o método do input da action getObject(Class), que vai retornar um novo objeto News populado com os dados do input da action. De posse do objeto News, tudo que temos que fazer é chamar newsService.create(news) para criar uma nova notícia no banco de dados.

Para o update é um pouco diferente. Primeiro carregamos do banco de dados a notícia que queremo editar. Depois atualizamos esse objeto com os valores que estão no input da action, através do métdo getObject(Object). Com o objeto atualizado, resta apenas chamar newsService.update(news) para fazer o update no banco de dados.

Agora vamos partir para a validação e vc verá como é fácil e prático fazer a validação com o Mentawai.

Precisamos validar as inner actions add e edit e para tal vamos fazer a nossa action NewsAction implementar a interface <i>DynValidatable</i>.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   public void prepareValidator&#40;Validator validator, String innerAction&#41; {
      
      if &#40;isPost&#40;&#41; && innerAction != null && &#40;innerAction.equals&#40;"add"&#41; || innerAction.equals&#40;"edit"&#41;&#41;&#41; {
         
         // the messages below can move to an i18n file easily...
         
         validator.add&#40;"section", RequiredFieldRule.getInstance&#40;&#41;, "Required field!"&#41;;
         validator.add&#40;"section", IntegerRule.getInstance&#40;1&#41;, "Section must be an intenger!"&#41;;
         
         validator.add&#40;"title", RequiredFieldRule.getInstance&#40;&#41;, "Required field!"&#41;;
         validator.add&#40;"title", StringRule.getInstance&#40;10, 100&#41;, "Title must be between %min% and %max% characters!"&#41;;
         
         validator.add&#40;"body", RequiredFieldRule.getInstance&#40;&#41;, "Required field!"&#41;;
         validator.add&#40;"body", StringRule.getInstance&#40;20, 2000&#41;, "Body invalid!"&#41;;
      }
   }
</pre>
		</div>

E no ApplicationManager vc adiciona o filtro de validação global:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

      // ...

      // load list...
      DBListData servicos = new DBListData&#40;"sections", "ID", "NAME", "SECTIONS", "NAME"&#41;;
      addList&#40;servicos, connHandler&#41;;
      
      // validation for actions that implement Validatable or DynValidatable interface...
      filter&#40;new ValidatorFilter&#40;&#41;&#41;;
      
      // create a global connection filter...
      filter&#40;new ConnectionFilter&#40;"conn", connHandler&#41;&#41;;

      // ...
</pre>
		</div>

Vc pode escrever suas próprias <i>rules</i> para a validação ou vc pode utilizar as diversas <i>rules</i> que o Mentawai oferece. Por exemplo, uma StringRule vai validar se o valor do campo é uma string com um tamanho mínimo e máximo. Note também que embora estejamos colocando as mensagens de erro de validação no código, nada nos impede de colocá-las num arquivo i18n onde elas ficarão separadas do código-fonte e poderão ser internacionalizadas e alteradas com mais facilidade. Para as informações completas sobre a validação do Mentawai, clique <a href="http://www.mentaframework.org/validation.jsp" target="_new" rel="nofollow">aqui</a>.

Abaixo temos o JSP para a adição de uma nova notícia:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

&lt;%@ page contentType="text/html; charset=ISO-8859-1" %&gt; 
&lt;%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %&gt;

&lt;h1&gt;Adding news:&lt;/h1&gt;
&lt;form action="&lt;mtw:contextPath /&gt;/NewsAction.add.mtw" method="post"&gt;
&lt;table border="0" cellspacing="3" cellpading="3"&gt;
&lt;tr&gt;&lt;td&gt;
Section: &lt;/td&gt;&lt;td&gt;&lt;mtw:select name="section" list="sections" emptyField="true" /&gt; 
&lt;mtw:outError field="section"&gt;&lt;font color="red"&gt;&lt;mtw:out /&gt;&lt;/font&gt;&lt;/mtw:outError&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
Title: &lt;/td&gt;&lt;td&gt;&lt;mtw:input type="text" name="title" maxlength="200" size="50" /&gt;
&lt;mtw:outError field="title"&gt;&lt;font color="red"&gt;&lt;mtw:out /&gt;&lt;/font&gt;&lt;/mtw:outError&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
Body: &lt;/td&gt;&lt;td&gt;&lt;mtw:textarea name="body" cols="50" rows="10" /&gt;
&lt;mtw:outError field="body"&gt;&lt;font color="red"&gt;&lt;mtw:out /&gt;&lt;/font&gt;&lt;/mtw:outError&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&nbsp;&lt;/td&gt;&lt;td align="right"&gt;&lt;input type="submit" value="Add" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/form&gt;
</pre>
		</div>

Repare como estamos as tags do mentawai para facilitar nossa vida. Repare que se houver um erro de validação os valores serão automaticamente re-exibidos no formulário sem qualquer trabalho necessário da sua parte. Repare como estamos exibindo os erros com as tags condicionais mtw:outError.

Agora vamos ao JSP de edição, /news/edit.jsp:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

&lt;%@ page contentType="text/html; charset=ISO-8859-1" %&gt; 
&lt;%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %&gt;

&lt;h1&gt;Editing news:&lt;/h1&gt;
&lt;form action="&lt;mtw:contextPath /&gt;/NewsAction.edit.mtw" method="post"&gt;
&lt;mtw:bean value="news"&gt;
&lt;mtw:input type="hidden" name="id" /&gt;
&lt;table border="0" cellspacing="3" cellpading="3"&gt;
&lt;tr&gt;&lt;td&gt;
Section: &lt;/td&gt;&lt;td&gt;&lt;mtw:select name="section" list="sections" emptyField="true" /&gt; 
&lt;mtw:outError field="section"&gt;&lt;font color="red"&gt;&lt;mtw:out /&gt;&lt;/font&gt;&lt;/mtw:outError&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
Title: &lt;/td&gt;&lt;td&gt;&lt;mtw:input type="text" name="title" maxlength="200" size="50" /&gt;
&lt;mtw:outError field="title"&gt;&lt;font color="red"&gt;&lt;mtw:out /&gt;&lt;/font&gt;&lt;/mtw:outError&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
Body: &lt;/td&gt;&lt;td&gt;&lt;mtw:textarea name="body" cols="50" rows="10" /&gt;
&lt;mtw:outError field="body"&gt;&lt;font color="red"&gt;&lt;mtw:out /&gt;&lt;/font&gt;&lt;/mtw:outError&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&nbsp;&lt;/td&gt;&lt;td align="right"&gt;&lt;input type="submit" value="Add" /&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/mtw:bean&gt;
&lt;/form&gt;
</pre>
		</div>

Esse JSP é bem parecido com o de adição, mas com algumas diferenças importantes. Primeiro estamos usando a tag mtw:bean para colocar um bean que veio no output da action no escopo da página. Dessa maneira as nossas tags de formulário podem exibir os valores desse bean para que esses sejam alterados/editados. E veja que como estamos editando precisamos do ID do objeto que estamos editando, e para tal usamos um campo hidden.

Estamos quase finalizando a nossa aplicação e falta agora uma action para visualizar a notícia por inteiro, visto que a nossa listagem apenas mostra o título da notícia e não o seu corpo.

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
   public String view&#40;&#41; throws Exception {
      
      int id = input.getIntValue&#40;"id"&#41;;
      
      if &#40;id &lt;= 0&#41; return ERROR;
      
      News news = newsService.load&#40;id&#41;;
      
      if &#40;news == null&#41; return ERROR;
      
      output.setValue&#40;"news", news&#41;;
      
      return SUCCESS;
   }
</pre>
		</div>

/news/view.jsp:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
&lt;%@ page contentType="text/html; charset=ISO-8859-1" %&gt; 
&lt;%@ taglib uri="/WEB-INF/lib/mentawai.jar" prefix="mtw" %&gt;

&lt;h1&gt;View news:&lt;/h1&gt;
&lt;mtw:bean value="news"&gt;
&lt;table border="1" cellspacing="3" cellpading="3"&gt;
&lt;tr&gt;&lt;td&gt;
Section: &lt;/td&gt;&lt;td&gt;&lt;mtw:out value="section" list="sections" /&gt; 
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
Title: &lt;/td&gt;&lt;td&gt;&lt;mtw:out value="title" /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;
Body: &lt;/td&gt;&lt;td&gt;&lt;mtw:out value="body" /&gt;
&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/mtw:bean&gt;
</pre>
		</div>

Note que estamos utilizando de novo a tag mtw:bean e dessa vez estamos apenas imprimindo no página os valores de section, title e body. Veja que para a section, adicionamos a lista da onde os valores serão pegos, lembrando que section é apenas um ID que corresponde a um valor da lista de dados Sections.

Vamos adicionar os links na primeira página para editar / visualizar a notícia:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
&lt;td&gt;&lt;a href="&lt;mtw:contextPath /&gt;/NewsAction.view.mtw?id=&lt;mtw:out value="id" /&gt;"&gt;View&lt;/a&gt; &lt;a href="&lt;mtw:contextPath /&gt;/NewsAction.edit.mtw?id=&lt;mtw:out value="id" /&gt;"&gt;Editar&lt;/a&gt;&lt;/td&gt;
</pre>
		</div>

E tb um link para adicionar uma nova notícia no alto da tabela:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>
&lt;h4&gt;&lt;a href="&lt;mtw:contextPath /&gt;/NewsAction.add.mtw"&gt;Adicionar nova notícia&lt;/a&gt;&lt;/h4&gt;
</pre>
		</div>

Último detalhe: Note que a data está sendo exibida no formato americano MM/dd/YYYY. Isso se deve ao fato de o Mentawai por default ter o locale en_US.

Para corrigirmos isso podemos criar formatadores para a tag mtw:out, mas isso daria muito trabalho. Uma solução melhor é mudar o default do Mentawai para pt_BR e para isso tudo que temos que fazer é adicionar a seguinte linha no ApplicationManager:

<span class="genmed"><b>Code:</b></span><br>
		<div style="overflow: auto; width: 100%;">
		<pre>

LocaleManager.add&#40;"pt_BR"&#41;;

</pre>
		</div>

Feito isso o Mentawai se vira para imprimir as datas no formato pt_BR.

Para abaixar um WAR com essa aplicação completa, <a href="http://www.mentaframework.org/beta/MentaNews.war" target="_new" rel="nofollow">clique aqui</a>. (Não se esqueça de criar o seu banco de dados mysql antes de rodar a aplicação!)

Dúvidas e sugestões podem ser colocadas diretamente no nosso fórum, na seção de Comentários Gerais.

Um abraço e até a próxima!


]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#11521</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#11521</link>
				<pubDate><![CDATA[Sat, 11 Aug 2007 08:23:12]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>MentaNews: Passo a Passo de uma aplicação completa com o Mentawai [UNDER CONSTRUCTION]</title>
				<description><![CDATA[ Onde estão declarados os métodos <i>isPost()</i> e <i>isGet()</i>?

http://www.mentaframework.org/api/org/mentawai/core/BaseAction.html

Não encontrei. oO]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#11892</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#11892</link>
				<pubDate><![CDATA[Tue, 28 Aug 2007 14:28:55]]> GMT</pubDate>
				<author><![CDATA[ YkyMatt]]></author>
			</item>
			<item>
				<title>Re:MentaNews: Passo a Passo de uma aplicação completa com o Mentawai [UNDER CONSTRUCTION]</title>
				<description><![CDATA[ 
Documentação deve estar desatualizada...

Está no BaseAction sim, mas só o isPost, isGet não existe... (vc pode usar !isPost())]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#11893</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#11893</link>
				<pubDate><![CDATA[Tue, 28 Aug 2007 14:46:00]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Re:30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ Pergunta bem básica...

Onde ficam minhas páginas jsp neste projeto? em que diretório? como o mentawai sabe que elas estão lá? como faço para quando a url <a href='http://localhost:8080/MentaNews/' target='_new' rel="nofollow">http://localhost:8080/MentaNews/</a> for invocada, a aplicação seja direcionada para a página inicial?

 :!: ]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#14480</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#14480</link>
				<pubDate><![CDATA[Thu, 21 Feb 2008 08:03:49]]> GMT</pubDate>
				<author><![CDATA[ cassioso]]></author>
			</item>
			<item>
				<title>Re:30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ <p></p>

		<cite>cassioso wrote:</cite><br>
		<blockquote>Pergunta bem básica...

Onde ficam minhas páginas jsp neste projeto? em que diretório? como o mentawai sabe que elas estão lá? como faço para quando a url <a href='http://localhost:8080/MentaNews/' target='_new' rel="nofollow">http://localhost:8080/MentaNews/</a> for invocada, a aplicação seja direcionada para a página inicial?

 :!: &nbsp;
		</blockquote>

A página inicial tu configuras diretamente no <i>web.xml</i>.

Pesquise pelo atributo <i>welcome-file-list</i>.]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#14481</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#14481</link>
				<pubDate><![CDATA[Thu, 21 Feb 2008 08:10:46]]> GMT</pubDate>
				<author><![CDATA[ YkyMatt]]></author>
			</item>
			<item>
				<title>Re:30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ hummm.. vou dar uma olhada no <i>welcome-file-list</i>. valeu!

e quanto ao diretório onde vão ficar minhas páginas jsp?

até agora só consigo visualizar isto:

HTTP Status 404 - /MentaNews/NewsAction.test.mtw
--------------------------------------------------------------------------------
type Status report
message /MentaNews/NewsAction.test.mtw
description The requested resource (/MentaNews/NewsAction.test.mtw) is not available.
--------------------------------------------------------------------------------
Apache Tomcat/6.0.2]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#14482</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#14482</link>
				<pubDate><![CDATA[Thu, 21 Feb 2008 08:24:14]]> GMT</pubDate>
				<author><![CDATA[ cassioso]]></author>
			</item>
			<item>
				<title>Re:30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ Conforme as configurações do ApplicationManager 

As suas páginas devem estar na raiz de sua aplicação.]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#14483</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#14483</link>
				<pubDate><![CDATA[Thu, 21 Feb 2008 12:18:49]]> GMT</pubDate>
				<author><![CDATA[ IceW0lf]]></author>
			</item>
			<item>
				<title>Re:30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ 
Esse exemplo está meio desatualizado. :-(

Veja o mybooks que é o que tem de mais atual e moderno em termos de Mentawai.]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#14484</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#14484</link>
				<pubDate><![CDATA[Thu, 21 Feb 2008 17:04:02]]> GMT</pubDate>
				<author><![CDATA[ saoj]]></author>
			</item>
			<item>
				<title>Re:30) MentaNews: Passo a Passo de uma aplicação completa com o Mentawai</title>
				<description><![CDATA[ obrigado,

vou estudar o mybooks.

=]]]></description>
				<guid isPermaLink="true">http://forum.mentaframework.org/posts/list/1432.page#14589</guid>
				<link>http://forum.mentaframework.org/posts/list/1432.page#14589</link>
				<pubDate><![CDATA[Tue, 26 Feb 2008 07:50:23]]> GMT</pubDate>
				<author><![CDATA[ cassioso]]></author>
			</item>
	</channel>
</rss>
