Pular para o conteúdo principal

Um pouco sobre a arquitetura do ScrumToys


O ScrumToys é um projeto que nasceu com o propósito de demonstrar o maior número possível de funcionalidades do JSF 2.0. Contudo, o ScrumToys vai alem e realiza alguns desafios que foram encontrados durante o seu refactoring para ser incorporado à versão final do NetBeans 6.8.

A primeira versão!


A primeira versão do ScrumToys foi desenvolvida aplicando efetivamente o padrão de projeto MVC. Através deste padrão, a camada view foi implementada com os componentes visuais do JSF, a camada controller foi implementada através de Managed Beans configurados via anotações e a camada model se distribuía em classes JavaBeans para realizar alguns componentes de negócios, entidades persistentes (JPA) e persistência através de Data Access Objects (DAOs). Estas várias camadas realizavam o ScrumToys para rodar no JBossAS 4.2.3 com banco de dados baseado no MySQL Database Server 5.0. Além disso, o projeto foi criado inicialmente através do Eclipse.

O refactoring!


Para simplificar ao máximo esta aplicação de demonstração, esta passou por um refactoring completo na camada model, além de uma revisão detalhada da camada de apresentação (view e controller). Neste refactoring, foi necessário tomar algumas decisões em prol da simplicidade que deixariam qualquer desenvolvedor purista de cabelos em pé. Algumas destas decisões envolveram:
  • Migrar o projeto do Eclipse para o NetBeans (inicialmente o NetBeans 6.7.1);
  • Alterar e eliminar possíveis configurações da aplicação Web para rodar no Glassfish sem a necessidade de configurações extras (tornando-o plug'n play);
  • Usar o banco de dados JavaDB (antigo Derby) que já vem integrado numa instalação padrão do NetBeans e do Glassfish. Isso eliminaria a necessidade de instalar um MySQL, criar um usuário e um esquema no banco;
  • Simplificar a configuração do JPA para usar o TopLink ou Eclipse Essentials, além de criar o banco de dados automaticamente no esquema padrão que já existe no JavaDB do NetBeans. Notamos que o Glassfish v2 (ainda Java EE 5) usa o TopLink como implementação de JPA 1.0 e o Glassfish v3 (que já é Java EE 6 e está embutido no NetBeans 6.8) usa o Eclipse Essentials, como implementação de JPA 2.0 (código aberto e doado do TopLink pela Oracle para o Eclipse.org, considerada a implementação de referência do JPA).
  • E agora a decisão de projeto mais radical e ofensiva para alguns desenvolvedores: simplificar a camada model ao eliminar componentes de negócios e todos os Data Access Object. Assim, a lógica necessária para persistência e manipulação das entidades de negócios seriam implementadas na camada controller (dentro dos Managed Beans).
A última decisão de projeto, levou a uma arquitetura muito mais simples em detrimento da organização comumente recomendada para as camadas de uma aplicação web robusta e escalonável. Mas, esta arquitetura permitiu evitar o uso de Enterprise JavaBeans para o gerenciamento do contexto de persistência e demarcação de transação com recursos do EJB Container. Aspecto que fugiria do escopo do projeto e do propósito inicial da demonstração implementada. Contudo, mesmo ao eliminar os DAOs, a aplicação ainda precisaria ter acesso ao contexto de persistência (JPA) e realizar a demarcação da transação (neste caso, demarcação programática) dentro dos Managed Beans.

Uma nova arquitetura!


A segunda versão da aplicação, após o refactoring, passou a oferecer uma arquitetura simples através de classes que realizam simplesmente o propósito de demonstrar o maior número possível de funcionalidades do JSF 2.0, sem desviar a atenção para outras tecnologias que constituem o Java EE 6.

Como parte do processo de simplificação da arquitetura e para atender a necessidade de gerenciar um contexto de persistência e demarcação dentro dos Managed Beans da camada controller, a seguinte classe abstrata foi implementada para servir de base para todos os Managed Beans implemenatados.
package jsf2.demo.scrum.web.controller;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import javax.persistence.EntityManagerFactory;
import javax.transaction.UserTransaction;
// Outros imports foram omitidos ...

/**
* @author Dr. Spock (spock at dev.java.net)
*/
public abstract class AbstractManager {

@PersistenceUnit
private EntityManagerFactory emf;
@Resource
private UserTransaction userTransaction;

protected final <T> T doInTransaction(PersistenceAction<T> action)
throws ManagerException {
EntityManager em = emf.createEntityManager();
try {
userTransaction.begin();
T result = action.execute(em);
userTransaction.commit();
return result;
} catch (Exception e) {
try {
userTransaction.rollback();
} catch (Exception ex) {
Logger.getLogger(AbstractManager.class.getName()).log(Level.SEVERE,
null, ex);
}
throw new ManagerException(e);
} finally {
em.close();
}
}

protected final void doInTransaction(PersistenceActionWithoutResult action)
throws ManagerException {
EntityManager em = emf.createEntityManager();
try {
userTransaction.begin();
action.execute(em);
userTransaction.commit();
} catch (Exception e) {
try {
userTransaction.rollback();
} catch (Exception ex) {
Logger.getLogger(AbstractManager.class.getName()).log(Level.SEVERE,
null, ex);
}
throw new ManagerException(e);
} finally {
em.close();
}
}

protected static interface PersistenceAction<T> {
T execute(EntityManager em);
}

protected static interface PersistenceActionWithoutResult {
void execute(EntityManager em);
}

// Alguns outros métodos foram omitidos

}
Esta classe aplica os padrões de projeto Template Method e Strategy ao disponibilizar o método doInTransaction() que demarca a transação via JTA e permite receber o algoritmo de persistência através de uma implementação de callback ao realizar a "inner" interface PersistenceAction ou PersistenceActionWithoutResult. Esta implementação foi inspirada em classes presentes na arquitetura do Spring Framework chamadas de Template que encapsulam códigos padrões.

Como os Managed Beans são componentes gerenciados e deverão herdar o código base apresentado acima, o Web Container Java EE 6 realizará a injeção de dependência ao fornecer referências válidas de objetos aos atributos dos tipos EntityManagerFactory e UserTransaction.

O diagrama a seguir ilustra a estrutura básica dos Managed Beans implementados no ScrumToys usando a classe abstrata acima como base.


O Managed Bean ProjectManager herdará a capacidade de persistência e já terá uma demarcação simples de transação através dos métodos Template doInTransaction(). A seguir está um fragmento de código deste controller.
package jsf2.demo.scrum.web.controller;

import jsf2.demo.scrum.model.entities.Project;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
// Outros imports foram omitidos

/**
* @author Dr. Spock (spock at dev.java.net)
*/
@ManagedBean(name = "projectManager")
@SessionScoped
public class ProjectManager extends AbstractManager
implements Serializable {

private static final long serialVersionUID = 1L;
private Project currentProject;
private DataModel<Project> projects;
private List<SelectItem> projectItems;
private List<Project> projectList;

@PostConstruct
public void construct() {
this.currentProject = new Project();
init();
}

// ...

public void init() {
try {
setProjectList(doInTransaction(new PersistenceAction<List<Project>>() {
public List<Project> execute(EntityManager em) {
Query query = em.createNamedQuery("project.getAll");
return (List<Project>) query.getResultList();
}
}));
} catch (ManagerException ex) {
Logger.getLogger(ProjectManager.class.getName()).log(Level.SEVERE,null,ex);
}
projectItems = new LinkedList<SelectItem>();
projectItems.add(new SelectItem(new Project(), "-- Select one project --"));
if (getProjectList() != null) {
projects = new ListDataModel<Project>(getProjectList());
for (Project p : getProjectList()) {
projectItems.add(new SelectItem(p, p.getName()));
}
}
}

// ...

public String remove() {
final Project project = projects.getRowData();
if (project != null) {
try {
doInTransaction(new PersistenceActionWithoutResult() {
public void execute(EntityManager em) {
if (em.contains(project)) {
em.remove(project);
} else {
em.remove(em.merge(project));
}
}
});
getProjectList().remove(project);
} catch (Exception e) {
Logger.getLogger(getClass()).log(Level.SEVERE,
"Error on try to remove Project: " + getCurrentProject(), e);
addMessage("Error on try to remove Project", FacesMessage.SEVERITY_ERROR);
return null;
}
}
init();
// Using implicity navigation, this request come from /projects/show.xhtml
// and directs to /project/show.xhtml could be null instead
return "show";
}

// Alguns métodos foram omitidos.

}
Veja, no código acima, as linhas 33 a 38 que aplica o uso do Template Method doInTransaction() e do callback do tipo PersistenceAction para recuperar da base de dados todas as instancias persistidas de projetos. Este trecho de código herda o gerenciamento do EntityManager (abri e fechar) e a demarcação de transação (begin/commit/rollback). Outro exemplo se encontra entre as linhas 58 e 66, ao usar o callback do tipo PersistenceActionWithoutResult.

A simplicidade tornando-se referência!


A arquitetura proposta no ScrumToys influenciou a implementação de alguns códigos dos exemplos contidos no livro JavaServer Faces 2.0, The Complete Reference escrito pelo Ed Burns, líder da especificação do JSF 2.0 no JCP, e pelo Chris Schalk, Developer Advocate no Google. Algumas páginas deste livro estão disponívels no Google Books:

JavaServer Faces 2.0, The Complete Reference


Segue abaixo uma página deste livro citando a arquitetura de persistência e gerenciamento de transação implementada na aplicação Virtual Trainer.


Luz, câmera, AÇÃO!


O vídeo a seguir ilustra a criação de um projeto no NetBeans 6.8 para ter acesso aos códigos do ScrumToys e avaliar a implementação da arquitetura proposta em ação.


Para mais informações sobre este projeto:
By Spock
http://blog.spock.com.br/
http://twitter.spock.com.br/
http://www.springbrasil.com.br/
Outros posts: http://blog.globalcode.com.br/search/label/Spock

Comentários

Marcio Duran disse…
Artigo interessante, e bem explicado entretanto:

ScrumToys é dependente da IDE NetBeans 6.8 para rodar na sua especificação,e na mesma velocidade sem crachs de erro posso executar no Eclipse atual, alguma recomendação ?

Thanks !!!!
Dr. Spock disse…
O ScrumToys está otimizado para rodar no Glassfish v3 com JavaDB. Não depende do NetBeans 6.8. Se durante a criação do projeto ScumToys através do wizard do NB8 for selecionada a categoria "Exemplos | Maven", será criado um projeto sem os arquivos específicos do NetBeans, mas terá um POM para build através do Maven. Assim, torna-se possível criar o projeto para o Eclipse usando algumas instruções do Maven. Contudo, ainda será necessário fazer as devidas configurações do servidor de aplicações no Eclipse.

Uma versão do ScrumToys portada para rodar no JBossAS 6 está disponível para download em http://dl.dropbox.com/u/3027034/jib2010/Scrumtoys.Jboss6M2.zip
Outros detalhes em: http://blog.globalcode.com.br/2010/05/jsf-20-uma-evolucao-nas-interfaces-web.html
Marcio Duran disse…
Obrigado , pelos esclarecimentos !!!

Vou procurar fazer os devidos testes, eu comentei sobre o Eclipse pois ele é o padrão pra o desenvolvimento Comercial preferido pelas empresas, poderia não ter features compativeis mas vou tentar por aqui....

Valeu !!!!
Filipe Névola disse…
Artigo muito bem explicado e conciso. Parabéns
Cristiano Moraes disse…
Olá, onde posso baixar o ScrumToys para Glassfish sem precisar fazer o download do Netbeans ?
Dr. Spock disse…
Este projeto está no repositório do Mojarra (JSF RI). Veja em:
https://mojarra.dev.java.net/source/browse/mojarra/trunk/jsf-demo/sandbox/scrumtoys2009/eclipseProject/
Instruções para download estão em:
https://mojarra.dev.java.net/source/browse/mojarra/

Postagens mais visitadas deste blog

10 reasons why we love JSF

1. One-slide technology: it's so simple that I can explain basic JSF with one slide. 2. Easy to extend: components, listeners, render kit, Events, Controller, etc. 3. Real-world adoption: JBoss, Exadel, Oracle, IBM, ... 4. Architecture model: you can choose between more than 100 different architecture. 5. Open-mind community: using JSF you are going to meet very interesting people. 6. We are using JSF the last 5 years and we found very good market for JSF in Brazil 7. Progress: look to JSf 1.1 to JSF 1.2, JSF 1.2 to JSF 2.0. People are working really hard! 8. Many professionals now available 9. It's a standard. It's JCP. Before complain, report and help! 10. Ed Burns, spec leader, is an old Globalcode community friend! EXTRA: My wife is specialist in JSF. She's my F1 for JSF :) Nice job JSF community! -Vinicius Senger

