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

Transmissão do minicurso Google App Engine

Os minicursos gratuitos realizados através da iniciativa Open4Education da Globalcode têm sido transmitidos ao vivo em forma de webcast e eu tenho acompanhado pessoalmente muitos deles, conversado com os alunos no chat, observando a qualidade e as limitações das transmissões. Sem dúvida o aproveitamento presencial é muito maior, principalmente pelo networking e pelo foco dado ao conteúdo. Mas, para aqueles que não estão em São Paulo o custo benefício é sensacional. Mesmo perdendo um pouco nas transmissões, é muito melhor poder assistir os minicursos à distância. Com o sucesso das transmissões do Profissão Java e do The Developer's Conference 2010 queremos melhorar e atingir um público ainda maior, e é por isto, que iremos fazer a primeira transmissão ao vivo em parceria com a WTV Streaming hoje! Os principais benefícios desta parceria são: Transmissão do vídeo e não apenas do conteúdo que está sendo projetado Captação e edição do conteúdo, para posterior disponibilizaç...

Brasil e a força de trabalho: Futuro incerto

Mais de 70 mil brasileiros estariam empregados se tivessem formação em TI (...) Apesar do bom salário, este profissional tem se tornado artigo raro no Brasil, o que explica as vagas neste setor estarem entre as dez mais difíceis de serem preenchidas (...) MDIC (Ministério do Desenvolvimento, Indústria e Comércio Exterior) vai avaliar carência de profissionais de TI no país (...) O presidente do Confea admitiu, no entanto, que, no curto e no médio prazo, parte das vagas terá de ser ocupada por profissionais do exterior porque o país não terá como suprir as carências de imediato (...). Notícias como estas estão sendo veiculadas todo o tempo e há anos. Em novembro de 2010 postei em Globalcoder´s um artigo sobre esta mesma questão e, passados quase seis meses, parece-me que o cenário realmente mudou ... para pior. Assim como as notícias sobre este fato, temo também em tornar-me entediante com a minha abordagem insistente em destacar esta que considero uma verdadeira calamidade nac...

Voucher Retake até 31/01

Um boa noticia para quem esta estudando para alguma certificação Java e precisa de um incentivo. Esta rolando a promoção do Voucher Retake para as certificações Java, Oracle Solaris (Cluster) e NetBeans, mas corram pois é apenas até 31/01. Para quem nunca ouviu falar do Voucher Retake, trata-se de um Voucher igual ao convencional que te permite fazer uma prova de certificação, mas com a possibilidade de refazê-la em caso de reprovação. E o período é o mesmo, ou seja, um ano para as duas tentativas. Com a Sun essa promoção já era esperada todo inicio de ano, mas como não sabemos qual será a estratégia da Oracle daqui pra frente então vale a pena aproveitar e divulgar. O local de compra é um "easter egg" dentro do site da Oracle, pois não esta tão acessível como deveria. Você precisa entrar no site: http://education.oracle.com, ai vai aparecer um banner no topo com três páginas, clique na terceira página onde haverá um link "comece agora" que direciona para página...

Construindo um império com R$40,00

Algo que nós da  YaW temos nos dedicado com bastante afinco nos últimos meses é o Google AppEngine(GAE) . Para quem ainda não conhece, o GAE é um ambiente de runtime disponibilizado pelo Google onde você hospeda a sua aplicação sem precisar se preocupar com manutenção de servidores. E ainda ganha com tudo isso a escalabilidade proporcionada pelos servidores do próprio Google. Hoje ele dá suporte a duas linguagens: Python e Java(e a grande maioria dos seus frameworks de mercado como Struts 1 e Struts 2, JSF 1 e JSF 2, JPA com algumas limitações, EhCache, GWT, SpringMVC, etc. Lista completa aqui ). Um detalhe importante sobre o GAE é que de início ele é completamente gratuito, e possui uma quota(beeeem generosa) de utilização, a partir do momento que você ultrapassar esta quota você tem de pagar pelo que ultrapassou. Detalhes sobre as quotas aqui . O próprio site da YaW está hospedado no GAE. E o que isso tudo tem ha ver com os R$40,00 e o império que você quer cri...

Vídeo Tutorial sobre Spring Roo + GWT + GAE

Após um longo período sem escrever para o Globalcoders, I'm back! Para o retorno preparei para a comunidade um vídeo tutorial demonstrando o uso do Spring Roo via linha de comando e via ferramenta Spring Tool Suite (STS). Neste tutorial, além da narração, crio uma aplicação chamada de ScroomToys utilizando o mesmo modelo de dados da demo do JSF 2 chamada de ScrumToys presente na ferramenta NetBeans . A parte final do tutorial mostra como gerar a interface (UI) da aplicação usando GWT ( Google Web Toolkit ) e a instalação na infra de cloud computing da Google chamada de GAE ( Google App Engine ). Chega de papo. Então, Luz, Câmera e Ação! Todos os slides desta apresentação estão disponíveis através do Blog do Spock no post: TDC2010 em Floripa foi sensacional! Enjoy it! By Spock Twitter: @drspockbr http://blog.spock.com.br/ http://linkedin.spock.com.br/ http://www.springbrasil.com.br/ Outros posts: http://blog.globalcode.com.br/search/label/Spock