[Logo] Mentawai Recipes
  [Search] Search   [Recent Topics] Recent Topics   [Hottest Topics] Hottest Topics   [Members]  Member Listing   [Groups] Back to home page 
[Moderation Log] Moderation Log   [Register] Register / 
[Login] Login 
Messages posted by: saoj
Forum Index » Profile for saoj » Messages posted by saoj
Author Message
Para agilizar as coisas para quem está começando com o Mentawai, preparamos um projeto completo com as principais funcionalidades do framework. Trata-se de uma aplicação web onde você pode realizar um cadastro, se logar, editar esse cadastro e dar logout.

Essa aplicação pode e deve ser utilizada como ponto de partida para outras aplicações web.

Os seguintes conceitos são utilizados:

Validação
Autenticação
Redirect after Login
IoC
Auto-Wiring
Pool de Conexões
Tratamento de Exceções
ORM (Mapeamento de Beans no BD)
Diversas tags do Mentawai (mtw:requiresAuthentication, mtw:bean, etc.)


Baixe o projeto aqui: http://www.mentaframework.org/files/MentaBlank.zip

Abaixa descreveremos um passo a passo de como colocar esse projeto para rodar dentro do Eclipse, assumindo que você possui o Tomcat e o Sysdeo instalado no seu ambiente de desenvolvimento.

Selecione a opção do menu File -> Import. Escolha a opção "Existing Projects into Workspace". Clique em "Next".





Selecione a opção "Select archive file", clique em "Browse" e selecione o arquivo MentaBlank.zip que você baixou. Você deverá visualizar o projeto MentaBlank selecionado na caixa de texto logo abaixo.





Clique em "Finish" e um novo projeto "MentaBlank" será criado no seu eclipse. Antes de colocarmos ele para rodar no Tomcat precisamos criar um database para ele. O MentaBlank utiliza o MySQL, mas é bastante fácil alterá-lo para qualquer BD de sua preferência.

Vá no diretório WEB-INF/db e lá você encontrará dois arquivos:

MentaBlank.sql com o script SQL para gerar a base de dados da aplicação
grant.txt com o sql para criar o usuário "MentaBlank" no MySQL

Crie um database "MentaBlank", rode os arquivos acima e o seu banco-de-dados estará pronto para receber a nossa aplicação.

Repare que no AppManager.java, a configuração do Pool de Conexões é feita nas seguintes linhas:


Agora para testar sua aplicação clique em Project -> Properties. Selecione a opção "Tomcat" e faça as seguintes alterações abaixo:





Clique em "Ok", inicie o seu Tomcat e acesse a URL http://localhost:8080/MentaBlank/ para testar a aplicação.

Obs: Versão para Eclipse WTP pode ser baixada em: http://www.mentaframework.org/files/MentaBlankWTP.zip (por Hélio Frota)
Especificação:

A aplicação de referência é bastante simples:

Uma tela de login, uma tela de cadastro, uma página principal de boas-vindas e uma tela para alterar o seu cadastro.

No ato do cadastro, o usuário escolherá um grupo (Guest, Admin ou Master). Esse grupo poderá ser alterado na tela de alteração de cadastro.

Um usuário do grupo Guest não poderá alterar o seu cadastro.

No ato do cadastro, o usuário escolherá um idioma (Inglês ou Português). Esse idioma poderá ser alterado na tela de alteração de cadastro.

A aplicação será apresentada no idioma escolhido pelo usuário.

Ao se cadastrar, o usuário receberá um email com os dados da sua conta. Esse email deve estar no idioma escolhido pelo usuário.

O username deve ser único por usuário, ou seja, dois usuários diferentes não podem possuir o mesmo username.

Aplicação rodando:

http://menta.seducaotecnologica.com.br/

Telas:

- Tela inicial para o login:



- Tela de cadastro:



- Tela de boas-vindas:



- Tela de boas-vindas para o Guest: (sem possibilidade de ir para alteração de cadastro)



- Tela para alteração de cadastro:


Ao invés de começar documentando todas as funcionalidades do Mentawai, que são muitas, optamos por disponibilizar uma aplicação completa como referência. Dessa maneira você pode olhar o código, ver exemplos de várias funcionalidades e decidir por si só a respeito da praticidade e simplicidade do Mentawai em relação aos outros frameworks.