O que é Lógica de programação?

Este é o segundo de uma série de posts voltados aos leitores do blog que estão dando início à carreira de desenvolvimento de software. O assunto de hoje é a lógica de programação. Para ler antes: Entendendo como funciona a programação de computadores: linguagens de programação, lógica, banco de dados A lógica de programação é um pré-requisito para quem quer se tornar um desenvolvedor de software, independente da linguagem de programação que se pretende utilizar. Mas o que é de fato a Lógica de Programação e como saber se eu tenho esse pré-requisito? A lógica de programação nada mais é do que a organização coerente das instruções do programa para que seu objetivo seja alcançado. Para criar essa organização, instruções simples do programa, como mudar o valor de uma variável ou desenhar uma imagem na tela do computador, são interconectadas a estruturas lógicas que guiam o fluxo da execução do programa. Isso é muito próximo ao que usamos em nosso cotidiano para realizar atividad...

Facelets uma forma mais ágil para construção de telas – Parte I

A construção de telas ou camada de apresentação em um sistema MVC seja web ou desktop é uma tarefa complexa e de extrema importância. Nesse post vou comentar e mostrar algum exemplo do Facelets como solução para os desafios existentes nessa etapa especificamente para web. Com a web cada vez mais presente em nosso dia-a-dia, um fato é que com isso nossos usuários tornam-se mais exigentes em relação a usabilidade, agilidade, performance ou de uma forma bem resumida “o usuário espera uma navegação simples e agradável aonde uma determinado tarefa possa ser concluída em poucos passos e em um curto espaço de tempo”. Atender as expectativas em relação ao que o usuário espera com o que realmente ele precisa, definir uma estrutura flexível a mudanças sem engessar o desenvolvimento, acessibilidade, portabilidade em múltiplos navegadores, tudo isso e muito mais, num prazo que quase sempre é apertado. Um outro ponto fundamental é manter o time motivado e produtivo em um ambiente que favoreça a...

