Conhecendo o Spring

Preview:

DESCRIPTION

Apresentação desenvolvida originalmente para trabalho de disciplina na graduação de Tecnologia em Desenvolvimento para a Internet em 2006.

Citation preview

Simplificando o desenvolvimento Java/Java EE - 2006 Maurício Linhares http://techbot.me/

No início era apenas o profeta...

Eu trago a linguagem

que vai funcionar em

todas as plataformas! Liberdade!

Mas a liberdade virou Libertinagem

Eu faço melhor!

Não! Eu faço

melhor!

Só quem tá certo aqui sou eu!

Acabou a farra! Agora quem não

seguir as especificações vai para os campos de

concentração!

JCP Hitler

EJB, BMP, JMS, CMP, JAAS, JSP, JSTL, JCA,

JTA, JDBC, AWT, JNDI!

Aprendam ou morram!

Porque é tão complicado desenvolver

aplicações Java EE?

Já tá na hora de

simplificar isso.

Vamos criar um

Framework para

resolver esse

problema!

Vamos criar um framework!

Mas o que é um framework?

¡  Um esqueleto semi-pronto para ser estendido;

¡  Contém implementações genéricas;

¡  Deve tornar o difícil fácil e o impossível possível;

O que é?

E então surge o grande Salvador!

framework

E qual é a missão dele?

¡  Desenvolver aplicações Java EE tem que ser mais fácil;

¡  Programar para interfaces é melhor do que programar para classes concretas;

¡  Desenvolvimento orientado a objetos é mais importante do que a tecnologia utilizada;

O que ele oferece pra isso?

¡  Um container de Inversão de Controle;

¡  Abstração para o controle de transações;

¡  Abstração para bancos de dados; ¡  Programação Orientada a Aspectos; ¡  Integração com vários outros

projetos;

E quem disse que eu sei o que é essa tal de

Inversão de Controle?

A Inversão de Controle redefine...

...dois princípios da Orientação a Objetos

Objetos não devem mostrar suas intimidades...

Objetos devem ser auto contidos...

E o que é que a

Inversão de controle

diz?

Objetos devem informar os contratos que eles precisam implementar

Trabalhando com contratos (ou interfaces) as intimidades deles não vão interessar a ninguém

Os objetos devem dizer de quais objetos eles dependem

Pra que alguém possa fornecer essas dependências

Inversão de Controle também é...

... uma inversão de responsabilidades

Inversão de qual responsabilidade?

Os dois princípios foram realmente redefinidos?

O que? Quando? Porque? Onde está Wally?

Existem dois tipos de inversão

¡  Injeção de dependências;

¡  Busca por dependências;

Busca por dependências

¡  Quem precisa, tem que correr atrás;

¡  As dependências ficam em um contexto geral do sistema, ou não;

¡  Costumam ser disponibilizadas em eventos específicos;

Injeção de dependências

¡  Quem precisa, diz que precisa e recebe na mão;

¡  As dependências ficam onde elas quiserem ficar;

¡  Podem ser disponibilizadas a qualquer momento, depende de quem precisa;

Voltando ao nosso assunto...

... Vejamos como é possível acessar o Spring

Acessando o Spring

¡  Configurado com (mais um) arquivo XML;

¡  Os objetos ficam no ApplicationContext;

¡  Os objetos não podem depender de objetos que não estejam no ApplicationContext;

Um ApplicationContext pode ser criado pelas seguintes classes:

¡  FileSystemXmlApplicationContext ¡  ClassPathXmlApplicationContext ¡  Em uma aplicação web o contexto

normalmente é carregado por um ServletContextListener específico do Spring

Meu primeiro SpringBean

<bean id="autenticador" class="org.maujr.newsletter.Autenticador">

<property name="usuario"> <value>mauricio.linhares</value> </property> </bean>

Como ficam os objetos

¡  Todos são singletons por default; ¡  Cada um deve ter o seu próprio “id”;

¡  Podem ser referenciados em um arquivo e utilizados em outro;

