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:


Outro dia, quando fui me logar no Gmail, digitei rapidamente meu login, apertei tab, digitei a senha e apertei enter. Na pressa, não percebi que, em vez de tab, eu tinha apertado shift. Ou seja, o campo login ficou preenchido como “loginsenha”, e a senha ficou em branco. Até aí tudo bem, o Gmail simplesmente me deu um aviso de login ou senha inválidos. Porém, esse “loginsenha” ficou no histórico de preenchimento de campos, o que é bem incômodo, já que contém minha senha. Eu queria excluir este item do histórico, mas sem perder todo o histórico do browser.

O Firefox possui uma opção “Clear Recent History”, no menu “Tools”, que permite excluir o histórico somente para um período de tempo (última hora, últimas 2 ou 4 horas, último dia ou tudo), e permite selecionar também o que se deseja excluir (URLs acessadas, downloads, formulários preenchidos, cookies, cache, logins ativos e preferências de sites). Apesar de esta opção ser bastante completa, eu queria algo mais específico: excluir somente aquele item.

Após uma rápida pesquisa no Google, encontrei algumas referências interessantes, e descobri que a solução era extremamente simples. Para excluir um item do histórico de preenchimento de campos de formulários, basta clicar no campo e, ao aparecer a lista de valores armazenados no histórico, selecione o item que você quer excluir usando a seta para baixo e pressione Del. É só isso!

Também é possível excluir itens individuais do histórico de URLs acessadas. Para isso, repita o procedimento acima, trocando apenas o Del por Shift+Del.

Referências:


Muitos componentes JSF, como os do Tomahawk, por exemplo, possuem o atributo rendered. Este atributo, como diz o nome, indica se o componente será renderizado ou não. No valor deste atributo, é possível utilizar expressões JSF EL; desta forma, a lógica que indicará se o elemento será exibido ou não pode (e deve) ser transferida para um Managed Bean. Isso permite que evitemos colocar muita lógica nos XHTMLs, deixando-os mais limpos e organizados.

Porém, em determinados momentos, precisamos fazer a renderização condicional de elementos que os componentes JSF não oferecem. Uma possível solução seria inserir este elemento num <t:div>, por exemplo, pois este componente do Tomahawk possui o atributo rendered. Porém, estaríamos criando um <div> em torno do elemento desejado sem necessidade. O melhor neste caso seria utilizar o componente [](http://myfaces.apache.org/tomahawk-project/tomahawk/tagdoc/t_htmlTag.html).

O <t:htmlTag> possui um atributo value que define a tag HTML que será renderizada em seu lugar, caso o atributo rendered seja igual a true. Se o value for vazio, ele não criará nenhuma tag adicional; assim, o <t:htmlTag> servirá somente para a renderização condicional de tudo o que estiver dentro deste componente.

Atenção: o atributo value é obrigatório; se você omití-lo, o componente não funcionará! Para que ele não gere nenhuma tag, é necessário definir value="", como no exemplo abaixo:

<t:htmlTag rendered="#{tipo.exibeDescricao}" value="">
    <div id="divDescricao_#{tipo.id}">
        <h:outputText value=" #{messages.descricao}" />
        <h:inputTextarea styleClass="inputAreaTexto" id="descricao" value="#{descricaoTipo}" />
    </div>
</t:htmlTag>

Muitos usuários de Linux têm dual boot com uma instalação de Windows, geralmente para executar alguma aplicação específica, como jogos mais recentes ou o iTunes (apesar de que o Ubuntu 10.04 deve suportar iPod e iPhone).

Quem utiliza esta configuração e usa Firefox em ambos os sistemas operacionais acaba tendo dois perfis independentes no browser, e não consegue acessar bookmarks, histórico e extensões instaladas no outro sistema. Uma solução para este problema é compartilhar os perfis do Firefox entre os sistemas operacionais.

O Firefox armazena um diretório com configurações pessoais do usuário. No Linux, esse diretório fica tipicamente em /home/usuario/.mozilla/Firefox/, e no Windows, em C:\Documents and Settings\usuario\Dados de aplicativos\Mozilla\Firefox\. Este diretório contém, entre outras coisas, um subdiretório Profiles com todos os perfis criados (mais detalhes sobre isso no post sobre gerenciamento de perfis no Firefox) e um arquivo profiles.ini. Este arquivo é carregado na inicialização do browser, e faz referência aos perfis utilizados. O formato do arquivo é como mostra o exemplo abaixo:

[General]
StartWithLastProfile=1

[Profile0]
Name=default
IsRelative=1
Path=Profiles/dwi06ij0.default

[Profile1]
Name=teste
IsRelative=1
Path=Profiles/nkc5ofgt.default
Default=1

O arquivo é dividido em seções. A primeira, General, tem somente o parâmetro StartWithLastProfile: se for 0, será exibida a tela de seleção de perfis; se for 1, o último perfil que foi usado será escolhido automaticamente.

As seções seguintes definem todos os perfis criados. Cada perfil tem um nome e um path - que será relativo ao diretório de configurações do Firefox se IsRelative for 1, e absoluto em caso contrário. O parâmetro Default indica se este é o perfil padrão.

Para que os dois sistemas operacionais compartilhem um perfil, primeiramente é necessário montar a partição do usuário utilizada pelo outro sistema operacional. Isso pode ser feito de duas maneiras:

Mapeando uma partição do Windows no Linux

Para montar uma partição do Windows, basta utilizar o comando mount, como no exemplo abaixo:

sudo mount /dev/sda1 /media/windows

Neste exemplo, a partição do Windows é /dev/sda1, e o diretório destino (que deve ser criado antes) é /media/windows. A partição pode ser FAT32 ou NTFS - neste caso, é necessário instalar o ntfs-3g, que já vem por padrão na maioria das distribuições atuais. Para que a partição seja montada automaticamente na inicialização do sistema, inclua a linha abaixo no arquivo /etc/fstab:

/dev/sda1 /media/windows ntfs defaults 0 0

Caso a partição seja FAT32, substitua ntfs por vfat na linha acima.

A configuração acima também pode ser feita utilizando uma ferramenta gráfica como o ntfs-config.

Mapeando uma partição do Linux no Windows

Para isso, é necessário instalar uma ferramenta como o Ext2 IFS - que, apesar do nome, também suporta ext3. Ao instalar esta ferramenta, será possível mapear qualquer partição ext2 ou ext3 como um drive comum. A figura abaixo mostra uma tela da ferramenta, onde aparecem todas as partições dos discos locais. Em cada partição do Linux, há uma combo box que permite selecionar a letra em que a partição será mapeada - selecionando none o mapeamento será desfeito.

Ext2 IFS

Entre as duas opções, pessoalmente, prefiro a segunda, pois não gosto da ideia do Windows acessando minhas partições do Linux - só mapeio uma partição com o Ext2 IFS quando preciso copiar algum arquivo, depois desfaço o mapeamento.

Após realizar o mapeamento da partição, de uma das duas formas acima, basta configurar o arquivo profiles.ini do Firefox. Para isso, é possível configurar o path completo para o perfil desejado e definir o parâmetro IsRelative=0, ou fazer um link no diretório onde o Firefox armazena os perfis e configurar o path relativo, com o parâmetro IsRelative=1. A primeira configuração ficaria como no exemplo abaixo:

[Profile0]
Name=default
IsRelative=0
Path=/media/windows/Documents and Settings/guilherme/Dados de aplicativos/Mozilla/Firefox/Profiles/sa8ww6mz.default

Para a segunda configuração, é necessário criar um link com o comando ln:

ln -s /media/windows/Documents\ and\ Settings/guilherme/Dados\ de\ aplicativos/Mozilla/Firefox/Profiles/sa8ww6mz.default /home/guilherme/.mozilla/Firefox/Profiles/

Neste caso, a configuração do arquivo ficaria assim:

[Profile0]
Name=default
IsRelative=1
Path=Profiles/sa8ww6mz.default

Possíveis problemas

Apesar de funcionar muito bem, o compartilhamento de perfis pode trazer alguns problemas:

  • Se as versões do Firefox nos dois sistemas forem diferentes (o que é muito comum, pois o repositório do Ubuntu costuma demorar para atualizar as versões), cada vez que você abrir o browser num sistema após tê-lo acessado no outro será como se você tivesse atualizado a versão do Firefox, ou seja, a inicialização será mais lenta, pois ele verificará a compatibilidade de cada extensão instalada com a versão atual;
  • Se você tentar abrir o Firefox num sistema operacional após ele ter travado no outro sistema, ele exibirá uma mensagem informando que já existe uma sessão aberta. Isso acontece por que, quando o Firefox é iniciado, ele cria um arquivo vazio chamado parent.lock no diretório do perfil que você estiver usando. Este arquivo é excluído quando o browser é fechado. Se isso ocorrer de maneira incomum (ex: travamento do browser ou do sistema operacional), este arquivo impedirá a abertura de outra sessão. Para resolver o problema, exclua esse arquivo;
  • Algumas extensões são incompativeis com determinados sistemas operacionais e versões de browser. Se for o caso, estas extensões serão desativadas pelo browser.