Java-magazine 138 Epflqpoig

76

description

Java Magazine 138 completa com destaque para o artigo Rest X Soap

Transcript of Java-magazine 138 Epflqpoig

  • Edio 138 2015 ISSN 1676-8361

    Editor

    Eduardo Spnola ([email protected])

    Consultor Tcnico Diogo Souza ([email protected])

    ProduoJornalista Responsvel Kaline Dolabella - JP24185

    Capa Romulo Araujo

    Diagramao Janete Feitosa

    DistribuioFC Comercial e Distribuidora S.A

    Rua Teodoro da Silva, 907, Graja - RJ

    CEP 20563-900, (21) 3879-7766 - (21) 2577-6362

    Fale com o Editor!

    muito importante para a equipe saber o que voc est achando da revista: que tipo de artigo voc gostaria de ler, que artigo voc mais gostou e qual artigo voc menos gostou. Fique a vontade para entrar em contato com os editores e dar a sua sugesto!Se voc estiver interessado em publicar um artigo na revista ou no site Java Magazine, entre em contato com o editor, informando o ttulo e mini-resumo do tema que voc gostaria de publicar:

    EDuaRDo olivEiRa SPnola

    eduspinola.wordpress.com

    @eduspinola / @Java_Magazine

    Assine agora e tenha acesso a todo o contedo da DevMedia:www.devmedia.com.br/mvp

    atendimento ao leitorA DevMedia possui uma Central de Atendimento on-line, onde voc pode tirar suas dvidas sobre servios, enviar crticas e sugestes e falar com um de nossos atendentes. Atravs da nossa central tambm possvel alterar dados cadastrais, consultar o status de assinaturas e conferir a data de envio de suas revistas. Acesse www.devmedia.com.br/central, ou se preferir entre em contato conosco atravs do telefone 21 3382-5038.

    [email protected] 21 3382-5038

    anncios Anunciando nas publicaes e nos sites do Grupo DevMedia, voc divulga sua marca ou produto para mais de 100 mil desenvolvedores de todo o Brasil, em mais de 200 cidades. Solicite nossos Media Kits, com detalhes sobre preos e formatos de anncios.

    Java, o logotipo da xcara de caf Java e todas as marcas e logotipos baseados em/ ou referentes a Java so marcas comerciais ou marcas registradas da Sun Microsystems, Inc. nos Estados Unidos e em outros pases.

    EXPEDiEnTE

  • Sumrio

    A Java Magazine tem que ser feita ao seu gosto. Para isso, precisamos saber o que voc, leitor, acha da revista!

    D seu voto sobre esta edio, artigo por artigo, atra-vs do link:

    www.devmedia.com.br/javamagazine/feedback

    D

    seu Fe

    edback

    sob

    re esta edio

    D seu feedback sobre esta edio!

    06 Criando uma aplicao corporativa em Java Parte 2[ Bruno Rafael Sant Ana ]

    20 Web services REST versus SOAP[ Web services REST versus SOAP ]

    30 Twitter Finagle: Desenvolvendo sistemas distribudos[ Leonardo Gonalves da Silva ]

    Contedo sobre Novidades, Artigo no estilo Soluo Completa

    Contedo sobre Engenharia de Software

    52 Conformao arquitetural: sincronizando o cdigo e a arquitetura do projeto [ Gabriel Novais Amorim ]

    42 Spring MVC: Construa aplicaes responsivas com Bootstrap Parte 2 [ Pablo Bruno de Moura Nbrega e Marcos Vinicios Turisco Dria ]

    Contedo sobre Novidades, Artigo no estilo Curso

    61 Construindo e otimizando um ambiente de alta disponibilidade Parte 1 [ Cleber Muramoto ]

  • EstE artigo faz partE dE um curso

    6 Java Magazine Edio 138

    Nesse artigo mostraremos como desenvolver toda a camada de per-

    sistncia da aplicao criada para gerenciamento de bibliotecas. Isso

    inclui a implementao das entidades e do DAO, alm de um esquema

    para gerenciamento de transaes. Para tirar proveito dos recursos

    disponveis na plataforma Java EE, faremos uso de um Interceptor

    relacionado ao CDI que ir gerir todas as transaes. Tambm ser

    mostrado como criar uma classe conversora (com a anotao @Conver-

    ter) para converter o estado dos atributos LocalDate de uma entidade

    em algum tipo de dado adequado que possa ser gravado no banco

    de dados. Essa possibilidade de converso que a JPA prov muito

    til na hora de persistirmos entidades com atributos tipados com as

    novas classes da API de data e hora do Java 8 como, por exemplo, a

    classe LocalDate. Dessa forma, este artigo de grande importncia

    para todos os leitores que buscam adquirir conhecimento sobre os

    recursos disponveis dentro da plataforma Java EE.

    Fique por dentro

    Como desenvolver a camada de persistncia com o Hibernate

    Criando uma aplicao corporativa em Java Parte 2

    Na primeira parte do artigo abordamos sobre a origem das especificaes JSF, JPA e CDI e fa-lamos um pouco sobre elas. Tambm deixamos todo o ambiente de desenvolvimento configurado, alm de criarmos o projeto no Eclipse. A essa altura, nosso projeto j contm o arquivo persistence.xml, que um dos principais requisitos para trabalharmos com JPA, porm isso apenas o incio quando se trata de persistncia de dados. Para podermos armazenar os dados em alguma base de dados, temos que criar tambm as classes que representaro nossas entidades, e para isso usaremos todos os conceitos sobre mapeamento objeto/relacional apresentados no primeiro artigo da srie.

    Ainda falando sobre persistncia, importante pla-nejarmos quais de nossas classes acessaro o banco de dados, pois no uma boa prtica ter cdigo de acesso a dados espalhado por todo o sistema. Por isso, faremos uso do padro Data Access Object, mais conhecido como DAO, que ser composto por diversas classes e interfa-ces. At poderamos lidar com transaes dentro dessas classes, o que comum de se ver em muitas aplicaes, mas optamos por uma soluo mais elegante, que far uso de um Interceptor para interceptar as chamadas aos mtodos que precisem de transaes.

    Como o leitor pode perceber, construir a parte que lida com a persistncia dos dados envolve muitas coisas e, portanto, temos bastante trabalho a ser feito.

    Criando e mapeando as entidadesA partir de agora, vamos criar as entidades e seus mapeamen-

    tos. Vale ressaltar que essa uma parte de grande importncia, pois o Hibernate ir criar as tabelas no banco de dados de acordo com o cdigo implementado em nossas entidades e como as mapeamos.

    Em nosso cdigo teremos onze entidades, a saber: Autor, Cate-goria, Editora, Emprestimo, Endereco, FuncionarioBiblioteca, Leitor, Livro, Pessoa, Telefone e Usuario. E como esperado, teremos uma tabela para cada entidade. No entanto, haver uma tabela a mais que no ter uma entidade correspondente (de nome livro_autor), totalizando doze tabelas. Isso ocorre porque existe um relacionamento do tipo ManyToMany entre as entidades Livro

  • Edio 138 Java Magazine 7

    e Autor, o que leva o persistence provider a gerar uma tabela de ligao livro_autor para viabilizar esse relacionamento.

    Para organizar o projeto, iremos colocar cada tipo de classe em um pacote diferente. Sendo assim, todas as entidades ficaro no pacote br.com.javamagazine.entidades.

    Na Listagem 1 temos o cdigo da entidade Autor, que nada mais do que uma classe Java comum com algumas anotaes. A anotao @Entity que vai em cima da classe, por exemplo, indica que ela uma entidade. Como no estamos usando a anotao @Table para especificar o nome da tabela, seu nome ser derivado do nome da entidade, que por padro o nome no qualificado da classe. Portanto, ser criada uma tabela chamada autor para essa entidade. J a anotao @Id serve para demarcar a chave primria. Neste caso, teremos uma coluna chamada id para representar essa chave. A anotao @GeneratedValue indica que o valor da chave primria deve ser gerado automaticamente, e de acordo com a estratgia (strategy) passada dentro da anotao, o persistence provider ir se orientar para viabilizar isso criando, por exemplo, uma coluna do tipo auto-increment/identity ou uma sequence no banco de dados. O persistence provider ir utilizar a estratgia indicada se for suportada pelo banco de dados.

    A JPA define quatro tipos de estratgia, a saber: @GeneratedValue(strategy=GenerationType.AUTO): indica que o persistence provider deve escolher a melhor estratgia para gerao dos valores da PK de acordo com o banco de dados. a opo com maior portabilidade. Quando usamos a anotao sem definirmos explicitamente uma estratgia, essa a opo default; @GeneratedValue(strategy=GenerationType.IDENTITY): especifica o uso de uma coluna auto-increment/identity como estratgia para gerao dos valores da chave primria; @GeneratedValue(strategy=GenerationType.SEQUENCE): especifica o uso de uma sequence para gerao dos valores da chave primria; @GeneratedValue(strategy=GenerationType.TABLE): espe-cifica que o persistence provider deve atribuir valores s chaves

    Listagem 1. Cdigo da entidade Autor.

    package br.com.javamagazine.entidades;

    import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;

    @Entitypublic class Autor { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String nome; //getters e setters}

    primrias de nossas entidades com base em uma tabela auxiliar que ir garantir que os valores das chaves sejam nicos.

    Para a tabela autor escolhemos a estratgia IDENTITY para gerao automtica dos valores da chave primria. Faremos uso dessa estratgia porque ela uma das mais simples e tambm porque muito comum ser usada uma coluna auto-increment/identity para representar a chave primria, mesmo nos casos onde o banco no gerado atravs de um framework ORM. Alm disso, o tipo de banco de dados que iremos utilizar, o MySQL, suporta essa estratgia, ao contrrio de alguns outros.

    As Listagens 2, 3 e 4 mostram o cdigo das entidades Categoria, Endereco e Telefone. Como pode ser verificado, esse contedo similar ao cdigo da classe Autor, j analisada; inclusive usam as mesmas anotaes.

    Listagem 2. Cdigo da entidade Categoria.

    package br.com.javamagazine.entidades;

    import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;

    @Entitypublic class Categoria { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String nome; //getters e setters}

    Listagem 3. Cdigo da entidade Endereco.

    package br.com.javamagazine.entidades;

    import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;

    @Entitypublic class Endereco { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String endereco; private String complemento; private String bairro; private String estado; private String cidade; private String cep; //getters e setters}

  • Criando uma aplicao corporativa em Java Parte 2

    8 Java Magazine Edio 138

    J na Listagem 5 temos o cdigo da entidade Editora. Conforme analisado, a anotao @OneToMany especifica um relacionamen-to do tipo um para muitos entre uma editora e seus telefones. Assim, uma editora poder ter muitos telefones. Por sua vez, a anotao @JoinColumn, colocada sobre a lista de telefones, define qual coluna da tabela telefone ser a chave estrangeira (nesse caso a coluna id_editora). Logo aps, a anotao @OneToOne determina um relacionamento do tipo um para um entre editora e endereo, ou seja, uma editora poder ter apenas um endereo e um endereo poder pertencer somente a uma editora.

    A anotao @JoinColumn, colocada em cima do endereco, indica que a coluna id_endereco da tabela editora ser chave estrangeira. Note que tanto na anotao @OneToMany como na anotao @OneToOne foi especificado um atributo cascade e importante entender para que ele serve. Esse atributo foi usado para propagar o efeito das operaes executadas atravs de um entityManager sobre instncias de Editora nas entidades relacionadas, que seriam Telefone e Endereco. Por exemplo, se persistirmos uma editora no banco de dados atravs do mtodo persist(), seus telefones e seu endereo tambm sero persistidos, conforme mostrado na Listagem 6.

    Uma vez entendida a entidade Editora, vejamos como funciona a entidade Emprestimo (Listagem 7). Em nosso caso, um emprs-timo de um livro realizado por um funcionrio da biblioteca para um leitor. Dessa forma, fica evidente que o ato de realizar o emprstimo tem relao direta com o livro que est sendo emprestado, e tambm com o funcionrio da biblioteca e com o leitor, pois ambos esto participando desse ato. Logo, quando vamos transpor tudo isso para o mundo OOP, precisamos rela-cionar a entidade Emprestimo com as entidades Livro, Leitor e FuncionarioBiblioteca. Portanto, teremos trs relacionamentos do tipo ManyToOne para expressar essas relaes, j que um nico livro pode ser emprestado vrias vezes, um mesmo leitor pode tomar emprestado vrios livros (para cada livro um emprstimo diferente, no caso do nosso sistema) e um mesmo funcionrio da biblioteca pode realizar vrios emprstimos.

    A classe java.time.LocalDate do Java 8 foi usada para definirmos o tipo da data do emprstimo, da data prevista para devoluo e da data efetiva da devoluo. Quando temos em nossa classe atri-butos do tipo java.util.Date ou java.util.Calendar, podemos usar a anotao @Temporal da JPA para realizarmos o mapeamento, mas como estamos usando o tipo java.time.LocalDate, teremos que criar uma classe que atuar como um conversor (mais detalhes sero explicados quando for mostrado o cdigo dessa classe). Isso necessrio porque a anotao @Temporal, por enquanto, no suporta o tipo java.time.LocalDate.

    No cdigo exibido na Listagem 8, referente entidade Livro, a anotao @ManyToOne da varivel editora indica um rela-cionamento do tipo muitos para um, pois podemos ter muitos livros publicados por uma nica editora. Logo aps, a anotao @ManyToMany define um relacionamento do tipo muitos para muitos, pois muitos livros podem pertencer a um mesmo autor, e um livro pode ser escrito por mais de um autor. Em conjunto com a anotao @ManyToMany usamos a anotao @JoinTable para configurar o nome da tabela de ligao nesse caso chamada livro_autor que ir relacionar os livros e os autores. Atravs dos

    Listagem 5. Cdigo da entidade Editora.

    package br.com.javamagazine.entidades;

    import java.util.ArrayList;import java.util.List;import javax.persistence.CascadeType;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.OneToMany;import javax.persistence.OneToOne;

    @Entitypublic class Editora { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String nome; @OneToMany(cascade={CascadeType.ALL}) @JoinColumn(name=id_editora) private List telefones = new ArrayList(); @OneToOne(cascade={CascadeType.ALL}) @JoinColumn(name=id_endereco) private Endereco endereco; private String site; private String email; //getters e setters}

    Listagem 6. Cdigo relacionado ao uso do cascade.

    //persistindo editora e entidades relacionadas por causa do cascadeEditora editora = new Editora();editora.getTelefones().add(new Telefone());editora.setEndereco(new Endereco());//persiste tudo com uma nica invocao do mtodo persist()entityManager.persist(editora);

    Listagem 4. Cdigo da entidade Telefone.

    package br.com.javamagazine.entidades;

    import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;

    @Entitypublic class Telefone { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String numero; private boolean fixo; //getters e setters}

  • Edio 138 Java Magazine 9

    atributos joinColumns e inverseJoinColumns configuramos as colunas da tabela de ligao id_livro e id_autor que sero as chaves estrangeiras. Para ficar mais claro, teremos a tabela livro_autor que possuir as colunas id_livro e id_autor como chaves estrangeiras, enquanto as chaves primrias esto nas tabelas livro e autor, ou seja, livro_autor estabelece um vnculo entre as tabelas livro e autor.

    Com relao anotao @ManyToOne, podemos encontr-la em dois lugares dentro das Listagens 7 e 8. Ela foi usada em cima da varivel categoria, presente na classe Livro, para indicar que muitos livros podem pertencer a uma mesma categoria. Essa anotao tambm foi usada para estabelecer um relacionamento bidirecional entre as entidades Livro e Emprestimo, e nesse caso o relacionamento definido por meio da prpria anotao @ManyToOne utilizada na classe Emprestimo e da anotao @OneToMany utilizada na classe Livro. Dentro da anotao @OneToMany, que aparece em cima da varivel emprestimos na classe Livro, temos o atributo mappedBy para indicar que a entidade Livro o lado inverso do relacionamento, enquanto a entidade Emprestimo a dona do relacionamento.

    A entidade Usuario, por sua vez, pode ser encontrada na Listagem 9. Com as explicaes que foram dadas nas listagens anteriores possvel entender o papel de cada anotao utilizada nesse cdigo, com exceo da anotao @Column, ainda no abordada. Utilizamos @Column com o atributo unique para

    assegurar que no existam dois nomes de usurios iguais. Dessa forma ser criada uma constraint no banco que ir garantir que esse tipo de duplicidade no acontea.

    Listagem 7. Cdigo da entidade Emprestimo.

    package br.com.javamagazine.entidades;

    import java.time.LocalDate;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.ManyToOne;

    @Entitypublic class Emprestimo { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private LocalDate dataEmprestimo; private LocalDate dataPrevista; private LocalDate dataDevolucao; @ManyToOne @JoinColumn(name = id_livro) private Livro livro; @ManyToOne @JoinColumn(name = id_leitor) private Leitor leitor; @ManyToOne @JoinColumn(name = id_funcionarioBiblioteca) private FuncionarioBiblioteca funcionarioBiblioteca; //getters e setters }

    Listagem 8. Cdigo da entidade Livro.

    package br.com.javamagazine.entidades;

    import java.util.List;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.JoinColumn;import javax.persistence.JoinTable;import javax.persistence.ManyToMany;import javax.persistence.ManyToOne;import javax.persistence.OneToMany;

    @Entitypublic class Livro { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String nome; @ManyToOne @JoinColumn(name=id_editora) private Editora editora; @ManyToMany @JoinTable(name=livro_autor, joinColumns={@JoinColumn(name=id_livro)}, inverseJoinColumns={@JoinColumn(name=id_autor)}) private List autores; @ManyToOne @JoinColumn(name=id_categoria) private Categoria categoria; private String Isbn; @OneToMany(mappedBy=livro) private List emprestimos; //getters e setters}

    Listagem 9. Cdigo da entidade Usuario.

    package br.com.javamagazine.entidades;

    import javax.persistence.Column;import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.OneToOne;

    @Entitypublic class Usuario { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; @Column(unique=true) private String usuario; private String senha; private boolean admin = true; @OneToOne(mappedBy=usuario) private FuncionarioBiblioteca funcionarioBiblioteca; //getters e setters}

  • Criando uma aplicao corporativa em Java Parte 2

    10 Java Magazine Edio 138

    Por ltimo, analisemos as trs entidades restantes: Pessoa, FuncionarioBiblioteca e Leitor, cujos cdigos so apresentados nas Listagens 10, 11 e 12, respectivamente.

    Ao analisar esse cdigo, observe que as classes Funcionario-Biblioteca e Leitor so subclasses de Pessoa, o que sinaliza um relacionamento por meio de herana. Assim como ocorreu em nosso exemplo, o uso da herana algo comum ao desenvolvimen-to de aplicaes Java, e foi pensando nisso que a JPA incorporou mecanismos para mapearmos nossas hierarquias de classes que nesse caso so entidades.

    Como podemos verificar, todas elas sero entidades e cada uma ser representada por sua respectiva tabela no banco de dados. Para atingirmos esse resultado usaremos a anotao @Inheritance com a estratgia JOINED. Repare que definimos uma chave primria (usando a anotao @Id) apenas na entidade Pessoa, mas na realidade o JPA provider criar as trs tabelas (pessoa, funcionariobiblioteca e leitor) com suas respectivas chaves primrias (nesse caso representadas pela coluna id de cada tabela). Os valores dessas chaves primrias sero utilizados para relacionar os registros da tabela pessoa com os registros da tabela funcionariobiblioteca ou os registros da tabela pessoa com os registros da tabela leitor.

    Como no persistence.xml configuramos a propriedade hibernate .hbm2ddl.auto com o valor create, se rodarmos o nosso projeto no JBoss WildFly, todas as tabelas sero criadas automaticamente, pois nesse momento j temos todas as entidades prontas com seus respectivos mapeamentos.

    O atributo mappedByQuando existe um relacionamento bidirecional, temos que defi-

    nir um lado como dono do relacionamento (owning side) e o outro lado como inverso (inverse side). O lado inverso do relacionamento o lado que fica com o atributo mappedBy. No momento em que persistimos as entidades envolvidas em uma relao bidirecional, a entidade que dona do relacionamento levada em considerao para que seja criada uma associao dentro do banco de dados atravs da chave estrangeira.

    Para ficar mais claro, podemos tomar como exemplo as entida-des Emprestimo e Livro. Como a entidade Livro no a dona da relao, no suficiente setarmos a lista de emprstimos no livro livro.setEmprestimos(listaEmprestimos); antes de persistir-mos os objetos. Dessa forma os relacionamentos entre o livro e os

    Listagem 10. Cdigo da entidade Pessoa.

    package br.com.javamagazine.entidades;

    import javax.persistence.Entity;import javax.persistence.GeneratedValue;import javax.persistence.GenerationType;import javax.persistence.Id;import javax.persistence.Inheritance;import javax.persistence.InheritanceType;

    @Entity@Inheritance(strategy=InheritanceType.JOINED)public class Pessoa { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Integer id; private String nome; private String email; private String sexo; private String cpf; //getters e setters}

    Listagem 11. Cdigo da entidade FuncionarioBiblioteca.

    package br.com.javamagazine.entidades;

    import java.util.ArrayList;import java.util.List;import javax.persistence.CascadeType;import javax.persistence.Entity;import javax.persistence.JoinColumn;import javax.persistence.OneToMany;import javax.persistence.OneToOne;

    @Entitypublic class FuncionarioBiblioteca extends Pessoa{ @OneToOne(cascade={CascadeType.ALL}) @JoinColumn(name=id_usuario) Usuario usuario; @OneToMany(cascade={CascadeType.ALL}) @JoinColumn(name=id_funcionarioBiblioteca) private List telefones = new ArrayList(); @OneToOne(cascade={CascadeType.ALL}) @JoinColumn(name=id_endereco) private Endereco endereco;

    //getters e setters}

    Listagem 12. Cdigo da entidade Leitor.

    package br.com.javamagazine.entidades;

    import java.util.ArrayList;import java.util.List;import javax.persistence.CascadeType;import javax.persistence.Entity;import javax.persistence.JoinColumn;import javax.persistence.OneToMany;import javax.persistence.OneToOne;

    @Entitypublic class Leitor extends Pessoa{ private String turma; private String matricula; @OneToMany(cascade={CascadeType.ALL}) @JoinColumn(name=id_leitor) private List telefones = new ArrayList(); @OneToOne(cascade={CascadeType.ALL}) @JoinColumn(name=id_endereco) private Endereco endereco; //getters e setters}

  • Edio 138 Java Magazine 11

    emprstimos no seriam criados dentro da base de dados. Devido entidade Emprestimo ser a dona do relacionamento, devemos associar cada objeto do tipo emprestimo com o livro que est sendo emprestado emprestimo.setLivro(livro);.

    Aps isso, certamente se persistssemos os objetos, a coluna da chave estrangeira id_livro, presente na tabela emprestimo, seria preenchida corretamente, criando as associaes dentro do banco. Isso porque apesar de em um relacionamento bidirecional termos que amarrar as duas pontas, o lado que o dono do relaciona-mento quem define o preenchimento da chave estrangeira na base de dados.

    Criando a classe de converso para localDateObserve que a entidade Emprestimo (Listagem 7) possui

    trs atributos do tipo java.time.LocalDate. Para cada atributo desse tipo, o persistence provider criar uma coluna corres-pondente do tipo TINYBLOB isso no momento em que a tabela for gerada a partir da entidade e seus mapeamentos. O TINYBLOB um dos quatro tipos de BLOB existentes no MySQL, e um BLOB (Binary Large Object) nada mais do que um campo que serve para armazenar qualquer tipo de dado em formato binrio. Vale ressaltar que a aplicao funcionaria normalmente, porm armazenar datas em colunas do tipo TINYBLOB definitivamente no uma boa prtica, visto que a performance pode ser prejudicada.

    Por enquanto, a JPA no tem uma anotao que mapeie adequa-damente atributos desse tipo (LocalDate). Para contornarmos esse problema/restrio, usaremos um recurso da JPA relacionado a converses. Este consiste em criar uma classe anotada com @Converter, que implemente AttributeConverter e que sobres-creva os dois mtodos dessa interface. O cdigo dessa classe mostrado na Listagem 13.

    A anotao @Converter indica que a classe ser responsvel por realizar converses. No nosso caso, ir converter de java.time.LocalDate para java.sql.Date na hora de gravar as datas na base de dados e fazer o oposto na hora de recuperar essas datas do banco e atribu-las aos atributos da entidade Emprestimo. Os mtodos que sobrescrevemos, convertToDatabaseColumn() e convertToEntityAttribute(), realizaro todo esse trabalho. Por fim, interessante notar que dentro da anotao @Converter setamos o atributo autoApply como true, o que possibilita que essas converses sejam feitas de forma automtica para qualquer atributo do tipo java.time.LocalDate que esteja presente em qualquer entidade.

    Aps a criao dessa classe conversora recomendado que voc execute novamente o projeto no JBoss para que a tabela emprestimo seja recriada. Dessa vez, as colunas que representam as datas sero criadas com sendo do tipo DATE, em vez do tipo TINYBLOB.

    Populando o banco de dadosComo mencionado na primeira parte do artigo, no GitHub foram

    disponibilizadas duas verses da aplicao para gerenciamento de bibliotecas. A verso completa contm todas as classes que fazem parte do DAO, e tambm os managed beans e telas para cadastro das categorias, autores, editoras, livros, leitores, funcionrios da biblioteca e usurios. A verso simplificada que igual a apre-sentada neste artigo no contm todas as classes DAO, managed beans e telas de cadastro, visando evitar listagens muito parecidas devido similaridade entre os cdigos. Desse modo conseguimos focar no que mais importante e explicar detalhadamente cada cdigo apresentado.

    Nessa verso reduzida teremos apenas uma tela de cadastro, onde poderemos inserir funcionrios da biblioteca e usurios. Mas se no temos as demais telas, como poderemos cadastrar os outros itens? Resolveremos essa questo de forma simples: cadas-trando tudo diretamente no banco de dados atravs de instrues SQL. Assim, o leitor poder criar o projeto de acordo com o que ensinado no artigo e execut-lo no servidor de aplicao.

    Dito isso, aps subir o servidor de aplicao e as tabelas serem criadas, os comandos SQL da Listagem 14 devem ser executados via MySQL Command-Line Tool.

    Como no queremos que as tabelas sejam recriadas na prxima execuo do JBoss (pois perderamos os dados que acabamos de inserir via SQL), devemos alterar a propriedade hibernate.hbm2ddl .auto no persistence.xml para o valor validate. Feito isso, clique com o boto direito no JBoss, localizado na aba Servers do Eclipse, e escolha a opo Clean.... Assim, na prxima inicializao do ser-vidor de aplicao o Hibernate ir realizar apenas as validaes necessrias.

    Criando o interceptor e as classes DaoDurante o desenvolvimento das entidades e das demais classes

    do projeto, utilizaremos a injeo de dependncias atravs do Weld, que a implementao de referncia da especificao CDI. Para habilitarmos esse recurso com CDI e assim aproveitarmos

    Listagem 13. Classe de converso para usar com LocalDate.

    package br.com.javamagazine.conversores;

    import java.sql.Date;import java.time.LocalDate;import javax.persistence.AttributeConverter;import javax.persistence.Converter;

    @Converter(autoApply = true)public class LocalDateConversor implements AttributeConverter {

    @Override public Date convertToDatabaseColumn(LocalDate dataDaEntidade) { return (dataDaEntidade == null) ? null : Date.valueOf(dataDaEntidade); }

    @Override public LocalDate convertToEntityAttribute(Date dataDoBancoDeDados) { return (dataDoBancoDeDados == null) ? null : dataDoBancoDeDados .toLocalDate(); }}

  • Criando uma aplicao corporativa em Java Parte 2

    12 Java Magazine Edio 138

    todas as vantagens advindas do mesmo, basta criarmos um ar-quivo vazio chamado beans.xml na pasta WEB-INF.

    Uma coisa comum de se encontrar em classes DAO so cdigos para gerenciamento de transaes (ver BOX 1). No entanto, se mantivermos cdigo que lida com transaes em cada classe que faz parte do DAO, acabaremos com uma grande quantidade de cdigo de infraestrutura duplicado. Para evitarmos essa situao, antes de comearmos a criar nossas classes DAO, vamos criar um mecanismo para gerenciar as transaes de nosso sistema e com isso evitar que esse tipo de cdigo fique espalhado em nosso DAO ou por toda a aplicao. A soluo que iremos adotar para isso faz uso de um Interceptor e um Interceptor binding (assuntos abordados na especificao de Interceptors e na es-pecificao de CDI).

    Uma transao pode ser definida como uma srie de aes subsequentes que devem ser concludas

    com sucesso. Caso alguma dessas aes no seja concluda com sucesso, as anteriores devem ser

    desfeitas, voltando o estado do sistema ao que era antes da transao iniciar. Uma transao deve

    terminar ou com um commit ou com um rollback.

    BOX 1. Transaes

    O Interceptor ser de suma importncia para chegarmos solu-o do problema relacionado a cdigo duplicado, ento vejamos onde ele se encaixa. Cada mtodo que precisar de uma transao ser marcado com uma anotao especfica (posteriormente vere-mos mais detalhes) e quando for feita uma chamada a um desses mtodos, essa chamada ser interceptada por um Interceptor que cuidar do gerenciamento da transao.

    Assim como o gerenciamento de transaes, comum encon-trarmos outras tarefas que devem ser realizadas em diversas partes do sistema, como gerao de logs, controle de autorizao/

    segurana, entre outras. Dizemos que esse tipo de tarefa uma preocupao transversal (crosscutting concern), pois atravessa o sistema todo, ou boa parte dele. Para lidarmos com isso, a progra-mao orientada a aspectos (ou AOP) sugere que encapsulemos essa preocupao transversal, e uma forma de fazer isso por meio de um Interceptor. Portanto, ao tratarem de Interceptors, as especificaes Java trazem consigo um pouco da AOP para dentro da Java EE.

    A Listagem 15 mostra o cdigo do Interceptor que ir gerenciar as transaes da aplicao. Veja que uma classe comum que anotada com @Interceptor. Dentro do cdigo temos um mtodo chamado intercept() que recebe a anotao @AroundInvoke e por conta disso ser responsvel por interceptar as chamadas aos nossos mtodos de negcio que precisarem de uma transao. Dentro desse mtodo usamos o entityManager que foi injetado via CDI para iniciarmos uma transao. Logo em seguida invocamos o mtodo proceed() do contexto para indicar que nesse momento queremos que seja executada a lgica contida no mtodo que

    Listagem 14. Instrues SQL para popular a base de dados.

    INSERT INTO endereco(id, bairro, cep, cidade, complemento, endereco, estado) VALUES(1, Pq Sao Rafael, 08311080, Sao Paulo, , Avenida Baronesa de Muritiba, num 51, SP);INSERT INTO endereco(id, bairro, cep, cidade, complemento, endereco, estado) VALUES(2, Santa Terezinha, 02460000, Sao Paulo, , Rua Lus Antonio dos Santos, num 110, SP);INSERT INTO pessoa(id, cpf, email, nome, sexo) VALUES(1, 34087772486, [email protected], Iris, F);INSERT INTO leitor(matricula, turma, id, id_endereco) VALUES(35012, TADS01, 1, 1);INSERT INTO autor(id, nome) VALUES(1, Ricardo R. Lecheta);INSERT INTO categoria(id, nome) VALUES(1, Informatica);INSERT INTO editora(id, email, nome, site, id_endereco) VALUES(1, [email protected], Novatec, www.novatec.com.br, 2);INSERT INTO livro(id, isbn, nome, id_categoria, id_editora) VALUES(1, 9788575222928, Google Android para Tablets, 1, 1);INSERT INTO livro(id, isbn, nome, id_categoria, id_editora) VALUES(2, 9788575224014, Desenvolvendo para iPhone e iPad, 1, 1);INSERT INTO livro_autor(id_livro, id_autor) VALUES(1, 1);INSERT INTO telefone(id, fixo, numero, id_leitor) VALUES(1, b0, 99999-9999, 1);INSERT INTO telefone(id, fixo, numero, id_leitor) VALUES(2, b1, 5555-5555, 1);INSERT INTO telefone(id, fixo, numero, id_editora) VALUES(3, b0, 98888-8888, 1);INSERT INTO telefone(id, fixo, numero, id_editora) VALUES(4, b1, 7777-7777, 1);

    Listagem 15. Interceptor que ir gerenciar as transaes.

    package br.com.javamagazine.interceptadores;

    import java.io.Serializable;import javax.inject.Inject;import javax.interceptor.AroundInvoke;import javax.interceptor.Interceptor;import javax.interceptor.InvocationContext;import javax.persistence.EntityManager;import br.com.javamagazine.util.MensagemUtil;

    @Interceptor @Transacionalpublic class TransacionalInterceptor implements Serializable {

    private static final long serialVersionUID = 1L; @Inject private EntityManager entityManager; @AroundInvoke public Object intercept(InvocationContext context){ Object resultado = null; try { entityManager.getTransaction().begin(); resultado = context.proceed(); entityManager.getTransaction().commit(); } catch (Exception e) { entityManager.getTransaction().rollback(); MensagemUtil.addMensagemDeErro(Erro - , Detalhes do erro: + e.getClass().getName() + - + e.getMessage()); e.printStackTrace(); } return resultado; }}

  • Edio 138 Java Magazine 13

    estamos interceptando, e por ltimo damos commit() na tran-sao. Caso ocorra alguma exceo executado o rollback() e adicionada uma mensagem que ser mostrada ao usurio.

    Agora que criamos o Interceptor, temos que achar um meio de dizer para ele quais mtodos precisam de uma transao e devem ser interceptados. Fazemos isso por meio de um Interceptor binding. Sendo assim, criaremos um conforme a Listagem 16. Para isso, basta definir uma anotao chamada Transacional e marc-la com @InterceptorBinding. E para estabelecermos um vnculo entre nosso Interceptor e o Interceptor binding, usamos a anotao @Transacional em cima da classe TransacionalIn-terceptor (vide Listagem 15). A partir de agora, sempre que um mtodo precisar ser executado dentro de uma transao, necessrio apenas anot-lo com @Transacional.

    Para que nosso interceptor funcione, precisamos registr-lo no arquivo beans.xml criado anteriormente, dentro de WEB-INF. A Listagem 17 mostra como deve ficar nosso beans.xml.

    Ao observarmos novamente a Listagem 15, que apresenta o cdigo do Interceptor TransacionalInterceptor, podemos notar que um Entity Manager injetado atravs da anotao @Inject. Pelo fato do processo de criao de um Entity Manager ser um pouco mais complexo do que o normal (no basta usar o new() para criar a instncia, necessrio instanciar a classe a partir de uma EntityManagerFactory), precisamos ensinar ao CDI provider como criar um Entity Manager. Assim, sempre que um

    Entity Manager for requerido, o CDI ser capaz de produzir um e injet-lo no injection point apropriado.

    A Listagem 18 mostra a classe que ficar encarregada de produzir os Entity Managers. A anotao @Produces indica o mtodo produtor de Entity Manager e a anotao @Request-Scoped indica que deve ser produzido um Entity Manager por requisio. No final de cada requisio, o Entity Manager que foi criado fechado atravs do mtodo fecharEntityManager(), que recebe o Entity Manager via parmetro. No entanto, para que isso funcione necessrio usar a anotao @Disposes conforme mostrado na listagem.

    A classe TransacionalInterceptor tambm faz uso do mtodo addMensagemDeErro(), presente na classe MensagemUtil. O cdigo dessa classe apresentado na Listagem 19. Como pode ser verificado, MesagemUtil bastante simples e no requer mui-tas explicaes. A classe disponibiliza alguns mtodos pblicos que delegam todo o trabalho para o mtodo privado addMen-sagem() que, por sua vez, usa um mtodo de FacesContext para adicionar uma mensagem que ser exibida ao usurio.

    Concluda essa etapa, nosso prximo passo criarmos as classes DAO e para cada uma delas criaremos tambm uma interface. Dessa forma, na hora de injetar qualquer DAO que precisarmos, poderemos usar uma varivel do tipo da interface com a anotao @Inject em cima dela e assim diminumos o acoplamento, pois no estamos declarando a implementao concreta que deve ser usada. Alm disso, quando definimos uma interface podemos ter mais de uma implementao para ela. No caso de um DAO, podemos ter, por exemplo, uma implementao que use JPA e outra que use JDBC, e atravs de algum recurso do CDI podemos escolher qual implementao deve ser injetada (usando Qualifiers, Alternatives ou a anotao @Vetoed conseguimos configurar isso).

    Listagem 16. Interceptor binding para associar o Interceptor com os beans.

    package br.com.javamagazine.interceptadores;

    import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;

    import javax.interceptor.InterceptorBinding;

    @InterceptorBinding@Target({ElementType.TYPE, ElementType.METHOD})@Retention(RetentionPolicy.RUNTIME)public @interface Transacional {}

    Listagem 18. Fbrica de Entity Manager.

    package br.com.javamagazine.fabricas;

    import javax.enterprise.context.ApplicationScoped;import javax.enterprise.context.RequestScoped;import javax.enterprise.inject.Disposes;import javax.enterprise.inject.Produces;import javax.persistence.EntityManager;import javax.persistence.EntityManagerFactory;import javax.persistence.Persistence;

    @ApplicationScopedpublic class FabricaDeEntityManager {

    private static EntityManagerFactory factory = Persistence.createEntityManager Factory(bibliotecaPersistence); @Produces @RequestScoped public EntityManager criarEntityManager() { return factory.createEntityManager(); } public void fecharEntityManager(@Disposes EntityManager manager){ manager.close(); }}

    Listagem 17. Contedo do arquivo beans.xml.

    br.com.javamagazine.interceptadores.TransacionalInterceptor

  • Criando uma aplicao corporativa em Java Parte 2

    14 Java Magazine Edio 138

    que um dos requisitos do sistema que esses logs no sejam de-letados da base de dados. Nessa situao poderamos at sobres-crever o mtodo remover() e lanar uma Exception caso algum tentasse us-lo, mas se os logs no devem ser apagados, no faz sentido termos um mtodo remover() na classe LogDao. Usando composio ao invs de herana no teremos esse problema.

    A Listagem 21 exibe o cdigo da classe EmprestimoDaoImpl, que implementa a interface EmprestimoDao, ou seja, a imple-mentao concreta que ir cuidar da persistncia dos objetos que representam os emprstimos. Nessa classe, usamos a injeo de dependncia via construtor. Como colocamos a anotao @Inject no construtor, o CDI provider ir instanciar a classe Empresti-moDaoImpl quando necessrio fornecendo um Entity Manager como argumento, e esse Entity Manager ser passado ao DAO genrico para que possa utiliza-lo. Lembre-se que os Entity Managers injetados sero produzidos pela fbrica que criamos

    Listagem 20. Implementao do DAO genrico.

    package br.com.javamagazine.daoimpl;

    import java.util.List;import javax.persistence.EntityManager;import br.com.javamagazine.dao.GenericoDao;

    public class GenericoDaoImpl implements GenericoDao { private Class classeDaEntidade; private EntityManager entityManager;

    public GenericoDaoImpl(Class classeDaEntidade, EntityManager entityManger) { this.classeDaEntidade = classeDaEntidade; this.entityManager = entityManger; }

    @Override public void inserir(T entidade) { entityManager.persist(entidade); }

    @Override public void remover(T entidade) { entityManager.remove(entityManager.merge(entidade)); }

    @Override public void atualizar(T entidade) { entityManager.merge(entidade); } @Override public T pesquisarPorID(K id) { return entityManager.find(classeDaEntidade, id); } @Override public List listarTodos(){ return entityManager.createQuery(select t from + classeDaEntidade.getSim-pleName() + t).getResultList(); }

    }

    Listagem 19. Cdigo da classe MensagemUtil, que ir adicionar mensagens para

    o usurio visualizar.

    package br.com.javamagazine.util;

    import javax.faces.application.FacesMessage;import javax.faces.context.FacesContext;

    public class MensagemUtil {

    public static void addMensagemDeErro(String mensagemDeErro, String detalhes){ addMensagem(FacesMessage.SEVERITY_ERROR, mensagemDeErro, detalhes); } public static void addMensagemDeAviso(String mensagemDeAviso, String detalhes){ addMensagem(FacesMessage.SEVERITY_WARN, mensagemDeAviso, detalhes); } public static void addMensagemInformativa(String mensagemInformativa, String detalhes){ addMensagem(FacesMessage.SEVERITY_INFO, mensagemInformativa, detalhes); } private static void addMensagem(FacesMessage.Severity severidade, String mensagem, String detalhes){ FacesMessage msg = new FacesMessage(severidade, mensagem, detalhes); FacesContext.getCurrentInstance().addMessage(null, msg); }}

    Para simplificar o artigo, os cdigos das interfaces sero omi-tidos, mas de qualquer forma fcil saber quais so os mtodos declarados em cada interface: basta observar na implementao concreta quais mtodos foram sobrescritos (os que esto marcados com a anotao @Override).

    Para que possamos reutilizar cdigo, usaremos um DAO gen-rico, conforme demonstra a Listagem 20. comum que desenvol-vedores criem primeiro o DAO genrico e posteriormente faam as demais classes DAO herdarem dele. Contudo, essa prtica traz alguns problemas e por isso iremos adotar uma estratgia diferente, dando lugar composio no lugar da herana, ou seja, nossas classes tero um DAO genrico em vez de serem um. Como nossas classes tero um DAO genrico, elas iro delegar as tarefas para ele. Com essa estratgia diminumos o acoplamento. Alm disso, no herdaremos os comportamentos do DAO genrico e com isso poderemos escolher quais mtodos implementar em cada classe. Assim, em cada implementao de mtodo, na maioria das vezes iremos apenas invocar o mtodo correspondente da classe GenericoDaoImpl (por exemplo: o mtodo inserir() da classe EmprestimoDaoImpl contm apenas uma chamada ao mtodo inserir() da classe GenericoDaoImpl).

    Vamos imaginar uma situao hipottica apenas para ficar mais claro o problema de herdar um comportamento nesse caso. Imagine que precisamos gravar no banco de dados alguns logs de atividades realizadas dentro do sistema e para isso poderamos ter uma classe LogDao que herdaria de GenericoDao e ganharia de bandeja todos os comportamentos do DAO genrico, inclusive o comportamento do mtodo remover(). Agora, imagine tambm

  • Edio 138 Java Magazine 15

    anteriormente que usa @Produces. Outro ponto que deve ser notado que os mtodos do DAO de emprstimo apenas dele-gam o trabalho para os mtodos do DAO genrico, promovendo a reutilizao de cdigo.

    O cdigo mostrado na Listagem 22 se refere implementao da classe LeitorDaoImpl. Como essa implementao muito se-melhante da classe EmprestimoDaoImpl vista anteriormente, no detalharemos o seu contedo.

    A Listagem 23 apresenta o cdigo da classe FuncionarioBiblio-tecaDaoImpl, que tambm muito semelhante ao das classes DAO vistas nas listagens anteriores. A maioria dos mtodos dessa classe apenas invocam algum outro mtodo no DAO genrico, com exceo do mtodo existeFuncionarioCadastrado(), que contm uma lgica que verifica se existe algum funcionrio cadastrado no banco de dados; em caso afirmativo retorna true, caso contrrio retorna false. Mais adiante veremos o cdigo da classe Funciona-rioEUsuarioVerificadorBean, onde esse mtodo ser usado.

    J na Listagem 24 temos o cdigo da classe UsuarioDaoImpl. Nessa classe temos trs mtodos: listarUsuarios(), existeUsuario-Cadastrado() e pesquisarUsuario(). O mtodo listarUsuarios() responsvel por retornar uma lista de objetos do tipo Usuario; lista que preenchida com o contedo presente na tabela usuario do banco de dados. O mtodo existeUsuarioCadastrado() verifica se existe algum usurio cadastrado na base de dados, retornando true se j existir algum ou false se no existir ao menos um. Esse mtodo ser usado pela classe FuncionarioEUsuarioVerifica-

    Listagem 21. Cdigo da classe EmprestimoDaoImpl, que compe o DAO.

    package br.com.javamagazine.daoimpl;

    import java.io.Serializable;import javax.inject.Inject;import javax.persistence.EntityManager;import br.com.javamagazine.dao.EmprestimoDao;import br.com.javamagazine.dao.GenericoDao;import br.com.javamagazine.entidades.Emprestimo;

    public class EmprestimoDaoImpl implements EmprestimoDao, Serializable{ private static final long serialVersionUID = 1L; private GenericoDao genericoDao; @Inject EmprestimoDaoImpl(EntityManager entityManager){ genericoDao = new GenericoDaoImpl (Emprestimo.class, entityManager); }

    @Override public void inserir(Emprestimo emprestimo) { genericoDao.inserir(emprestimo); } @Override public void atualizar(Emprestimo emprestimo) { genericoDao.atualizar(emprestimo); }

    }

    Listagem 22. Cdigo da classe LeitorDaoImpl, que compe o DAO.

    package br.com.javamagazine.daoimpl;

    import java.io.Serializable;import java.util.List;import javax.inject.Inject;import javax.persistence.EntityManager;import br.com.javamagazine.dao.GenericoDao;import br.com.javamagazine.dao.LeitorDao;import br.com.javamagazine.entidades.Leitor;

    public class LeitorDaoImpl implements LeitorDao, Serializable {

    private static final long serialVersionUID = 1L; private GenericoDao genericoDao; @Inject LeitorDaoImpl(EntityManager entityManager){ genericoDao = new GenericoDaoImpl (Leitor.class, entityManager); } @Override public Leitor pesquisarPorId(Integer id) { return genericoDao.pesquisarPorID(id); }

    @Override public List listarLeitores() { return genericoDao.listarTodos(); } //restante dos mtodos omitidos

    }

    dorBean, como veremos adiante. Por ltimo temos o mtodo pesquisarUsuario(), que ser usado para validar se o usurio e senha digitados na tela de login so vlidos. A lgica empregada bastante simples: passada uma String JPQL para o mtodo createQuery() do Entity Manager, e este mtodo retorna um ob-jeto do tipo Query. Com esse objeto em mos, o utilizaremos para que seja feita uma consulta ao banco de dados em busca de um registro que seja compatvel com o usurio e senha digitados na tela de login. Se algum registro for encontrado ser retornado um objeto do tipo Usuario preenchido com os dados desse registro, caso contrrio ser retornado null.

    Para encerrarmos a implementao do DAO, falta apenas a classe LivroDaoImpl, apresentada na Listagem 25. Nessa listagem temos quatro mtodos: pesquisarPorId(), listarLivros(), listarLivros-DisponiveisParaEmprestimo() e listarLivrosEmprestados(). O mtodo pesquisarPorId() ir delegar para o DAO genrico a tarefa de pesquisar um livro pelo id e o mtodo listarLivros() ir delegar para o DAO genrico a tarefa de recuperar uma lista com todos os livros. Os outros dois mtodos esto relacionados ao em-prstimo e devoluo de livros. Neste momento, lembre-se que na tela de emprstimos s devero ser exibidos os livros disponveis para emprstimo e na tela de devoluo, devero aparecer apenas os livros que esto emprestados. E estas so, respectivamente, as funes destes dois mtodos.

  • Criando uma aplicao corporativa em Java Parte 2

    16 Java Magazine Edio 138

    package br.com.javamagazine.daoimpl;

    import java.io.Serializable;import java.util.List;import javax.inject.Inject;import javax.persistence.EntityManager;import br.com.javamagazine.dao.GenericoDao;import br.com.javamagazine.dao.FuncionarioBibliotecaDao;import br.com.javamagazine.entidades.FuncionarioBiblioteca;

    public class FuncionarioBibliotecaDaoImpl implements FuncionarioBibliotecaDao, Serializable {

    private static final long serialVersionUID = 1L; private GenericoDao genericoDao; @Inject FuncionarioBibliotecaDaoImpl(EntityManager entityManager){ genericoDao = new GenericoDaoImpl(FuncionarioBiblioteca.class, entityManager); } @Override public void inserir(FuncionarioBiblioteca funcionarioBiblioteca) { genericoDao.inserir(funcionarioBiblioteca); }

    @Override public void remover(FuncionarioBiblioteca funcionarioBiblioteca) { genericoDao.remover(funcionarioBiblioteca); } @Override public void atualizar(FuncionarioBiblioteca funcionarioBiblioteca) { genericoDao.atualizar(funcionarioBiblioteca); }

    @Override public List listarFuncionariosBiblioteca() { return genericoDao.listarTodos(); }

    @Override public boolean existeFuncionarioCadastrado() { List listaDeFuncionarios = listarFuncionariosBiblioteca(); if(listaDeFuncionarios != null && listaDeFuncionarios.size() > 0){ return true; } return false; }

    }

    Listagem 23. Cdigo da classe FuncionarioBibliotecaDaoImpl, que compe o DAO.

    package br.com.javamagazine.daoimpl;

    import java.io.Serializable;import java.util.List;import javax.inject.Inject;import javax.persistence.EntityManager;import javax.persistence.NoResultException;import javax.persistence.Query;import br.com.javamagazine.dao.GenericoDao;import br.com.javamagazine.dao.UsuarioDao;import br.com.javamagazine.entidades.Usuario;

    public class UsuarioDaoImpl implements UsuarioDao, Serializable {

    private static final long serialVersionUID = 1L; private GenericoDao genericoDao; private EntityManager entityManager; @Inject UsuarioDaoImpl(EntityManager entityManager){ genericoDao = new GenericoDaoImpl (Usuario.class, entityManager); this.entityManager = entityManager; } @Override public List listarUsuarios() { return genericoDao.listarTodos(); }

    @Override public boolean existeUsuarioCadastrado() { List listaDeUsuarios = listarUsuarios(); if(listaDeUsuarios != null && listaDeUsuarios.size() > 0){ return true; } return false; }

    @Override public Usuario pesquisarUsuario(Usuario usuario) { Usuario usuarioEncontrado = null; Query query = entityManager.createQuery(select u from Usuario u where u.usuario = :usuarioParam and u.senha = :senhaParam) .setParameter(usuarioParam, usuario.getUsuario()) .setParameter(senhaParam, usuario.getSenha());

    try{ usuarioEncontrado = (Usuario)query.getSingleResult(); }catch(NoResultException e){ // no faz nada, se no achar o usurio deixa retornar null }

    return usuarioEncontrado; }

    }

    Listagem 24. Cdigo da classe UsuarioDaoImpl, que compe o DAO.

  • Edio 138 Java Magazine 17

    Para entender a lgica contida nesses mtodos, precisamos estar cientes de que um livro pode estar relacionado a muitos emprstimos e que cada um desses emprstimos tem uma data de devoluo, que representa a data efetiva em que a devoluo do livro foi realizada. Enquanto um livro no devolvido, a data de devoluo permanece nula. Dito isso, os dois mtodos em questo recuperam uma lista com todos os livros e iteram sobre ela. A cada passada dentro do loop for so recuperados os emprstimos de um livro especfico e verificado se os emprstimos possuem data de devoluo. Se todos os emprstimos vinculados quele livro especfico possurem data de devoluo, significa que o livro est disponvel e pode ser emprestado, mas se por ventura algum dos emprstimos tiver a data de devoluo nula, significa que ele j se encontra emprestado.

    Note que apenas fizemos uso de uma pequena parte de tudo que est disponvel dentro das especificaes da JPA e do CDI. Isso porque cada sistema tem requisitos diferentes, e escolhemos justamente as partes de ambas as especificaes que pudessem nos ajudar a atender os requisitos da aplicao de gerenciamento de bibliotecas.

    Podemos falar de algumas possibilidades citando alguns exemplos para que tudo se torne um pouco mais tangvel para o leitor. Um exemplo relacionado JPA seria o uso da anotao @Inheritance com a estratgia JOINED. Existem outras estra-tgias que poderiam ser adotadas, como SINGLE_TABLE e TABLE_PER_CLASS. E por que utilizar a opo JOINED? O banco de dados fica normalizado (o que no acontece com a op-o SINGLE_TABLE), podemos aplicar constraints NOT NULL nas colunas mapeadas para os atributos das subclasses (isso no seria possvel com a opo SINGLE_TABLE), tem performance razovel (no to boa quanto se usssemos SINGLE_TABLE, mas melhor do que se usssemos TABLE_PER_CLASS em uma situao onde SQL UNIONs no fossem suportados).

    Outro exemplo relacionado ao CDI, seria o uso de Qualifiers, Alternatives e @Vetoed assuntos que apenas mencionamos vagamente. No caso da nossa aplicao, no foi necessrio o uso de nenhum desses recursos, porm vale a pena conhec-los, pois so de grande utilidade. O uso de um Qualifier pode ser aplicado quando temos mais de uma implementao para um determinado tipo e precisamos informar de alguma forma ao CDI provider qual

    package br.com.javamagazine.daoimpl;

    import java.io.Serializable;import java.util.ArrayList;import java.util.List;import javax.inject.Inject;import javax.persistence.EntityManager;import br.com.javamagazine.dao.GenericoDao;import br.com.javamagazine.dao.LivroDao;import br.com.javamagazine.entidades.Emprestimo;import br.com.javamagazine.entidades.Livro;

    public class LivroDaoImpl implements LivroDao, Serializable { private static final long serialVersionUID = 1L; private GenericoDao genericoDao; @Inject LivroDaoImpl(EntityManager entityManager){ genericoDao = new GenericoDaoImpl(Livro.class, entityManager); } @Override public Livro pesquisarPorId(Integer id) { return genericoDao.pesquisarPorID(id); }

    @Override public List listarLivros() { return genericoDao.listarTodos(); }

    @Override public List listarLivrosDisponiveisParaEmprestimo() { List todosLivros = listarLivros(); List livrosDisponiveis = new ArrayList(); for(Livro livro : todosLivros){

    List emprestimos = livro.getEmprestimos(); boolean todosEmprestimosTemDataDevolucao = true; for(Emprestimo emprestimo : emprestimos){ if(emprestimo.getDataDevolucao() == null) todosEmprestimosTemDataDevolucao = false; } if(todosEmprestimosTemDataDevolucao) livrosDisponiveis.add(livro); } return livrosDisponiveis; } @Override public List listarLivrosEmprestados() { List todosLivros = listarLivros(); List livrosEmprestados = new ArrayList(); for(Livro livro : todosLivros){ List emprestimos = livro.getEmprestimos(); for(Emprestimo emprestimo : emprestimos){ if(emprestimo.getDataDevolucao() == null) livrosEmprestados.add(livro); } } return livrosEmprestados; } //restante dos mtodos omitidos

    }

    Listagem 25. Cdigo da classe LivroDaoImpl, que compe o DAO.

  • Criando uma aplicao corporativa em Java Parte 2

    18 Java Magazine Edio 138

    das implementaes deve ser injetada. A anotao @Alternative, quando usada em algum bean, o torna indisponvel para injeo, no entanto, ao adicionar tambm uma declarao alternatives no beans.xml, tornamos o bean novamente disponvel para injeo. Para finalizar, vamos falar da anotao @Vetoed, que ao ser uti-lizada em alguma classe, faz com que essa classe seja ignorada pelo container CDI.

    Bruno Rafael Sant ana [email protected] em Anlise e Desenvolvimento de Sistemas pelo SENAC. Possui as certificaes OCJP e OCWCD. Atualmente tra-balha na Samsung com desenvolvimento Java e atua como CTO na startup Vesteer. Entusiasta de linguagens de programao e tecnologia.

    autor

    links:

    aplicao reduzida (igual a desenvolvida no artigo) no GitHub.https://github.com/brunosantanati/javamagazine-app-reduzida

    aplicao completa no GitHub.https://github.com/brunosantanati/javamagazine-app-completa

    Endereo para download do JDK 8.http://www.oracle.com/technetwork/pt/java/javase/downloads/index.html

    Endereo para download do Eclipse luna.https://www.eclipse.org/downloads/

    Endereo para download JBoss WildFly.http://wildfly.org/downloads/

    Endereo para download do instalador do MySQl.http://dev.mysql.com/downloads/installer/

    Endereo para download do driver do MySQl.http://dev.mysql.com/downloads/connector/j/

    D seu voto em www.devmedia.com.br/javamagazine/feedback

    Ajude-nos a manter a qualidade da revista!

    voc gostou deste artigo?

  • Edio 138 Java Magazine 19

  • 20 Java Magazine Edio 138

    Este artigo abordar as principais tecnologias para criao de web

    services: REST e SOAP, explicando o conceito por trs de cada uma

    delas e como aplic-las em um projeto Java. O assunto em anlise

    ser de bastante interesse para desenvolvedores que no possuem

    domnio sobre web services e que desejam conhecer estas opes,

    assim como para desenvolvedores mais experientes, que buscam

    compreender as diferenas e vantagens de cada uma dessas aborda-

    gens e quando adot-las.

    Fique por dentro

    Diferenas e vantagens ao adotar essas tecnologias em seu projeto Java

    Web Services REST versus SOAP

    A comunicao entre sistemas e a capacidade de expor servios atravs da Internet se tornaram uma necessidade comum para a grande maioria dos sistemas corporativos. Seja apenas para prover su-porte a outros mdulos na mesma rede privada ou para permitir o acesso pblico a um determinado servio, os web services so uma das tecnologias mais utilizadas tanto no Java como em outras linguagens de grande porte e fazem parte do dia a dia dos desenvolvedores.

    Entre as abordagens existentes para a implementao de web services, o protocolo SOAP e o REST so as opes de maior destaque nos dias de hoje, estando presentes em grande parte das discusses relacionadas a arquiteturas orientadas a servios na web. Ganhando destaque no mercado do incio da dcada de 2000, o protocolo SOAP teve grande importncia em 2003, quando passou a ser uma recomendao da W3C para desenvolvimento de servios web, sendo o padro mais implementado na poca e deixando um legado de siste-mas e integraes que perdura at hoje.

    O REST, por sua vez, foi desenvolvido juntamente com o protocolo HTTP 1.1 e, ao contrrio do SOAP, que tem como objetivo estabelecer um protocolo para comunicao de objetos e servios, props algumas ideias de como utilizar corretamente os verbos HTTP (GET, POST, PUT, HEAD, OPTIONS e DELETE) para criar servios que poderiam ser acessados por qualquer tipo de sistema. Sua concepo, portanto, no era de um protocolo, mas sim de um Design Pattern arquitetural para servios expostos numa rede, como a internet, atravs do protocolo HTTP.

    Para introduzir essas duas tecnologias, nesse artigo apresentaremos o funcionamento de ambos os mtodos, explicando as principais caractersticas, vantagens e des-vantagens de cada um deles e tambm demonstraremos como implement-los em um projeto Java.

    Alm disso, apresentaremos tambm as boas prticas de desenvolvimento de cada uma dessas tecnologias

    e introduziremos situaes reais em que essas solues podem ser aplicadas, atravs de um exemplo a ser desenvolvido no final do artigo.

    Com isso, seremos capazes de diferenciar claramente ambas as abordagens e teremos o conhecimento necessrio para entender em quais cenrios cada uma delas se aplica, permitindo, assim, que o leitor tenha um arsenal maior para o desenvolvimento e consumo de servios dos mais variados formatos.

    uma breve introduo sobre web servicesWeb services so, por definio, servios expostos em uma rede

    que permitem a comunicao entre um ou mais dispositivos ele-trnicos, sendo capazes de enviar e processar dados de acordo com sua funcionalidade.

    Essa comunicao, por sua vez, segue alguns protocolos, princi-palmente relacionados ao formato da transmisso de dados, o que permite que, uma vez que um sistema implemente essas regras, qualquer outro sistema que siga o mesmo protocolo seja capaz de se comunicar com ele.

    Devido a isso, os web services se tornaram extremamente populares, pois acabaram por permitir a comunicao entre plataformas completamente diferentes (Java, C#, C++, Ruby) sem grandes esforos.

    Entre essas padronizaes estipuladas, as duas de maior desta-que so o protocolo SOAP e o modelo de design REST, as quais iremos discutir nos prximos tpicos.

  • Edio 138 Java Magazine 21

    Essa definio de como os mtodos que compem um web service SOAP devem funcionar feita atravs de um documento XML chamado WSDL, abreviao de Web Service Description Language, um XML que descreve o formato dos dados que o servio aceita, seu funcionamento e comportamento (se assncrono ou no, por exemplo) e os dados de sada do mtodo, incluindo desde o formato at o envelope SOAP que deve ser retornado.

    Na Listagem 2 apresentamos um exemplo de WSDL especifi-cando nosso servio GetRevista, que aceita uma String como entrada e devolve, como retorno, outra String.

    Conforme podemos verificar, o WSDL apresenta diversos atribu-tos referentes ao servio, como a localizao do endpoint, nomes de cada um dos servios, nomes de cada parmetro e seu respectivo tipo. Atravs dessa definio, qualquer sistema externo pode se

    Protocolo SOAPO protocolo SOAP, abreviao para Simple Object Access Protocol,

    uma especificao para a troca de informao entre sistemas, ou seja, uma especificao de formato de dados para envio de es-truturas de dados entre servios, com um padro para permitir a interoperabilidade entre eles. Seu design parte do princpio da uti-lizao de XMLs para a transferncia de objetos entre aplicaes, e a utilizao, como transporte, do protocolo de rede HTTP.

    Os XMLs especificados pelo SOAP seguem um padro definido dentro do protocolo. Esse padro serve para que, a partir de um objeto, seja possvel serializar o mesmo para XML e, tambm, deserializ-lo de volta para o formato original. Alm do formato dos objetos, nesse protocolo tambm so definidos os padres que os servios SOAP devem seguir, ou seja, a especificao dos endpoints que as implementaes de SOAP devem ter.

    A serializao de objetos, que acabamos de descrever, tem como objetivo formar uma mensagem SOAP, composta pelo objeto denominado envelope SOAP, ou SOAP-ENV. Dentro desse enve-lope existem mais dois componentes: o header SOAP, que possui informaes de atributos de metadados da requisio como, por exemplo, IP de origem e autenticao; e o SOAP body, que possui as informaes referentes requisio, como o nome dos mtodos que deseja se invocar e o objeto serializado que ser enviado como payload da requisio.

    Na Listagem 1 apresentamos um exemplo de um envelope SOAP simplificado representando uma requisio SOAP. Nele podemos identificar claramente os elementos body e header e tambm ter uma breve viso da sintaxe do SOAP. Dentro do body ainda se nota a descrio do mtodo para o qual esse envelope deve ser direcionado (GetRevista) e o payload especfico que foi enviado a essa funo.

    Como verificado, no existe muito segredo no transporte de objetos atravs do SOAP. No caso do nosso exemplo, a requisio ao mtodo GetRevista enviada para o servidor juntamente com o objeto RevistaNome, que servir de parmetro de entrada ao nosso mtodo e tem, como contedo, a String Java Magazine. Ao chegar ao servidor, essa informao parseada e a aplicao realiza a lgica necessria para process-la.

    Como boa prtica, esse servio tambm tem seu funcionamento e formato de dados de entrada especificados pelo protocolo SOAP.

    Listagem 2. Exemplo de WSDL para o servio getRevista.

    WSDL File for HelloService

    Listagem 1. Exemplo de um envelope SOAP que transporta um objeto com o nome RevistaNome.

    Java Magazine

  • Web Services REST versus SOAP

    22 Java Magazine Edio 138

    comunicar com o web service que criamos no WSDL, enviando a requisio atravs do protocolo SOAP.

    Entre os elementos do WSDL que apresentamos na Listagem 2, podemos observar que a definio de um servio basicamente composta por quatro partes principais. A primeira delas, definida pela tag , onde definimos o formato de nossos dados, podendo ser esses de entrada e sada. Nesse ponto, podemos utili-zar tanto atributos primitivos, como no exemplo o uso de String, como tambm utilizar schemas XMLs (chamados de XSDs) para definir nossos objetos.

    Uma vez definido o formato de nossas informaes, a segunda parte de um WSDL especificar as operaes que desejamos expor e suas respectivas entradas e sadas. Isso feito na tag , onde definimos a operao GetRevista e determinamos, tambm, os dados de entrada e sada, baseados nas tags que criamos anteriormente.

    Em seguida, especificamos a tag do WSDL chamada de e, dentro desta, a nossa tag portType (criada no passo anterior) e suas respectivas operaes a um servio. Esse servi-o, que representar a implementao de nosso web service, determinado na tag , onde explicitamos o endereo do endpoint atravs da tag .

    Alm de tudo isso, o SOAP tambm possibilita funcionalidades bastante interessantes, como o caso do WS-Addressing. Esse tipo de tecnologia permite que, uma vez enviada alguma informao dentro de um envelope SOAP, seja possvel o envio de um par-metro extra definindo um endpoint de callback para ser chamado logo que a requisio termine de ser processada.

    Dessa forma, uma vez que termine a requisio, o web service capaz de chamar essa URL de callback, passando em seu con-tedo o resultado do processamento e permitindo, dessa forma, o trabalho assncrono entre sistemas.

    Modelo arquitetural RESTAo introduzir e adotar essas padronizaes, muitos sistemas

    comearam a implementar esse modelo na criao de seus web services, fazendo com que o protocolo SOAP se tornasse uma das tecnologias essenciais no desenvolvimento de web services em sistemas corporativos.

    No entanto, o protocolo SOAP trazia tambm diversas desvan-tagens. A primeira delas (e talvez uma das mais importantes) o fato de que ao transportar todas as informaes dentro de um envelope SOAP em XML, o contedo dos dados enviados de um sistema para outro se torna muitas vezes maior que o necessrio, elevando tanto o consumo da banda de rede como o tempo de processamento dos dados.

    Em segundo lugar, a utilizao de web services SOAP no faz o uso correto dos verbos HTTP. Isso se deve ao fato de que todas as requisies SOAP so feitas atravs do POST de um XML, que contm o envelope SOAP. Porm, em grande parte das requisies, o mais adequado seria outro verbo, como um GET ou PUT, de acordo com a funcionalidade exposta pelo servio. Graas a essa limitao do protocolo, o SOAP acaba por contrariar alguns dos

    princpios de uma boa modelagem HTTP, ferindo as boas prticas dessa especificao.

    Por esses e outros motivos, desenvolvedores e pesquisadores vm adotando outra abordagem para criar seus web services, chamada de servios REST. A modelagem por trs de um servio REST parte do princpio de seguir as boas prticas da criao de servios HTTP e utilizar esses padres para desenvolver web services simples e performticos.

    Um dos pontos cruciais nesse modelo arquitetural o uso cor-reto dos mtodos disponibilizados pelo HTTP. Ao contrrio do SOAP, que s utiliza o mtodo POST para transmitir os dados, uma arquitetura REST prev que, dentro de um cenrio ideal, o mtodo HTTP a ser utilizado seja diretamente relacionado funcionalidade do servio a ser consumido.

    Portanto, servios de busca de informaes so feitos atravs de mtodos GET, servios de atualizao de informao atravs de mtodos PUT, servios de criao de dados atravs do mtodo POST, servios de deleo atravs do DELETE e assim por diante. A partir do correto uso dos verbos HTTP ganhamos tambm a vantagem de no termos diversas URLs para cada um dos nossos servios, podendo expor somente uma URL e, conforme o mtodo, executar uma ao diferente.

    Como exemplo, vamos imaginar um simples servio CRUD (Criao, atualizao, leitura e deleo de dados) para clientes. Dentro de uma arquitetura REST, esse servio pode ser definido somente com uma URL, por exemplo: http://nosso.exemplo.com/client/12345. Para realizar uma consulta ao cliente 12345, basta realizarmos uma requisio GET URL mencionada e para delet-lo, realizar uma requisio DELETE.

    O mesmo pode se aplicar s requisies PUT e POST, onde uti-lizamos o corpo da requisio que nos foi enviado para atualizar ou criar uma nova entidade em nosso sistema, respectivamente. Deste modo, fcil observar que, utilizando os mtodos corre-tamente, os web services REST se tornam bastante simples de serem desenvolvidos e altamente intuitivos, sem a necessidade de descries, como os WSDLs ou documentaes extensas, para explicar sua funcionalidade.

    Outra vantagem do REST em relao ao SOAP se refere ao for-mato do dado a ser trafegado. Enquanto o SOAP se restringe a utilizar XMLs, o REST no impe restries quanto a isso, ou seja, qualquer um pode ser enviado em suas requisies. Diretamente relacionado a isso, como boa prtica, uma requisio REST deve sempre conter o header Content/Type para explicitar o formato do dado em sua requisio e, para o retorno, o header Accepts, determinando o formato de dado que a aplicao espera. Como exemplo, caso uma aplicao deseje enviar um dado em XML e receber, como retorno, um JSON, basta ela explicitar ambos os for-matos nos respectivos headers e o web service REST deve ser capaz de resolver a requisio de acordo com essas necessidades.

    Dentro do REST, outra diferena o chamado HATEOAS, abre-viao para Hypermedia as the Engine of Application Status. Conside-rado um dos principais benefcios dessa arquitetura, o HATEOAS define que, dentro de uma aplicao REST, o estado da aplicao

  • Edio 138 Java Magazine 23

    e da interao do usurio deve ser controlado atravs das URLs (Hypermedia) retornadas pelo servio. Isso implica que, em um servio REST, quando a primeira URL dessa aplicao acessada, todos os possveis caminhos que o cliente pode seguir a partir dali so retornados dentro da resposta da requisio, como as URLs dos servios que podem ser invocados no passo seguinte.

    Atravs dessa tcnica evitamos diversos problemas em nossos clientes, uma vez que eles s precisam ter a primeira URL de nossa aplicao hardcoded em seu cdigo, possibilitando que as URLs seguintes sejam capturadas durante a prpria execuo do web service.

    Aplicaes RESTfulAs caractersticas apresentadas anteriormente so somente al-

    gumas das principais definies do modelo REST. Podemos dizer que, uma aplicao que segue todas as definies e funcionalida-des desse modelo, chamada de RESTful. Essas especificaes arquiteturais, denominadas de Architectural Constraints, so divididas em cinco grupos principais, cada um referenciando as caractersticas mais importantes do modelo REST.

    A primeira funcionalidade desse grupo exige que um sistema RESTful siga o modelo Cliente-Servidor. Nesse modelo, as respon-sabilidades de cada uma das partes ficam claramente divididas, deixando todo ou grande parte do cdigo do lado do servidor, que expe essas funcionalidades atravs de uma interface uniforme ao cliente (web services) e, consequentemente, minimiza problemas na aplicao provenientes de cdigo no cliente.

    Em segundo lugar, servios RESTful devem ser stateless, ou seja, no devem guardar estado. Isso explicita que, dada uma requisi-o, todas as informaes necessrias para o processamento desta devem estar presentes no payload enviado ao servio.

    Tambm como uma necessidade importante, essencial que os servios REST sejam cacheados, ou seja, o cliente deve ser capaz de acessar um cache das respostas, evitando que sejam feitas requisies seguidas a recursos que no sofreram alterao e permitindo, portanto, um menor consumo de banda. Alm disso, quando um desses recursos for atualizado, esse cache deve ser capaz de automaticamente notar isso e responder a requisio atualizada ao cliente.

    Outro ponto importante para o cliente que os servios REST devem poder ser separados em camadas de forma transparente ao usurio. Isso implica que, se quisermos colocar um servio intermedirio ou um Load Balancer entre o servio final e o consumidor desse sistema, no deve haver grandes alteraes em ambos os lados, sendo essa transio o mais transparente possvel.

    Por fim, um sistema RESTful deve ser capaz de prover uma interface uniforme atravs de endpoints HTTP para cada um dos recursos disponveis possibilitando, tambm, a implementao dos itens que mencionamos anteriormente, incluindo o HATE-OAS, uso correto das URLs e dos mtodos HTTP e a capacidade de descrever o tipo de dado atravs de headers (Content/Type e Accept).

    Criando os nossos web services em JavaAgora que entendemos os principais conceitos por trs desses

    dois modelos de web service, iremos apresentar como cri-los dentro de um projeto Java. Para isso, vamos introduzir duas bibliotecas bastante importantes: a JAX-WS, para projetos SOAP; e a JAX-RS, para projetos REST.

    Configurando nosso projetoO primeiro passo realizar o download de um servidor que

    implementa as bibliotecas da Java EE 6, permitindo assim o uso das funcionalidades do JAX-WS e do JAX-RS. Como escolha para esse artigo, decidimos adotar o servidor WildFly, considerado o sucessor do famoso JBoss AS (veja o endereo para download na seo Links).

    Feito o download do WildFly, para realizar a instalao basta descompact-lo em alguma pasta de seu computador e, em sua IDE, criar a configurao de um novo servidor e identificar, dentro das propriedades, o caminho do diretrio em que os arquivos do mesmo foram descompactados. Neste exemplo, iremos utilizar a IDE Eclipse Kepler para desenvolver nossos servios e o plugin do JBoss Tools para configurar nosso servidor.

    A instalao e configurao do plugin do JBoss, juntamente com a instalao do servidor na IDE,

    podem ser visualizadas com mais detalhes no endereo indicado na seo Links.

    Nota:

    Configurado o servidor, podemos agora criar o projeto na IDE. Para isso, basta clicarmos em New > Dynamic Web Project, nomear-mos nosso projeto e escolher, como runtime de nossa aplicao, o servidor recm-configurado, o WildFly 8. Na Figura 1 mostramos essa configurao.

    Feito isso, precisamos configurar o projeto como sendo do tipo Maven. Essa etapa pode ser feita com a ajuda do plugin do Maven (que pode ser baixado pelo prprio eclipse), bastando adicionar o pom .xml apresentado na Listagem 3 na raiz do projeto e clicar com o boto direito no projeto e escolher Configure > Convert to Maven Project.

    Como pode ser visto no pom.xml, basicamente definimos duas dependncias ao nosso projeto: a dependncia relacionada ao resteasy-jaxrs e a dependncia relacionada ao resteasy-jackson. Essas bibliotecas servem, respectivamente, para implementar o redirecionamento das requisies HTTP aos respectivos servios REST, e, tambm, para permitir o processamento de objetos em formato JSON.

    Criando nosso servio SOAPCom o projeto configurado, podemos demonstrar os passos para

    a criao de um web service SOAP. Para viabilizar esse exemplo, iremos utilizar a biblioteca JAX-WS e, tambm, as Annotations do Java, para declarar quais sero nossos mtodos que iro represen-tar os servios expostos na web.

    Assim, uma vez que a aplicao seja colocada no servidor, o JAX-WS responsvel por verificar quais das classes esto anotadas

  • Web Services REST versus SOAP

    24 Java Magazine Edio 138

    com @Webservice e informar ao servidor quais so as URLs de conexo para cada uma dessas classes, criando tambm os res-pectivos WSDLs.

    Na Listagem 4 apresentamos a classe JavaMagazineSoap, onde criamos um servio SOAP expondo o mtodo hello(), respons-vel por receber uma String e imprimir a mensagem Hello no console.

    Como demonstrado nesse cdigo, a criao de web services SOAP bastante simples, sendo necessrio apenas anotar a clas-se que queremos para que seus mtodos sejam expostos como servios.

    Assim que finalizar o desenvolvimento dessa classe, voc pode subir nosso projeto no WildFly e ento observar o WSDL gerado pelo JAX-WS. Para verificar esse arquivo, basta acessar o diretrio indicado no log (exibido no console de sada de sua IDE), na li-nha WSDL published to:. No caso do projeto desse artigo, a linha de log gerada foi: WSDL published to: file: /Users/brunnoattorre1/Documents/servers/Wildfly8.2/standalone/data/wsdl/JavaMagazineWS .war/JavaMagazineSoapService.wsdl.

    O caminho ser gerado de acordo com o nome do seu projeto. No nosso caso, como o nome do

    projeto JavaMagazineWS, o contexto do caminho ficou com esse nome. Caso seu projeto tenha

    outro nome, basta substituir o caminho de acordo com a respectiva nomenclatura que ser

    apresentada.

    Nota:

    Tambm importante notar que, no desenvolvimento dos ser-vios SOAP, podemos utilizar objetos dentro dos parmetros de entrada e sada. Na Listagem 5 apresentamos um exemplo que utiliza objetos como parmetros de entrada, representados pelos objetos user1 e user2, e sada do servio, representado pelo objeto retornado pelo mtodo hello(). Alm disso, tambm implemen-tamos a classe User, que representar o objeto que servir de parmetro para o nosso web service.

    Casos de uso do SOAPPara apresentarmos um caso de uso real de web services SOAP

    e contextualizarmos o que mostramos at aqui, vamos intro-duzir nesse tpico uma situao em que devemos desenvolver um sistema capaz de receber notificaes externas de diversas aplicaes.

    A escolha do SOAP, nesse caso, se d pelo fato de que, em nosso cenrio fictcio, trabalharemos com sistemas das mais diversas linguagens e, muitos deles, no possuem suporte ao REST. Numa situao semelhante a essa, o SOAP se mostra como uma alterna-tiva mais vivel, uma vez que viabiliza um suporte mais extenso principalmente para plataformas mais antigas.

    O exemplo dessa implementao se encontra na Listagem 6, onde apresentamos o cdigo da classe NotificationSoap, responsvel por receber uma notificao atravs do protocolo SOAP.

    Figura 1. Configurao de nosso projeto

    Listagem 3. Pom.xml a ser adicionado ao projeto.

    4.0.0 com.java.mag WS 0.0.1-SNAPSHOT org.jboss.resteasy resteasy-jaxrs 3.0.6.Final org.jboss.resteasy resteasy-jackson-provider 3.0.6.Final

    Listagem 4. Criando uma classe para expor um web service SOAP.

    @WebServicepublic class JavaMagazineSoap {

    public String hello(String hi){ System.out.println(Hello!!!); return hi; }}

  • Edio 138 Java Magazine 25

    Nessa listagem, alm das anotaes que j apresentamos an-teriormente, introduzimos a anotao @Oneway. Essa anotao define que o servio referente ao mtodo que for anotado ser apenas de notificao, ou seja, ele no ter retorno, servindo somente para enviar mensagens. Neste caso, mesmo que ocorra alguma exceo no processamento da mensagem, essa exceo no ser retornada ao cliente. Deste modo, vlido ressaltar que, quando desejamos criar servios de notificao SOAP, sempre importante tratarmos corretamente a exceo no prprio servio, evitando que erros no tratados aconteam.

    Uma vez implementada essa classe, basta subirmos o servidor e acessarmos o WSDL gerado (da mesma forma que acessamos no exemplo anterior) para observarmos as caractersticas do servio

    criado e, caso seja necessrio testar, basta utilizarmos um cliente capaz de realizar requisies SOAP.

    O aplicativo SoapUI uma alternativa vivel para desenvolvedores que precisam testar seus

    web services. Ela permite, atravs de um WSDL previamente gerado, realizar requisies com um

    contedo definido pelo usurio. Na seo de Links adicionamos mais algumas informaes de como

    realizar o download e utilizar essa ferramenta para testar web services.

    Nota:

    Criando servios RESTAgora que entendemos o bsico por trs da criao de servios

    SOAP, vamos introduzir a biblioteca JAX-RS, responsvel por habilitar a criao de servios utilizando o modelo REST. Para isso, partiremos do mesmo princpio da biblioteca JAX-WS, ou seja, implementaremos, dentro de uma classe Java comum, os mtodos que desejamos expor via web service REST.

    Uma vez implementada, utilizaremos annotations do Java para indicar a classe e os mtodos que desejamos disponibilizar via REST, referenciando tambm outras informaes como o tipo do verbo HTTP para uma determinada requisio, o contedo produ-zido por determinado servio e a URI de cada um dos servios.

    Alm do JAX-RS, iremos utilizar a biblioteca RESTEasy, que declaramos anteriormente como dependncia de nosso projeto. Esta ser responsvel por tratar as requisies REST e direcion-las ao servio correto. A configurao dessa biblioteca feita no arquivo web.xml, sendo o arquivo de nosso exemplo apresentado na Listagem 7.

    Nessa listagem podemos observar a configurao de alguns itens importantes. O primeiro deles, indicado pelo context-param de nome resteasy.scan, permite referenciar se queremos que o RESTEasy rastreie em nosso projeto todas as classes que possuem a anotaes @Path do JAX-RS e, em seguida, disponibilize essas classes como servios REST. No caso de nosso projeto, indicamos o valor do parmetro resteasy.scan como true e possibilitamos ao RESTEasy realizar esse trabalho automaticamente.

    Em segundo lugar, configuramos o listener ResteasyBootstrap e a servlet HttpServletDispatcher, responsveis por, para cada requisio, fazer o redirecionamento classe correta, que foi escaneada no passo anterior.

    Por fim, definimos tambm qual sero as URLs que serviro de endpoints para nossas requisies REST. Essas so indicadas tanto no parmetro resteasy.servlet.mapping.prefix como, tambm, no servlet-mapping do nosso servlet HttpServletDispatcher, ambas colocando, como endereo da URL, o endpoint com o caminho /rest/*.

    Uma vez terminadas as configuraes dentro do web.xml, basta anotarmos uma classe com as anotaes do JAX-RS para podermos indicar, ao RESTEasy, que essa classe servir como um servio REST. Para demonstrar o uso dessas anotaes, na Listagem 8 apresentamos o cdigo da classe JavaMagazineRest, que rece-be uma requisio GET e devolve um HTML com a mensagem Hello, World!!.

    Listagem 5. Implementao do web service SOAP JavaMagazineSoapObject.

    @WebServicepublic class JavaMagazineSoapObject {

    public User hello(User user1, User user2){ System.out.println(user1.getName()); return user2; } }

    class User{ private String name;

    public String getName() { return name; }

    public void setName(String name) { this.name = name; }}

    Listagem 6. Classe NotificationSoap implementando um web service de notificao.

    @WebServicepublic class NotificationSoap {

    @Oneway public void notificate(Message message){ System.out.println(Recebeu a mensagem + message.getPayload()); } }

    class Message implements Serializable{ private String payload; private String error; public String getPayload() { return payload; } public void setPayload(String payload) { this.payload = payload; } public String getError() { return error; } public void setError(String error) { this.error = error; }}

  • Web Services REST versus SOAP

    26 Java Magazine Edio 138

    Conforme podemos verificar, a criao da classe JavaMagazi-neRest e o uso das anotaes do JAX-RS podem ser explicados em trs etapas principais. A primeira delas, definida pela anota-o @Path aplicada em um mtodo, permite que indiquemos o caminho pelo qual o servio REST ir responder. No caso desse exemplo, qualquer requisio URI /rest ser redirecionada ao nosso servio.

    Logo em seguida, explicitamos o mtodo HTTP no qual o con-tedo da requisio deve ser enviado pelo cliente. Assim, uma vez que essa requisio chegue aplicao, ser respondida pelo mtodo anotado de nossa classe JavaMagazineRest. No nosso exemplo, isso feito atravs da anotao @GET, espe-cificando que o recurso anotado s responder s requisies do tipo GET.

    Por fim, a anotao @Produces indica o tipo do dado de retorno (no nosso exemplo, HTML). Caso recebssemos algum parmetro de entrada, poderamos fazer uso da anotao @Consumes, que indica o tipo de dado aceito como input para o servio.

    Com a classe desenvolvida, para observarmos o REST em fun-cionamento, basta subir nossa aplicao no WildFly, acessar a URL http://localhost:8080/JavaMagazineWS/rest/rest e ento verificar a mensagem Hello, World.

    Casos de uso do RESTAgora que aprendemos os conceitos bsicos por trs do de-

    senvolvimento de servios REST, apresentaremos nesse tpico uma anlise simplificada de um caso de uso real dessa opo de web service para um sistema comercial. Para isso, suponha um cenrio onde vamos desenvolver um servio de CRUD para um cadastro de usurios.

    A construo desse servio feita a partir do cdigo da Listagem 9, onde implementamos a classe CrudRest. Esta define os endpoints REST que serviro para expor os endereos de criao, atualizao, recuperao e deleo de instncias da classe User, que representa os usurios de nosso sistema.

    Nesse cdigo, podemos observar que seguimos alguns dos princpios primordiais do REST. O primeiro deles est relaciona-do ao caminho de nossas URLs: todas seguem o mesmo padro e nomenclatura, somente mudando o tipo do mtodo HTTP que ser utilizado. Esse tipo de abordagem permite que os servios se tornem mais intuitivos, ou seja, no necessria uma extensa documentao para descrever o que cada um faz, pois o prprio mtodo HTTP j nos indica sua funcionalidade.

    Alm disso, tambm relacionado s URLs expostas, imple-mentamos o conceito de trabalhar com as entidades do sistema na forma de recursos nos links e operaes REST. Esse conceito permite que, em uma aplicao REST, sempre trabalhemos com a referncia dos recursos que desejamos utilizar nas prprias URLs (por exemplo, em nosso caso, ser uma palavra que servir de identificador nico para cada uma de nossas entidades).

    Contextualizando essa funcionalidade para o nosso exemplo, se quisermos fazer qualquer ao em cima do objeto User com id igual a 345abd, a URL de destino seria sempre a represen-tada pelo endereo /user/345abd. A partir da, qualquer ao que desejamos tomar sobre esse recurso (User) deve ser definida pelos mtodos HTTP correspondentes. Consequentemente, uma requisio do tipo DELETE a essa URL iria remover o usurio cujo id igual 345abd, enquanto uma requisio do tipo GET iria trazer, como retorno, os dados desse usurio.

    Alm das URLs, podemos observar que tambm definimos em nossa classe quais so os tipos de dados de entrada e sada para cada um dos servios. Nas anotaes @Consum