¡  As dependências só são inseridas uma única vez;

¡  Não é possível acessar objetos que não tem um contrutor público;

Mas eu não quero

um Singleton!

Calma, calma!

<bean id="autenticador" class="org.maujr.newsletter.Autenticador“

singleton=“false”> <property name="usuario"> <value>mauricio.linhares</value> </property> </bean>

O ApplicationContext transforma automaticamente de String para:

¡  Tipos numéricos; ¡  Class; ¡  URL; ¡  File; ¡  Array de Strings (separando por

vírgulas);

E os outros tipos?

São transformados de String

para os seus objetos usando PropertyEditors customizados

Como eu crio um PropertyEditor?

¡  Extendendo a classe PropertyEditorSupport;

¡  Implementando os métodos setAsText() e getAsText();

¡  E basta registrar ele no ApplicationContext;

¡  99% das vezes isso não é necessário;

<property/>

Define uma propriedade do bean que vai ser inserida pelo Spring, pode conter diversas outras tags dentro dela

<constructor-arg/>

Funciona da mesma maneira que a tag <property/>, mas passa as dependências como parâmetros do construtor

<ref/>

Referencia um outro bean que esteja configurado. Pode ser um bean no mesmo arquivo ou em arquivos diferentes

Outras tags

¡  <props/> ¡  <list/> ¡  <map/> ¡  <set/> ¡  <value/>

E se eu não tiver

como chamar

um construtor

?

FactoryBeans estão na mão!

Implementando a interface FactoryBean

¡  O método getObject() retorna o objeto que essa fábrica deve produzir;

¡  O método isSingleton() avisa se o objeto produzido é um singleton ou não;

¡  O método getObjectType() deve retonar o tipo (Class) do objeto que esta fábrica produz;

Como implementar o acesso ao banco de dados no nosso sistema?

Por que não deixar as classes acessarem a classe utilitária diretamente?

Nosso primeiro FactoryBean

O gerenciador das conexões com o banco de dados

Qual a responsabilidade dele?

Abrir conexões com o banco de dados para que os repositórios possam trabalhar livremente

Como funciona o nosso banco?

Banco de dados ObjectServer

Conexões ObjectContainers

Em código...

ObjectServer bancoDeDados = Db4o.openServer(nomeDoArquivo, porta);

O que é um Repositório?

Um adaptador entre mecanismos distintos

Como é o nosso repositório?

public interface Repositorio {

public void adicionar(Persistivel objeto); public void atualizar(Persistivel objeto); public void remover (Persistivel objeto); public Persistivel pegarPeloId(Long id); public List pegarTodos(Class clazz);

}

A nossa implementação dele...

...é a classe RepositorioDoDb4o

Ei! Essa classe é abstrata!

O método getContainer() é abstrato

Então nós temos que encontrar uma maneira de oferecer os ObjectContaners da nossa fábrica

Mas ainda existe outro problema

O Repositório é um singleton, mas tem que receber novos ObjectContainers a cada chamada do método getContainer()

Como resolver isso?

¡  Criar uma classe que estenda a RepositorioDoDb4o;

¡  Implementar a interface ApplicationContextAware;

¡  Pegar o ApplicationContext e pegar os ObjectContainers diretamente;

Em código.... public class RepositorioSpring extends RepositorioDoDb4o

implements ApplicationContextAware { private ApplicationContext context; public ObjectContainer getContainer() { return context.getBean(“objectContainerFactory”); }

public void setApplicationContext(ApplicationContext context) { this.context = context; }

}

Isso tá muito

complicado!

Injeção de métodos

Um objeto Singleton pode depender de objetos não-Singleton sem problemas

Como isso é feito?

O Spring responde pela dependência em vez do objeto dependente

Em código

<bean id="repositorio" class="org.maujr.persistencia.db4o.RepositorioDoDb4o">

<lookup-method bean="objectContainerFactory" name="getContainer"/> </bean> <bean id="objectContainerFactory" class="org.maujr.persistencia.db4o.ObjectContainerFactory"/>

O que vai acontecer?

Sempre que o método getContainer() for chamado no Repositório, o FactoryBean que cria os ObjectContainers vai ser chamado

Complicando um pouco mais...

Ninguém está fechando as transações nem as conexões com o banco. Onde isto está acontecendo?

No FiltroDoDb4o

Ele faz o “commit” ou “rollback” das transações e no fim fecha a conexão com o banco de dados;

Em código...

try { chain.doFilter(request, response); ServerUtil.commitTransaction();

} catch (Exception e) {

e.printStackTrace(); ServerUtil.rollbackTransaction();

} finally {

ServerUtil.closeContainer(); }

E qual é a vantagem

disso?

Todo o código está livre da interação com o banco

O Spring provê mecanismos mais simples de se utilizar para os frameworks mais conhecidos, como o Hibernate

Spring MVC

Simplificando o Desenvolvimento web com o Spring

Peraí!

É necessário adicionar o Servlet que vai responder as requisições do Spring no web.xml com um mapeamento Sem o Servlet do Spring ele não pode responder a requisições feitas ao servidor

Características

¡  Várias classes de suporte para formulários e requisições normais;

¡  Transformação automática de valores do request para objetos;

¡  Suporte transparente a vários mecanismos de visualização;

¡  Totalmente configurado dentro do próprio Spring

¡  Os controladores não são thread-safe;

Mapeadores de URL

Existem várias estratégias disponíveis, mas os mais utilizados são BeanNameUrlHandlerMapping e o SimpleUrlHandlerMapping

BeanNameUrlHandlerMapping

Direciona as requisições para as classes através dos seus identificadores. Uma requisição para “/contados.html” seria enviada para o bean com o “ID” “/contados.html”

SimpleUrlHandlerMapping

Mais complexo, direciona as requisições através de um mapa de chaves e valores. É possível usar “curingas” “como “*” nas URLs.

Em código... <bean id="urlMapper"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<property name="mappings"> <props> <prop key="/noticia.html"> inserirNoticiaAction </prop> <prop key="/noticias.html"> listarNoticiasAction </prop> <prop key="/principal.html"> principalAction </prop> </props>

</property> </bean>

ViewResolvers

¡  São as classes responsáveis pela descoberta das views;

¡  Transformam nomes lógicos em uma requisição para a view apropriada;

Em código....

<bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">

<property name="basenames"> <value>views</value> </property> <property name="defaultParentView"> <value>mostrar-principal</value> </property> </bean>

Configurando...

mostrar-principal.class= org.springframework.web.servlet.view.velocity.VelocityView

mostrar-principal.url= org/maujr/velocity/principal.html

mostrar-principal.exposeSpringMacroHelpers= true

noticia.url=org/maujr/velocity/noticia.html noticia.exposeSpringMacroHelpers=true noticias.url=org/maujr/velocity/noticias.htm

A interface Controller

¡  É a interface base para a parte web do Spring;

¡  Define um único método, “handleRequest()” que deve retornar um objeto ModelAndView;

¡  Esse é o método chamado quando uma dessas classes recebe uma requisição HTTP;

Os objetos ModelAndView

¡  Servem como abstração para colocação de objetos que devem aparecer na visualização;

¡  Também recebe o nome lógico pelo qual a view responsável vai ser encontrada;

¡  Não é necessário indicar qual o tipo da view que vai gerar a resposta;

Controlador AbstractController

¡  Classe simples para a resposta a requisições diretas;

¡  Não é indicada para o uso de formulários;

¡  Pode responder a qualquer método HTTP;

¡  Não tem suporte a validação; ¡  O método que deve ser sobrescrito

é o handleRequestInternal()

Criando o ListarAction

¡  Um objeto que lista todos os objetos de uma certa classe;

¡  Faz uma busca utilizando o

repositório;

Propriedades do nosso objeto

private Class classe; private String view; private Repositorio repositorio;

Em código...

protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {

ModelAndView mv = new ModelAndView( this.getView() ); mv.getModel().put("objetos", this.getRepositorio().pegarTodos( this.getClasse()) ); return mv; }

O Controlador SimpleFormController

¡  É utilizado para lidar com formulários;

¡  Faz a conversão automática de tipos primitivos e também pode registrar seus próprios PropertyEditors;

¡  Tem suporte a validação; ¡  Os objetos podem ficar na sessão

ou podem ser recriados a cada requisição

Configurando <bean id="inserirNoticiaAction"

class="org.maujr.action.FormAction"> <property name="commandClass"> <value>org.maujr.noticia.Noticia</value> </property> <property name="formView"> <value>noticia</value> </property> <property name="successView"> <value>noticias-redirect</value> </property> <property name="validator"> <ref bean="noticiasValidator"/> </property> <property name="repositorio"> <ref bean="repositorio"/> </property>

</bean>

É o mesmo objeto para o GET e o POST

¡  No GET ele carrega o objeto e coloca ele para ser visualizado no método formBackingObject();

¡  No POST ele faz a validação do

formulário e se não tiver nenhum erro chama o método onSubmit();

Criando o FormAction

¡  É responsável por inserir e editar os objetos no banco de dados;

¡  É capaz de tranformar todas as propriedades simples;

¡  Pode ser extendido para lidar com propriedades complexas;

Quando ele recebe um GET

String id = request.getParameter("chave");

if ( id != null ) { Persistivel objeto =repositorio.pegarPeloId( new Long(id) ); return objeto;

}

return super.formBackingObject(request);

Quando ele recebe um POST

this.getRepositorio().adicionar( (Persistivel) command);

return new ModelAndView( this.getSuccessView() );

Sequência de execução do Spring MVC

Não estou vendo a validação!

A validação é feita pela interface Validator

Basta implementar os métodos supports() e validate(). Quando ocorrer um erro, chama-se o método “reject()” no objeto Errors, o Spring retorna a requisição e mostra o erro automaticamente.

Em código...

public void validate(Object obj, Errors errors) {

Pessoa pessoa = (Pessoa) obj; if (pessoa.getNome() == null) {

errors.rejectValue(“nome”, “obrigatorio”, “Este campo é obrigatório”); }

}

Revisando...

O que é...

Inversão de controle?

Quais são os...

Tipos de inversão de controle?

É possível...

Utilizar objetos que não tenham construtores públicos?

O que é...

Um FactoryBean?

Todos os objetos...

Tem que ser singletons?

E então?

Acabou?

Agora eu vou

dominar a Fenda do Biquini!

Não tão rápido! Ainda falta o Velocity!

O que é o Velocity?

É uma ferramenta de geração texto dinamicamente, para aplicações desktop ou web

Como ele funciona?

¡  Você escreve um arquivo de texto qualquer com as diretivas da Velocity Template Language (VTL);

¡  Manda o Velocity carregar o arquivo;

¡  Cria um conjunto de objetos que vai ser utilizado para gerar o resultado;

¡  E recebe um String com o que for criado;

VelocityEngine

¡  É a classe que é utilizada para se acessar o Velocity;

¡  Faz o carregamento dos Templates; ¡  Uma mesma VelocityEngine pode

ser reutilizada por toda a aplicação;

Configurando uma VelocityEngine

engine = new VelocityEngine();

Properties props = new Properties();

props.put("resource.loader", "class"); props.put("class.resource.loader.class",

ClasspathResourceLoader.class.getName()); props.put("class.resource.loader.cache",

"false");

engine.init(props);

Criando e executando um template

Template template = engine.getTemplate("org/maujr/velocity/noticias.html");

Context context = new VelocityContext();

List<Noticia> noticias = new ArrayList<Noticia>();

//criando as notícias context.put("objetos", noticias);

Writer writer = new StringWriter(); template.merge(context, writer); System.out.println(writer.toString());

O que é a VTL?

É uma linguagem simples para o tratamento dos templates

Utilizando uma variável do Context

