Alguns anos atrás, comecei a sentir necessidade de manter meus bookmarks sincronizados entre os diversos computadores que eu utilizava. Até que conheci o Delicious. Isso foi em 2007, e desde então eu comecei a usá-lo constantemente. Cada vez que eu usava o Firefox em algum computador pela primeira vez, a primeira extensão que eu instalava era a do Delicious. Através desta extensão, um simples Control+D abre a janela para adicionar a página atual ao seus bookmarks do Delicious, e Control+B abre a barra lateral com seus bookmarks, organizados por tags.

Há alguns meses, eu havia pensado em migrar meus bookmarks para o Google Bookmarks, mas desisti, pois eu já estava bastante acostumado com o Delicious. Até que no início de dezembro veio a bomba: o Yahoo, que havia comprado o Delicious em 2005, anunciou que encerraria o serviço! Imediatamente comecei a pensar em alternativas, e o Google Bookmarks foi minha primeira opção. Alguns dias depois, o Yahoo voltou à cena informando que iria vender, e não fechar o serviço, e o próprio Delicious publicou uma nota sobre o assunto. Mas, mesmo assim, para mim foi a deixa para fazer a migração para outro serviço. Apesar de existirem várias alternativas ao Delicious, escolhi o Google Bookmarks pela simplicidade, e por já estar integrado à minha conta no Google.

A primeira parte da migração foi fácil: exportar os bookmarks do Delicious, através da opção Settings -> Export/Backup Bookmarks. Para importá-los no Google Bookmarks, uma das maneiras mais simples é importar os bookmarks do Delicious no Firefox e sincronizá-los com o Google Toolbar. Também é possível fazer a importação usando o Google Chrome, ou usar algum script (como este) ou serviço, como o del.icio.us to Google Bookmarks.

Em seguida, procurei as opções para integração com o browser (adicionar e pesquisar nos bookmarks). No Firefox existem diversas extensões para Google Bookmarks. Testei algumas, e a que achei melhor foi o GMarks. Com ela, é possível adicionar bookmarks com Control+D, de forma bem semelhante à extensão do Delicious, e também há uma barra lateral, acionada com Alt+M. Porém, não há integração com a barra de endereços, ou seja, não é possível pesquisar nos bookmarks digitando diretamente o endereço (como permitem as versões mais recentes da extensão do Delicious). Porém, há duas maneiras de pesquisar (além de acessar diretamente a página do Google Bookmarks para fazer a pesquisa):

  1. Ao digitar a tecla Home duas vezes, aparecerá uma caixa de texto para pesquisa. É só digitar qualquer coisa e depois escolher um resultado e apertar Enter (ou Alt+Enter para abrir em outra aba)
  2. Criando um atalho para a busca: acesse o Google Bookmarks, clique com o botão direito sobre o campo de busca e selecione a opção “Add a keyword for this search”. O Firefox adicionará a pesquisa nos bookmarks locais, e você poderá adicionar um keyword a este bookmark. Digite “gb”, por exemplo, e clique em OK. Agora, ao digitar qualquer texto precedido desta keyword na barra de endereços (por exemplo: “gb teste”), o Firefox pesquisará este texto no Google Bookmarks. Mas os resultados não aparecem diretamente, você precisa escolher a opção “Search Google Bookmarks” entre as sugestões que aparecem

Para integrar o Google Bookmarks ao Chrome é ainda mais simples, pois não é necessário instalar qualquer extensão (afinal, ambos são do Google). Para adicionar bookmarks, acesse a página de ajuda. Ela disponibiliza um botão que pode ser arrastado para a barra de bookmarks, e ao clicar nele, a página atual será adicionada. Para adicionar a pesquisa no Google Bookmarks à barra de endereços, clique na barra com o botão direito, selecione “Edit search engines” e adicione um novo, com as seguintes configurações:

Nome: Google Bookmarks

Keyword: gb

URL: http://google.com/bookmarks/find?&q=%s

Agora, a pesquisa integrada à barra de endereços funcionará da mesma forma que no Firefox (“gb texto para pesquisa”).


Outro dia um amigo me pediu para instalar o Ubuntu no netbook dele, um HP Mini (não lembro exatamente qual modelo). Baixei o Ubuntu Netbook Remix 10.10 e instalei no pen drive, seguindo as instruções que aparecem na página de download. Em seguida, fiz o boot pelo pen drive e iniciei a instalação. Tudo ia bem até que em determinado momento recebi uma mensagem de erro. Não lembro qual era a mensagem, mas parecia ser algo relacionado a disco. Tentei novamente e o erro se repetiu.

Em seguida, lembrei que quando eu havia instalado este mesmo sistema operacional num outro netbook HP Mini, mas a versão do Ubuntu era 10.04. Como a página principal do Ubuntu só disponibiliza links para download da última versão, encontrei as versões anteriores na página Ubuntu Releases. Na página específica da versão 10.04 (Lucid Lynx) o link aparece como PC (Intel x86) netbook live CD.

