tag:blogger.com,1999:blog-37602732458945569292024-03-13T07:02:58.189-07:00A arte de desenvolver, entender e manter sistemasSoftware, distribuindo informação.Unknownnoreply@blogger.comBlogger102125tag:blogger.com,1999:blog-3760273245894556929.post-69641867830675726712011-04-20T14:21:00.000-07:002011-04-20T14:21:02.047-07:00Novo blog - www.leandromoreira.com.br<div style="text-align: justify;">Não estou abandonando este blog (eu espero) mas agora também estou postando em um outro blog o <a href="http://www.leandromoreira.com.br/">Leandro Moreira</a> lá pretendo escrever e abordar assuntos de desenvolvimento de sistemas do mesmo modo que aqui só que em inglês. :) </div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com3tag:blogger.com,1999:blog-3760273245894556929.post-59546892935922573362011-04-07T19:44:00.000-07:002011-04-07T19:44:22.442-07:00A experiência do TDD na vida de um desenvolvedor<div class="separator" style="clear: both; text-align: center;"><a href="http://www.softwareagility.gr/userfiles/image/sTEyF.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="http://www.softwareagility.gr/userfiles/image/sTEyF.jpg" width="163" /></a></div><span class="Apple-style-span" style="color: red; font-size: x-large;"><b>Pré-TDD</b></span><br />
<br />
<div style="text-align: justify;">Um <b>pouco <a href="http://www.visitcumbria.com/photos/ostrich-0776.jpg">cético</a></b> quanto ao processo <b>mas estudando e lendo opiniões que fazem sentido</b>, logo você "compra" a ideia. No inicio <b>escreve-se os testes depois</b> que (quase) tudo foi feito e o pior é <b>o vício de escreve-los para que os mesmos funcionem</b>. Nessa fase <b>não se vê nem o beneficio</b> real que os testes unitários trazem (nem mesmo <a href="http://improveit.com.br/xp/praticas/tdd/">a "metodologia" TDD</a> traz). As <b>perguntas mais freqüentes</b> nessa era são:</div><div style="text-align: justify;">Devo testar os CRUD's? Devo testar <a href="http://blog.caelum.com.br/nao-aprender-oo-getters-e-setters/">Getters and Setters simples</a>?</div><b>Sintomas:</b> perdendo tempo escrevendo testes (pós-testes)<br />
<b>Ferramentas que conhece:</b> <a href="http://www.junit.org/">JUnit</a> :(<br />
Prefere criar um <span class="Apple-style-span" style="background-color: black; color: white;">public static void main(String[] args)</span> e usar <b>Alt+Shift+X + J</b> ao criar uma <span class="Apple-style-span" style="background-color: black; color: white;">ClasseTest</span> com um método anotado com <a href="http://kentbeck.github.com/junit/javadoc/latest/org/junit/Test.html">@Test</a>.<br />
<br />
<span class="Apple-style-span" style="font-size: x-large;"><b><span class="Apple-style-span" style="color: #274e13;">Pós-TDD</span></b></span><br />
<br />
<div style="text-align: justify;">Você (realmente) <b>sente inseguro</b> quanto olha pra <b>massa de testes</b> e vê que novas (ou antigas) funcionalidades <b>não estão sendo testadas</b>, de alguma forma não ter os testes te causa uma sensação terrível de que está faltando algo. Suas <b>idéias nascem pensando em testes</b> (indo para <a href="http://pt.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a>) você muda mesmo a forma de pensar. Você (realmente) sabe do <b>valor inestimável de se ter testes para rodar antes de um build</b>. Começa a achar estranho o <b>desaparecimento de bugs esporádicos</b>. Tem toda <b>certeza que quase todo</b> pedaço de <b>código pode gerar bug</b> inesperado. <b>Ferramentas que</b> já conhece e <b>não vive sem</b> : <a href="http://mockito.org/">Mockito</a>, <a href="http://maven.apache.org/">Maven</a>, <a href="http://hudson-ci.org/">Hudson</a>... <b>Ferramentas</b> que começam a despertar seu <b>interesse</b>: <a href="http://jbehave.org/">JBehave</a>, <a href="http://seleniumhq.org/">Selenium</a>. Claro que algumas dessas ferramentas não estão ligadas diretamente ao TDD mas sim ao modo de pensar em testes e automação dos mesmos. <a href="http://pt.wikipedia.org/wiki/Teste_de_software">Testes de software</a> é algo complexo, extenso e sempre em evolução mas é uma <b>maneira eficiente</b> de <b>diminuir os erros</b> na criação ou manutenção de software.</div><div style="text-align: justify;"><br />
</div><span class="Apple-style-span" style="color: blue; font-size: x-large;"><b>Materiais para ajudá-lo na busca pelo TDD</b></span><br />
Link: <a href="http://improveit.com.br/xp/praticas/tdd/">http://improveit.com.br/xp/praticas/tdd/</a><br />
Livro: <a href="http://www.amazon.com/Test-Driven-Development-Kent-Beck/dp/0321146530">TDD by example</a> (<a href="http://www.livrariacultura.com.br/scripts/cultura/resenha/resenha.asp?nitem=5094527&sid=62497119813315517451920139&k5=177204E&uid=">traduzido para pt_BR</a>)<br />
<br />
só pra lembrar: <span class="Apple-style-span" style="background-color: black;"><span class="Apple-style-span" style="font-size: large;"><b><span class="Apple-style-span" style="color: red;">test fails</span>, <span class="Apple-style-span" style="color: lime;">test passes</span>, <span class="Apple-style-span" style="color: #cfe2f3;">refactor</span></b></span></span>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-47554797953873574552011-03-16T06:17:00.001-07:002011-03-17T11:55:45.733-07:00Novo projeto WetSand<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://code.google.com/p/wetsand/"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 85px; height: 55px;" src="http://code.google.com/p/wetsand/logo?cct=0" alt="" border="0" /></a><span style="font-size:180%;">O que estive fazendo...</span><br /><br /><div style="text-align: justify;">Estou tentando reduzir meus (re)trabalhos para criação de <a href="http://pt.wikipedia.org/wiki/CRUD">CRUD</a>'s. O resultado desse esforço é a ideia de criar um framework pra aumentar a produtividade na criação de CRUDS. O conceito principal é que você tem uma API e pode provê várias implementações para essa API (<a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/">W0)</a>. Isso tudo não é nenhuma novidade, apenas minha tentativa de padronizar a criação de CRUDS.<br /><br /><span style="font-size:180%;"><a href="http://code.google.com/p/wetsand/">WetSand</a></span><br /><br />É o conjunto de projetos para criação de aplicações que vão inevitavelmente ter CRUDs.<br /><br /><a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/"><span style="color: rgb(0, 0, 102); font-weight: bold;font-size:130%;" >W0 - A API base</span></a><br /><br />A arquitetura básica está toda nesse projeto, que é fortemente baseado nos conceitos de <a href="http://blog.fragmental.com.br/2007/06/22/cuidado-com-domain-driven-design/">Domain-Driven Design (DDD)</a>. Infelizmente o conceito de <a href="http://blog.fragmental.com.br/2007/10/15/arquitetos-mcdonalds/">arquitetura de referência</a> é empregado aqui, engessar sua aplicação tem vários efeitos colaterais e más implicações mas foi o <span style="font-weight: bold;">jeito que encontrei </span>de "criar" uma estrutura, até certo ponto flexível, <span style="font-weight: bold;">para servir genericamente</span> para isso. Resumidamente um arquitetura de referência te força a usar a mesma estrutura para matar uma "barrata" e matar uma "baleia" <span style="font-weight: bold;">por outro lado</span> há uma <span style="font-weight: bold;">padronização de interfaces e mensagens entre os componentes</span>, o que para a criação de CRUD's pode ajudar muito.<br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);font-size:130%;" >W1 - Primeira implementação <a href="http://jcp.org/en/jsr/detail?id=317">JPA 2.0</a>, <a href="http://www.springsource.com/developer/spring">Spring 3.x.x</a>, <a href="http://javaserverfaces.java.net/">JSF 2.0</a></span><br /><br />Para ter mesmo certeza que tal API poderá ser útil, trabalho na primeira implementação dessa API. Essa implementação utiliza JPA 2.0, Spring 3.x.x, JSF 2.0 e <a href="http://www.primefaces.org/downloads.html">Primefaces 2.2.1</a> dentre suas dependências. Foram criados os subprojetos:<br /><ul><li><a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w10/">W10</a> - A implementação para os Dao's (<a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/src/main/java/com/google/code/wetsand/api/dao/CrudDao.java">CrudDao</a>) baseada no JPA 2.0 bem como a implementação da API <a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/src/main/java/com/google/code/wetsand/api/repository/Query.java">Query</a>.</li><li><a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w11/">W11</a> - A implementação base para o <a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/src/main/java/com/google/code/wetsand/api/repository/CrudRepository.java">CrudRepository</a>.<br /></li><li><a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w12/">W12</a> - A implementação base para o <a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/src/main/java/com/google/code/wetsand/api/service/CrudService.java">CrudService</a>.<br /></li><li><a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w13/">W13</a> - A implementação base para o <a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/src/main/java/com/google/code/wetsand/api/controller/ManagedBeanCrudController.java">ManagedBeanCrudController</a> que é uma especificação do controlador mais genérico <a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w0/src/main/java/com/google/code/wetsand/api/controller/CrudController.java">CrudController</a>.<br /></li></ul><span style="font-size:180%;">Em que pé anda...</span><br /><br />O projeto exemplo já está rodando mas ainda considero longe de uso em produção ou algo assim, está na fase de evolução. Logo, toda e qualquer sugestão ou crítica será bem vinda. Penso em <span style="font-weight: bold;">criar implementações compatíveis para <a href="http://community.jboss.org/wiki/RichFaces40ReleaseCenter">Richfaces 4.0</a>, </span><a style="font-weight: bold;" href="http://vraptor.caelum.com.br/">VRaptor 3</a><span style="font-weight: bold;">, </span><a style="font-weight: bold;" href="http://code.google.com/appengine/">GAE</a><span style="font-weight: bold;"> e </span><a style="font-weight: bold;" href="http://code.google.com/webtoolkit/">GWT</a> para realmente testar se é possível que essa API e suas implementações possam diminuir o retrabalho de CRUDS. Também há um <a href="http://code.google.com/p/wetsand/source/browse/trunk/wetsand/w1generator/">gerador de CRUD</a> mas esse é bem específico e a única implementação que tem é para o W1X.<br /><br /><span style="font-size:180%;">Enfim</span><br /><br /><span style="font-weight: bold;">Se o projeto não servir de nada </span>talvez ele sirva de <span style="font-weight: bold;">exemplo de como</span> construir <span style="font-weight: bold;">telas usando JSF 2.0</span>, <span style="font-weight: bold;">components do facelets</span>, usar o <span style="font-weight: bold;">primefaces</span>, utilizar o <span style="font-weight: bold;">Spring 3.x.x juntamente com JPA 2.0,</span> bem como <span style="font-weight: bold;">Maven</span> e outras boas práticas de "novas" tecnologias. Logo terá uma <span style="font-weight: bold;">documentação básica</span> com um <span style="font-weight: bold;">Quick Start e demonstração de exemplos</span>.<br /></div><span style="font-size:130%;"></span>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-23305583853048795342011-01-04T03:51:00.000-08:002011-01-05T16:16:10.256-08:00Segurança, CCC, Assinatura digital, Consoles...<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.ccc.de/images/header.png?1257022543"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 484px; height: 119px;" src="http://www.ccc.de/images/header.png?1257022543" alt="" border="0" /></a><br /><br /><div style="text-align: justify;">O <a href="http://www.ccc.de/">CCC - Chaos Computer Club</a> promoveu, esse ano, um <a href="http://events.ccc.de/">evento</a> que mostrou muitos fatos interessantes. Em uma das apresentações o grupo <a href="http://fail0verflow.com/">fail0verflow</a> demonstrou um pouco da história das falhas de segurança nos consoles da nova geração (Wii, Xbox 360, PS3). E foi interessante ver o modelo de segurança do PS3 e como eles desvendaram as chaves privadas do mesmo, eu só conhecia bem superficialmente o <a href="http://wiibrew.org/wiki/Wii_Security">modelo de segurança do Wii</a>. Se você interessa por segurança, consoles e hacking é uma ótima apresentação.<br /><br /><object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/hcbaeKA2moE?fs=1&hl=pt_BR"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/hcbaeKA2moE?fs=1&hl=pt_BR" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="640" height="385"></embed></object><br /><a href="http://www.youtube.com/watch?v=hcbaeKA2moE">http://www.youtube.com/watch?v=hcbaeKA2moE</a><br /><br /><span style="font-weight: bold; color: rgb(51, 51, 255);">[update]</span><span style="color: rgb(51, 51, 255);"> <span style="color: rgb(0, 0, 102);">- Parece que </span></span><a style="color: rgb(0, 0, 102);" href="http://psx-scene.com/forums/f6/psp-now-also-open-console-developers-74290/">a chave do PSP estava "dentro" do PS3</a><span style="color: rgb(0, 0, 102);"> agora tanto a cena do PSP e PS3 podem, teoricamente, escrever e rodar código dentro das plataformas da sony.</span><br /></div><div style="text-align: justify;"><span style="color: rgb(0, 0, 102);"><br /></span></div><div style="text-align: justify;"><span style="color: rgb(0, 0, 102);"><span class="Apple-style-span" style="color: rgb(51, 51, 255); font-weight: bold; ">[update]</span> - Baixe a <a href="http://events.ccc.de/congress/2010/Fahrplan/attachments/1780_27c3_console_hacking_2010.pdf">apresentação do evento</a>. A <a href="http://www.bbc.co.uk/news/technology-12116051">BBC também noticiou o fato da descoberta do conjunto de chaves</a> que a Sony usa para o PS3 e PSP.</span></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-33258955511210087802010-11-04T05:30:00.000-07:002010-11-04T07:24:50.328-07:00A prática do SEO e os resultados<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.seobrasilis.com/MyImages/seo-blocks.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 282px; height: 217px;" src="http://www.seobrasilis.com/MyImages/seo-blocks.gif" alt="" border="0" /></a>Apesar de ter um trabalho fixo; hora ou outra também executo trabalhos <a href="http://archsofty.blogspot.com/2010/03/freelancer-java-tive-bons-resultados.html">freelancer java</a>. E ultimamente as propostas de trabalho tem aumentado consideravelmente. E esse aumento se deve (na maioria absoluta) ao uso de um conjunto de técnicas (e ou estratégias) <a href="http://pt.wikipedia.org/wiki/Otimiza%C3%A7%C3%A3o_para_motores_de_busca">SEO</a>.<br /><br />É impressionante o quanto o google pode lhe dar retorno com um bom posicionamento, e digo isso baseado apenas no lucro que obtive em pequenos trabalhos ou ajuda (consultória) em <span style="font-weight: bold;">Java, Richfaces, JSF, JPA</span> enfim...<br /><br />Por isso e outros fatores noto que a propaganda paga ao google é um investimento que tem retorno garantido. Só pra esclarecer não tenho nenhum vinculo com google (empregatício porque de uso muito de seus serviços).<br /><br />Para se ter uma ideia, se você procurar por <a href="http://www.google.com.br/search?q=freelancer+java">freelancer java</a> no google, o blog vem em 5º lugar (claro esse posicionamento vai se atualizar) e com esse "5º lugar" noto que a diferença de divulgação por email, forum e etc é extremamente irrisória se comparada ao jeito google de ser.<br /><br />Portanto fica aqui a dica se não conhece vale a pena dar uma estudadinha em SEO e suas consequências.<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-84060730204142089172010-08-10T12:10:00.000-07:002010-08-17T12:18:32.622-07:00Decisões de design - Herança X Composição<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.puzzlingpuzzles.com.au/IMAGES%20UPDATE/MagicCube5x5.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 163px; height: 160px;" src="http://www.puzzlingpuzzles.com.au/IMAGES%20UPDATE/MagicCube5x5.jpg" alt="" border="0" /></a>Mesmo que esse assunto pareça já explorado de todas as formas ainda há certas situações que relutamos (pelos menos eu) em usar a <a href="http://blog.caelum.com.br/2006/10/14/como-nao-aprender-orientacao-a-objetos-heranca/">herança ao invés da composição</a>.<br />Invejando descaradamente o <a href="http://fragmental.tw/category/everyday-tales/">conto de cada dia</a> do <a href="http://blog.fragmental.com.br/">Phillip</a> <img style="width: 29px; height: 29px;" alt="http://images.americanas.com.br/produtos/item/2508/8/2508843gg.jpg" src="http://images.americanas.com.br/produtos/item/2508/8/2508843gg.jpg" />. Vou contar de uma experiência que tive. O exemplo clássico é o controlador CRUD (seja seu servelet, managed bean, action form... ) que contém os métodos para uso geral e genérico e alguns ganchos. Vou dar um exemplo bem simples de um Managed Bean CRUD.<br /><pre><br />public class ManagedBeanCRUD [E,ID]{<br />private E instancia;<br />public E getInstancia(){return instancia;}<br />public Void setInstancia(E entidade){this.instancia = entidade;}<br /><br />public String salvar(){<br />preSalvar();<br />servicoCrud.salvar(getInstancia);<br />return "navegacaoListar";<br />}<br />public void preSalvar(){}<br />}<br /></pre><br />E apartir desse MB crio os meus outros CRUDS simples, exemplo telefone:<br /><pre><br />public class TelefoneMB extends ManagedBeanCRUD [Telefone, Integer] {<br />@Override<br />public void preSalvar(){<br />System.out.println("Oi esse é gancho ...");<br />}<br />}<br /></pre><br />Ótimo, houve reuso por meio da herança mas logo veio as seguintes perguntas: p<span style="color: rgb(0, 0, 153);">orque não transformou os métodos </span><span style="font-weight: bold; color: rgb(0, 0, 153);">preXXX</span><span style="color: rgb(0, 0, 153);"> em métodos abstratos?</span> Porque daí eu teria que obrigar o usuário a implementar sempre mesmo quando não fosse necessário. <span style="color: rgb(0, 0, 102);">porque não usou composição ao invés da herança?</span> Porque minha visão (xhtml) já está toda padronizada.<br /><br /><span style="color: rgb(0, 0, 102); font-weight: bold;">[c:campoentrada binding="#{mb.instancia.numero}"/]</span><br /><span style="color: rgb(0, 0, 102); font-weight: bold;">[c:botao binding="#{mb.salvar}"/]</span><br /><br />Note que o método salvar não existe (ao menos no fonte) na classe TelefoneMB ele é acessado por herança. A primeira tentativa foi substituir a herança por composição por meio de delegação, minha classe TelefoneMB ficaria mais ou menos assim:<br /><br /><pre>public class TelefoneMB{<br />private ManagedBeanCRUD[Telefone, Integer] delegate;<br />public String salvar(){<br /> return delegate.salvar();<br />}<br />// + do mesmo<br />}</pre>Mas será que não pode ser melhorado?!<br /><br />Claro que sim até agora consegui chegar num patamar assim: os métodos ganchos se transformam no padrão <a href="http://www.javabeat.net/tips/129-decorator-design-pattern.html">decorator</a> e a herança se torna composição por delegação mas de um modo diferente, fiz o MangedBeanCRUD ser um atributo de leitura :<br /><br /><pre>public class TelefoneMB{<br />private ManagedBeanCRUD[Telefone, Integer] crud;<br /><br />public TelefoneMB(){<br /> crud.addEventoPreSalvar(new Evento(){<br /> public void executar(){<br /> System.out.println("antes de salvar...");<br /> }<br /> });<br />}<br /><br />public ManagedBeanCRUD getCrud(){<br /> return crud;<br />}<br />}</pre>E na view (jsf, xhtml ...) não terei muita mudança será uma navegação a mais na #EL #{telefonemb.<span style="font-weight: bold;">crud</span>.salvar} terei que adicionar o crud antes do padrão CRUD de ser.<br /><br />Com isso tenho um managed bean livre de más práticas, melhorei o sistema de eventos e mais um plus não terei problemas futuros com proxies do JDK ou GLIB2! Mais camadas e indireções sempre foi o caminho conforme post sobre <a href="http://fragmental.tw/2010/08/17/thoughts-on-abstractions-part-1-%E2%80%93-abstractions-everywhere/">abstrações pra todo lado</a>.<br /><br />Todo comentário sempre é e será bem-vindo!<br /><br />ps: <span style="font-style: italic;">só pra deixar claro não sou contra o uso da herança, há casos que você pode usar </span><a style="font-style: italic;" href="http://ambientinformatica.servehttp.com:443/xwiki/bin/view/Blog/Heranca+com+Jpa">herança para compor suas entidades</a><span style="font-style: italic;"> e outros n usos. O único cuidado que deve ter é pensar, pensar, pensar e pensar para </span><a style="font-style: italic;" href="http://edgarddavidson.com/?p=30">decidir se é herança ou não</a><span style="font-style: italic;">.</span></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-91721895467737030802010-07-13T05:12:00.000-07:002010-07-13T09:09:36.204-07:00Wii Hacking ;D<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://blogdopseudo.files.wordpress.com/2009/09/nintendo_wii.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 203px; height: 203px;" src="http://blogdopseudo.files.wordpress.com/2009/09/nintendo_wii.jpg" alt="" border="0" /></a><span style="font-style: italic; color: rgb(255, 0, 0);">Primeiramente, pra esclarecer...</span><br /><div style="text-align: justify;"><span style="font-size:130%;">O que esse post não é?</span><br /><br />Um tutorial de como fazer hacking, desbloquear, instalar o homebrew channel...<br /><br /><span style="font-size:130%;">O que é?</span><br /><br />Uma visão geral (BEM resumida) sobre a arquitetura do wii, os processos de hacking atuais; enfim, se trata mais de um post de curiosidade do que um manual. :P (quem quiser isso pode ir no <a href="http://wiiplayersforum.com">wii players forum</a> ou <a href="http://gbatemp.net/">gbatemp</a>, nesses sites você encontra o melhor e mais atualizado conteúdo sobre wii hacking).<br /></div><br /><br /><span style="font-size:130%;">Wii Hacking</span><br /><br /><div style="text-align: justify;">É o ato de tentar hackear a máquina <a href="http://www.nintendo.com/wii">nintendo Wii</a> :)<br /><br /><span style="font-size:130%;">Mas pra que hackear o Wii?</span><br /><br />Pra essa pergunta há N-respostas que vão desde um simples desejo de rodar programas feitos por você ou outras pessoas (<a href="http://wiibrew.org/wiki/Main_Page">homebrew</a> - <span style="font-style: italic;">código</span> <span style="font-style: italic;">não assinados</span>) até rodar jogos (seus backups) pelo <a href="http://code.google.com/p/usbloader-gui/">hd usb externo</a>.<br /><br /><span style="font-size:130%;">Então como é feito o processo de hacking do Wii?</span><br /><br />Como quase todo hacking, baseado nas falhas existentes. Pra melhor entender e explorar o assunto é necessário ter a visão básica de como funciona (bem básico) a pilha de software do Wii.<br /><br /><span style="color: rgb(0, 0, 102);">[Quase sempre vísivel ao usu] - System Menus (4.2U , 3.5K).</span><br /><span style="color: rgb(51, 51, 255);">[Quase sempre invísivel ao usu] - IOS sistemas internos (IOS 222,36).</span><br /><span style="color: rgb(153, 153, 255);">[Quase nunca vísivel ao usu] - BOOT0, BOOT1 e BOOT2.</span><br /><br /><span style="font-size:130%;">Os <a href="http://pt.wikipedia.org/wiki/Exploit">Exploits</a>!</span><br /><br />O mais famoso (e também antigo, obsoleto, só funciona com system menus até o 3.4...) deles é o que é executado por meio do jogo The Legend of Zelda: Twilight Princess, mas tem o "inconveniente" de que você necessita de ter o jogo (você deveria tê-lo mesmo :P). Se você quiser saber mais sobre esse exploit (criado pelo <a href="http://wiibrew.org/wiki/Team_Twiizers">Team Twiizers</a>) leia <a href="http://wiibrew.org/wiki/Twilight_Hack">Twilight Hack</a>.<br /><br />Hoje em dia as pessoas utilizam com maior frequência o <span style="font-weight: bold;"><a href="http://wiibrew.org/wiki/Bannerbomb">Bannerbomb</a> </span>que é um processo bem mais seguro, testado e fácil. Você carrega um SDcard <a href="http://bannerbomb.qoid.us/index.new.php">com arquivo</a> compatível com seu system menu e o executa pelo ícone do SDcard.<br /><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://wiibrew.org/w/images/1/13/Bg4545_bannerbomb_Load.png"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 238px; height: 133px;" src="http://wiibrew.org/w/images/1/13/Bg4545_bannerbomb_Load.png" alt="" border="0" /></a><br /></div><br /><br /><br /><br /><br /><br /><br /><span style="font-size:130%;"><br />A famosa expressão Brick!</span><br /><br />Há, sempre que se fala desse assunto, um risco ao fazer tais operações. A partir do exploit executado você começa o processo de hacking... isso envolve você 'retirar' algumas IOS que podem lhe 'barrar' de algumas operações, substituir algumas IOS por outras cIOS feitas pela comunidade. Sempre que você alterar essas características você corre o risco. Mas hoje o risco mais é de você atualizar o Wii (pela wifi) para uma versão mais nova do system menu (claro que a nintendo sempre corrige esses bugs, ou tenta) e daí você pode sim ter o Wii invalidado pra sempre. (isso não é brincadeira)<br /><br /><span style="font-size:130%;">E o hacking ... como é feito?</span><br /><br />Você executa um dos exploits (por sua conta é total risco, sobre a pena do Bricked Wii) que normalmente lhe dá condições para que o <a href="http://hbc.hackmii.com/">HomeBrew Channel</a> seja instalado. Esse será sua porta pra rodar aplicativos feitos por você ou outras pessoas na Internet. Além do homebrew channel é importante também remover alguns IOS e substituir outros por cIOS. Isso é feito pra que você volte a ter 'bugs' conhecidos e também acesso a dispositivos externos como HD USB. Um fato importante e muito bom de se 'hacker' o wii, é que você pode fazer várias operações que garantem uma vida útil maior e também ferramentas pra recuperação de erros. Backup da NAND pode lhe garantir num futuro uma possível 'restauração' do sistema.<br /><br /><span style="font-size:130%;">Ferramentas que normalmente são instaladas</span><br /><br /><span style="font-weight: bold;">HomeBrew Channel</span> - também conhecido como HBC, é o canal (aparece no menu inicial do Wii) que lhe permite executar aplicativos não assinalados.<br /><span style="font-weight: bold;">BootMii</span> - Um conjunto de sistemas que você pode instalar no wii pra lhe oferecer mais 'utilidades' ao aparelho.<br /><span style="font-weight: bold;">Priiloader</span> - Sistema que fica exatamente entre a sequência de boot e o system menu. Hoje em dia ele é instalado como se fosse um IOS. Ele lhe dá acesso à vários hacks interessantes e úteis, por exemplo: remover a atualização automática, apertar A naquela tela chata de inicio... e claro pode ser sua salvação, caso o venha a Brickar, ele fornece meios pra você recuperar sua NAND (baseado no seu bkp). Mas ele como IOS não garante 100% de unbrickablility. (Perfeito é quando você consegue, em versões mais antigas do Wii, instala-lo as boot2 aí sim você tem um Wii quase unbrickable, já que você detém o poder do boot :) )<br /><span style="font-weight: bold;">Multiple WAD Manager</span> - O famoso MMM é um gerenciador de pacotes de instalação para o Wii ele é essencial. É díficil de usar, a principio, pois sua interface (textual, não gráfica) não ajuda muito. Nele que você instala cIOS (custom IOS), remove IOS, instalar canais...<br /><br /></div><div style="text-align: justify;"><span style="font-weight: bold;">ps:</span> mais uma vez, não mude seu wii sem conhecer o que é feito com ele e sem ter a noção dos riscos ao substiuir IOS's por cIOS's. E claro, sempre assuma os riscos por sua conta. <span style="font-style: italic;">(<span style="font-weight: bold;">ps2:</span> eu, depois de me informar, acho seguro e com possibilidades pequenas [mas ainda existem] de você perder seus wii.)</span><br /><br />E lembre-se há homebrews que valem muito a pena.<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://img691.imageshack.us/img691/39/usbloadergxscreenshotja.png"><img style="display: block; margin: 0px auto 10px; text-align: center; cursor: pointer; width: 529px; height: 395px;" src="http://img691.imageshack.us/img691/39/usbloadergxscreenshotja.png" alt="" border="0" /></a><br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-36562831052843832372010-06-29T11:23:00.000-07:002010-06-29T11:51:00.562-07:00Habilitando Cache level 2 no JPA 1.0 (Hibernate)<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://community.devexpress.com/blogs/aspnet/image_C/Cheetah-fast.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 151px; height: 112px;" src="http://community.devexpress.com/blogs/aspnet/image_C/Cheetah-fast.jpg" alt="" border="0" /></a>Uma das características prometidas para o <a href="http://jcp.org/en/jsr/detail?id=317">JPA 2.0</a> e já implementada no hibernate é <a href="http://www.devx.com/dbzone/Article/29685">Second Level </a>cache! Pra habilita-lo é bem simples:<br /><div style="text-align: justify;"><br />Basta informar ao Hibernate (seja pelo persistence.xml ou pelo applicationContext.xml) as seguintes propriedades.<br /><span style="font-size:85%;"><span style="font-weight: bold;">hibernate.cache.provider_class</span>=org.hibernate.cache.EhCacheProvider <span style="font-style: italic; color: rgb(51, 0, 153);">{classe padrão pra prover serviços de cache}</span><br /><span style="font-weight: bold;">hibernate.cache.use_query_cache</span>=true <span style="font-style: italic; color: rgb(0, 0, 102);">{se deve ou não fazer caches de queries}</span></span><br /><br />Lembrando que por padrão você deve configurar entidade a entidade as quais devem ou não serem cacheadas (com a anotação <span style="font-weight: bold;">@Cache</span> junto a @Entity, você também pode cachear coleções!) e qual a política (de concorrência) que deve ser usada no esquema de cache (<span style="font-weight: bold;">NONSTRICT_READ_WRITE, NONE, READ_ONLY, WRITE_ONLY, TRANSACTIONAL</span>). Depois é só observar pelo log de sql :D! <span style="font-weight: bold;">Have fun!</span><br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-73216698775239979362010-05-29T18:32:00.000-07:002010-05-31T04:55:10.100-07:00NoSuchFieldException no Hibernate (JPA)<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://tell.fll.purdue.edu/JapanProj/FLClipart/Adjectives/headache.gif"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 180px; height: 149px;" src="http://tell.fll.purdue.edu/JapanProj/FLClipart/Adjectives/headache.gif" alt="" border="0" /></a><div style="text-align: justify;">No padrão <a href="http://java.sun.com/developer/technicalArticles/J2EE/jpa/">JPA</a> você pode anotar suas entidades pelos métodos (getters) ou pelos atributos, é um ou exclusivo ou vocÊ anota tudo pelos atributos ou pelos getters. O relato que segue é sobre um código que funcionou muito bem por muito tempo mas que na última sexta feira (28/05/2010) me deu muita dor de cabeça.<br /><br />Devido a limitação do <a href="http://java.sun.com/javaee/javaserverfaces/">JSF</a> (1.X) quanto a população de combos (o usuário do framework é obrigado a passar uma lista/matriz de SelectItem), eu criei um código para que dado uma lista de objetos, o nome do atributo à ser mostrado (descricao) e o nome do atributo com valor (id) retorna uma matriz de SelectItem.<br /><br /><span style="font-weight: bold;">API</span> <span style="color: rgb(0, 0, 102); font-weight: bold;">SelectItem[] converterListaParaCombo(final List objetos,String attMostrar,String attValor)</span><br /><br />O código é simples; faz um loop nos objetos e vai recuperando os valores dos campos por <a href="http://java.sun.com/docs/books/tutorial/reflect/index.html">reflexão </a>e criando objetos do tipo SelectItem e os adicionando na lista/matriz.<br /><br />Bem, voltando ao relato. Quase sempre eu usei anotar (JPA Annotations) as entidades nos campos, por boa prática comecei anotar pelos getters.<br /><br />Quando fui testar percebi que o método <span style="font-weight: bold;">converterListaParaCombo</span> estava lançando a exceção <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/lang/NoSuchFieldException.html">NoSuchFieldException</a>. Dessa vez o log não ajudou quase nada, <a href="http://blog.caelum.com.br/2010/05/27/logar-e-preciso-debugar-nao-e-preciso/">tive que debugar</a>... para minha surpressa a lista ia sendo populada normalmente até chegar num objeto (da lista) que não tinha o campo descrição :S. A primeira pergunta: Como isso é possível se eu mesmo declarei o campo na entidade?<br /><br />Para responder essa pergunta criei mais um teste sobre a lista de objetos que eu passava para o método. Mandei (imperativamente) um sysout sobre getId e getDescrição... aqui outra surpresa não houve nenhum erro :S. Numa pesquisa mais profunda sobre o assunto descobri que o hibernate tem "seu modo de fazer cache" que pode causar alguma surpresa para os mais desavisados e na verdade ele nem sempre retorna a sua entidade e sim um proxy {eu pensava<br />que esse proxy era somente para List}. E um desses proxies "não tinha" o campo descricao...<br /><br />Para resolver o problema, eu apenas mudei no método a forma de recuperar os valores. Ao invés<br />de pegá-los pelo atributos agora pelo pelos <a href="http://commons.apache.org/beanutils/">métodos getters</a>. :D </div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-80523329585182078552010-05-07T07:48:00.000-07:002010-05-07T09:57:54.416-07:00Adicionando escopo de conversação ao JavaServer Faces 1.X (JSF 1.2)<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://thinkingbrew.files.wordpress.com/2009/04/the_session_logo1.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 175px; height: 205px;" src="http://thinkingbrew.files.wordpress.com/2009/04/the_session_logo1.jpg" alt="" border="0" /></a>Que o JSF não é perfeito <a href="http://ptrthomas.wordpress.com/2009/05/15/jsf-sucks/">todos sabemos</a> mas se há algo que me incomoda muito são duas coisas chatas: <span style="font-weight: bold;">URL amigáveis </span>(que consegui <a href="http://archsofty.blogspot.com/2010/04/url-amigaveis-com-javaserver-faces-jsf.html">resolver facilmente com </a><a href="http://ocpsoft.com/prettyfaces/v123/">PrettyFaces</a>.) e tratar tudo como escopo de sessão (por falta de um escopo entre o requisição e o sessão).<br /><br />Para o último problema começei a pesquisar algumas soluções possíveis e cheguei ao framework <a href="http://myfaces.apache.org/orchestra/">MyFaces Orchestra</a>.<br /><br />O <span style="font-weight: bold;">MyFaces Orchestra</span> é um framework que pode ser usado em aplicações web para prover as caracteristicas de escopo conversacional. Apesar de ter sido criado para ser um framework de escopo para web presentations ele tem, hoje, só implementações para JSF 1.1, 1.2 e 2.0.<br /><br />Para utilizar o framework você precisa, <span style="font-weight: bold;">obrigatoriamente</span>, usar o <a href="http://cagataycivici.wordpress.com/2005/12/25/integrating_jsf_and_spring/">Spring 2.0 (ou maior) como gerenciador de seus managed beans</a>. E claro ter os modulos do Orchestra (<a href="http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-orchestra-core12-1.4.zip">core12</a> e o <a href="http://www.apache.org/dyn/closer.cgi/myfaces/binaries/myfaces-orchestra-core15-1.0.zip">core15</a> são os usados no exemplo) no seu classpath.<br /><br /><span style="font-size:130%;">Exemplo</span><br /><br />Fiz um exemplo utilizando Eclipse juntamente com quarteto fantástico : <span style="font-weight: bold;">richfaces 3.3.3</span> + <span style="font-weight: bold;">Facelets</span> + <span style="font-weight: bold;">spring 3.0.1 </span>+ <span style="font-weight: bold;">hibernate 3.0.2</span><span style="font-weight: bold;"> (JPA)</span>! e tive que mudar/configurar os seguintes arquivos:<br /><br /><span style="font-weight: bold;">web.xml</span><br /><pre><br /><span style="color: rgb(0, 0, 153);"> <listener></span><br /><span style="color: rgb(0, 0, 153);"> <listener-class>org.apache.myfaces.orchestra.conversation.servlet.ConversationManagerSessionListener</listener-class></span><br /><span style="color: rgb(0, 0, 153);"> </listener></span><br /></pre><br /><span style="font-weight: bold;">applicationContext.xml</span><br /><pre><br /><span style="color: rgb(0, 0, 102);"> <import resource="classpath*:/META-INF/spring-orchestra-init.xml" /></span><br /><span style="color: rgb(0, 0, 102);"> </span><br /><span style="color: rgb(0, 0, 102);"> <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer"></span><br /><span style="color: rgb(0, 0, 102);"> <property name="scopes"></span><br /><span style="color: rgb(0, 0, 102);"> <map></span><br /><span style="color: rgb(0, 0, 102);"> <entry key="conversation.manual"></span><br /><span style="color: rgb(0, 0, 102);"> <bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope"></span><br /><span style="color: rgb(0, 0, 102);"> <property name="timeout" value="30" /></span><br /><span style="color: rgb(0, 0, 102);"> <property name="lifetime" value="manual"/></span><br /><span style="color: rgb(0, 0, 102);"> </bean></span><br /><span style="color: rgb(0, 0, 102);"> </entry></span><br /><br /><span style="color: rgb(0, 0, 102);"> <entry key="conversation.access"></span><br /><span style="color: rgb(0, 0, 102);"> <bean class="org.apache.myfaces.orchestra.conversation.spring.SpringConversationScope"></span><br /><span style="color: rgb(0, 0, 102);"> <property name="timeout" value="30" /></span><br /><span style="color: rgb(0, 0, 102);"> <property name="lifetime" value="access"/></span><br /><span style="color: rgb(0, 0, 102);"> </bean></span><br /><span style="color: rgb(0, 0, 102);"> </entry></span><br /><span style="color: rgb(0, 0, 102);"> </map></span><br /><span style="color: rgb(0, 0, 102);"> </property></span><br /><span style="color: rgb(0, 0, 102);"> </bean></span><br /></pre><br /><span style="font-weight: bold;"></span><br />Simplesmente após ter feito tais mudanças e ter atendido aos <span style="font-weight: bold;">requisitos básicos</span>: declarei meu bean no applicationContext com <span style="font-weight: bold;">scope="conversation.access"</span>. No exemplo naveguei de uma página listar.xhtml para outra editar.xhtml mantendo o estado! Fiz testes posteriores também com uso de Ajax (a4j) com multiplos requests para mesma página ou outra tudo passou perfeito!<br /><br />Se quiser ver o projeto <a href="http://www.mediafire.com/?nymj1gmoyde">baixe aqui o projeto (.war com sources)</a>!<br /><br /><span style="font-size:130%;">Further Reading!</span><br /><br />O framework também fornece uma solução (essa eu não testei) para os lazy initializations lançados (esse com integração forte ao hibernate). Há também um esquema de <a href="http://myfaces.apache.org/orchestra/myfaces-orchestra-core/component-bindings.html">binding</a> muito legal.<br /><br />ps: todo o post está levando em consideração as características do Jsf 1.x o Jsf 2.0 resolve alguns desses empecilhos.<br />ps2: ainda há algo que me incomoda é a quantidade de linhas no faces-config para lhe dar com navegação entre as páginas.<br /><a href="http://oglobo.globo.com/fotos/2006/11/14/14_MVG_tec_playstation3.jpg">ps3</a>: fiz testes básicos nesse projeto aconselho fazer mais testes reais na sua aplicação antes de substituir session por conversation.<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com1tag:blogger.com,1999:blog-3760273245894556929.post-63545886394489168572010-04-28T07:25:00.000-07:002010-04-28T10:10:20.387-07:00Integrando google app engine (GAE) + Spring 3.0.2 + Hibernate (JPA)<div style="text-align: center;"><img style="width: 79px; height: 60px;" alt="Google App Engine - GAE" src="http://code.google.com/intl/pt-BR/appengine/images/appengine_lowres.gif" /><img style="width: 161px; height: 49px;" alt="Spring Framework" src="http://www.springsource.org/sites/all/themes/zen/framework/logo.png" /><img style="width: 203px; height: 56px;" alt="Hibernate - JPA" src="http://blog.aplikacja.info/wp-content/uploads/2009/09/hibernate_logo_a.png" /><br /></div><br /><span style="font-weight: bold;font-size:180%;" >Introdução </span><br /><br /><div style="text-align: justify;">Usar a infraestrutura do <a href="http://pt.wikipedia.org/wiki/Computa%C3%A7%C3%A3o_em_nuvem">google para hospedar suas aplicações</a> pode parecer algo fantástico. Imagine ter todo o poder e segurança fornecido pelo Google diretamente nas suas aplicações. É com essa promessa que o <a href="http://code.google.com/intl/pt-BR/appengine/">Google App Engine (GAE) </a>foi lançado. Pode-se criar aplicações Web usando Python ou Java.<br /><span style="font-weight: bold;"><span style="font-size:180%;">+</span>Vantagens:</span> boa <a href="http://code.google.com/intl/pt-BR/appengine/docs/">documentação em pt_BR</a>, aproveitar da escalabilidade do google, desenvolver em Java (no ponto de vista de número de pessoas aptas) e etc.<br /><span style="font-weight: bold;"><span style="font-size:180%;">-</span>Desvantagens:</span> <a href="http://code.google.com/intl/pt-BR/appengine/docs/java/jrewhitelist.html">JRE com menos classes</a>, <a href="http://groups.google.com/group/google-appengine-java/web/will-it-play-in-app-engine?pli=1">frameworks não funcionando ou funcionando parcialmente</a>, <a href="http://code.google.com/intl/pt-BR/appengine/docs/java/datastore/usingjpa.html#Unsupported_Features_of_JPA">restrições ao uso do JPA</a> e etc.<br /></div><br /><span style="font-weight: bold;font-size:180%;" >Configurando plugin no Eclipse</span><br /><br />Para facilitar, muito, a criação, deploy e debug de seus aplicativos aconselho a utilizar o <a href="http://code.google.com/intl/pt-BR/appengine/docs/java/tools/eclipse.html">Eclipse juntamente com o plugin</a> fornecido pelo google.<br /><br /><span style="font-size:180%;">Integrações</span><br /><br /><span style="font-size:130%;">Spring 3.0.2</span><br /><br />Gosto de usar o controle transacional do Spring (@Transactional) , injeção de dependência e a implementação do open session in view (OpenEntityManagerInView) e para usar tais recursos tive que configurar o <span style="font-weight: bold;">web.xm</span>l dessa forma.<br /><br /> <listener><br /> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class><br /> </listener><br /> <listener><br /> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class><br /> </listener><br /><br /> <filter><br /> <filter-name>SpringOpenEntityManagerInViewFilter</filter-name><br /> <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class><br /> </filter><br /> <filter-mapping><br /> <filter-name>SpringOpenEntityManagerInViewFilter</filter-name><br /> <url-pattern>/*</url-pattern><br /> </filter-mapping><br /><br />Já o arquivo <span style="font-weight: bold;">applicationContext.xml</span> ficou assim.<br /><br /> <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" /><br /> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean" lazy-init="true"><br /> <property name="persistenceUnitName" value="t3st3" /><br /> </bean><br /> <bean name="txManager" class="org.springframework.orm.jpa.JpaTransactionManager"><br /> <property name="entityManagerFactory" ref="entityManagerFactory" /><br /> </bean><br /> <tx:annotation-driven transaction-manager="txManager" /><br /><br /><span style="font-size:130%;">JavaServer Faces 2 (JSF 2.0)</span><br /><br />Costumo repassar o trabalho de cuidar do ciclo de vida dos managedbean para o Spring. A utilização do jsf 2 (implementação myfaces) traz as novidades do jsf 2.0 (que é um grande passo) e saber que é compatível com gae é muito bom. Bem meu <span style="font-weight: bold;">web.xml </span>ficou assim.<br /><br /> <servlet><br /> <servlet-name>Faces Servlet</servlet-name><br /> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class><br /> <load-on-startup>1</load-on-startup><br /> </servlet><br /><br /> <servlet-mapping><br /> <servlet-name>Faces Servlet</servlet-name><br /> <url-pattern>*.jsf</url-pattern><br /> </servlet-mapping><br /> <br /> <br /> <!--<br /> We need to set annotation lifecycyle provider manually as org.apache.myfaces.config.annotation.NoInjectionAnnotationLifecycleProvider.<br /> Other providers use some classes that are restricted on Google App Engine. <br /> --> <br /> <context-param><br /> <param-name>org.apache.myfaces.config.annotation.LifecycleProvider</param-name><br /> <param-value>org.apache.myfaces.config.annotation.NoInjectionAnnotationLifecycleProvider</param-value><br /> </context-param><br /> <br /> <!--<br /> Need to set a secret to avoid javax.crypto.BadPaddingException.<br /> "param-value" must be Base64 encoded.<br /> More details: http://wiki.apache.org/myfaces/Secure_Your_Application<br /> --><br /> <context-param><br /> <param-name>org.apache.myfaces.SECRET</param-name><br /> <param-value>NzY1NDMyMTA=</param-value><br /> </context-param> <br /><br />e o <span style="font-weight: bold;">faces-config.xml</span> assim:<br /><br /> <application><br /> <variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver><br /> </application><br /><br /><span style="font-size:130%;">Hibernate<br /><br /></span>Só usar! Ahh é mesmo tem que se criar um arquivo persistence.xml (META-INF) mínimo.<br /><br /><span style="font-size:130%;">Observações gerais:</span><br />Tente usar sempre o objeto <a href="http://code.google.com/intl/pt-BR/appengine/docs/java/javadoc/com/google/appengine/api/datastore/Key.html">Key</a> como id, pois objetos filhos devem usar Key ou String codificada, não sendo possível usar long ou int.<br />Você pode acompanhar o <a href="http://code.google.com/status/appengine">status do ambiente</a>, quais serviços estão online qual a latência de uso e etc.leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com1tag:blogger.com,1999:blog-3760273245894556929.post-86466226168693846822010-04-09T07:03:00.000-07:002010-04-09T07:04:02.183-07:00Artigo publicado na InfoQ Gringa<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://cdn2.infoq.com/styles/i/logo.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 140px; height: 44px;" src="http://cdn2.infoq.com/styles/i/logo.gif" alt="" border="0" /></a><span style="font-weight: bold;">Nota rápida</span>: o pessoal da InfoQ publicou meu artigo sobre <a href="http://www.infoq.com/articles/lucene-did-you-mean">Implementing Google's "Did you mean" Feature In Java</a>. Todo feedback será bem-vindo.<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-43459231475294580072010-04-09T04:19:00.000-07:002010-04-09T09:16:03.441-07:00URL amigáveis com JavaServer Faces (jsf) 1.X<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.mestreseo.com.br/wp-content/uploads/2009/06/url1.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 169px; height: 169px;" src="http://www.mestreseo.com.br/wp-content/uploads/2009/06/url1.jpg" alt="" border="0" /></a>Uma das críticas dos usuários de JSF é : "você não consegue criar urls que podem ser bookmarked (favoritadas)".<br /><br />Eu pensei que iria ter uma trabalheira do cão... pensei que não iria dar muito certo com <span style="font-weight: bold;">Richfaces</span>, <span style="font-weight: bold;">Spring</span> ... enfim todas as <span style="font-weight: bold;">integrações</span>... pensei... pensei errado! :)<br /><br />Há um framework chamado <a href="http://ocpsoft.com/prettyfaces/v123/">PrettyFaces</a> (para jsf 1.1 , 1.x e 2.0) o qual o uso é extremamente fácil.<br /><br />Com apenas dois passos você adiciona url amigáveis ao JSF:<br /><br />1º Passo: Registrar o filtro no web.xml<br /><div style="border-width: 1px; color: white; border-style: solid; background-color: gray;"><br /><filter><br /><filter-name>Pretty Filter</filter-name><br /><filter-class>com.ocpsoft.pretty.PrettyFilter</filter-class><br /></filter><br /><filter-mapping><br /><filter-name>Pretty Filter</filter-name><br /><url-pattern>/*</url-pattern><br /><dispatcher>REQUEST</dispatcher><br /><dispatcher>FORWARD</dispatcher><br /><dispatcher>ERROR</dispatcher><br /></filter-mapping><br /></div><br />2º Passo: criar o arquivo <span style="font-weight: bold;">pretty-config.xml</span> dentro de WEB-INF:<br /><div style="border-width: 1px; color: white; border-style: solid; background-color: gray;"><br /><pretty-config<br />xmlns="http://ocpsoft.com/prettyfaces-xsd"<br />xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br />xsi:schemaLocation="http://ocpsoft.com/prettyfaces-xsd<br />http://ocpsoft.com/xml/ns/prettyfaces/pretty-1.0.xsd"><br /><url-mapping id="verNoticia"><br /><pattern>/noticia/#{myBean.currentStoryId}/</pattern><br /><view-id>/noticia.xhtml</view-id><br /><action>#{myBean.loadComment}</action><br /></url-mapping><br /></pretty-config><br /></div><br /><br />Com as configurações acima se você digitasse http://seuhost/seuprojeto/noticia/12345/ você mostraria o bean (de ViewID=/noticia.xhtml) com a notícia de id=12345 :)<br /><br />ps: um passo omitido seria o download do jar e o registro do mesmo no classpath da sua aplicação.leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com5tag:blogger.com,1999:blog-3760273245894556929.post-4664819455016585232010-03-29T12:17:00.000-07:002010-03-29T12:36:33.600-07:00Freelancer Java - Tive bons resultados.<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.actionscriptdeveloper.co.uk/wp-content/themes/upstart-blogger-minim-01/images/actionscript_freelancer.gif"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 197px; height: 197px;" src="http://www.actionscriptdeveloper.co.uk/wp-content/themes/upstart-blogger-minim-01/images/actionscript_freelancer.gif" alt="" border="0" /></a><h1>Freelancer Java</h1>De acordo com a Wikipedia: <i><b>"Freelancer</b></i> é o termo inglês para denominar o <a href="http://pt.wikipedia.org/wiki/Profissional_aut%C3%B4nomo" title="Profissional autônomo">profissional autônomo</a>, que se auto-emprega em diferentes empresas ou, ainda, guia seus trabalhos por projetos, captando e atendendo seus clientes de forma independente. É uma tendência muito em voga no mercado de <a href="http://pt.wikipedia.org/wiki/Jornalismo" title="Jornalismo">jornalismo</a>, <a href="http://pt.wikipedia.org/wiki/Design" title="Design">design</a>, <a href="http://pt.wikipedia.org/wiki/Propaganda" title="Propaganda">propaganda</a>, <a href="http://pt.wikipedia.org/wiki/Web" title="Web" class="mw-redirect">web</a>, <a href="http://pt.wikipedia.org/wiki/Tecnologia_da_informa%C3%A7%C3%A3o" title="Tecnologia da informação">tecnologia da informação</a>, <a href="http://pt.wikipedia.org/wiki/M%C3%BAsica" title="Música">música</a> e muitos outros."<br />Há - muito - tempo atrás li um post interessantíssimo denominado o <a href="http://www.fragmental.com.br/wiki/index.php?title=Guia_de_Guerra_Para_Freelancers">guia de guerra para freelancers</a>. E eu também tentei me aventurar pelo mundo dos <a href="http://archsofty.blogspot.com/2009/03/ofereco-trabalho-de-freelancer-em-java.html">serviços de freelancer java</a>. Até que me posicione bem no google, se você pesquisar <a href="http://www.google.com/search?q=trabalho+freelancer+java">"trabalho freelancer java"</a> no google, meu blog aparecerá no fim da primeira página ou no inicio da segunda, claro (quase) todos os créditos aos trabalhos que obtive foram vindos do google. Para minha surpresa tive alguns contatos bem rápidos e um ponto interessante foi que a maioria deles não moravam próximo a mim. Todo trabalho desenvolvido (para os clientes) foi baseado na confiança e a comunicação basicamente foi por emails. Dá pra ganhar uma graninha extra com disciplina e responsabilidade. =D<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com3tag:blogger.com,1999:blog-3760273245894556929.post-1576702702037388322010-03-09T05:54:00.000-08:002010-03-09T06:42:22.486-08:00boasPraticas.add deploy, tdd, ddd<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://nunoveloso.eu/files/imagecache/blog_full/blog/engrenages.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 183px; height: 222px;" src="http://nunoveloso.eu/files/imagecache/blog_full/blog/engrenages.jpg" alt="" border="0" /></a>Recebi a visita de um super amigo das antigas (leia-se VB.NET), eu tinha que entegrar um <a href="http://blog.fragmental.com.br/2007/10/07/sistemas-simples-como-portais-por-exemplo/">simples gerenciador de conteúdo</a> e meu amigo me acompanhou e ficou questionando sobre por que eu fazia assim, usava aquilo, não fazia isso... no fim ele disse que precisava de desenvolver com mais qualidade, controle e facilidade. Ele ainda me pediu uma <a href="http://gc.blog.br/2008/03/27/10-livros-recomendados-para-desenvolvedores/">lista de livros</a> pra ler e quais praticas eu usava, naquele momento começei a falar tanta coisa, ferramenta, framework, metodo... que ele mesmo disse "escreva uma lista dessas boas práticas"! E aqui estou eu, vou tentar apenas listar os tópicos e os links que acho interessante.<br /></div><div style="text-align: justify;"><br /><span style="font-weight: bold;">Não reivente a roda</span> - quase sempre há uma <a href="http://archsofty.blogspot.com/2009/08/minhascommonslibutils-apachecommons.html">common</a> pronta, então quando surgir uma necessidade pesquise antes sobre o assunto. Tive uma péssima experiência com um agendador de tarefas (que eu criei) em Java, tudo isso porque não conhecia o <a href="http://www.opensymphony.com/quartz/;jsessionid=LDKHONNCOPJC">Quartz</a>.<br /><span style="font-weight: bold;">Melhore seu design OO</span> - por mais que pareça esgotado esse assunto, ainda há pessoas que não compreendaram assuntos básicos, esse tópico (sobre OO) não dá pra ser resolvido com uns poucos links mas se eu pudesse indicar um site seria o do <a href="http://blog.fragmental.com.br/">Philip Calçado</a>. PS: outras boas práticas abaixo listadas podem lhe ajudar também num design mais charmoso.<br /><span style="font-weight: bold;">TDD</span> - uma ótima prática que pode lhe livrar de dores de cabeças infernais. No inicio pode parecer perda de tempo mas com tempo você vai ver o valor de <a href="http://archsofty.blogspot.com/2009/02/tdd-desenvolvimento-guiado-por-testes.html">usar Test Driven Development</a>.<br /><span style="font-weight: bold;">Logging</span> - não há nada mais chato do que ler grandes arquivos de logging não é mesmo?! Há sim, debugar! :P então: prefira Logar do que Degubar! Pode começar lendo um <a href="http://hotwork.sourceforge.net/hotwork/manual/log4j/log4j-user-guide.html">tutorial de log4j</a>.<br /><span style="font-weight: bold;">Deploy</span> - Automatizar suas construções e criar um <a href="http://blog.caelum.com.br/2010/03/01/o-processo-de-deploy-continuo/">processo de deploy continuo</a> :)<br /><a href="http://blog.caelum.com.br/2008/01/28/os-7-habitos-dos-desenvolvedores-hibernate-e-jpa-altamente-eficazes/"><span style="font-weight: bold;">Boas práticas com JPA</span></a> - às vezes passamos raiva só por desconhecimento (profundo) de um certo recurso do framework. Logo digo leia esse ótimo post sobre os <a href="http://blog.caelum.com.br/2008/01/28/os-7-habitos-dos-desenvolvedores-hibernate-e-jpa-altamente-eficazes/">bons habitos de usar JPA</a>.<br /><span style="font-weight: bold;">Integração continua</span> - Leia o post de <a href="http://martinfowler.com/articles/continuousIntegration.html">Integração continua</a> ahhh outra dica <a href="http://gc.blog.br/2009/04/15/louco-por-automatizacao/">automatize tudo</a> o possível.<br /><span style="font-weight: bold;">Aprenda outra linguagem</span> - Sua cabeça pode se tornar <a href="http://java.sun.com/">viciada numa linguagem</a> só e isso pode lhe privar de conhecer ou melhor entender como outros organismos funcionam. Além do mais é divertido aprender <a href="http://www.ruby-lang.org/pt/">Ruby</a> e ver como as pessoas<a href="http://rubyonrails.org/"> resolvem problemas</a> de maneiras tão distintas.<br /><span style="font-weight: bold;">Comunidade </span>- Nem só de código fonte a comunidade open-source se alimenta, usar <a href="http://www.guj.com.br/">forums para aprender</a> e ensinar é algo muito valioso.<br /><a href="http://blog.fragmental.com.br/2008/05/20/trilha-de-livros-desenvolvedor/">Outros bons livros</a> :)<br /><br />Tudo isso pode parecer plágio de um grande <a href="http://blog.caelum.com.br/">blog de ótimo desenvolvedores</a>, mas não é :) Juro!<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-61906991054305934882010-02-23T04:59:00.000-08:002010-02-23T05:35:10.130-08:00Como usar JavaScript na plataforma Java<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://weber.eti.br/wp-content/uploads/2009/09/javascript.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 241px; height: 194px;" src="http://weber.eti.br/wp-content/uploads/2009/09/javascript.jpg" alt="" border="0" /></a>Em minha mente o assunto <a href="http://java.sun.com/javase/6/docs/technotes/guides/scripting/programmer_guide/">scripting na plataforma Java</a> já estava bem explorado e difundido. Mas hoje fui supreendido por um amigo com um mini-framework que servia de analisador e parser para simples fórmulas matemáticas como p.ex:<br />2+2-1*3/3<br />(2+2)*10<br /></div><br />Usando Java 6 basta esse simples código.<br /><pre><br /> ScriptEngineManager factory = <span style="color: rgb(51, 102, 255);">new</span> ScriptEngineManager();<br /> ScriptEngine engine = factory.getEngineByName("JavaScript");<br /> <span style="color: rgb(51, 102, 255);">try</span> {<br /> String script = " 10 + 2 * 2 "; //ou sua expressão<br /> Object result = engine.eval(script);<br /> System.<span style="color: rgb(51, 204, 0);">out</span>.println(result);<br /> } <span style="color: rgb(51, 102, 255);">catch</span> (ScriptException ex) {<br /> System.out.println("deu erro :P "+ex);<br /> }<br /></pre>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com1tag:blogger.com,1999:blog-3760273245894556929.post-20380107140915491552010-02-13T17:30:00.000-08:002010-02-14T15:35:03.558-08:00JTableAnnotations - Um jeito mais simples de criar JTable<div style="text-align: center;"><span style="font-weight: bold;font-size:180%;" >JTableAnnotations</span><br /></div><div style="text-align: justify;">Há algum tempo atrás escrevi um mini-framework para <span style="font-weight: bold;">criação de JTable por anotação.</span> Talvez esse pedaço de código possa lhe servir, criar JTable sempre é uma tarefa chata e tediosa (e para alguns dificil). O <a href="http://code.google.com/p/jtableannotations/">JTableAnnotations</a> <span style="font-weight: bold;">propõe uma simplificação</span> no processo de configuração e preenchimento das tabelas.<br /><br />Basicamente você precisará anotar suas entidades<br /><pre><div style="border: 1px solid blue;"><br />@JTableConfiguration(rowHeight=48)<br /><span style="color: rgb(0, 0, 153);">public class</span> <span style="font-weight: bold;">Product</span> {<br />@JTableColumnConfiguration(order=1,width=55)<br /><span style="color: rgb(51, 0, 153);">private</span> Long <span style="color: rgb(0, 51, 0);">id</span>;<br />@JTableColumnConfiguration(order=2,width=300,editable=true,align=Align.CENTER)<br /><span style="color: rgb(51, 0, 153);">private</span> String <span style="color: rgb(0, 51, 0);">name</span>;<br />@JTableColumnConfiguration(order=3,name=<span style="color: rgb(204, 102, 0);">"Price"</span>,decimalFormat=<span style="color: rgb(204, 102, 0);">"U$ 0.00"</span>)<br /><span style="color: rgb(51, 0, 153);">private</span> BigDecimal <span style="color: rgb(0, 51, 0);">value</span>;<br />@JTableColumnConfiguration(order=4,name=<span style="color: rgb(204, 102, 0);">"Costumer Name"</span>,width=300)<br /><span style="color: rgb(51, 0, 153);">private</span> Customer <span style="color: rgb(0, 51, 0);">customer</span>;<br />@JTableColumnConfiguration(order=0,name=<span style="color: rgb(204, 102, 0);">"Photo"</span>,cellRender=IconCellRender.class)<br /><span style="color: rgb(51, 0, 153);">private</span> String <span style="color: rgb(0, 51, 51);">picturePath</span>;<br /></div><br />E então o trabalho de configurar e popular fica a cargo da classe <a href="http://code.google.com/p/jtableannotations/source/browse/trunk/JTableAnnotations/src/com/google/code/jtableannotation/Configurator.java">Configurator</a>:<br /><div style="border: 1px solid blue;"><br />Customer master = <span style="color: rgb(0, 0, 102);">new</span> Customer();<br />master.setName(<span style="color: rgb(204, 102, 0);">"Master"</span>);<br />master.setUserName(<span style="color: rgb(204, 102, 0);">"Admin"</span>);<br />list = <span style="color: rgb(0, 0, 102);">new</span> ArrayList<product>();<br />list.add(<br />createProduct(<br />master, 0L,<br /><span style="color: rgb(204, 102, 0);">"Nintendo Wii"</span>,<br /><span style="color: rgb(204, 102, 0);">"pictures/wii.jpg"</span>,<br /><span style="color: rgb(0, 0, 102);">new</span> BigDecimal(999.50)));<br />list.add(<br />createProduct(<br />master, 1L,<br /><span style="color: rgb(204, 102, 0);">"XBox360"</span>,<br /><span style="color: rgb(204, 102, 0);">"pictures/xbox360.jpg"</span>,<br /><span style="color: rgb(0, 0, 102);">new</span> BigDecimal(1020.85)));<br />list.add(<br />createProduct(<br />master, 2L,<br /><span style="color: rgb(204, 102, 0);">"PS3"</span>,<br /><span style="color: rgb(204, 102, 0);">"pictures/ps3.jpg"</span>,<br /><span style="color: rgb(0, 0, 102);">new</span> BigDecimal(1000.0)));<br />list.add(<br />createProduct(<br />master, 3L,<br /><span style="color: rgb(204, 102, 0);">"PSP"</span>,<br /><span style="color: rgb(204, 102, 0);">"pictures/psp.jpg"</span>,<br /><span style="color: rgb(0, 0, 102);">new</span> BigDecimal(490.0)));<br />list.add(<br />createProduct(<br />master, 4L,<br /><span style="color: rgb(204, 102, 0);">"Nintendo DS"</span>,<br /><span style="color: rgb(204, 102, 0);">"pictures/nds.jpg"</span>,<br /><span style="color: rgb(0, 0, 102);">new</span> BigDecimal(359.59015)));<br />new Configurator().configureAndPopulateJTable(<span style="color: rgb(0, 51, 0);">jTable</span>, list);<br /></product></div></pre><div style="text-align: center;"><span class="lit" style="font-size:100%;"><span style="font-weight: bold;">E voilá!<br />(odeio essa resolução do blogspot)<br />[<a href="http://jtableannotations.googlecode.com/files/jtable%20annotation%20sample.JPG">Clique aqui para ver a figura abaixo</a>]<br /></span></span></div><div style="text-align: center;"><span class="lit" style="font-size:100%;"><p style="text-align: center;"><span style="font-weight: bold;"> </span><img style="width: 653px; height: 215px;" src="http://jtableannotations.googlecode.com/files/jtable%20annotation%20sample.JPG" /> </p></span></div></div>Mais informações na página do projeto <a href="http://code.google.com/p/jtableannotations/">http://code.google.com/p/jtableannotations/</a>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com1tag:blogger.com,1999:blog-3760273245894556929.post-8100941433565999442010-01-27T04:22:00.000-08:002010-01-27T04:37:34.843-08:00Vagas Agile Funny - OFF<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://freshome.com/wp-content/uploads/2007/05/ikea.jpg"><img style="float: left; margin: 0pt 10px 10px 0pt; cursor: pointer; width: 450px; height: 366px;" src="http://freshome.com/wp-content/uploads/2007/05/ikea.jpg" alt="" border="0" /></a>Com o título <a href="http://www.gojava.org/node/526">Vagas na Fibonacci Soluções Agéis</a> - foi um anuncio feito pelo <a href="http://www.gojava.org/">GOJava</a> (legal) veja:<br /><br /><p>Requisitos:</p> <p>Imprescindíveis:</p> <p>- Gostar muito de programação<br /><span style="font-weight: bold;">- Não achar que a carreira ideal é aquela em que você começa como programador, é "promovido" para analista e um dia se torna gerente de "sua própria equipe"</span><br />- Preferir trabalhar em uma equipe auto-gerenciável<br />- Não acreditar que uma única tecnologia é a solução para todos os problemas, mas sim que existe a ferramenta correta para cada trabalho<br /><span style="font-weight: bold;">- Ser bom em google-fu</span></p> <p>Desejáveis</p> <p>- Experiência/conhecimento em <span style="font-weight: bold;">Desenvolvimento Orientado a Testes</span>, Desenvolvimento para Web, Arquitetura de Software, Desenvolvimento Orientado a Objetos, Metodologias Ágeis<br /><span style="font-weight: bold;">- Saber jogar truco</span><br /><span style="font-weight: bold;">- Ser ala-direita ou centro-avante no futebol (precisamos completar o time)</span><br /><span style="font-weight: bold;"> - Gostar de video-game</span></p> <p>Benefícios:</p> <p>- Os tradicionais vale-transporte e plano de saúde<br />- Uma cozinha com lanche disponível o tempo todo e dois horários de lanche por dia (de manhã e de tarde)<br /><span style="font-weight: bold;">- Não ter chefe, porque aqui não é nenhuma tribo.</span><br /><span style="font-weight: bold;">- Você nunca vai ter que explicar seu trabalho nem vai ser avaliado com base em um Diagrama de Gantt</span></p><br />Quem derá as empresas tivessem um pouco mais desse espírito.<br /><span style="font-weight: bold;">PS: não trabalho, não conheço nada nem ninguém da empresa.</span>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-70454074904510448012009-12-23T03:37:00.000-08:002009-12-23T03:55:43.453-08:00Jpcsp - v0.4 lançado - Castelvania Dracula X Chronicles<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://jpcsp.org/images/header2.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 415px; height: 97px;" src="http://jpcsp.org/images/header2.jpg" alt="" border="0" /></a><h1>JPCSP - O emulador do PSP feito em Java</h1><div style="text-align: justify;">A muito tempo não dou mais nenhuma contribuição no projeto <a href="http://jpcsp.org/">Jpcsp</a> mas não deixo de acompanhar o progresso do projeto. (Pra quem não sabe <a href="http://archsofty.blogspot.com/2008/08/jpcsp-um-emulador-de-psp-feito-em-java.html">o que é o Jpcsp</a>!) A última notícia foi mesmo um presente de natal, a versão 0.4 do <span style="font-weight: bold;">Jpcsp </span>foi lançada e já está disponível para <a href="http://jpcsp.org/index.php?p=Downloads">download</a>.<br /><br />Sinto um pouco de orgulho por ter conseguido participar, efetivamente, e realizar um dos meus sonhos de moleque. (Criar um emulador :) )... agora deixando de conversa fiada segue alguns screenshots!<br /><div style="text-align: center;"><span style="font-weight: bold;"><h2>Castlevania - Dracula X Chronicles</h2></span><br /></div><div style="text-align: center;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://jpcsp.org/images/thumbs/ULES00841-Shot-3.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 402px; height: 227px;" src="http://jpcsp.org/images/thumbs/ULES00841-Shot-3.jpg" alt="" border="0" /></a><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://jpcsp.org/images/thumbs/ULES00841-Shot-7.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 403px; height: 228px;" src="http://jpcsp.org/images/thumbs/ULES00841-Shot-7.jpg" alt="" border="0" /></a><span><span style="font-weight: bold;"><h2>Heatseeker</h2></span></span></div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://jpcsp.org/images/thumbs/Hs1.jpg"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 409px; height: 295px;" src="http://jpcsp.org/images/thumbs/Hs1.jpg" alt="" border="0" /></a><br /><div style="text-align: center;"><span><span><span><span style="font-weight: bold;"><h2>God of war (In menu)<br /></h2></span></span></span></span></div><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://jpcsp.org/images/thumbs/god1.JPG"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 407px; height: 288px;" src="http://jpcsp.org/images/thumbs/god1.JPG" alt="" border="0" /></a><br /><span style="font-weight: bold;"><br /></span><div style="text-align: center;"><span style="font-weight: bold; color: rgb(0, 0, 102);">Feliz Natal! ho ho ho</span><span style="font-weight: bold; color: rgb(0, 0, 102);"> - </span><span style="color: rgb(0, 0, 102);">Veja mais </span><a style="color: rgb(0, 0, 102);" href="http://jpcsp.org/index.php?p=News">notícias do Jpcsp</a><span style="color: rgb(0, 0, 102);"> ou os meus <a href="http://archsofty.blogspot.com/search/label/jpcsp">posts antigos sobre Jpcsp</a>.</span><br /></div></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com8tag:blogger.com,1999:blog-3760273245894556929.post-3787292201780359802009-12-03T04:28:00.000-08:002009-12-03T05:28:00.758-08:00Adicione o recurso "você quis dizer" nas suas aplicações Java<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.mundoseo.com.br/wp-content/uploads/2009/03/search-engines2.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 179px; height: 177px;" src="http://www.mundoseo.com.br/wp-content/uploads/2009/03/search-engines2.png" alt="" border="0" /></a><h1>SpellChecker - Uma extensão no Lucene</h1>Continuando <a href="http://archsofty.blogspot.com/2009/12/tutorial-apache-lucene-300-motor-de.html">brincando com Lucene</a>, no novo <span style="font-weight: bold;">Lucene 3.0.0</span> encontrei uma pasta <span style="font-weight: bold;">contrib</span> na qual há libs diversas. Uma delas é o <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/search/spell/SpellChecker.html">SpellChecker</a> que lhe oferece recursos para que você implemente em suas aplicações java (web ou desktop) recursos como <span style="font-weight: bold;">"Você quis dizer"</span>.<br /><br /><h2>Recurso Você quis dizer</h2>Imagine : Você é dono de uma loja virtual na qual é oferecido DVDs para venda. Um fanático pelo ator <a href="http://www.imdb.com/name/nm0000216/">Arnold Schwarzenegger</a> entra no sua loja e tem em mente comprar todos os DVDs desse ator (hoje, governador) a primeira ação do usuário é digitar o nome do ator no campo busca. Facilmente ele irá errar a digitação do nome, por exemplo digitando "<span style="font-style: italic;"><span style="color: rgb(0, 0, 102);">arnold swuazeneger</span></span>", e isso não deveria ser algo impeditivo para compra dos DVDs. Para esse problema bastaria a solução do tipo "<span style="font-weight: bold;">Você quis dizer foo</span>" implementada pelo <a href="http://www.google.com/corporate/">Google Inc.</a> no seu motor de busca. Você consegue esse mesmo, ou próximo, efeito em suas buscas utilizando uma das extensões do Lucene, chamada de SpellChecker. O exemplo-código abaixo é simples e demonstra como fazer isso.<br /><h3>Código</h3><br /><pre> <span style="color: rgb(0, 0, 102);"><span style="font-weight: bold;">Directory</span> diretorioDicionario = new <span style="font-weight: bold;">RAMDirectory</span>();</span><br /> //criação do diretório<br /><span style="color: rgb(0, 0, 102);"> <span style="font-weight: bold;">SpellChecker</span> sp = new <span style="font-weight: bold;">SpellChecker</span>(diretorioDicionario);</span><br /> //instânciação do objeto SpellChecker<br /><span style="color: rgb(0, 0, 102);"> sp.indexDictionary(new <span style="font-weight: bold;">PlainTextDictionary</span>(new <span style="font-weight: bold;">File</span>("dicionario.txt")));</span><br /> //indexação do Dictionary (há duas implementações).<br /><span style="color: rgb(0, 0, 102);"> <span style="font-weight: bold;">String</span> pesquisa = "arnold swuazeneger";<br /> /<span style="color: rgb(0, 0, 0);">/seu termo pesquiado</span><br /></span><span style="color: rgb(0, 0, 102);"> <span style="font-weight: bold;">int</span> numeroDeSugestoes = 5;</span><br /> //número de sugestões similares<br /><span style="color: rgb(0, 0, 102);"> <span style="font-weight: bold;">String[]</span> similares = sp.suggestSimilar(pesquisa, numeroDeSugestoes);</span><br /> //as sugestões em si.<br /><br /><span style="color: rgb(0, 0, 102);"> System.<span style="font-weight: bold;">out</span>.println("Seu Termo : " + pesquisa);</span><br /><span style="color: rgb(0, 0, 102);"> for (String palavra : similares) {</span><br /><span style="color: rgb(0, 0, 102);"> System.out.println("Você quis dizer: " + palavra);</span><br /><span style="color: rgb(0, 0, 102);"> }</span><br /><br /><span style="color: rgb(0, 0, 102);"> pesquisa = "bava";</span><br /><span style="color: rgb(0, 0, 102);"> similares = sp.suggestSimilar(pesquisa, numeroDeSugestoes);</span><br /><span style="color: rgb(0, 0, 102);"> System.<span style="font-weight: bold;">out</span>.println("Seu Termo : " + pesquisa);</span><br /><span style="color: rgb(0, 0, 102);"> for (String palavra : similares) {</span><br /><span style="color: rgb(0, 0, 102);"> System.out.println("Você quis dizer: " + palavra);</span><br /><span style="color: rgb(0, 0, 102);"> }</span><br /></pre><br /><h3>Saída</h3><hr /><span style="font-weight: bold;">Seu Termo : <span style="color: rgb(204, 0, 0);">arnold swuazeneger</span></span><br /><span style="font-weight: bold;">Você quis dizer: arnold schwarzenegger</span><br /><hr /><span style="font-weight: bold;">Seu Termo : <span style="color: rgb(204, 0, 0);">bava</span></span><br /><span style="font-weight: bold;">Você quis dizer: java</span><br /><span style="font-weight: bold;">Você quis dizer: lava</span><br /><span style="font-weight: bold;">Você quis dizer: bala</span><br /><hr /><br />Arquivo <span style="font-weight: bold;">dicionario.txt</span>:<br /><div style="border: 1px solid black; color: blue; width: 230px;">arnold schwarzenegger<br />jean claude van damme<br />java<br />lava<br />bala</div><br /><h2>Conclusão</h2>Nem sempre é tão difícil quanto parece, sempre há uma roda já pronta para seu problema. Você ainda pode ajustar a acurácia da pesquisa pelo método <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/search/spell/SpellChecker.html#setAccuracy%28float%29">setAccuracy</a> do SpellChecker. Claro que o uso do recurso em produção requer mais e mais atenção quanto ao diretório e o dicionário de busca. Baseado nos códigos acima, facilmente você consegue levar essa características para seus sistemas Java Web ( JSF - JavaServer Faces, Struts, JSP).<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com1tag:blogger.com,1999:blog-3760273245894556929.post-36635329382485336252009-12-01T08:42:00.000-08:002009-12-02T08:16:32.236-08:00Tutorial Apache Lucene 3.0.0 - motor de busca textual<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://lucene.apache.org/images/lucene_green_300.gif"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 300px; height: 46px;" src="http://lucene.apache.org/images/lucene_green_300.gif" alt="" border="0" /></a><br /><h1><a href="http://archsofty.blogspot.com/2009/12/tutorial-apache-lucene-300-motor-de.html">Lucene um motor de busca textual</a><br /></h1><div style="text-align: justify;">No dia 25 de novembro foi lançado a <a href="http://lucene.apache.org/java/docs/index.html#25+November+2009+-+Lucene+Java+3.0.0+available">nova versão do motor de busca <span style="font-weight: bold;">Lucene</span></a>, a versão 3.0.0. Lucene é um framework de alta performance para busca textual feito em java. (há versões para <a href="http://ifacethoughts.net/2008/02/07/zend-brings-lucene-to-php/">php</a> e <a href="http://incubator.apache.org/lucene.net/">.net</a> também) Uma das características marcantes dele é a integração com <a style="font-weight: bold;" href="http://hadoop.apache.org/">Hadoop</a>. (um framework para computação distribuida - que possui, dentre outros, um <a style="font-weight: bold;" href="http://hadoop.apache.org/common/docs/current/mapred_tutorial.html">MapReduce</a> e um <a href="http://hadoop.apache.org/common/docs/current/hdfs_design.html">sistema de arquivos distribuido</a> <span style="font-weight: bold;">HDFS</span>)<br /></div><br /><h1>Porque usar Lucene?</h1><div style="text-align: justify;">Imagine o seguinte cenário: Seu usuário deseja criar um modulo de <span style="font-weight: bold;">gerenciamento de artigos</span> e também expó-los na Internet. As informações do artigo são: <span style="font-weight: bold;">título, autor e o contéudo.</span> Normalmente cada artigo desse contém cerca de <span style="font-weight: bold;">1500 palavras</span> e o usuário poderá <span style="font-weight: bold;">buscar pelo conteudo</span> desses artigos. Suponha que há <span style="font-weight: bold;">1 milhão e meio de artigos </span>para serem cadastrados, o simples uso de um banco de dados e o operador LIKE '%palavra%' é <a href="http://blogs.msdn.com/varund/archive/2009/11/30/index-usage-by-like-operator-query-tuning.aspx">inviável</a>. E aí que entra um bom framework de busca textual, usá-lo passa ser a solução mais tranquila e viável. Além de trazer velocidade, também traz outras características nas buscas que dificilmente fariamos codificando tudo do zero.<br /></div><h1>Domain-Specific Language | Ubiquitous Language<br /></h1><div style="text-align: justify;">Há vários termos usados na terminologia do framework, os principais são: <span style="font-weight: bold;">Documento, Campo, Diretório, Indexador, Pesquisador, Analisador e Termo</span>.<br /></div><br /><ul><li><span style="font-weight: bold;">Documento </span>- é o conjunto de dados que você deseja indexar, por ex. título, conteudo e autor formam o documento artigo, pode ser visto como um objeto no lucene é visto como <a href="http://lucene.apache.org/java/3_0_0/api/core/org/apache/lucene/document/Document.html">Document</a>.</li><li><span style="font-weight: bold;">Campo </span>- é o dado, identificado, que pode ser analogo a um campo de uma tabela ou uma propriedade de um objeto no lucene é visto como <a href="http://lucene.apache.org/java/3_0_0/api/core/org/apache/lucene/document/Field.html">Field</a>.</li><li><span style="font-weight: bold;">Diretório </span>- conceito abstrato que denota um local para guardar os índices no lucene é visto como uma interface <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/store/Directory.html">Directory</a>, que possui diversas implementações<a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/store/db/DbDirectory.html" title="class in org.apache.lucene.store.db"> DbDirectory</a>, <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/store/FSDirectory.html" title="class in org.apache.lucene.store">FSDirectory</a>, <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/store/je/JEDirectory.html" title="class in org.apache.lucene.store.je">JEDirectory</a>, <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/store/RAMDirectory.html" title="class in org.apache.lucene.store">RAMDirectory</a>.</li><li><span style="font-weight: bold;">Indexador </span>- é o responsável por indexar os documentos num diretorio no lucene é visto, geralmente, como <a href="http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/index/IndexWriter.html">IndexWriter</a>.</li><li><span style="font-weight: bold;">Pesquisador </span>- responsável por pesquisar uma <a href="http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/search/Query.html">Query</a> no diretorio de índices, no lucene é visto como <a href="http://lucene.apache.org/java/2_4_0/api/org/apache/lucene/search/Searcher.html">Searcher</a>.</li><li><span style="font-weight: bold;">Analisador </span>- atua como um filtro e faz uma pré-avaliação do que pode ser indexado ou não, no lucene há <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/analysis/class-use/Analyzer.html">uma lista de vários analisadores</a>. </li><li><span style="font-weight: bold;">Termo </span>- pode ser visto como objeto que pode ser usado como parametro da pesquisa, composto pelo nome do campo e o valor a ser pesquisado, no lucene é visto como <a href="http://lucene.apache.org/java/2_2_0/api/org/apache/lucene/index/Term.html">Term</a>.</li></ul> <h1>Como isso funciona?</h1><div style="text-align: justify;">A descrição a seguir é um resumo bem simplificado sobre o funcionamento de um motor de busca textual. A primeira fase, geralmente, é a indexação do documento, nessa fase o documento é analizado (por um <a href="http://lucene.apache.org/java/3_0_0/api/contrib-analyzers/org/apache/lucene/analysis/br/BrazilianAnalyzer.html">Analizer</a> que também já retira as <a href="http://en.wikipedia.org/wiki/Stop_words">stopwords</a>) para posteriomente ser indexado.<br /><pre><br /><span style="color: rgb(0, 0, 102);"></span><blockquote><span style="color: rgb(0, 0, 102);">Set<string></string></span><string><span style="color: rgb(0, 0, 102);"> stopWords = new HashSet</span><string><span style="color: rgb(0, 0, 102);"><string>();</string></span><br /><span style="color: rgb(0, 0, 102);">stopWords.add("the");</span><br /></string></string><span style="color: rgb(0, 0, 102);">stopWords.add("it");</span><br /><span style="color: rgb(0, 0, 102);">stopWords.add("is");</span><br /><string><string><span style="color: rgb(0, 0, 102);">IndexWriter <span style="font-weight: bold;">writer</span> = new IndexWriter(FSDirectory.open(INDEX_DIR),<br /> new StandardAnalyzer(Version.LUCENE_CURRENT,<br /> stopWords),<br /> false,<br /> IndexWriter.MaxFieldLength.LIMITED);</span><br /></string></string></blockquote><string><string><br /></string></string></pre>No Lucene você pode criar um índice usando o IndexWriter, a criação desse objeto envolve dizer onde será (ou está) o diretório dos índices, qual analizador você irá utilizar, se irá criar o indice e qual a quantidade máxima de campos.<br /><br />O objetivo do indexador é indexar documentos, para tanto é necessário que haja documentos para serem indexados.<br /><pre><span style="color: rgb(0, 0, 102);"></span></pre><blockquote><pre><span style="color: rgb(0, 0, 102);">Document <span style="font-weight: bold;">doc</span> = new Document();</span><span style="color: rgb(0, 0, 102);"></span><br /><span style="color: rgb(0, 0, 102);">doc.add(new Field("nomedocampo", "valores a serem guardados", Field.Store.YES, Field.Index.NOT_ANALYZED));</span><br /><span style="color: rgb(0, 0, 102);"></span><span style="color: rgb(0, 0, 102);">doc.add(new Field("camp1","valores a serem analisados tokenizados",Field.Store.YES, </span><span style="color: rgb(0, 0, 102);">Field.Index.toIndex(true, true)</span><span style="color: rgb(0, 0, 102);">));</span><br /><span style="color: rgb(0, 0, 102);"></span><span style="color: rgb(0, 0, 102);"><span style="font-weight: bold;">writer</span>.addDocument(<span style="font-weight: bold;">doc</span>);</span><br /></pre></blockquote>É o objetivo final de todo processo de busca textual é mesmo a busca em si.<br /><pre style="color: rgb(0, 0, 102);"></pre></div><blockquote><div style="text-align: justify;"><pre style="color: rgb(0, 0, 102);">String valueToBeSearched = "red";<br />String index = "indexDir"; //dirotorio base do indice<br />IndexReader reader = IndexReader.open(FSDirectory.open(new File(index)), true); //indexador<br />Searcher searcher = new IndexSearcher(reader); //pesquisador<br />QueryParser parser = new QueryParser(Version.LUCENE_CURRENT, field, analyzer); //transoformador do texto em uma query<br />Query query = parser.parse(valueToBeSearched); //a consulta (query) em si<br />TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, false); //os melhores resultados<br />searcher.search(query, collector);<br />ScoreDoc[] hits = collector.topDocs().scoreDocs; //o conjunto de melhores documentos para a consulta<br /><br />int maximo = hits.length;<br />Document doc = searcher.doc(hits[index].doc);<br />String valor = doc.get("nomeDoCampo");<br /></pre></div><h1></h1></blockquote><h1>Recursos na busca de documentos</h1><div style="text-align: justify;">Quando se faz uma <span style="font-weight: bold;">pesquisa por documentos</span> no Lucene podemos utilizar de alguns <span style="font-weight: bold;">operadores</span> (+, -, AND, NOT, OR, * e etc.) juntamente com o termo pesquisado ou apenas pesquisar uma frase completa.<br /></div><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">termo</span><br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar a palavra "termo" nos documentos indexados.</span><br /><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">termo</span> OR <span style="font-weight: bold;">palavra </span>( == <span style="font-weight: bold;">termo palavra</span>)<br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar "termo" ou "palavra" nos documentos indexados.</span><br /><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">+termo</span> <span style="font-weight: bold;">+palavra </span>( == <span style="font-weight: bold;">termo </span>AND<span style="font-weight: bold;"> palavra</span>)<br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar "termo" e "palavra" nos documentos indexados.</span><br /><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">campo:termo</span><span style="font-weight: bold;"></span><br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar "termo" no campo "campo" nos documentos indexados.</span><br /><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">+homer +simpsons -house</span><br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar documentos que contenham homer e simpsons e não tenha house.</span><br /><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">"termo exato"</span><br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar documentos que contenham exatamente "termo exato".</span><br /><span style="color: rgb(0, 0, 102);"><br />Exemplo :</span> <span style="font-weight: bold;">java*</span><br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar documentos que contenham palavras que começem com java (javadb, javanet...).</span><br /><br /><span style="color: rgb(0, 0, 102);">Exemplo :</span> <span style="font-weight: bold;">java~</span><br /><span style="color: rgb(0, 0, 102);">Consequência:</span> <span style="font-style: italic;">Irá pesquisar documentos que contenham palavras similares a java como por ex. lava, jaba...</span><br /><br />Finalizando tive as seguintes impressões sobre essa nova versão do Lucene.<br /><br /><span style="font-weight: bold;">Prós:</span><br /><ul><li>Maior facilidade para uso do framework, ex: criações de <a href="http://lucene.apache.org/java/3_0_0/api/core/org/apache/lucene/document/Field.html">Fields</a> estão bem mais fluentes.</li><li>Sensível otimização nos tempos de busca e indexação. </li></ul><br /><span style="font-weight: bold;">Contras:</span><br /><ul><li>Otimas ferramentas como <a href="http://code.google.com/p/luke/">luke</a> ainda não tem suporte para a versão 3.0.0. (mas já há uma solicitação aberta para tal mudança.)</li><li>Muitas mudanças no core do framework; o que fez livros mais antigos quase perderem seu valor.</li></ul><h1>Referências</h1><ul><li style="font-weight: bold; font-family: courier new;"><a href="http://lucene.apache.org/java/docs/">Lucene Demo - http://lucene.apache.org/java/docs/</a></li><li style="font-weight: bold;font-family:courier new;"><a href="http://infolab.stanford.edu/%7Ebackrub/google.html">The Anatomy of a Large-Scale Hypertextual Web Search Engine</a></li><li face="courier new" style="font-weight: bold;"><a href="http://www.slideshare.net/otisg/lucene-introduction">Slides de introdução ao uso do lucene</a><br /></li><li face="courier new" style="font-weight: bold;"><span style="font-size:130%;"><a href="http://www.manning.com/hatcher3/">Lucene in Action, Second Edition</a></span></li><li><a style="font-weight: bold; font-family: courier new;" href="http://pt.wikipedia.org/wiki/P%C3%A1gina_principal">Wikipédia</a></li><li style="font-weight: bold;"><a href="http://www.slideshare.net/eriksencosta/voc-quis-dizer-buscas-poderosas-com-apache-solr-lucene">Apache Solr, Lucene Slides</a></li><li><a style="font-weight: bold;" href="http://www.lucenetutorial.com/lucene-in-5-minutes.html">Tutorial Lucene em 5 Minutos </a><br /></li></ul>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com36tag:blogger.com,1999:blog-3760273245894556929.post-54395097651390339762009-11-24T02:24:00.000-08:002009-11-24T02:39:26.625-08:00Ótimos slides sobre Domain Specific Language (DSL) interna<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.tiresias.org/images/ff.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 163px; height: 144px;" src="http://www.tiresias.org/images/ff.jpg" alt="" border="0" /></a>Esse é apenas um encaminhamento para o ótimo post sobre <a href="http://martinfowler.com/bliki/InternalDslStyle.html">dsl interna</a> e tecnicas para construção da mesma.<br /><a href="http://blog.brianguthrie.com/articles/2009/11/23/slides-for-my-talk-on-construction-techniques-for-internal-dsls">http://blog.brianguthrie.com/articles/2009/11/23/slides-for-my-talk-on-construction-techniques-for-internal-dsls</a> para acessar diretamente o link dos <a href="http://brianguthrie.com/talks/construction_techniques_for_domain_specific_languages.pdf">slides clique aqui</a>.<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-76044284599916204652009-10-29T06:31:00.000-07:002009-10-29T10:48:26.215-07:00JPA - lock otimista e pessimista, concorrência e afins<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.softwaresecretweapons.com/jspwiki/attach/2008/04/concurrency.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 152px; height: 155px;" src="http://www.softwaresecretweapons.com/jspwiki/attach/2008/04/concurrency.jpg" alt="" border="0" /></a><span style="font-size:180%;"><a href="http://java.sun.com/javaee/technologies/persistence.jsp">JPA - Java Persistence API</a></span><br /><br /><div style="text-align: justify;"><a href="http://jcp.org/en/jsr/detail?id=220">JPA é especificação</a> para mapeamento ORM e persistência de dados inspiradíssima no famoso framework Hibernate.<br /><br />A especificação JPA (1.0) já é amplamente usada e aceita na comunidade de desenvolvedores Java. Há vários provedores de implementação para o padrão (<a href="https://www.hibernate.org/"> Hibernate</a> , <a href="http://www.eclipse.org/eclipselink/">EclipseLink</a>, <a href="http://www.oracle.com/technology/products/ias/toplink/jpa/index.html">TopLink</a> ...)<br /><br />Um assunto pouco explorado, quando se trata de tutoriais de jpa, é sobre locks (otimista e pessimista). E é sobre esse assunto que tento escrever um pouco aqui.<br /><br /><span style="font-size:180%;">Tratamento de concorrência em bancos de dados</span><br /><br />Há basicamente três tipos de tratamento para concorrência em banco de dados:<br /><ol><li><span style="font-weight: bold;">Otimista</span> - Quando é criado mecanismos para versionar o dado, no momento em que o banco vai efetivar sua operação sua versão é checada para garantir que você está com um dado que não foi alterado.<br /></li><li><span style="font-weight: bold;">Pessimista</span> - O banco simplesmente trava o dado e só aquele que tem a trava consegue trabalhar com os dados.<br /></li><li><a style="font-weight: bold;" href="http://www.weirdmeat.com/uploaded_images/ostrich-743207.jpg">Ostrich</a><span style="font-weight: bold;"> </span>- Quando não há tratamento nenhum pra concorrência :) , ou seja, a maioria dos casos atuais.<br /></li></ol><br /><span style="font-size:180%;">O exemplo básico</span><br /><br />Começaremos com os perigos do modo <span style="font-weight: bold;">Ostrich</span> de agir. Para exemplificar criaremos uma simples classe.<br /><pre style="color: rgb(0, 0, 102);">@Entity<br />public class <span style="font-weight: bold;">Produto</span> implements <span style="font-weight: bold;">Serializable</span> {<br />private static final <span style="font-weight: bold;">long</span> serialVersionUID = 1L;<br />@Id<br />@GeneratedValue(strategy = GenerationType.AUTO)<br />private <span style="font-weight: bold;">Long</span> id;<br />private <span style="font-weight: bold;">String</span> nome;<br />private <span style="font-weight: bold;">double</span> quantidade;<br />//<span style="font-style: italic;">getters and setters omitidos</span><br />}</pre>Agora considere dois usuários <span style="font-weight: bold;">A</span> e <span style="font-weight: bold;">B</span> trabalhando sobre o <span style="font-weight: bold;">Produto com id = 1( Nintendo Wii) </span>ambos usuários têm o mesmo produto na tela de edição, o usuário <span style="font-weight: bold;">A </span>modifica <span style="font-weight: bold;">quantidade</span> e salva antes do usuário B, já o usuário <span style="font-weight: bold;">B</span> modifica o <span style="font-weight: bold;">nome</span> e salva depois. Note que há incosistência, o usuário A acredita (porque ele editou e salvou) que alterou a quantidade de nintendos wii, porém o usuario B (ainda com a quantidade antiga) mudou o nome e salvou o objeto. O que acontece? Depende do seu provedor de JPA, há casos em que o update só é feito para a coluna modificada mas há casos em que o objeto todo é modificado, o que causa claramente inconsistência. Escrever, escrever e escrever pode não ajudar então veja o código abaixo exemplificando esse cenário.<br /><pre><span style="color: rgb(0, 0, 102);"> <span style="font-weight: bold;">Produto </span>nintendoWiiA = em.find(Produto.class,1L);</span><br /><span style="color: rgb(0, 0, 102);"> <span style="font-weight: bold;">Produto </span>nintendoWiiB = em.find(Produto.class,1L);</span><br /><span style="color: rgb(0, 0, 102);"> /*Usuário A*/</span><br /><span style="color: rgb(0, 0, 102);"> em.getTransaction().begin();</span><br /><span style="color: rgb(0, 0, 102);"> nintendoWiiA.setQuantidade(45.0D);</span><br /><span style="color: rgb(0, 0, 102);"> em.getTransaction().commit();</span><br /><br /><span style="color: rgb(0, 0, 102);"> /*Usuário B*/</span><br /><span style="color: rgb(0, 0, 102);"> em.getTransaction().begin();</span><br /><span style="color: rgb(0, 0, 102);"> nintendoWiiB.setNome("Nintendo WII");</span><br /><span style="color: rgb(0, 0, 102);"> em.getTransaction().commit();</span><br /><br /><span style="color: rgb(0, 0, 102);"> System.out.println(em.find(Produto.class,1L));</span><br /></pre>ps: O código é apenas para demonstrar como isso é feito, não é funcional.<br /><br />Agora para mudar esse exemplo para o modo <span style="font-weight: bold;">otimista</span> de ser basta criarmos uma propriedade no objeto com a anotação <a href="http://java.sun.com/javaee/5/docs/api/javax/persistence/Version.html">@Version</a> para denotar que este campo será usado para o fim da implementação otimista. Esse campo deve ser int, long ou timestamp.<br /><br />Com a adição do lock otimista quando o usuário B fosse tentar salvar suas modificações ele receberia a execeção <a href="http://java.sun.com/javaee/5/docs/api/javax/persistence/OptimisticLockException.html">OptimisticLockException</a>. Isso já garantiria ao menos a notificação ao usuário que alguém estava trabalhando sobre o mesmo dado e ( lembra das canseiras que o IDE nos livra no versionamento de código) apartir dai você poderia mostrar o que foi mudado para o usuário tomar a decisão de salvar ou não suas alterações.<br /><br />A parte chocante fica por conta do modo <span style="font-weight: bold;">pessimista </span>de ser, a JPA 1.0 não suporta diretamente o modo pessimista de ser (O <a href="http://jcp.org/en/jsr/detail?id=317">JPA 2.0</a> prevê esse modo a mais :)<br /><br /><span style="font-size:180%;">Então o que fazer?</span><br /><br />Imaginem duas contas bancárias: (sempre esse exemplo) <span style="font-weight: bold;">aMinhaConta</span> (com saldo de R$ 150,00) e a <span style="font-weight: bold;">suaConta</span> (com saldo de R$ 25.000,00) e você quer me presentear com um Wii mas não tem como mandá-lo pelo correio, logo acha mais conviniente realizar uma transferência para que eu compre. O processo (bem simplificado) se resume a isso:<br /><br />#0 <span style="color: rgb(0, 0, 102);">quantiaASerDoada</span> = R$ 1390,00;<br />#1 <span style="font-weight: bold;">se</span> <span style="color: rgb(0, 0, 102);">suaConta</span>.saldo > <span style="color: rgb(0, 0, 102);">quantiaASerDoada</span><span style="font-weight: bold;"> então</span><br />#2 <span style="color: rgb(0, 0, 102);">suaConta</span>.transerePara(minhaConta, quantiaASerDoada);<br />#3 <span style="font-weight: bold;">fim se</span><br /><br />Se entre a linha 1 e 2 você fizer um saque de R$ 25.000,00 (isso pode ocorrer) a transferência não deveria ser realizada. Um modo para que isso ocorra é travar (lock) o dado que pode sofrer com essas concorrências. No JPA 1.0 você pode travar um objeto em dois passos (ai reside el peligro).<br /><br />#0 Conta suaConta = em.find(Conta.class, 175789);<br />#1 em.lock(suaConta,LockMode.Write);<br /><br />Mais uma vez entre a linha 0 e a 1 pode ocorrer um problema de concorrência. (tanto que a especificação JPA 2.0 já prêve um modo similar ao session do hibernate, o travamento no momento da leitura, em.find(Conta.class, 175789, LockMode.PESSIMISTIC);)<br /><br /><span style="font-size:180%;">Solução fácil para o problema acima</span><br /><br />Basta (se estiver usando Hibernate as your JPA provider) :<br /><br /><span style="font-weight: bold; color: rgb(0, 0, 102);">((Session) ((EntityManagerImpl) em.getDelegate()).getSession())</span><br /><br />O session já tem um jeito de select for update <span style="font-weight: bold;">session.get(SuaClasse.class, seuId, tipoDeTravamento)</span>. ( já perceberam que pra cada problema que você encontra na JPA 1.0 o hibernate quase sempre tem a solução?!)<br /><br /><span style="font-size:180%;">Referências</span><br /><br /><a href="http://en.wikibooks.org/wiki/Java_Persistence/Locking">http://en.wikibooks.org/wiki/Java_Persistence/Locking</a><br /><a href="http://www.javaworld.com/jw-07-2001/jw-0713-optimism.html">http://www.javaworld.com/jw-07-2001/jw-0713-optimism.html</a><br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com2tag:blogger.com,1999:blog-3760273245894556929.post-53883942604410720492009-10-22T06:48:00.000-07:002009-10-22T10:54:55.600-07:00Organizacao é tudo<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://www.caelum.com.br/caelumday/images/h1-logo-trans.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 124px; height: 97px;" src="http://www.caelum.com.br/caelumday/images/h1-logo-trans.png" alt="" border="0" /></a>Para as pessoas que moram no Rio de Janeiro ou que tenham disponibilidade para verem o evento <a style="font-weight: bold;" href="http://www.caelum.com.br/caelumday/index.html">Caelum Day | in Rio</a> já bastaria dizer que o evento será no mínimo bom. Mas dessa notícia o que gostaria de destacar não é só o evento ( se puder ir, vá :) ) e sim a organização do site do evento... algo que deveria ser copiado, isso mesmo <span style="font-weight: bold;">ctrl+c ctrl+v</span>! <a href="http://www.caelum.com.br/caelumday/index.html">Vejam o site do evento Caelum Day</a>, ele possui as características padrões como : <a href="http://www.caelum.com.br/caelumday/programacao.html">Programação do Evento</a> , grandes nomes para palestrar (<a href="http://www.fragmental.com.br/">Philip Calçado</a>), <a href="http://www.caelum.com.br/caelumday/inscricao.html">inscrições</a> e etc. porém dentro dessas características comuns ele traz informações IMPORTANTÍSSIMAS como dicas de <a href="http://www.caelum.com.br/caelumday/restaurantes.html?height=300&width=300">restaurantes</a>, <a href="http://www.caelum.com.br/caelumday/hoteis.html?height=300&width=300">hotéis</a> e até mesmo estacionamentos (dicas com valores :) ). Ahh1 o evento ocorrerá no dia <span style="font-weight: bold;">7 de Novembro de 2009 das 8h às 18h</span>. Parabéns pela organização do evento.<br /><br />Ahh2 : só pra complementar no final do evento será sorteado um <a href="http://www.nintendo.com/wii">Nintendo Wii</a>. :)<br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0tag:blogger.com,1999:blog-3760273245894556929.post-20706957054719013362009-10-17T17:15:00.000-07:002009-10-17T17:37:39.210-07:00Quer pagar quanto?<div style="text-align: justify;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://diegomonteiro.files.wordpress.com/2008/06/ganancia.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 258px; height: 178px;" src="http://diegomonteiro.files.wordpress.com/2008/06/ganancia.jpg" alt="" border="0" /></a>O portal de notícias da <a href="http://rederecord.r7.com/">Record</a> o <a href="http://r7.com/">R7</a> foi lançado a alguns dias atrás... até ai nada de anormal, <a href="http://www.google.com.br/search?q=g1+x+r7&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:pt-BR:official&client=firefox-a">certo</a>?! Pois bem, fui verificar quanto valia o portal de acordo com o <a href="http://bizinformation.org/">BizInformation</a>. Se você ainda não conhece, se trata de um site que baseado em diversos parametros informa quanto seu site vale. Logo a primeira reação foi me assustar com o <a href="http://bizinformation.org/br/www.r7.com">resultado</a> para o site <a href="http://www.r7.com">R7.com</a> :<br /></div><h1 style="text-align: justify;"><span>R$2.692,79</span></h1><div style="text-align: justify;">Somente isso! Imaginem meu site alternativo <a href="http://the-empyrean.blogspot.com">the empyrean</a> foi <a href="http://bizinformation.org/br/www.the-empyrean.blogspot.com">cotado</a> ao valor de :<br /></div><h1 style="text-align: justify;"><span>$3,946.8</span></h1><div style="text-align: justify;">Outro detalhe é que para o site the empyrean foi usado (dolar americano) U$ ,ou seja, meu blog vale mais do que o portal R7 :-) brincadeira.... <br /><span style="font-weight: bold;">ps: </span><span style="font-style: italic;">penso que está claro o fato de que, o BizInformation, nesse caso do portal R7, falhou nas suas estátisticas.</span><br /></div>leandrohttp://www.blogger.com/profile/09724892719833243149noreply@blogger.com0