As características particulares do Mentawai, que o diferenciam de outros frameworks, são:

Full-stack (completo e auto-suficiente, não necessitando de outros frameworks)
KISS principle (se você não sabe ou não consegue fazer algo a culpa é do framework, não sua)
Configuração Programática (sem XML ou annotations)

A aplicação de referência pode ser baixada do SVN:

svn co svn://saoj-la.dyndns.org/menta/trunk Menta

Você também pode vê-la rodando aqui: http://menta.seducaotecnologica.com.br/

Clique aqui para as instruções de como importar esse projeto para dentro do seu Eclipse.

Poderíamos utilizar o bom marketing para convence-lo de que o Mentawai é bom, mas ao invés disso estaremos incentivando a política do SHOW DON'T TELL (mostre não fale) com um comparativo de frameworks através da aplicação de referência. Essa política funciona assim:

Estarei disponibilizando vários repositórios de SVN, um para cada framework como VRaptor, Struts, Spring MVC, etc.

Uma pessoa com experiência no framework X pode solicitar uma senha de committer para o repositório do framework X.

Feito isso ela pode implementar a aplicação de referência com o framework X de forma que possamos compará-la às outras implementação com diferentes frameworks.

Essaa implementações serão disponibilizadas lado-a-lado com a implementação de referência do Mentawai, ou seja, você poderá decidir por conta própria o framework de sua preferência.

A especificação completa da aplicação de referência pode ser consultada aqui: http://forum.mentaframework.org/posts/list/0/2406.page

Abaixo listamos as funcionalidades do Mentawai exemplificadas na aplicação de referência:

1) Autenticação

Filtro de autenticação para bloquear/permitir o acesso às actions
Tags de autenticação para bloquear/permitir os acesso às páginas (JSP, Velocity, etc.)
Redirect after login, ou seja, quando um usuário acessa uma página sem estar logado, ele é redirecionado para a página de login. Após um login bem sucedido ele é novamente redirecionado para a página que ele inicialmente tentou acessar.

2) Autorização

Filtro de autorização para bloquear/permitir o acesso às actions
Tags de autorização para bloquear/permitir o acesso às páginas (JSP, Velocity, etc.)
Tags de autorização para exibir/remover partes de uma página
Setar os grupos que um usuário logado pertence (a autorização ou não é concedida de acordo com os grupos do usuário logado)

3) Internacionalização (i18n)

Arquivos de i18n ficam dentro do diretório i18n. Os nomes são master_pt_BR.i18n, master_en_US.i18n, etc. Um arquivo (com possibilidade de prefixos para as chaves) para tudo, ao invés de vários arquivos espalhados pela aplicação, como um por action por exemplo.
Para mensagens que vieram de dentro das actions (mensagens dinâmicas de successo ou erro por exemplo, validação, etc.)
Para textos dentro do JSP, com tags aceitando prefixos e valores dinâmicos como por exemplo Hello $1.
Reload automático quando os arquivos de propriedades (i18n) são alterados. Você não quer ter que re-iniciar a sua aplicação porque mudou "Olá" para "Oi".
Tradução padrão quando uma chave não é encontrada (para Produção).
Exibição de texto com erro (! en_US.hello !) quando uma chave não é encontrada (para QA).
Localização para imagens através de uma tag para imprimir o sub-diretório do locale.

4) IoC

IoC completo, integrado com o framework, sem a necessidade de Spring. Mas quem quiser usar Spring também pode.
Configuração programática para IoC ao invés de usar um milhão de XMLs. Perguntem para o Google porque eles resolveram lançar o Guice.

5) Mensagens dinâmicas vindo das actions

"Sua conta foi atualizada com sucess"
Integração limpa e fácil com o sistema de i18n, ou seja, essas mensagens virão do arquivo master i18n.

6) Lista de dados estáticos

É bastante recorrente a necessidade de ter combos com listas estáticas, como grupos, idiomas, países, etc.
Eles precisam ser igualmente internacionalizados
Tags para facilmente exibir esses combos em um formulário HTML
Tags para facilmente exibir um valor (localizado) para um determinado id.

7) Filtros

Não estamos falando aqui de filtros de Servlet, mas de filtros do framework, como os interceptors do Struts.
Filtros precisam ser simples para que você possa fazer os seus e fáceis de usar, para que você possa utilizar os que o framework oferece.