Após baixar esta versão e instalá-la no pen drive, tudo funcionou. Aparentemente é algum problema relacionado com a versão 10.10 mesmo. Tudo funciona de primeira, sem necessitar qualquer configuração (bluetooth, som, webcam, etc.), exceto o wifi. A página Hardware support do wiki do Ubuntu traz a solução: basta conectar o netbook à Internet via porta Ethernet e reinstalar o driver bcmwl, digitando no terminal: sudo apt-get install bcmwl-kernel-source. Após a instalação, reinicie o netbook e tudo funcionará.


No dia 09 de outubro aconteceu o Dev in Rio 2010. Como a edição de 2009 foi muito boa, a expectativa para a deste ano era alta. E foi correspondida! Desta vez foram duas salas com palestras acontecendo simultaneamente. Eu fiquei na sala 2, onde assisti às seguintes palestras:

  • HTML 5 e as novas JS APIs - Leonardo Balter

    Na primeira palestra foram apresentadas as principais APIs do HTML5. A palestra foi bem interessante, apesar de bastante prejudicada pela falta de WiFi no local, o que impediu que o palestrante mostrasse os vários exemplos que ele tinha preparado.

  • NodeJS - a performance que eu sempre quis ter - Emerson Macedo

    A palestra do Emerson foi excelente. Ele apresentou o problema de bloqueio de I/O no acesso a banco de dados, que é um dos principais gargalos no desempenho para a maioria das linguagens de programação. O NodeJS ajuda a resolver este problema pois usa Javascript, que é uma linguagem orientada a eventos. No final da apresentação, ele divulgou o Nodecasts, site de screencasts sobre NodeJS que ele acaba de criar. A apresentação está disponível no blog do Emerson.

  • Lightning Talks

    Após o almoço, foi disponibilizado um horário para lightning talks, pequenas apresentações de 5 minutos para quem tivesse algo interessante para mostrar. Como o tempo foi curto, foram apenas duas apresentações: a primeira sobre desenvolvimento de aplicações Python para celular e outra sobre a Apache Foundation.

  • Symfony - OO PHP para gente grande - Luã de Souza

    Nesta palestra, foi apresentado o Symfony, um framework PHP para desenvolvimento web que vem crescendo bastante. É um framework MVC que, a exemplo de praticamente qualquer framework atual, inspira-se no Rails para simplificar o desenvolvimento de aplicações web.

  • Refactoring - Porque apenas fazer funcionar não é o suficiente - Caike Souza

    Esta foi uma das melhores palestras do evento. Caike Souza falou sobre refactoring - destacando que não existe refactoring sem testes -, apresentou as principais vantagens e alguns exemplos práticos em Ruby.

  • Arquitetura: cansado da mesmice? - Guilherme Silveira

    Apesar do título não deixar claro, esta palestra foi direcionada a arquitetura com serviços Restful. Como todas as palestras dele, Guilherme Silveira foi bastante claro, mostrando as vantagens de uma arquitetura voltada para serviços, que vai além da simples troca de arquivos XML entre aplicações. Ele mostrou um exemplo bem interessante, sobre integração entre sites de viagens, reserva de hotéis e calendário, onde o compartilhamento de recursos permite que uma aplicação acesse diretamente os serviços de outra. Mais detalhes no post que ele escreveu no blog da Caelum.

  • Testes unitários em JavaScript: usar ou não usar mock? - Márcio Santana

    Na última palestra, foram apresentadas ferramentas para testes de código Javascript. Esta palestra também foi muito interessante, pois testes de Javascript são muito pouco comuns, mas não deveriam, já que Javascript também é código, e as aplicações web atuais possuem uma quantidade cada vez maior de código Javascript, principalmente para manipular interações com os usuários. Além do QUnit - framework para testar Javascript -, foram apresentadas bibliotecas de mock, como o Chameleon.

Enquanto isso, na sala 1 ocorreram palestras sobre Arduino, empreendedorismo, Scum e Ruby.

Apesar de tudo, o evento teve alguns problemas de organização. Além da já citada indisponibilidade de WiFi, as duas salas ficavam em andares diferentes, e o coffee break era ao lado da sala 1, o que dificultava o deslocamento. Num determinado momento, a palestra da sala 2 terminou e todos desceram para o andar da sala 1 para o coffee break, porém não podíamos entrar, pois a palestra não havia terminado. Apesar destes pequenos problemas, o Dev in Rio deste ano manteve a qualidade da primeira edição. Agora, ficamos aguardando a edição de 2011!