¡  $nomeDaVariável – Declaração simples

¡  ${nomeDaVariavel} – Declaração completa

¡  $!{nomeDaVariavel} – Declaração silenciosa

Chamando métodos

Métodos que não recebem parâmetros podem ser chamados normalmente, como em: ${pessoa.calcularPeso()}

Acessando propriedades JavaBeans

Propriedades JavaBeans podem ser acessadas da mesma maneira que em Expression Language: ${noticia.titulo} ${aluno.curso.nome}

Tem alguma diferença?

<a href=“/verArtigo/$command.id.do”> Ver artigo

</a>

<a href=“/verArtigo/${command.id}.do”> Ver artigo

</a>

Como criar uma variável no template?

Usando #set: #set( $nome = “Maurício”)

Execução Condicional - #if

¡  Operador para tratar condições ¡  Recebe um boolean ¡  Se o valor retornar “null” ele

interpreta como false ¡  Pode conter uma condição #else ¡  Pode conter várias condições #elseif

para funcionar como um switch ¡  Pode conter os operadores ==, >=,

<= e !=

Em código....

#if (${command.id}) <input type="hidden"

name="chave" value="$!{command.id}"/>

#end

Em código com #else e #elseif

#if (${command.id}) <input type="hidden"

name="chave" value="$!{command.id}"/>

#elseif (${command.id} == 10) O valor do id é 10

#else

Caiu no Else

#end

Passeando pelas coleções com #foreach

¡  Faz a iteração dentro de todas as coleções do Java

¡  Não tem controle nativo do tamanho do loop

¡  O contador pode ser acessado pela variável ${velocityCounter}

Em código...

#foreach($noticia in ${objetos}) <tr> <td>${noticia.titulo}</td> <td>${noticia.texto}</td> <td> <a href="noticia.html?chave=${noticia.id}">

Editar </a> </td> </tr> #end

E esse #springBind é

o que?

É um #macro!

Um macro é uma função que pode ser reutilizada em vários templates diferentes

Como se define isso?

#macro (nomeDoMacro $variavel $outraVariavel $maisOutra)

escreve qualquer coisa

#end

Onde colocar isso?

¡  Macros devem ser colocados em arquivos separados

¡  Eles são carregados pelo próprio Velocity quando uma VelocityEngine é criada, através da propriedade “velocimacro.library”

Em código...

velocimacro.library=spring.vm Ou se forem vários: velocimacro.library=

spring.vm,struts.vm,webwork.vm

Incluindo conteúdo estático com #include

Inclui um arquivo de texto qualquer, mas não faz avaliações de VTL ou variáveis

Em código

#include(“noticias.html”) #include(“noticias.html”, “rodape.html”, “topo.html”)

Incluindo templates dinâmicos com #parse

Funciona do mesmo modo que o #include, mas faz avaliação de conteúdo dinâmico em VTL

E agora?

Acabou? Mais alguma coisa? Tá na hora de ir pegar o menino na escola?

Agora eu vou colocar em prática o

meu plano maligno!

A aplicação de exemplo precisa de novas funcionalidades

¡  Cadastrar, editar e listar usuários

¡  Montar as mensagens de e-mail que vão ser enviadas para cada endereço

Trabalhem!

Referências

¡  Harrop, Rob; Machacek, Jan. Pro Spring. Apress, 2005.

¡  Harrop, Rob. Pro Jakarta Velocity. Apress, 2004.

¡  Evans, Eric. Domain Driven Design:Tackling Complexity in the Heart of Software. Addisson-Wesley, 2004

Referências

¡  Johnson, Rod; Hoeller, Juergen. Expert One-On-One J2EE Development Without EJB. Wrox Press, 2004

¡  Johnson, Rod. Expert One-On-One J2EE Development. Wrox Press, 2002

Trilha Sonora

Arch Enemy – Doomsday Machine

Black Label Society - Mafia

Trilha Sonora

Therion – Lemuria & Sirus B

Nickelback – All The Right Reasons