8 ) Validação

Integrada com o i18n
Tags fáceis para mostrar os erros nas páginas
Jeito fácil de validar uma action (implementando uma interface ou filtro por exemplo)

9) Jeito fácil de testar as actions

JUnit para as actions sem complexidades, mocks, etc.

10) Tags pra a view

Diversas tags para facilitar a sua vida na view, muito melhores do que as genéricas da JSTL.
Facilidade para criar suas próprias tags, sem qualquer complexidade ou enrolação (abstraindo a bagunça inicial da api de JSP)
Tags para paginação e muitas outras. Ou você faz a paginação na mão com código no JSP?

11) Enviando email

Tem que ser integrado com o i18n, ou seja, cada usuário recebe um email no seu idioma. Os emails ficam separados dentro do diretório /letters, com um sub-diretório para cada locale.
Tem que suportar algum tipo de template, porque você precisa carregar um email e fazer algumas substituições no corpo da mensagem, como username, password, etc.
Tem que corretamente suportar charsets, caso contrário o usuário receberá lixo para os caracteres acentuados.
Tem que suportar emails em plain/text e também em HTML.
Precisa suportar defaults para hostname, from, authentication, etc. para que você só precise configurar isso uma vez de acordo com o ambiente (produção, QA, dev, etc.)
Precisa suportar o desativamento dos envios de email para quando você está rodando os unit tests. De maneira fácil e na configuração! (Não vai sair colocando IF em tudo)
Tem que suportar envio assíncrono, ou seja, na maioria das vezes você não quer bloquear a action enquanto o email está sendo enviado.
Tem que suportar SSL se você quiser utilizar o SMTP do GMAIL.
E não se esqueça do título do email, que precisa também ser internacionalizado e suportar templates.

12) Configurações por ambiente

As configurações estáticas e textuais, como dados de conexão com o banco, smtp, hibernate, logging, etc. precisam ser carregadas de um arquivo properties. A aplicação deve suportar um arquivo properties por ambiente, além de um default que pode ser sobrescrito pelo mais específico do ambiente.

13) Suporte a dois tipos de persistência (opcional)

a aplicação pode suportar JDBC ou Hibernate, ou seja, ela implementa uma versão dos DAOs com JDBC e outra com HIBERNATE. De acordo com uma variável de ambiente ("persistency") ela decide quais implementações do DAO ela vai utilizar. A flexibilidade de IoC demonstrada na prática.



1) Importando para o Eclipse:

A aplicação de referência utiliza o Maven2. Com o maven é bastante fácil importar um projeto Java qualquer para dentro do Eclipse. Siga os passos abaixo:

Caso ainda não tenha, instale o SVN na sua máquina: http://subversion.tigris.org/

Caso ainda não tenha, instale o Maven 2.x.x na sua máquina: http://maven.apache.org

Utilize o comando abaixo para fazer o checkout da aplicação de referência. O diretório 'Menta' será criado com a aplicação.

svn co svn://saoj-la.dyndns.org/menta/trunk Menta

Vá para dentro do diretório Menta e execute 'mvn clean install'. Os testes deverão ser executados e o WAR da aplicação gerado.

Ainda dentro do diretório Menta, execute 'mvn eclipse:eclipse -Dwtpversion=2.0'. Feito isso o seu projeto está pronto para ser importado para dentro do Eclipse.

Utilize a função Import... do Eclipse para importar o diretório Menta. Um novo projeto será criado no Eclipse.

OBS: Para os testes unitários o banco H2 é utilizado, logo não é necessário instalar ou configurar nenhum banco de dados.

2) Configurando o banco de dados: (para rodar a aplicação no TOMCAT)

Caso ainda não tenha, instale o MYSQL na sua máquina: http://www.mysql.org

Crie um database com o nome 'Menta'

Conceda permissões para o usuário 'menta' acessá-lo do localhost:

grant all privileges on Menta.* to 'menta'@'localhost' identified by 'menta';

3) Inicializando o banco de dados:

Execute o script 'WEB-INF/db/menta.sql' para a inicialização do banco de dados, tomando cuidado com o charset que deve ser UTF-8:

Vá para o diretório 'WEB-INF/db' onde está o script menta.sql

Acesse o seu banco de dados utilizando o mysql client:

mysql -u menta -p Menta

Ative o charset UTF-8:

SET NAMES utf8;

Execute o script menta.sql:

source menta.sql;

4) Rodando no Tomcat:

Para executar a aplicação você pode utilizar o SYSDEO (plugin do Tomcat para Eclipse) ou o WTP (integração do Eclipse com o Tomcat). Caso utilize o SYSDEO você precisará configurá-lo para reconhecer um projeto Maven. Siga os passos abaixo:

Vá em propriedades do seu projeto e selecione Tomcat

Coloque 'src/main/webapp' como "Subdirectory to set as web application root (optional)"

Ative o DevLoader e selecione os jars que deverão ser utilizados pelo Tomcat. Veja imagem no final desse post.

5) Deployando o WAR em um Tomcat standalone:

Copie o menta.war para dentro do webapps do seu Tomcat.

Restarte o seu tomcat

Um diretório menta deverá ser criado no webapps com sua aplicação.

6) Problemas de permissão com o Tomcat:

A aplicação utiliza o método System.getenv() para acessar uma variável de ambiente. É possível que o Tomcat não permita essa operação devido ao seu SecurityManager. Isso ocorreu comigo no tomcat6 rodando em um Ubuntu Server, mas não no meu tomcat6 rodando no Mac. Para resolver isso você pode desativar o SecurityManager assim:

Abra o arquivo /etc/default/tomcat6

Adicione a seguinte linha:

TOMCAT6_SECURITY=no

Reinicie o seu Tomcat

OBS: Você também pode tentar fazer um ajuste fino no SecurityManager do Tomcat dentro do diretório 'policy-d'.

Ativando o DevLoader para o Sysdeo:

Simon Brown postou no seu blog uma aplicação simples com o objetivo de comparar vários frameworks web, ou seja, de avaliar como cada um se comportaria na hora de implementar essa aplicação simples.

Link do blog:

http://weblogs.java.net/blog/simongbrown/archive/2005/11/comparing_webap.html

Implementação com o Mentawai:

http://www.mentaframework.org/wp/index.php

Implementação com o Rife:

http://rifers.org/blogs/gbevin/2006/3/16/comparing_web_frameworks_rife

Implementação com o Struts1:

http://weblogs.java.net/blog/simongbrown/archive/2006/01/comparing_webap_7.html

Implementação com o Wicket:

http://weblogs.java.net/blog/simongbrown/archive/2006/03/comparing_webap_8.html

Implementação com o Stripes:

http://weblogs.java.net/blog/simongbrown/archive/2006/03/comparing_webap_9.html

Implementação com o WebWork:

http://weblogs.java.net/blog/simongbrown/archive/2006/03/comparing_webap_10.html
Esse artigo tem como intuito analisar a mesma aplicação web implementada por dois frameworks bastante diferentes: Mentawai e Seam.

A implementação com o Seam pode ser analisada e baixada aqui:
http://www.infoq.com/articles/jboss-seam

A implementação com o Mentawai pode ser baixada aqui: (Utilizamos o banco de dados embarcado H2 de forma que vc não precisa se preocupar em criar/configurar o seu próprio banco de dados para esse exemplo)
http://www.mentaframework.org/files/Menta_versus_Seam.zip

Alguns pontos que vc deve observar em relação a implementação com o Mentawai:

Foi difícil configurar um pool de conexões? Duas linhas de código e temos um pool de conexões configurado sem qualquer enrolação.

Repare como a arquitetura da aplicação com o Mentawai fica bem dividida e organizada. Temos nossas actions, entities, repositórios (ou DAOs), implementações para os nossos repositórios (ou DAOs) e nossos serviços onde as regras do negócio serão utilizadas.

Repare que vc utilizou Inversão de Controle de uma maneira bem simples e fácil, sem precisar de Spring ou outro framework. No ApplicationManager estamos dizendo que o nosso UserRepository será do tipo H2UserRepository. Se amanhã quizermos utilizar um OracleUserRepository, tudo que temos que fazer é mudar a configuração de IoC (1 linha).

Repare que vc utilizou Auto-Wiring de uma maneira bem simples e fácil, sem precisar de Spring ou outro framework. No ApplicationManager estamos dizendo que tudo que precisar de uma Connection irá receber automaticamente uma Connection. No nosso exemplo o H2UserRepository vai receber essa connection via auto-wiring.

Repare que as configurações da sua aplicação ficam centralizadas em um único lugar e que a linguagem utilizada na configuração é o Java (poderia ser outras linguagens também).

Repare que para algumas configurações bem burras e estáticas podemos utilizar também o arquivo properties default chamado AppManager.properties que deve estar no diretório WEB-INF. (mais info sobre isso aqui)

Repare como foi fácil persistir o objeto User no banco de dados utilizando o MentaBean. Repare que a sua entidade e o seu modelo de negócios não receberam qualquer tipo de anotação, em outras palavras, estão totalmente desacopladas do framework web.

Repare que vc não precisou escrever uma linha de SQL para persistir o seu objeto User no banco de dados e que se amanhã vc quiser mudar o seu mecanismo de persistencia para Hibernate, IBatis, JPA, Arquivos Texto, Lista em Memória, etc. tudo que vc tem que fazer é implementar uma nova versão do UserRepository e reconfigurar o seu IoC.

Repare como a sua action UserAction é bem simples e como vc pode validar campos, obter objetos (Pojos) populados com os dados do seu formulário, retornar facilmente vários resultados, criar várias inner actions, etc.

Repare que na camada de apresentação o Mentawai te oferece diversas tags simples e poderosas como mtw:outError, mtw:list, mtw:loop, mtw:isEmpty, etc. Nada te impede de usar JSTL ou EL, mas as tags do Mentawai são bem mais simples, poderosas e com menos verbosidade pois se encaixam perfeitamente ao framework, enquanto as JSTL são genéricas para todos os frameworks. (Migre o hello.jsp para JSTL e analise por si mesmo!)

Se amanhã eu quiser colocar a minha aplicação num ambiente distribuído (pouco provável), tudo que eu tenho que fazer é transformar os meus services em web services. (recomendamos xFire para isso) Partir do pressuposto que toda aplicação web vai ser integrada com EJB como o Seam faz não é legal. Dá para entender porque ele faz isso: JBoss

Estrutura da Aplicação e Classes:



User.java


UserRepository.java


H2UserRepository.java


UserService.java


UserAction.java


ApplicationManager.java


AppManager.properties


hello.jsp


web.xml

- Validação:

O Struts2 oferece validação via XML ou Annotations.

A documentação do Struts2 continua sendo, na minha opinião, pouco objetiva e pouco clara. Clique aqui para acessar a documentação oficial sobre validação, e tire suas próprias conclusões. Repare que não há nenhum código Java, apenas XML.

Validação via XML: (repare que existe código Java dentro do XML !!!! )



Validação via Annotations: (como deturpar o uso de annotations assim como foi feito com o uso de XML)

Clique aqui para ver que isso está na documentação oficial do Struts2



Mais uma vez a configuração programática do Mentawai mostra todo o seu poder facilitando a implementação dessa funcionalidade tão essencial e importante:

Filtro de Validação do Mentawai: (pode ser aplicado em mais de uma action)

Ou vc pode também fazer a validação diretamente na action através da interface Validatable: http://recipes.mentaframework.org/posts/list/4.page



E para internacionalizar essas mensagens, tudo que vc precisa fazer é criar um arquivo HelloWorldValidator_en_US.i18n dentro do diretório /validation:



E o filtro de validação ficaria assim:



- Internacionalização:

A documentação oficial do Struts para internacionalização está aqui: http://struts.apache.org/2.x/docs/localization.html

Mais uma vez a documentação deixa em aberto as seguintes questões:

- Struts2 utiliza ResourceBundle, o que provavelmente vai forçar um restart da aplicação a cada mudança nos arquivos properties do resourcebundle.

- Se o locale do meu usuário está salvo no banco, como forço para que o locale da aplicação seja esse locale para esse usuário?

- Tenho a opção de criar apenas um único arquivo onde todo o meu conteúdo internacionalizado estará presente (arquivo master) ?

- O Struts2 permite internacionalizar actions colocando arquivos properites dentro do pacote da action. É boa prática colocar os arquivos de internacionalização separados do seu código e num lugar que possa ser acessível pelo designer e/ou tradutor. (Ou vc programador vai fazer essa tarefa?)

Compare o approach do Struts2 com o approach do Mentawai e tire suas próprias conclusões: http://www.mentaframework.org/i18n.jsp?loc=pt


- Conversão:

Assim como sua documentação, os conversores do Struts não são nem simples, nem claros, nem pragmáticos:



É difícil entender e/ou justficar algo tão bizarro acima para algo tão simples como uma conversão, principalmente quando olhamos a versão do Mentawai abaixo:



- Filtros:

A configuração dos filtros é feita via XML, como sempre. Se tivermos que por exemplo aplicar o mesmo filtro em 100 actions diferentes, teremos que usar copy/paste e transformar a nossa configuração num arquivo XML gigantesco. Em contrapartida, se utilizarmos configuração programática, podemos fazer um for/loop, métodos, if, etc.

Veja o exemplo de um interceptor do Struts:



Reparem que, talvez pela falta de um INPUT/OUTPUT para as actions, o interceptor acima está fortemente acoplado a action MyAction, ou seja, só pode ser aplicado a ela.

Na versão do Mentawai ficaria assim:

(reparem que o filtro abaixo poderá ser aplicado em qualquer action, e não apenas MyAction)



Aguardem mais comparativos !!!
Fonte: http://www.javafree.org/content/view.jf?idContent=1


Código ou arquivos de configuração

Um assunto separado, mas freqüentemente adicionado, é quando usar arquivos de configuração ou código sobre uma API para amarrar os serviços. Para a maioria das aplicações que tem de ser instaladas em vários lugares, um arquivo de configuração separado normalmente faz mais sentido. Quase sempre será um arquivo XML, e isto faz sentido. Entretanto, há casos onde é mais fácil usar código de programação para fazer a montagem. Um caso é onde se tem uma aplicação simples, que não tem muitas variações de instalação. Neste caso, um pouco de código pode ser mais claro que um arquivo XML separado.

Um caso constrastante é onde a montagem é muito complexa, envolvendo passos condicionais. Uma vez que se chega mais próximo de uma linguagem de programação, o XML começa a entrar em colapso, e é melhor usar uma linguagem real que tem toda a sintaxe para se escrever um programa claro. É feita então uma classe construtora que faz a montagem. Se há diferentes cenários de montagem, pode-se prover várias classes construtoras e usar um arquivo de configuração simples que faz a seleção entre eles.

Muitas vezes penso que as pessoas estão ansiosas demais por definir arquivos de configuração. Muitas vezes, uma linguagem de programação serve como um mecanismo de configuração direto e poderoso. Linguagens modernas podem facilmente compilar pequenos montadores que podem ser usados para juntar plugins em sistemas maiores. Se a compilação é trabalhosa demais, existem também linguagens script que podem funcionar muito bem.

É freqüentemente falado que arquivos de configuração não deveriam usar uma linguagem de programação, porque eles precisam ser editados por não-programadores. Mas quão freqüente este é o caso? As pessoas realmente esperam que não-programadores alterem os níveis de isolamento de transações de aplicações servidoras complexas? Arquivos de configuração que não usam uma linguagem de programação funcionam bem apenas enquanto simples. Se eles se tornaram complexos, então é hora de pensar sobre usar uma linguagem de programação apropriada.

Uma coisa que vemos no mundo Java no momento é uma dissonância de arquivos de configuração, onde cada componente tem seus próprios arquivos de configuração, que são diferentes de quaisquer outros. Se uma dúzia destes componentes forem usados, pode-se facilmente acabar com uma dúzia de arquivos de configuração que devem ser atualizados.

Meu conselho aqui é sempre prover uma maneira de fazer toda a configuração facilmente com uma interface programática, e então tratar o arquivo de configuração separado como uma característica opcional. Pode-se facilmente construir a manipulação de um arquivo de configuração usando uma interface programática. Quando se cria um componente, deve-se deixar a cargo do usuário quando utilizar a interface programática, o formato padrão do arquivo de configuração, ou criar seu próprio formato de arquivo, amarrando-o à interface programática.
Separando Configuração do Uso

A coisa mais importante nisto tudo é assegurar-se de que a configuração dos serviços seja separada de seu uso. Isto é um princípio fundamental do design próximo à separação entre interfaces e implementação. É algo que vemos dentro de um programa orientado-a-objetos quando lógica condicional decide que classe instanciar, e então, futuras avaliações desta condição é feita por polimorfismo ao invés de ter código condicional duplicado.

Se esta separação é útil dentro de uma única base de código, é especialmente vital quando se usa elementos externos, como componentes e serviços. A primeira questão é se é desejável deferir a escolha da classe de implementação para instalações particulares. Se sim, é necessário o uso de alguma implementação de plugin. Uma vez que plugins estejam sendo utilizados, é essencial que a montagem dos plugins seja feita separadamente do resto da aplicação, para que seja possível substituir diferentes configurações facilmente para diferentes instalações. Como se consegue isto é secundário. Este mecanismo de configuração pode tanto configurar um service locator quanto usar injeção para configurar os objetos diretamente.

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

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

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

Now we talk about consequences for other types of output:

1) AJAX consequence generating JSON:

Action:

Configuration:

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

Action:

Configuration:



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

When the user is authenticated, you set his locale:

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

/i18n/master_en_US.i18n

/i18n/master_es_ES.i18n

Then in the JSP you can do:

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

/i18n/master_en_US.i18n

/i18n/master_es_ES.i18n

Then in the JSP you do:

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

/i18n/master_en_US.i18n

/i18n/master_es_ES.i18n

An in the JSP:

And there is much more:

You can have localized texts inside your actions.

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

You can use placeholders to help the designer:

You can configure what to do if the key is not found: show the default locale translation or show the key with exclamation marks around it so someone can spot the problem and fix it. (good for QA)
An authenticated user can belong to one or more groups. All you have to do is:

Now to protect access to an action you can do:

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

And how to protect access to an JSP page

1) Blocking access to a page:

2) Block access to a portion of the page:

Mentawai also supports authorization by permissions. For more info see here: http://www.mentaframework.org/authorization.jsp
After checking username and password, in any way you want, you decide that your user is authenticated. So you do:

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

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

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

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

That's it. Mentawai also supports redirect after login in a very simple way. See here: http://www.mentaframework.org/authentication.jsp
Below we have a simple tutorial for the features of the Mentawai integration with JRuby

Simple API to call ruby methods on any Ruby object from Java
JRubyWrapper for making ruby method calls even easier
Support method chaining. Ex: "methods.sort.grep"
Auto-reload any ruby file from the loadpath
Load any ruby file from the classpath with the loadFromClasspath method
Get a singleton instance of the JRubyInterpreter anywhere in your code with the JRubyInterpreter.getInstance() method
Support all JRuby environment variables and provide defaults for them. Ex: JRUBY_OPTS for -rubygems and -Ku , JRUBY_SHELL, JRUBY_SCRIPT, JRUBY_LIB and JRUBY_HOME.
Windows and Linux support


The file foo.rb anywhere in your loadpath (Ruby equivalent of Java's classpath)

OBS: Don't forget to change this file to see how it will be automatically reloaded by JRubyInterpreter.



Plug and play with JRubyInterpreter:



Using the JRubyWrapper:




Abaixo temos um resumo completo das funcionalidades do suporte a JRuby do Mentawai. (somente em inglês) (a partir da versão 1.15) (baixe o jar beta aqui)

Simple API to call ruby methods on any Ruby object from Java
JRubyWrapper for making ruby method calls even easier
Support method chaining. Ex: "methods.sort.grep"
Auto-reload any ruby file from the loadpath
Load any ruby file from the classpath with the loadFromClasspath method
Get a singleton instance of the JRubyInterpreter anywhere in your code with the JRubyInterpreter.getInstance() method
Support all JRuby environment variables and provide defaults for them. Ex: JRUBY_OPTS for -rubygems and -Ku , JRUBY_SHELL, JRUBY_SCRIPT, JRUBY_LIB and JRUBY_HOME.
Windows and Linux support


The file foo.rb anywhere in your loadpath (Ruby equivalent of Java's classpath)

OBS: Don't forget to change this file to see how it will be automatically reloaded by JRubyInterpreter.



Plug and play with JRubyInterpreter:



Using the JRubyWrapper:




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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

 
Forum Index » Profile for saoj » Messages posted by saoj
Go to:   
Powered by JForum 2.1.8 © JForum Team