Desde a versão 3.6.4, o Firefox possui um recurso chamado Crash protection (somente para Windows e Linux). Agora o browser cria um processo à parte chamado plugin-container para execução dos plugins do Flash, QuickTime e Silverlight. O objetivo é impedir que um erro na execução de um destes plugins trave o browser - caso isto ocorra, somente o plugin será interrompido.

Depois que atualizei o Firefox para esta versão - na verdade, atualizei diretamente do 3.6.3 para o 3.6.6 - no Ubuntu 10.04, o Flash simplesmente parou de funcionar, exibindo a mensagem “The Adobe Flash plugin has crashed”. Tentei reinstalar o Flash diversas vezes, tanto pelos pacotes adobe-flashplugin e flashplugin-installer usando o apt-get quando baixando um arquivo .deb diretamente. A página plugin check informava que o Flash estava instalado, porém com uma versão desatualizada (9.x). Também tentei reinstalar o Firefox e nada.

Depois de alguns dias de tentativas frustradas, finalmente tive a ideia de testar com outro browser. Pelo Chrome o Flash funcionava perfeitamente, ou seja, o problema estava diretamente relacionado com o Firefox.

Após mais algumas pesquisas, encontrei o artigo Plugin-container and out-of-process plugins. Descobri que há um parâmetro na configuração do Firefox (digite about:config na barra de endereços para acessá-la) chamado dom.ipc.plugins.enabled que permite habilitar ou desabilitar o crash protection para plugins de terceiros. Este parâmetro serve para qualquer plugin não especificado, e o valor padrão é false. Há um parâmetro específico para o plugin do Flash: no Linux é o dom.ipc.plugins.enabled.libflashplayer.so, e no Windows é dom.ipc.plugins.enabled.npswf32.dll. Este parâmetro tem o valor padrão true; depois que mudei para false, o Flash passou a funcionar na maioria dos sites; porém, os vídeos da Globo.com, por exemplo, continuaram não funcionando, mas passaram a exibir uma mensagem dizendo que o Flash estava desatualizado.

Para descobrir mais informações sobre os plugins, digitei about:plugins na barra de endereços. A página que apareceu mostrou duas versões de Flash instaladas: uma era a mais recente (10.x) e a outra estava desatualizada (9.x). Porém, esta tela não mostrava a localização de cada plugin. Para descobrir o path completo para cada plugin, voltei para a tela de configuração (about:config) e alterei o valor do parâmetro plugin.expose_full_path para true. Agora, a tela do about:plugins passa a exibir o path de cada plugin instalado.

Desta forma, descobri que havia uma versão mais antiga do Flash instalada no meu home (em /home/guilherme/.mozilla/plugins/libflashplayer.so). Não sei a ordem em que o Firefox procura os plugins, mas aparentemente este estava sendo utilizado em vez do mais atual, que fica em /usr/lib/flashplugin-installer/libflashplayer.so. Removi a versão que estava no home e o Flash voltou a funcionar perfeitamente, inclusive depois de reativar o crash protection.

Outras referências úteis não citadas:


Atualmente estou trabalhando em alguns projetos que possuem diversas características em comum. Para facilitar o reaproveitamento de código, criamos um módulo à parte, uma espécie de framework, com todo o código comum aos projetos, e modularizamos os projetos usando Maven.

Quando chegamos na camada de apresentação, percebemos que não estávamos reaproveitando código como nas demais camadas. Pelo contrário, os XHTMLs de várias telas eram bastante parecidos, e estávamos basicamente copiando e colando quando surgia uma tela nova. Inclusive dentro de um mesmo XHTML, muita parte do código era copiada, pois vários elementos se repetiam (ex: elementos de formulário, com um label e um campo de texto ao lado). Decidimos então criar componentes Facelets.