JavaMail: Enviando mensagem HTML com anexos

Introdução Depois do post "JavaMail: Enviando e-mail com Java" , que apresentava como enviar um e-mail com Java, resolvi complementar a assunto apresentando como enviar uma mensagem formatada, em HTML , e também como realizar o envio de anexos. Bibliotecas Além da biblioteca JavaMail, veja mais no post anterior , é necessário incluir o JavaBeans Activation Framework (JAF), apenas se a versão utilizada for anterior ao JSE 6.0 , que já tem o JAF incluso. O JAF está disponível em http://www.oracle.com/technetwork/java/javase/downloads/index-135046.html , e neste download encontramos, alguns exemplos na pasta demo , documentação, incluindo javadocs, na pasta docs e a biblioteca activation.jar , que deve ser acrescentada no classpath da aplicação para versões anteriores ao JSE 6.0. Exemplo Primeiramente devemos realizar a configuração da javax.mail.Session e da javax.mail.internet.MimeMessage , estes passos podem ser vistos no post anterior . Agora vamos montar um...

Alguma certificação Java nos seus planos em 2010 ?

A discussão sobre certificações é super polêmica, alguns acham muito importante, outros acham totalmente insignificante. Eu particularmente acho que é uma meta de aprendizado, que nos força a aprender bem detalhadamente uma tecnologia. É claro que é "burlável" quero dizer, todo mundo conhece alguém que é certificado e "não sabe nada". Mas, evidentemente quando você se prepara, estuda, vai aprender muitas coisas novas e solidificar ainda mais seu conhecimento. Eu sempre fui muito "orientada" por deadlines... estas metas nos obrigam a encaixar algumas horas de estudo nesta vida tão corrida. E o inicio do ano é muito bom para estas iniciativas, porque estamos um pouco mais descansados, com aquele espírito de inicio de ano. Imagine chegar em março e já ter cumprido uma das metas de final de ano, e estar com a certificação "tirada" ? Não acho que precisa ser um caçador de certificações, e tentar tirar todas as certificações possíveis, mas acho ...

Sistema interativo de TV Digital com Ginga-J

No início de 2009, os estudantes de Sistema de Informação do Centro Universitário de Votuporanga ( UNIFEV ), Caio César Pereira de Souza e Rodrigo Gonçalves Constantino me apresentaram uma proposta para que eu fosse co-orientador junto ao professor orientador Djalma Domingos da Silva , em seu Trabalho de conclusão de curso (TCC) com tema TV Digital. A base que motivou o assunto, foi a palestra apresentada por Maurício Leal na I Conferência Java Noroeste sobre o tema TV Digital, realizada em 2006 em Votuporanga-SP. Ficamos muito entusiasmados com a possibilidade de interatividade na TV Digital, e a grande quantidade de possibilidades de desenvolvimento de aplicativos nesta área. Acompanhamos de perto as notícias na imprensa e todo o esforço e iniciativas realizadas pelo Fórum do Sistema Brasileiro de TV Digital Terrestre (SBTVD) , que organizou e produziu especificações ABNT, normatizando o sistema de TV Digital Terrestre. O foco do TCC foi realizar o desenvolvimento de uma pequena ...