1

Como Fiz o EncomendaZ 3.0 – Parte 1

Antes de mais nada, quer tirar dúvidas sobre este post? Acompanhe-me no Twitter: @marlonscarvalho. Agora, vamos ao que interessa. O EncomendaZ foi um projeto que surgiu meio que do nada. A primeira versão eu fiz só para aprender um pouco sobre programação com Swing. Aliás, eu sou fanzarço de programação desktop e não curto muito “programação orientada a tags”. A primeira versão você encontra até hoje no Google Code, neste endereço: http://code.google.com/p/encomendaz/. Foi uma versão sem muitas pretensões, mas acredito que já aconteceu com você também: você faz um programa, algumas pessoas começam a usar e elogiar mas você acha que podia ter feito melhor. E foi assim comigo. Resolvi, então, fazer uma nova versão, só que desta vez bem melhor.

O sucesso da versão 2.0 me fez pensar na versão 3.0. Fui bastante relutante em lançar ela, pois daria um trabalho monstro fazer. Mas eu fiz. E, desta vez, a motivação foi aprender ainda mais a programar para desktop, desta vez usando frameworks diferentes e padrões de projeto bastante conhecidos. Eu já tinha vontade de descrever todo o processo de criação desta versão. Sei que muitas pessoas também curtem programação desktop, mas não sabem por onde começar. Aliás, ultimamente você só encontra referências para programação Web. Parece que tudo é Web hoje em dia e sistemas desktop morreram. Pra mim, pura balela.

Eu vejo mais um mundo onde serviços estão na internet e aplicativos, seja desktop, mobile ou web, os consome. Tem aplicativos que são muito mais fáceis de serem usados no Desktop. São mais práticos, elegantes, tem mais funcionalidades, são rápidos e podem funcionar offline. O que é errado é criar aplicativos desktop “autocontidos”. Ou seja, tem seu próprio banco de dados, não compartilha dados com outros aplicativos. Enfim, falo dos “aplicativos ilha”: vivem em seu próprio mundo e esquecem o resto. Mas, hoje, todo mundo só pensa em fazer aplicativo pra browser, como se fosse a bala de prata. Estão errados.

O meu objetivo é criar uma sequência de posts descrevendo todo o processo criativo que levou à concepção da versão 3.0, que você pode usar através do Webstart, clicando aqui. O código fonte do EncomendaZ 3.0 está disponível no Bitbucket e você pode baixar, usar, brincar… Espero que estes posts sejam úteis para você.

Código fonte da camada de apresentação: https://bitbucket.org/alienlabz/encomendaz-swing
Código fonte do core: https://bitbucket.org/alienlabz/encomendaz-core

Primeiro, vamos listar as tecnologias envolvidas. São muitas:

  1. Maven para gerenciar o projeto;
  2. Eclipse Indigo como ambiente de desenvolvimento;
  3. Java/Swing para a camada de apresentação;
  4. Framework Demoiselle;
  5. Hibernate para persistência;
  6. HSQLDB para armazenar os dados;
  7. Velocity para geração dos templates de e-mail;
  8. Jasypt para criptografia de senhas e etc;
  9. Apache Commons E-mail para o envio de e-mail;
  10. Barbecue para a geração do código de barras;
  11. JasperReports para a geração dos relatórios;
  12. Jide OSS para alguns componentes de tela;
  13. HTTPClient da Apache para conexão com a internet;
  14. Quartz para o agendamento de tarefas;
  15. MigLayout para a criação de formulários;
  16. SwingX para componentes de tela;
  17. L2FProd para ter o componente de barra de ações lateral;
  18. Insubstantial para os temas Swing;
  19. JCalendar para ter um calendário bonito no Swing;
  20. JBusyComponent para ter um “Loading” tipo o Ajax em Web;
  21. Zeus JSCL para ter um componente mais amigável para exibir erros;
  22. Java WebStart para publicação.

Vou tentar justificar o uso de cada uma destas tecnologias. Ou não. 🙂 São muitas e talvez eu não consiga chegar até o final. Vou começar justificando o uso do Framework Demoiselle. Você conhece? Não? Pois saiba que você deveria dar uma chance a ele. E não foi só porque eu participei da equipe que o criou, mas porque é um ótimo framework, de fato. O Demoiselle teve sua concepção inicial no Serpro, mas hoje já é usado por diversas empresas, incluindo aí outros órgãos governamentais, como: TRT, MPU, Prodeb, Fundação Luís Eduardo Magalhães e por aí vai.

E estas empresas não o estão usando por imposição. Ninguém é obrigado a usar o Demoiselle. Usam porque gostaram e tecnicamente é um ótimo framework. Quer entrar em contato com a equipe do Demoiselle? Primeiro, use a lista de discussão. Depois, acesse o fórum. E também tem os @zyc, @wegneto, @e_saito e @Atiboni no Twitter para vocês tirarem dúvidas. 🙂

E como foi que o Demoiselle facilitou no EncomendaZ? Simples:

  • Injeção de Dependência com Weld é o bicho! 🙂 Nada de criar exaustivas fábricas;
  • As classes de template para CRUD diminuíram consideravelmente a quantidade de código para escrever;
  • O POM (Maven) parent do Demoiselle para aplicações Desktop simplificou a criação do projeto;
  • O controle de transações é fácil e extensível. Não fosse por isso, eu não teria conseguido resolver alguns problemarços que apareceram!
  • O ResourceBundle próprio do Demoiselle, com substituição de palavras-chave é uma mão na roda;
  • Já fornece algumas validações comuns no Brasil através do componente demoiselle-validation.

Eu poderia citar outras, mas estas aí já são suficientes. O que posso dizer é que o Demoiselle está funcionando rock-solid no EncomendaZ 3.0 e nenhum erro reportado até hoje foi proveniente dele. Contudo, tive alguns probleminhas e vou citar eles em breve. No próximo post, vou descrever o principal padrão de projeto que usei: Passive View. É um ótimo padrão e, em conjunto com o Demoiselle, forma a base do aplicativo.

3

O Eclipse, o Maven e o Tomcat 7

Um post rápido para lhe ensinar uma gambiarra que pode lhe ajudar a poupar muito tempo de sua vida. Quando Maven não quer funcionar, só partindo pra gambiarra. Já aconteceu com você de criar um projeto Maven, colocar ele como packaging war, mandar atualizar as configurações do projeto pelo Maven, deixar tudo lindo mas o miserável não rodar dentro do Tomcat 7? Pois é. Pode acontecer com você. Aconteceu comigo.

Primeiro de tudo, não sei porque caceta o Maven não configura o projeto para ser “deployavel” no Tomcat 7. Você sequer consegue arrastar o projeto para o Servidor configurado. Ele não deixa por não reconhecer ele como um projeto Web. A primeira questão é que seu projeto não está multifacetado (facets). Aí você tem que fazer isso na mão. Vai nas propriedades do projeto, em Project Facets. Seleciona Dynamic Web Module e Java.

Feito isto, já dá merda. Ele cria uma pasta /WebContent fora da estrutura padrão do Maven. Deveria ser a pasta /src/main/webapp. Agora você precisa ir na pasta do seu projeto no seu workspace, abrir a pasta oculta chamada .settings e editar o arquivo org.eclipse.wst.common.component.

Deve ter uma linha escrito isso: <wb-resource deploy-path=”/” source-path=”/WebContent” tag=”defaultRootSource”/>. Tá errado. Mude pra <wb-resource deploy-path=”/” source-path=”/src/main/webapp” tag=”defaultRootSource”/>. Feito isto, continua sem funcionar. O motivo é que ele não faz o deploy das dependências do Maven dentro da pasta /WEB-INF/lib. Para consertar isso, vá nas propriedades do projeto. Opção Deployment Assembly. Clica em Add, depois em Java Build Path Entries e seleciona Maven Dependencies. Pronto, esta merda agora deve funcionar! 😛

Pense em um armengue. Acabei de lhe apresentar um! 🙂

Quando o Maven vira um Tormento

Conhece o Maven? É uma ferramenta muito legal. Muito legal mesmo. Eu não o usava a até bem pouco tempo. Comecei a usar fortemente quando entrei pra equipe do Demoiselle. A partir daí, não consegui mais viver sem ele. E o principal motivo é o controle de dependências. É sucesso. É muito chato ter que sair procurando as dependências manualmente e incluir no seu projeto, né não? E quando tem versão nova de alguma biblioteca? É um saco ter que ir mudando tudo de novo! Ninguém merece.

E eu agora sempre uso o Maven para todos os meus projetos. E saiu colocando indiscriminadamente as dependências de que preciso. Sequer olho as dependências transitivas que cada projeto fornece consigo. Explicando para os incautos: dependências transitivas são aquelas dependências trazidas indiretamente por suas dependências diretas. Por exemplo, se seu projeto depende do Spring, você verá que não vem apenas o Jar do Spring, mas mais alguns que você nem esperava, como bibliotecas de log. E é aí que mora o perigo. Vou relatar para vocês como o aplicativo EncomendaZ saiu de 33mb de bibliotecas para 19mb. Vai ser um post meio que crítico e de desabafo. Vamos lá.

Começo alertando: usem o Maven com inteligência. Entendam que suas bibliotecas serão usadas em outros projetos e você não pode sobrecarregá-los com dependências desnecessárias. Veja na imagem abaixo uma pequena parte da árvore de dependências do EncomendaZ. Perceba a quantidade de dependências que existe. Você vai me perguntar: e você precisa de tanta dependência assim mesmo? Eu achava que sim. E agora descobri que não. Eu não entendia como um programa tão simples como o EncomendaZ poderia ter enormes 33mb de tamanho. Tinha algo errado.

Descobri erros dos mais simples a alguns gritantes. Vamos começar pelos mais loucos que vi. Estão vendo na imagem abaixo a biblioteca ezmorph? Ela é uma dependência indireta. E coloca indireta nisso. Mas, o mais curioso é você ver que o JUnit é uma dependência dele. Mas como “compile”?! JUnit é para ser uma dependência “test”. Esta biblioteca não é para ir junto com o deploy da aplicação. É apenas para estar na máquina dos desenvolvedores que realizam testes. Fail total!

Vamos a mais um exemplo, no mínimo, esquisito. Olha a imagem aí embaixo. É a biblioteca Jaxen. Eu sei que vocês já perceberam algo estranho. Por qual motivo uma versão mais recente de uma biblioteca precisaria depender de uma versão mais antiga dela mesma? Credo! Tem algo de errado com este projeto! Olha lá. A versão 1.1-beta-8 depende da versão 1.1-beta-6. Nunca tinha visto isso na minha vida. Eles devem ter um motivo, mas isto indica que tem algo de errado aí. Não faz sentido isso.

Mais uma. Tentem me explicar por qual motivo o Jasper Reports depende do jdtcore. Só tentem, porque não vão conseguir me convencer. Sabe o que é o JDT? Retirado do próprio site do Eclipse: “JDT Core is the Java infrastructure of the Java IDE“. WTF? Uma dependência de uma biblioteca da parte de infraestrutura do Eclipse? E o Jar dele é enorme, meu caro! Quase uns 4mb.

Agora chegamos na seção críticas construtivas. As críticas acima foram pra sacanear mesmo. Aliás, tem sacanagem maior do que fazer um POM porco como os caras acima fizeram? JUnit como compile? Haja paciência. Nesta sequência, quero apenas fazer um pedido para os criadores de bibliotecas. Modelem seus projetos pensando nas pessoas que irão usá-los. Seu projeto pode ser o MEGA-FAZ-TUDO, mas você não precisa incluir todas estas funcionalidades em um único módulo. Você acabará levando para o projeto dos outros dependências que eles podem não precisar. Vamos exemplificar.

Eu precisei gerar uma impressão no EncomendaZ e parti logo para o JasperReports. Mas minha impressão era bem simples. Eu não precisava gerar PDF. Não precisava gerar XLS. Era só mandar para a impressora e pronto. O JasperReports leva pra você, “de grátis”, o iText. Trata-se de uma ferramenta para geração de PDF. E o iText já lhe fornece o Bouncy Castle. Este último é uma biblioteca que será usada caso você queira assinar digitalmente seu PDF. O iText tem cerca de 2mb. O BouncyCastle uns 3mb. Veja a imagem abaixo.

Não acho a melhor estratégia embarcar o bcprov-jdk14 junto com o iText. Quantas pessoas vão querer realmente assinar digitalmente seus PDFs? Será que são tantas assim que é melhor incluí-lo logo? Eu, sinceramente, acho que não. Muito melhor seria o iText ter dois módulos: um core e outro que inclui assinatura digital. Teria me poupado 3mb. E digo mais, o JasperReports também poderia ter sido mais modularizado de forma que eu não precisasse trazer o iText caso não quisesse criar PDFs. Teria me poupado, agora, 5mb. Caso fossem mais modularizados, eu poderia ir escolhendo exatamente o que meu projeto necessita e não ficar criando EXCLUDES no meu POM. Esses excludes são chatos e poluem sensivelmente meu arquivo POM.

Eu sei que vocês perceberam mais um detalhe na última imagem. E é até engraçado. Não percebeu? Olha lá de novo. Tem uma dependência bcprov-jdk14 na versão 138 que o iText usa. E tem uma mesma bcprov-jdk14 mas na versão 1.38 de outra dependência. Sinistro, não? É simplesmente a mesma biblioteca mas com “groupId” e versões diferentes. Credo. Existia uma duplicidade de bibliotecas no meu projeto. Eram mais 3mb desnecessários.

Finalizando, quero deixar um alerta e um apelo! Cuidado com seus projetos Maven. Não coloquem indiscriminadamente as dependências. Analisem exatamente o que você precisa. No meu caso, eu precisava do JasperReports, mas não precisava de muitas das dependências transitivas que ele trazia. Consegui tirar quase 6mb de dependências indiretas só do JasperReports. O apelo fica para quem disponibiliza seus artefatos Maven. Cuidem com carinho o seu POM. Muito carinho. Não façam asneiras como colocar o Junit como dependência compile. Cuidem bem do seu projeto para que uma versão mais recente não precise depender de uma mais antiga. E tentem modularizar para que seus usuários escolham exatamente o que precisam e não sobrecarreguem seus projetos com megabytes a mais que são desnecessários. Vocês não tem ideia de quanto os usuários do EncomendaZ agradeceram em não terem que baixar 33mb ou mais a cada versão nova lançada.

AuctionX – Informações do Mercado Livre

Fale sério pra mim! Você já fez um sistema, biblioteca, ou algo que o valha, que não tem a mínima ideia se é útil? 🙂 Estou neste dilema. Na falta do que fazer numa noite dessas, resolvi brincar com o Mercado Livre, Java, XML e Maven.

E no que deu isso? Nasceu o AuctionX. Uma biblioteca pra você fazer consultas aos produtos vendidos no Mercado Livre. E aí? Tem utilidade isso? Sei lá, oras! Só sei que eu fiz e tá legal.

Pra usar é bem simples. A API eu fiz com o Hibernate em mente, logo, você verá algumas semelhanças com a classe Criteria deles. Vamos começar com os exemplos. Você quer pesquisar “iphones” vendidos apenas por vendedores certificados (Gold, Platinum):

	Search search = AuctionXService.createSearch("ML");
	Collection<Auction> auctions = search
				.addRestriction(Restriction.onlyCertifiedSellers())
				.search("iphone");

Certo. Legal. Agora você quer pesquisar por “iphones” que não estão em leilão, mas em venda direta. E também que os vendedores sejam da Bahia e mais, que os produtos sejam apenas novos!

	Search search = AuctionXService.createSearch("ML");
	Collection<Auction> auctions = search
			.addRestriction(Restriction.onlyCertifiedSellers())
			.addRestriction(Restriction.buyNow())
			.addRestriction(Restriction.location("BAHIA"))
			.addRestriction(Restriction.onlyNewProducts())
			.search("iphone");

Onde está o projeto? No lugar de sempre: Google Code! http://code.google.com/p/auctionx/. Tá completo? Não. Ainda falta implementar a ordenação do resultado. Mas vai ser rapidinho! 🙂 Vá lá, tou só esperando você me chamar de maluco e coisa de quem não tem o que fazer.