A criação de componentes Facelets é muito simples, basta seguir os passos abaixo:

  1. Criar o componente. Como exemplo, criei um chamado itemFormulario, que exibe um label, um campo de texto e as mensagens de erro correspondentes:

     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     <html xmlns="http://www.w3.org/1999/xhtml"
         xmlns:ui="http://java.sun.com/jsf/facelets"
         xmlns:h="http://java.sun.com/jsf/html"
         xmlns:f="http://java.sun.com/jsf/core"
         xmlns:t="http://myfaces.apache.org/tomahawk"
         xmlns:c="http://java.sun.com/jstl/core"
         xmlns:fn="http://java.sun.com/jsp/jstl/functions">
    
     <ui:component>
         <h:outputLabel for="#{id}" value="#{label}" />
         <h:inputText id="#{id}" value="#{value}" />
         <h:message for="#{id}" />
     </ui:component>
     </html>
    

    Esse arquivo será salvo em /WEB-INF/facelets/ com o nome itemFormulario.xhtml. Neste exemplo, o componente utiliza os parâmetros id, label e value.

  2. Criar um arquivo de taglib para registrar os componentes criados. Este arquivo, que vou chamar de projeto.taglib.xml, será criado no diretório /WEB-INF/facelets do projeto, e será como no exemplo abaixo:

     <?xml version="1.0"?>
     <!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd">
     <facelet-taglib>
         <namespace>http://exemplo.com.br/jsf</namespace>
         <tag>
             <tag-name>itemFormulario</tag-name>
             <source>itemFormulario.xhtml</source>
         </tag>
     </facelet-taglib>
    

    Neste exemplo, registrei o componente itemFormulario. Sempre que criar um novo componente, ele deverá ser registrado neste arquivo, através de uma nova tag <tag>.

  3. Registrar a biblioteca de taglib no projeto, adicionando o trecho abaixo ao arquivo web.xml:

     <context-param>
         <param-name>facelets.LIBRARIES</param-name>
         <param-value>/WEB-INF/facelets/projeto.taglib.xml</param-value>
     </context-param>
    

    Desta forma, os componentes declarados no arquivo de taglib poderão ser usados no seu projeto, como neste exemplo:

     <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
     <html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:t="http://myfaces.apache.org/tomahawk"
      xmlns:c="http://java.sun.com/jstl/core"
      xmlns:fn="http://java.sun.com/jsp/jstl/functions"
      xmlns:custom="http://exemplo.com.br/jsf">
    
     <head>
         <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
         <title>
         </title>
     </head>
     <body>
         <custom:itemFormulario id="username" label="Digite seu login:" value="#{loginController.username}" />
     </body>
     </html>
    

A partir deste ponto, precisamos compartilhar estes componentes entre os diferentes projetos. Para isso, seguimos os passos abaixo:

  1. Mover o conteúdo do diretório /WEB-INF/facelets (arquivo de taglib e componentes criados) para o módulo compartilhado. Colocar estes arquivos na raiz do diretório /META-INF

  2. Atualizar no arquivo web.xml o trecho que registra a taglib:

     <context-param>
         <param-name>facelets.LIBRARIES</param-name>
         <param-value>/META-INF/projeto.taglib.xml</param-value>
     </context-param>
    

    Se for utilizar mais de uma taglib, declare-as separadas por “;” no trecho acima.

  3. Repetir o passo anterior para cada projeto que irá utilizar os componentes criados

Nas versões atuais do Facelets, a declaração da taglib no arquivo web.xml é desnecessária caso este arquivo esteja na raiz do diretório /META-INF. Os arquivos de componentes poderão ficar em outro diretório (ex: /META-INF/facelets), bastanto atualizar o arquivo de taglib de acordo com o diretório escolhido:

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd">
<facelet-taglib>
    <namespace>http://exemplo.com.br/jsf</namespace>
    <tag>
        <tag-name>itemFormulario</tag-name>
        <source>/META-INF/facelets/itemFormulario.xhtml</source>
    </tag>
</facelet-taglib>

Há ainda um passo opcional, que é a criação de um arquivo TLD (taglib descriptor) para que a IDE possa validar os componentes que você criou. Um arquivo TLD tem o seguinte formato:

<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">

<taglib xmlns="http://java.sun.com/JSP/TagLibraryDescriptor">
    <tlib-version>1.0</tlib-version>
    <jsp-version>2.0</jsp-version>
    <short-name>Componentes</short-name>
    <uri>http://exemplo.com.br/jsf</uri>
    <display-name>Minha biblioteca de componentes</display-name>
    <tag>
        <name>itemFormulario</name>
        <tag-class />
        <body-content>empty</body-content>
        <description>
            Cria um item de formulário com label, campo de texto e mensagens de erro.
        </description>
        <attribute>
            <name>id</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
            <type>java.lang.String</type>
            <description>
                Identificação do componente
            </description>
        </attribute>
        <attribute>
            <name>label</name>
            <required>false</required>
            <rtexprvalue>false</rtexprvalue>
            <type>java.lang.String</type>
            <description>
                Texto exibido no label do componente
            </description>
        </attribute>
        <attribute>
            <name>value</name>
            <required>true</required>
            <rtexprvalue>false</rtexprvalue>
            <type>java.lang.String</type>
            <description>
                Valor associado ao inputText do componente
            </description>
        </attribute>
    </tag>
</taglib>

Salve esse arquivo com o nome projeto.taglib.tld, no mesmo diretório do arquivo projeto.taglib.xml. Agora, ao abrir um arquivo XHTML que esteja usando o componente itemFormulario, a IDE exibirá os erros de validação (ex: um atributo marcado como required não foi definido). Com este arquivo criado, ao abrir um XHTML no Eclipse usando o editor de JSP, você terá também o recurso de autocomplete (Control + espaço), que exibirá todos os atributos do componente, assim como a descrição de cada um.

Referências: