Mostrando postagens com marcador mauricio da silva marinho. Mostrar todas as postagens
Mostrando postagens com marcador mauricio da silva marinho. Mostrar todas as postagens

domingo, 22 de junho de 2014

[HTML 5] Web Workers

Essa vai de uma das questões do simulado para o exame 70-480 da Microsoft (HTML 5, JavaScript e CSS3).

A API Web Worker permite executar scripts em background (em uma thread separada da thread principal), sem bloquear a execução da página. A API é implementada no objeto Worker.

Você deve, antes de mais nada, instanciar o objeto Worker usando a palavra chave "new", atribuindo a instância resultante a uma variável, conforme o exemplo:

var worker = new Worker("ArquivoComScriptParaExecutar.js");

O parâmetro do construtor é o arquivo JavaScript que contém o script que será executado em background. Tipicamente são tarefas de longa duração, que poderiam bloquear a execução da página principal por algum tempo. O código do script pode informar o término da execução pelo envio de uma mensagem para o seu chamador, através da função postMessage.

Posteriormente, é necessário associar um event handler ao evento onmessage do objeto Worker. Isto permite à thread principal ser notificada do final da execução do script em background. Para manipular o evento com uma função anônima faça o seguinte:

worker.onmessage = function(e) {window.alert(e.data);};

O parâmetro para a função anônima é um event object. Este objeto contém uma propriedade data, que é o dado enviado como parâmetro pela função postMessage. Esta propriedade pode ser tanto uma string quanto um JSON (JavaScript Object Notation).

O script em background inicial quando o evento onmessage é invocado pelo objeto Web Worker e com o seguinte código, força-se a execução da função anônima no script em background:

worker.postMessage("");

A função AddEventListener permite a você associar um event handler a um evento. O primeiro parâmetro da função deve especificar o nome de um evento, não o nome do script em background. O segundo parâmetro deve especificar uma função de callback ou uma função anônima.

A função close do objeto Worker termina a thread avulsa e é chamada no script em background.

Exemplo:

Script em background (Workers.js):

onmessage = function(e){
  setTimeout(function()
  { 
    postMessage("Terminou a execução em background!");
  }, 5000);
}

Página (chamaWorker.html):

<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
<script>
 var worker = new Worker("Worker.js");
 worker.onmessage = function(e)
 {
   window.alert(e.data); 
 };
 worker.postMessage("");
</script>
</body>
</html>

domingo, 20 de janeiro de 2013

[JPA] Conceitos Importantes

Fonte: http://tomee.apache.org/jpa-concepts.html

Se tem uma coisa que você precisa entender para usar com sucesso a JPA (Java Persistence API), é o conceito de Cache. Infelizmente o cache é uma estrutura interna, não exposta pela JPA via código.

O que você tem que ter em mente sobre o cache da JPA:
  • Um Cache é uma cópia de dados, uma cópia desconectada do banco de dados.
  • Flushing é o ato de levar as modificações feitas em cache para o banco de dados.
  • Um PersistenceContext é, essencialmente, um Cache.
  • Um EntityManager represetne um PersistenceContext (logo, um cache).
  • Um EntityManagerFactory cria um EntityManager (e todavia um PersistenceContext/Cache).

Comparando os contextos de persistência RESOURCE_LOCAL e JTA.

Com <persistence-unit transaction-type="RESOURCE_LOCAL"> você é que se responsabiliza por criar e rastrear o EntityManager (PersistenceContext/Cache).

  • Você precisa usar o EntityManagerFactory para obter um EntityManager.
  • A instância do EntityManager obtida é um PersistenceContext/Cache.
  • Um EntityManagerFactory pode ser injetado com a anotação @PersistenceUnit apenas (sem @Persistence Context).
  • Não é permitido usar @PersistenceContext para se referir a uma unit do tipo RESOURCE_LOCAL.
  • Você deve usar EntityTransaction API para iniciar/comitar todas as chamadas para seu ENtityManager.
  • Chamar ENtityManagerFactory.createEntityManager() duas vezes resulta em duas instâncias separadas de EntityManager e, é claro, dois PersistenceContext/Caches separados.
  • Não é uma boa idéia ter mais de uma instânciade um EntityManager em uso (não crie um segundo EntityManager antes de destruir o primeiro).

Com <persistence-unit transaction-type="JTA"> o container irá cuidar da criação e do rastreamento do EntityManager para você, e neste caso:


  • Você não pode usar o EntityManagerFactory para obter um EntityManager.
  • Você só pode ter o EntityManager que é fornecido pelo container.
  • Um EntityManager pode ser injetado pela anotação @PersistenceContext, somente (sem @PersistenceUnit).
  • Você não pode usar @PersistenceUnit para fazer referência a uma unit do tipo JTA.
  • O EntityManager fornecido pelo container é uma referência ao PersistenceContext/Cache associado a transação JTA.
  • Se não há transações JTA em progresso, o EntityManager não pode ser usado porque não há PersistenceContext/Cache.
  • Qualquer um com uma referência para a mesma unit na mesma transação irá automaticamente ter uma referência para o mesmo PersistenceContext/Cache.
  • O PersistenceContext/Cache é flushed e limpo a cada commit JTA.

É isso aí! Mais informações e exemplos veja em http://tomee.apache.org/jpa-concepts.html

domingo, 13 de janeiro de 2013

[JSF] Enviar requisição com Ajax

Referência: The Java EE 6 Tutorial Sending an Ajax Request.

Como prometido no post anterior Usando Ajax com JSF vou continuar nos estudos do The Java EE 6 Tutorial, agora mostrando como enviar requisições com Ajax.

O Java EE 6 Tutorial mostra quatro formas para enviar requisições Ajax, são elas:

Usando o atributo event da tag f:ajax

O atributo event define que evento d o DOM irá disparar a ação ajax. Alguns valores possíveis são click, keyup, mouseover, focus e blur.

Se um valor não for especificado para este atributo, ele irá assumir o evento default do componente pai da tag f:ajax correspondente.

Componentes ActionSource, como commandButton, commandLink e inputText tem o valor do atributo action como alvo de seus eventos default.

Exemplo:

<h:commandButton id="submit" value="Submit"> 
    <f:ajax event="click" />
</h:commandButton>
<h:outputText id="result" value="#{userNumberBean.response}" />


Note que estes eventos JSF, apesar de serem baseados em JavaScript, são diferentes dos eventos do DOM que possuem o prefixo "on".

Usando o atributo execute da tag f:ajax

Define o componente ou componentes que serão executados no servidor. O componente é identificado pelo seu atributo id e você pode especificar mais de um componente executável, separando-os com um espaço em branco.

Ao ser executado, o componente participa de todas as fases do ciclo de vida da requisição, exceto da fase Render Response.

O valor do atributo execute também pode ser uma palavra chave como @all, @none, @this@form, explicados no post anterior Usando Ajax com JSF, referindo-se ao componente com que a tag f:ajax está aninhada.

A seguir, um exemplo mostrando como especificar que um inputText de id userNo seja executado no click de um commandButton de forma assíncrona:

<h:inputText id="userNo" 
             title="Type a number from 0 to 10:"
             value="#{userNumberBean.userNumber}">
    ...
</h:inputText>
<h:commandButton id="submit" value="Submit"> 
    <f:ajax event="click" execute="userNo" />
</h:commandButton>

Usando o atributo immediate

Se seu valor estiver configurado para true, seus eventos serão propagados durante a fase Apply Request Values. O valor default é false. Conheça o ciclo de vida JSF para complementar entendimentos.

Usando o atributo listener

Utilizado para referenciar um método do lado do servidor a ser executado por uma ação Ajax do lado do cliente. No seguinte exemplo o atributo listener da tag f:ajax chama um método em um bean quando o evento correspondente é disparado, observe:

<f:ajax listener="#{mybean.someaction}" render="somecomponent" />


Beleza?!

Agora você já pode sofisticar as interações com usuário em sua camada de apresentação JSF.

No próximo post vamos falar de CDI. Até lá!

quinta-feira, 3 de janeiro de 2013

[JSF] Usando Ajax com JSF.

The Java EE 6 Tutorial, Part II The Web Tier, Cap. 11 Using Ajax with JavaServer Faces Technology.

Visão Geral sobre Ajax.

Ajax refere-se a JavaScript e XML, tecnologias que são amplamento usadas para criar conteúdo web dinâmico e assíncrono. O foco deste tutorial está em usar JavaScript em funcionalidades baseadas em Ajax em aplicações web JSF.

JavaScript é uma linguagem orientada a objetos que permite adicionar funcionalidades à camada de apresentação para interações assíncronas com o cliente, onde é originalmente executada (também há JavaScript Side Server).

Quando uma função JavaScript envia uma requisição assíncrona para o servidor, o servidor envia de volta uma resposta usada para atualizar o DOM (Document Object Model) da página.

A resposta do servidor não precisa ser, necessariamente, em XML, também pode ser em JSON (formato de dados JavaScript).

Ajax permite atualização assíncrona e parcial da camada de apresentação, ou seja, funcionalidades Ajax podem trocar informações com o servidor sem a necessidade de submeter ou atualizar a página inteira (refresh).

Usando Ajax com JSF.

Funcionalidades Ajax podem ser adicionadas a aplicações JSF de uma das duas maneiras seguintes:
  • Programando a funcionaliade Ajax em JavaScript diretamente na página.
  • Usando uma biblioteca com funcionalidades Ajax embutidas.
A plataforma JEE 6 suporta Ajax por uma biblioteca JavaScript embutida. Logo, os componentes UI JSF respondem a funcionalidades Ajax. Você também pode carregar esta biblioteca JavaScript e usar diretamente seus métodos dentro dos Managed Beans.

A tag JSF específica para Ajax é f:ajax e seus atributos serão explicados a seguir.

Atributo Tipo Descrição
disabled javax.el.ValueExpression retorna um Boolean Se true o comportamento Ajax não deve ser renderizado, se false, o comportamento Ajax deve ser renderizado, o default é false.
event javax.el.ValueExpression retorna uma String Uma String que identifica o tipo de evento em que a ação Ajax será aplicada. Se especificado, deve ser um dos eventos suportados pelo componente. Se não especificado, o evento default (o evento que dispara a requisição Ajax) é determinado para o componente. O evento dafult é action para componentes ActionSource e valueChange para componentes EditableValueHolder.
execute javax.el.ValueExpression retorna um Object Uma Collection que identifica uma lista de componentes para ser executada no servidor. Se uma literal é especificada, deve ser uma String delimitada por espaços de identificadores de componentes e/ou uma das palavras chave. Se uma ValueExpression é especificada, deve referenciar uma propriedade que retorna uma Collection de String objetos. Se não especificada, o valor default é @this.
immediate javax.el.ValueExpression retorna um Boolean Um Boolean que indica se a entrada é para ser processada antes do ciclo de vida.
listener javax.el.MethodExpression O nome do método listener que será chamado quando um AjaxBehaviorEvent for disparado.
onevent javax.el.ValueExpression retorna uma String O nome da função JavaScript que irá manipular os UI events.
onerror javax.el.ValueExpression retorna uma String O nome da função JavaScript que irá manipular os erros.
render javax.el.ValueExpression retorna um Object Uma Collection que identifica uma lista de componentes a serem renderizados. Se uma literal é especificada deve ser uma String delimitada por espaços de identificadores de componentes e/ou de palavras-chave. Se uma ValueExpression é especificada, deve referenciar uma propriedade que retorna uma Collection de objetos String. Se não especificada, o valor default é @none.

Palavra-chave Descrição
@all Todos os componentes identificados
@form Os componentes do formulário
@none Nenhum componentes identificado
@this O elemento que disparou a requisição

Exemplo de uso da tag f:ajax

<h:inputText value="">
   <f:ajax />
</h:inputText>

Note que quando você usa a tag f:ajax em uma página Facelets, a biblioteca JavaScript que suporta Ajax que já vem no J2EE 6 é carregada implicitamente. Este recurso também pode ser carregado explicitamente, veja mais detalhes em Loading JavaScript as a Resource no The Java EE 6 Tutorial.

No próximo post veremos como enviar uma requisição Ajax e receber uma resposta. Até lá.

segunda-feira, 31 de dezembro de 2012

[JPA] Melhorando a performance de aplicações JPA com cache de segundo nível.


O cache de segundo nível é um repositório local, gerenciado pelo mesmo mecanismo de persistencia responsável pelo ORM da aplicação, para melhorar a performance da mesma.

A intenção é melhorar a performance reduzindo as conversações entre aplicação e banco de dados.

É suportado pela especificação JPA e pode ser configurado para os seguintes modos de trabalho (Cache Mode):

ALL Todas as entidades declaradas na unidade de persistência irão para o cache.
NONE Nenhuma entidade da unidade de persistência irá para o cache.
ENABLE_SELECTIVE Habilita o cache para entidades que forem declaradas para tal com a anotação @Cacheable.
DISABLE_SELECTIVE Habilita o cache para todas as entidades da unidade de persistência, exceto para aquelas que estiverem anotadas com @Cacheable(false).
UNSPECIFIED Adota o comportamento default do mecanismo de persistência JPA utilizado.

Um problema comum do uso do cache de segundo nível é quando os dados mudam no banco mas não mudam no cache. É o que se chama de stale read. Stale reads podem ser resolvidos com a estratégia adequada de configuração do modo de trabalho do cache e outras configurações possíveis. Por isso, é muito importante conhecer profundamente o cache de segundo nível do mecanismo de persistência que você pretende adotar.

No modo ENEABLE_SELECTIVE, as subclasses das entidades anotadas com @Cacheable também serão cacheadas a menos que a anotação seja sobrescrita com @Cacheable(false).

Especificando as configurações de cache mode para melhorar a performance.

Para ajustar o cache mode para uma unidade de persistencia, especifique um dos modos possíveis como valor do elemento shared-cache-mode no persistence.xml.

<persistence-unit name="examplePU" transaction-type="JTA">
  <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
  <jta-data-source>jdbc/__default</jta-data-source>
  <shared-cache-mode>DISABLE_SELECTIVE</shared-cache-mode>
</persistence-unit>

Ou então, programaticamente:

EntityManagerFactor emf = 
    Persistence.createEntityManagerFactory(
        "myExamplePU", new Properties().add(
            "javax.persistence.sharedCache.mode", "ENABLE_SELECTIVE"));

OBS: Se o mecanismo de persistencia adotado não suportar cache de segundo nível, as configurações acima não produzirão qualquer efeito na aplicação.

Configurando cache retrieval e store modes.

Se o cache de segundo nível estiver habilitado na unidade de persistência pela configuração do shared cache mode, o comportamento do cache de segundo nível poderá ser modificado configurando as propriedades javax.persistence.cache.retrieveMode e javax.persistence.cache.stroreMode. Estas propriedades podem ser configuradas no nível do contexto de persistência, passando o nome e o valor da propriedade para o método EntityManager.setProperty, ou configurando uma operação per-EntityManager, ou seja, por entidade (EntityManager.find ou EntityManager.refresh) ou no nível per-query, ou seja, por query.

Cache Retrieval Mode

O modo de recuperação de dados a partir do cache, configurado pela propriedade javax.persistence.retrieveMode, controla como os dados são lidos do cache por chamadas ao método EntityManager.find e a partir de queries.

A propriedade retrieveMode pode ser configurada com uma das constantes definidas pelo enum javax.persistence.CacheRetrieveMode (USE que é o default ou BYPASS). Quando configurada para USE, os dados são recuperados a partir do cache, se disponíveis. Se o dado não estiver no cache, o mecanismo de persistência irá buscá-lo no banco. Quando configurada com BYPASS, o mecanismo de persistência ignora o cache e os dados são recuperados diretamente do banco de dados.

Cache Store Mode

O modo de salva dos dados do cache, configurado pela propriedade javax.presistence.storeMode, controla como os dados serão salvos no cache.

A propriedade storeMode pode ser configurada por uma das constantes definidas pelo enum javax.persistence.CacheStoreMode, podendo ser USE, que é o default, BYPASS ou REFRESH. Configurada como USE, o dado no cache é criado ou atualizado na primeira vez que for lido do banco de dados ou gravado (commited) no mesmo. Se o dado já estiver no cache, o modo USE não irá forçar um refresh quando o dado for lido do banco.

Quando configurada para BYPASS, os dados lidos ou gravados no banco não serão inseridos no cache. É isso! O cache será imutável.

Quando configurada para REFRESH o dado é salvo no cache toda vez que for lido ou gravado no banco. Se o dado já estiver no cache, será atualizado (refreshed) no cache.

Configurando o Cache Retrieval ou o Store Mode.

Para configurar o cache retrieval ou store mode, basta chamar o método EntityManager.setProperty do contexto de persistência e passar como parâmetro o par {nome, valor} da propriedade:

EntityManager em = ...;
em.setProperty("javax.persistence.cache.storeMode", "BYPASS");

Para configurar o cache retrieval ou store mode quando chamar os métodos EntityManager.find ou EntityManager.refresh, primeiro crie uma instância de Map<String, Object> e adicione os pares nome, valor conforme a seguir:

EntityManager em = ...;
Map<String, Object> props = new HashMap<String, Object>();
props.put("javax.persistence.cache.retrieveMode", "BYPASS");
String personPK = ...;
Person person = em.find(Person.class, personPK, props);

OBS: O cache retrieve mode será ignorado na chamada do método EntityManager.refresh, pois as chamadas para refresh resultam sempre em dados lidos do banco e nunca do cache.

Para configurar o retrieval ou store mode quando for usar queries, chame o método Query.setHint ou o método TypedQuerie.setHint, dependendo do tipo de query:

EntityManager em = ...;
CriteriaQuery<Person> cq = ...;
TypedQuery<Person> q = em.createQuery(cq);
q.setHint("javax.persistence.cache.storeMode", "REFRESH");
...

OBS: Configurar o store ou o retrieval mode em uma query ou chamando os métodos EntityManager.find ou EntityManager.refresh sobrescreve as configurações do entity manager.


Controlando o cache de segundo nível programaticamente.

A interface javax.presistence.Cache define métodos para interagir com o cache de segundo nível programaticamente. A interface Cache define métodos para checar se uma entidade particular tem dados salvos no cache, para remover uma entidade particular do cache, para remover todas as instâncias (inclusive de subclasses) de qualquer classe de entidade do cache e para limpar o cache de todos os dados das entidades.

OBS: Se o cache de segundo nível for desabilitado, chamadas aos métodos da interface Cache não terão qualquer efeito sobre a aplicação, exceto para o método contains, que sempre irá retornar false.

Checando se os dados de uma entidade estão no cache.

Chame o método Cache.contains para achar ou simplesmente para verificar se uma entidade está no cache de segundo nível. Este método retornará true se os dados da entidade estiverem em cache e false em caso contrário.

EntityManager em = ...;
Cache cache = em.getEntityManagerFactory().getCache();
String personPK = ...;
if (cache.contains(Person.class, personPK)) {
  // the data is cached
} else {
  // the data is NOT cached
}

Removendo uma entidade do cache.


Chame um dos métodos Cache.evict para remover uma entidade em particular ou todas as entidades de um dado tipo do cache de segundo nível.

Para remover uma entidade em particular chame Cache.evict passando a classe da entidade e o Id (chave primária).


EntityManager em = ...;
Cache cache = em.getEntityManagerFactory().getCache();
String personPK = ...;
cache.evict(Person.class, personPK);

Para remover todas as instâncias de uma classe de entidade, incluindo suas subclasses, chame evict e especifique a classe:

EntityManager em = ...;
Cache cache = em.getEntityManagerFactory().getCache();
cache.evict(Person.class);

Todas as instâncias da classe Person serão removidas do cache. Se Person tiver subclasse, chame o método evictAll para remover suas instâncias também.


Removendo todos os dados do cache.


Chamar o método Cache.evictAll irá limpar completamente o cache de segundo nível:


EntityManager em = ...;
Cache cache = em.getEntityManagerFactory().getCache();
cache.evictAll();

E é isso! Este post é o resultado da tradução, com poucas adaptações, do The Java EE 6 Tutorial, Part VI Persistence, Chapter 38 Improving the Performance of Java Persistence APIApplications by Setting a Second-Level Cache.


Fonte: http://docs.oracle.com/javaee/6/tutorial/doc/gkjjj.html
Tradução: Mauricio da Silva Marinho
Ao copiar, dê crédito ao autor.

sexta-feira, 9 de novembro de 2012

[VRaptor] Melhorando Hash MD5 com Salt

Vamos utilizar uma técnica chamada Salt, para adicionar melhor segurança à estratégia de guardar o hash das senhas no banco.

Esta técnica consiste em atribuir um valor aleatório, por cadastro, para que somado a senha, gere um hash.

O objetivo é impedir que existam senhas fracas no banco, suscetíveis a ataques de força bruta baseados em dicionários.

Alguns sites undergrounds oferecem dicionários com mais de 8 bilhões de entradas. O Linkedin sofreu um ataque desta natureza há algum tempo e como resultado, vazaram cerca de 6 milhões de senhas.

Espero que você goste:



O salt pode ser modificado de tempos em tempos, automaticamente, atualizando os hashes. E pode ser mantido em um local diferente. Você ainda pode guardar o salt cifrado em um algoritmo diferente.

Outras estratégias podem auxiliar a sofisticar mais ainda o processo, como gerar o hash do hash com diferentes algoritmos em várias iterações e por aí vai...

OBS: Esta técnica ajuda defesas contra ataques no banco de dados. Não elimina a necessidade da adoção de senhas fortes, uma vez que existem ataques direto a formulários e que exploram as fragilidades do protocolo http.

Espero ter te ajudado, apreciarei todas as críticas, dúvidas e sugestões.

Forte abraço,

Mauricio da Silva Marinho.

quinta-feira, 8 de novembro de 2012

[Java] Thread X Runnable

Threads está entre os assuntos mais difíceis do exame SCJP/OCJP. O que podemos dizer sobre elas...

Basicamente, temos dois tipos de ambiente de execução (em se tratando de execução):

  • Execução de segmentação única. Onde as ações são executadas em fila, uma após a outra, necessariamente. 
  • Execução concorrente. Onde várias ações disputam a atenção dos recursos de forma independente.

Neste último caso, em Java, as ações concorrentes são threads concorrentes. É o que chamamos de threads de execução. Dispomos deste recurso quando precisamos que alguma ação ocorra independente de outra(s), quando não podemos ficar esperando uma ação terminar para continuar executando uma tarefa ou uma sequencia de tarefas.

Em Java, uma thread é uma instância de java.lang.Thread. As execuções de aplicações Java, ocorrem em pilhas de chamadas. Cada pilha de chamadas reside em uma única Thread. Logo, ao criar uma Thread, estamos criando uma nova pilha de chamadas, no mesmo processo.

Um processo é um conjunto de tarefas, que em um SO multitarefa, pode executá-las concorrencialmente. Exatamente, as Threads!

Como a VM tratará a execução das threads dependerá da implementação da VM. Isso mesmo! Não espere garantir que uma aplicação que crie várias instâncias de Thread tenha o mesmo comportamento em VMs diferentes. Então, se este for o caso, não se pode basear a implementação em uma VM específica, a menos que saiba que a aplicação só será executada naquela VM.

A classe java.lang.Thread expõe alguns métodos para gerenciar as threads:

  • start()
  • yield()
  • sleep()
  • run() - chame aqui o código que será executado pela thread.
Cria-se uma Thread de duas formas:
  • Estendendo java.lang.Thread, ou
  • implementando java.lang.Runnable.

Estender Thread pode parecer mais fácil, mas certamente não é a solução mais elegante!

Por que? Simplesmente pelo fato de que a herança, em OO, é um recurso para se especializar uma classe, para que se faça algo novo.

Então se você precisa apenas criar uma execução em uma thread separada, não há necessidade de especializar Thread. Lembre-se que ao estender Thread, não poderá estender mais nada! Neste caso, o mais lógico, seguindo princípios de OO, seria implementar Runnable.

Implementar Runnable vai permitir que sua classe estenda outra classe de negócio, além de dispor dos comportamentos de Thread (ou de Runnable. Thread implementa Runnable, sabia?!).

Dizemos que estender Thread é mais simples porque por este caminho, para criar uma nova thread, basta instanciar a subclasse de Thread que você criou:

public class minhaThread extends Thread{
  public void run(){
    //Chama a execucao da nova thread aqui.
  }
}

MinhaThread novaThread = new MinhaThread();

Implementando Runnable (recomendável na esmagadora maioria dos casos), ficaria assim:

//Cria a classe que implementa Runnable
public class MinhaRunnable implements Runnable{
  public void run(){
    //Chama a execucao da nova thread aqui.
  }
}

//Instancia MinhaRunnable
MinhaRunnable minhaRunnable = new MinhaRunnable();

//Cria uma instancia de Thread, passando sua Runnable para executar
Thread novaThread = new Thread(minhaRunnable);

A classe Runnable que passamos para a Thread, tecnicamente chama-se destino (target).

Até o momento, a thread foi criada, mas não foi executada, dizemos que o estado dela é new. Para executar a thread, basta chamar .start() e a thread passará de new para running:

//Para iniciar a thread
novaThread.start();

Sacou?

Espero ter te ajudado. Críticas, dúvidas e sugestões são bem vindas.

Forte abraço e até o próximo post.

Mauricio da Silva Marinho

terça-feira, 6 de novembro de 2012

[VRaptor] Configurando o Hibernate

Olá, mais uma vez.

Neste vídeo tento explicar como configurar o Hibernate no VRaptor, para que ele (o VRaptor) gerencie a injeção das sessões do Hibernate nos DAOs. O projeto utilizado é o kanban, projeto criado no post anterior.
 
 Espero que este tutorial e suas explicações lhe sejam úteis de alguma forma. Apreciarei qualquer crítica e/ou sugestão.

 Forte abraço, Mauricio da Silva Marinho

sábado, 3 de novembro de 2012

[VRaptor] vraptor-blank-project no NetBeans

Importar o projeto em branco do vraptor (vraptor_blank_project) pode ser um pouquinho problemático pelo fato de os arquivos de propriedades do projeto para o NetBeans não estarem atualizados com o projeto. Veja neste vídeo explicativo como fazê-lo, inclusive, mudando o nome do projeto sem muitos problemas.


Espero que gostem, pois é o primeiro vídeo de muitos. Estou aprendendo a editar, os próximos serão melhores.

Forte abraço,

Mauricio da Silva Marinho

sexta-feira, 2 de novembro de 2012

[Java] Conversão de Tipos (Cast)

Pode parecer um assunto batido, mas será que não tem uns "peguinhas" para quem está de olho no exame para certificação?

Convertendo variáveis de referência.

Este assunto tem uma relação com polimorfismo. A mágica do polimorfismo está em você poder referenciar um tipo mais específico com uma variável de um tipo mais genérico.

Isto é possível porque o compilador verifica a árvore de herança das classes envolvidas neste processo, veja:

public class Veiculo{
  public void informaLotacao(){
     System.out.println("Um motorista.");
  }
}

public class Ferrari extends Veiculo{
  public void informaLotacao(){
    System.out.println("Um motorista e um passageiro.");
  }
  public void informaPotencia(){
    System.out.println("460 cavalos.");
  }
}

public class Onibus extends Veiculo{
  public void informaLotacao(){
    System.out.println("Um motorista e trinta e dois passageiros.");
  }
  public void informaCombustivel(){
    System.out.println("Diesel.");
  }
}

public class TestaVeiculo{
  public static void main(String[] args){
    Veiculo ferrari = new Ferrari();
    Veiculo onibus = new Onibus();
    System.out.println("Uma ferrari tem espaço para " + ferrari.informaLotacao() + " e possui " + ferrari.informaPotencia());
    System.out.println("Um ônibus tem espaco para " + onibus.informaLotacao() + " e funciona com " + onibus.informaCombustivel());
  }
}

Ao executar TestaVeiculo que saída você espera receber?

Na verdade, vai acontecer um erro de compilação dizendo cannot find symbol. Isso porque as referências são do tipo Veiculo, que não possui o metodo informaPotencia() e nem informaCombustivel().

Entenda que você só pode chamar os métodos que o tipo da sua variável de referência expõe para você, mesmo que seja uma referência para uma instância de um tipo mais especializado, com mais métodos.

Para acessar os métodos do tipo especializado temos primeiro que converter os tipos, veja:

public class TestaVeiculo{
  public static void main(String[] args){
    Veiculo ferrari = new Ferrari();
    Veiculo onibus = new Onibus();
    Ferrari ferrariConvertida = (Ferrari) ferrari;
    Onibus onibusConvertido = (Onibus) onibus;
    System.out.println("Uma ferrari tem espaço para " + ferrariConvertida.informaLotacao() + " e possui " + ferrariConvertida.informaPotencia());
    System.out.println("Um ônibus tem espaco para " + onibusConvertido.informaLotacao() + " e funciona com " + onibusConvertido.informaCombustivel());
  }
}

Agora você fez as pazes com o compilador, realizando o cast (conversão) de sua referência generica para um tipo mais específico, que expõe os métodos que você quer usar. Tudo certo! Mas pense comigo: já que o compilador olha apenas para a árvore de herança, o que aconteçe em uma situação assim:

public class TestaVeiculo{
  public static void main(String[] args){
    Veiculo ferrari = new Veiculo();
    Veiculo onibus = new Veiculo();
    Ferrari ferrariConvertida = (Ferrari) ferrari;
    Onibus onibusConvertido = (Onibus) onibus;
    System.out.println("Uma ferrari tem espaço para " + ferrariConvertida.informaLotacao() + " e possui " + ferrariConvertida.informaPotencia());
    System.out.println("Um ônibus tem espaco para " + onibusConvertido.informaLotacao() + " e funciona com " + onibusConvertido.informaCombustivel());
  }
}

Bom neste caso, você prova que o compilador só olha para a árvore de herança, porque ele não vai reclamar de nada. Entretanto, ao executar o código você vai receber um java.lang.ClassCastException, porque as variáveis de referência ferrari e onibus agora são do tipo Veiculo e um tipo generalizado não cabe em um tipo especializado, ou seja, Ferrari é um Veiculo, mas Veiculo, não necessariamente, é uma Ferrari. Ou ainda, Veiculo pode ser um Onibus, que é bem diferente de uma Ferrari, concorda?

Saber o que não compila e o que compila e não roda é fundamental para o exame.

Forte abraço e até a próxima.

Mauricio da Silva Marinho.

[Java] Overloading ou Overriding? (Parte 2/2)

Uns chamam de sobrescrita outros de subscrita, eu acho subscrita feio, mas sobrescrita está errado, já que overriding não quer dizer isto. Bem vou adotar subscrita e os que tiverem outras idéias podem postar como resposta a este post. Ficarei muito grato!

Overriding (Subscrita).

Subscrita é dar outra implementação a um método que já existe na classe herdada, exceto, é claro, se o método em questão for declarado, na classe mãe, como final ou static.

É o que ocorre com os métodos abstratos herdados de uma superclasse abstrata. Neste caso, a menos que a subclasse também seja abstrata, é obrigatório prover a implementação do método.

Então podemos dizer sem medo de errar, que a subclasse concreta subscreve os métodos abstratos herdados de uma superclasse abstrata.

Nestes casos, você concorda que poderemos ter várias implementações para cada subclasse que subscrever um método abstrato herdado de uma mesma subclasse?

Então podemos dizer que teremos, neste caso, várias formas (implementações) do mesmo método?

É claro que sim, concordo com você, então estamos diante de um polimorfismo, correto?

Correto, você acertou novamente.

Veja um exemplo para prosseguirmos em nosso raciocínio:

public class Animal{
  public void moveSe(){
    System.out.println("Sai de um lugar para outro.");
  }
}

public class Cobra extends Animal{
  public void moveSe(){
    System.out.println("Sai de um lugar para outro, rastejando.");
  }
}

public class Canguru extends Animal{
  public void moveSe(){
    System.out.println("Sai de um lugar para outro, saltando.");
  }
}

public class TesteAnimal(){
  public static void main(String[] args){
    Animal cobra = new Cobra();
    Animal canguru = new Canguru();
    cobra.moveSe();
    canguru.moveSe();
  }
}

O exemplo anterior, compilando sem problemas, produzirá que saída ao executarmos a classe TestAnimal?

Exatamente, a saída será:

Sai de um lugar para o outro, rastejando.
Sai de um lugar para o outro, saltando.

Isto porque, apesar de cobra e canguru serem do tipo Animal, cada uma destas referências, aponta para uma instância de Cobra e Canguru, respectivamente. Portanto, o método subscrito será invocado na execução.

Lembre-se que isto só é possível porque Animal também tem um método moveSe(). Caso contrário, o método moveSe() não teria visibilidade para uma referência do tipo Animal. E mesmo porque, se Animal não tivesse moveSe(), não estaríamos falando de subscrita (e o animal não estaria no código).

Veja outras restrições para um método subscrito:
  • Não pode ter um modificador de acesso mais restritivo.
  • Não pode ter uma assinatura diferente.
  • Não pode ter um tipo de retorno diferente.
  • Não pode ter nível de acesso mais restritivo.
  • Apenas métodos herdados podem ser subscritos. Lembrando, se o método original for final ou static, não poderá ser subscrito, e se for private, só poderá ser subscrito por subclasses no mesmo pacote da superclasse.
  • Não pode lançar exceções verificadas novas ou mais abrangentes que as declaradas pelo método original da superclasse.


É isso! Espero ter-lhe ajudado de alguma forma com estas informações. Qualquer dúvida ou contribuição, fique a vontade para postar. Terei imenso prazer em responder todas.

Mauricio da Silva Marinho.


[Java] Overloading ou Overriding? (Parte 1/2)

Qual a diferença entre estas duas técnicas de programação OO? O que significam?

Overloading (Sobrecarga).

Um método sobrecarregado é aquele que aparece mais de uma vez em uma classe (ou subclasse) com assinatura (lista de argumentos) distinta.

O tipo de retorno e a implementação, podem ser, opcionalmente diferentes. Então podemos dizer que métodos sobrecarregados:

  • devem possuir assinaturas distintas.
  • podem possuir tipos de retorno distintos.
  • podem possuir modificadores de acesso distintos.
  • podem declarar exceções verificadas novas ou mais abrangentes.

Veja o seguinte exemplo de método sobrecarregado:

class Aritmetica{
  public int soma(int a, int b){
    return a + b;
  }
  public double soma(double a, double b){
    return a + b;
  }
}

//Chamando o metodo soma sobrecarregado.
public class TestaAritmetica{
  public static void main(String[] args){
    Aritmetica calculadora = new Aritmetica();
    int a = 10;
    int b = 20;
    int somaDosInts = calculadora.soma(a, b);
    int somaDosDoubles = calculadora.soma(10.5 + 20.5);
  }
}

No exemplo anterior, na classe TestaAritmetica, somaDosInts recebe o retorno da chamada a primeira forma do método sobrecarregado Aritmetica.soma que é soma(int, int). E somaDosDoubles recebe o retorno da chamada a segunda forma do método sobrecarregado Aritmetica.soma, que é soma(double, double). É um método polimórfico, pois tem mais de uma forma.

É o tipo de argumento que irá acionar a forma chamada de um método sobrecarregado, pois a identidade do método é dada pela sua assinatura. Veja este outro exemplo:

class Pet{}

class Cao extends Pet{}

class Lar{
  public void maisUmNaFamilia(Pet pet){
    System.out.println("Chegou um pet na casa!");
  }
  public void maisUmNaFamilia(Cao cao){
    System.out.println("Chegou um cão na casa!");
  }
  public static void main(String[] args){
    Lar lar = new Lar();
    Pet pet = new pet();
    Cao cao = new Cao();
    Pet refParaCao = new Cao();
    lar.maisUmNaFamilia(pet);
    lar.maisUmNaFamilia(cao);
    lar.maisUmNaFamilia(refParaCao);
  }
}

E no caso do exemplo anterior, qual seria a saída?

Lembre-se: a forma do método sobrecarregado será identificada pelos tipos da lista de parâmetros, pela assinatura do método. Logo, independente de refParaCao guardar uma referência de Cao, seu tipo é Pet e por isso o método forma do método sobregarregado Lar.maisUmNaFamilia que será invocada é: Lar.maisUmNaFamilia(Pet). Potanto a saída será:

Chegou um pet na casa!
Chegou um cao na casa!
Chegou um pet na casa!

É isso aí! Estes conhecimentos são cobrados na prova SCJP/OCJP e espero que lhe ajudem a esclarecer algumas questões importantes. No próximo post discutiremos Overriding, as confusões entre os dois conceitos e como o examinador pode se aproveitar disso para lhe confundir no exame.

Forte abraço,

Mauricio da Silva Marinho


quarta-feira, 31 de outubro de 2012

[JavaScript] JavaScript SideServer!? Isso pode, Arnaldo?

Ainda há pouco estava passeando na Internet, buscando material sobre JavaScript side server quando lembrei, que há muito tempo atrás, entrei em contato com uma iniciativa da antiga Borland, em produzir algo do tipo e vejam o que achei:

Isso deve arrancar nostalgia de alguns. Foi uma excelente ferramenta para o desenvolvimento de páginas dinâmicas para a web, nos idos de 1997/98. Permitia o desenvolvimento de formulários no melhor estilo drag and drop, com um editor muito parecido com o do Delphi. Muito bem feita. Curiosamente teve poucas versões e vida curtíssima. Na Amazon ainda restam 4 unidades do software original para venda. Veja que esta versão é para Windows 95 ou NT e que vinha com o navegador Netscape. Cara!!! Pra quem quiser matar a saudade: 
  • http://www.theopensourcery.com/keepopen/2006/blast-from-the-past-2-borland-intrabuilder/
  • http://alamopc.org/pcalamode/reviews/archive1/rev187.htm
  • http://www.drdobbs.com/borlands-intrabuilder-10/184415559
Bom, recentemente tivemos uma iniciativa da Aptana com o Jaxer, um servidor ajax rodando sobre a máquina do Mozilla. Possuía recursos para escalonamento elástico, preparado para cloud. Com ele era possível marcar um bloco <script> para rodar no cliente, no servidor ou em ambos. Como ele rodava em qualquer container Servlet/JSP, aproveitava recursos da VM para conexão com bancos de dados com prepared statement e tudo mais.

Bem, infelizmente, pouco se encontra do Jaxer hoje na Internet. Muitas outras iniciativas entre o IntraBuilder e o Jaxer aconteceram e curiosamente morreram antes de atingir a maturidade.

Por que alguém anteciparia a aposentadoria de um bom produto a ponto de explodir na indústria e no mercado antes da hora? Por que ninguém quer usar JavaScript fora do navegador?

A bola da vez é o Node.js. Tecnologia JavaScript side server que promete. Já nasce quebrando paradigmas. A idéia de que uma linguagem de programação tem seu sucesso dependendo de sua interação com bancos relacionais é uma delas. Node.js não se propõe a isso. É uma tecnologia para requisições massivas, mais próximo dos No SQL.

No Node.js, do lado do server, para criar uma API RESTful, você importa o módulo http com a instrução require, atribuindo-o a uma variável. Utiliza o método createServer do http para passar uma função anônima que recebe dois parâmetros request e response - há agora sim - e que tem uma propriedade listen, que recebe uma porta. Fica algo assim:

var http = require("http");

http.createServer(function(request, response){
    //Aqui eh a hora do show me the code...
}).listen(80);

Este exemplo é uma API RESTful. O código fica em um arquivo .js e executamos ele chamando o node na linha de comando passando o arquivo como parâmetro. Um servidor será criado ouvindo na porta 80.

O exemplo completo você vê aqui: http://www.ibm.com/developerworks/br/library/os-nodejs/

O Node.js é um paradigma novo, a idéia é um recurso do lado do servidor, rápido, assíncrono e sem bloqueio. Bancos relacionais são síncronos e com bloqueio, logo, Node.js não foi feito para bancos relacionais. O mundo do Node.js é Cloud + No SQL. Sacou?

Forte abraço, até o próximo post.

Mauricio da Silva Marinho

terça-feira, 30 de outubro de 2012

[JavaScript] Onde colocar o script?

Salve salve. Conforme prometido, segue o post (que já estava preparado, mas faz de conta que não), sobre onde colocar o bloco <script> na sua página.

Alguns podem estar se perguntando, mas que importância tem a localização do bloco <script>. Respondo: Muita!

É verdade. Muita coisa pode melhorar ou piorar quanto a performance de execução da sua página a depender da localização do seu javascript, acredite.

Para entender melhor, vamos falar um pouco sobre carga e execução da página.

Como você já sabe, sua página HTML é interpretada e executada pelo seu navegador (sério!?). Ocorre que - regra geral - ao encontrar blocos <script> a execução de HTML é interrompida para que o script seja carregado, interpretado e executado e só então a execução do HTML continua.

Como o processo que executa a página é o mesmo (HTML e JavaScript) - regra geral - não dá pra fazer as duas coisas ao mesmo tempo.

Ainda existe o problema de você carregar um script de manipulação de um elemento DOM antes da declaração do elemento em HTML. O resultado disto é que seu script não poderá manipular o objeto, pois ele ainda não existe, não foi interpretado e muito menos executado pelo browser.

Neste momento, é irrelevante se o código está declarado dentro da tag <script> ou em um arquivo externo .js referenciado no atributo src daquela tag. A página vai ter que esperar até que o código seja baixado, lido e executado.

A especificação do HTML 4 indica que <script> deve ficar em <head> ou <body> e pode aparecer várias vezes dentro destes dois elementos.

Tradicionalmente, as tags <script> são utilizadas para carregar arquivos .js e são posicionadas no <head> junto com tags <link> que carregam arquivos .css.

Pense no seguinte: O HTML só vai começar a ser renderizado, após todos os scripts referenciados serem baixados e executados. Se você permitisse que todo o conteúdo HTML fosse carregado antes dos scripts, talvez pudesse melhorar a percepção de performance da página. Lembre-se que os navegadores não começam a mostrar nada na página (fica em branco) até que cheguem na tag <body>. Se os scripts forem pesados, o delay da página em branco será maior e consequentemente a percepção de lentidão vai aumentar. Observe um exemplo hipotético de página com 3 scripts referenciados em seu <head> e o tempo de carga/execução de cada um deles:

  • arquivo1.js (500ms).
  • arquivo2.js (350ms).
  • arquivo3.js (400ms).

Movendo estas referências para o final da página, você irá ganhar mais de 1s no início da exibição do documento, o suficiente para melhorar a percepção de performance.

IE 8+, Firefox 3.5+, Safari 4+ e Chrome 2+ já permitem o download paralelo dos recursos externos, incluindo outros scripts. Mesmo assim, o download dos scripts irá concorrer com o download de outros recursos visuais da página e o cliclo de vida irá interromper a execução da página até que todos os scripts do <head> sejam executados.

Conclusão: Colocar os scripts mais próximos do rodapé da página, antes de </body>, pode melhorar a performance, este é o posicionamento recomendado, respeitando a ordem de dependência dos scripts. Ah! Muito importante: Mantenha os blocos <script> agrupados e compactados. Várias técnicas de compactação e agrupamento de scripts estão disponíveis, dentre elas a minificaçao e a concatenação de scripts por uma ferramenta de build como o Yahoo combo handler, que permite que você referencia mais de um script em uma mesma tag <script>, mas estes são assuntos para serem explorados em outra oportunidade.

Espero que estes conhecimentos lhe sejam úteis de alguma forma.

Forte abraço,

Mauricio da Silva Marinho.

[JavaScript] Scripts Dinâmicos

[JavaScript] Scripts Dinâmicos.

Com conhecimentos de DOM (Document Object Model) você pode criar praticamente qualquer parte do seu HTML dinamicamente, usando apenas JavaScript. O elemento <script> não é diferente. Referências podem ser recuperadas do DOM, modificadas, removidas ou até mesmo criadas. Um novo elemento <script> pode ser facilmente criado usando métodos do DOM da seguinte forma:

var script = document.createElement("script");
script.type = "text/javascript"; //desnecessario no HTML5
script.src = arquivo1.js;
document.getElementsByTagName("head")[0].appendChild(script);

Este novo elemento <script> carrega o arquivo arquivo1.js. O arquivo começa a ser transferido para o browser tão logo o elemento seja adicionado na página. Vale lembrar que a interpretação do HTML é interrompida cada vez que um elemento <script> é encontrado e retomada após a execução do código em <script>.

O interessante nesta técnica, é que o arquivo é transferido e executado sem bloquear outros processos na página, não importando onde o download tenha sido iniciado. Você pode colocar este código no <head> do documento sem afetar o resto da página.

OBS: Trataremos do melhor lugar para colocar o <script> no próximo post. Por enquanto, é mais seguro colocá-lo no <head> e não no <body>, especialmente se tratamos de um elemento <script> executado durante o carregamento da página. No IE, se o <script> estiver no <body> é possível receber um erro do tipo "operation aborted" se todo o conteúdo do <body> não estiver completamente carregado.

Quando um arquivo é carregado pela criação dinâmica de um nó <script> no DOM, o código transferido, geralmente, é executado imediatamente (ressalvas para o Firefox e Opera, que irão aguardar até que <script>'s anteriores sejam executados.

Isto funciona bem com scripts auto suficientes (sefl-executing), mas podem ser problemáticos se o código contém interfaces para serem usadas por outros scripts na página. Neste caso você precisa rastrear quando o código foi completamente carregado e está disponível para uso. Se não estiver utilizando JQuery, teremos que fazê-lo pelos eventos que podem ser disparados pelo <script>.

Firefox, Opera, Chrome e Safari 3+ disparam um load quando o src de um <script> for recuperado. Você pode programar uma notificação, atribuindo a este evento uma função anônima para ficar ouvindo-o:

var script = document.createElement("script");
script.type = "text/javascript";

//Firefox, Opera, Chrome, Safari 3+
script.onload = function(){
    alert("Script carregado!");
};

script.src = "arquivo1.js";
document.getElementsByTagName("head")[0].appendChild(script);

No IE, bom... no caso do IE, pra variar, é diferente. Este navegador suporta uma implementação alternativa que dispara um evento readystatechange. Existe uma propriedade readyState no <script> que é carregada várias vezes durante a transferência do arquivo referenciado em seu src. Existem cinco possíveis valores para esta propriedade, são eles:

  • uninitialized, que é o default.
  • loading, quando o download do arquivo começa.
  • loaded, quando o download do arquivo termina.
  • interactive, quando os dados já foram baixados mas ainda não estão completamente disponíveis.
  • complete, quando os dados baixados estão prontos para serem utilizados.

O IE mostra-se inconsistente com os valores loaded e complete. Por vezes ele irá atingir o estado loaded e vai parar, sem disparar o complete. Calma que ainda pode piorar: outras vezes ele vai atingir o complete sem passar pelo loaded.

Sendo assim, é preciso tratar os dois estados relevantes para o carregamento loaded e complete, removendo o event handler (a função anônima atribuída ao evento) quando qualquer um deles ocorrer, para evitar de tratarmos duas vezes a mesma coisa (Ê laiá):

var script = document.createElement("script);
script.type = "text/javascript";

//Internet Explorer
script.onreadystatechange = function(){
    if(script.readyState == "loaded" || script.readyState == "complete"){
        script.onreadystatechange = null; //remove o event handler
        alert("Script carregado, eu acho!");
    }
};

Espero que os conhecimentos deste post lhe sejam úteis. No próximo post veremos o melhor lugar para colocar nossos scripts na página. Forte abraço.

Fonte: High Performance Javascript (Build Faster Web Application Interfaces) - Kindle Version, Location 603. Adaptações e sarcasmos de Mauricio da Silva Marinho.

terça-feira, 9 de novembro de 2010

[Java] Criando templates com Facelets

Obs: As referências a bibliotecas de tags, xml, imports e configurações serão omitidas. O objetivo é apenas compreender a composição de um template.

Sabemos que é possível compor uma página JSP utilizando includes para melhor reaproveitar trechos de páginas que serão comuns em todo o site ou aplicação.

Com JSP é possível fazer isso pela tag <%@include%> ou ainda, utilizando-se dos recursos JSTL, por meio da construção c:import.

Interessante! Entretanto, estas abordagens podem nos trazer alguns problemas. Por exemplo, é impossível passar parâmetros, dinamicamente, da página que declara os includes para os arquivos incluídos. O recurso <jsp:param> não funcionará nem para o JSF, porque este recurso guarda conteúdo em escopo de página, o que não é suportado pelo JSF. Além disso, alguns containers poderão causar replicações inesperadas de conteúdo, executando uma instrução include mais de uma vez (ver ciclo de vida jsf). Estes problemas vão além de meros bugs da implementação de alguns containers.

O Facelets resolve estes problemas com mecanismo de template baseado em uma abordagem de passagem de parâmetros por EL e suporte completo ao modelo de componentes do JSF.

Veremos por meio de exemplos a composição de um template comum a uma aplicação hipotética, utilizando os recursos do Facelets.

Para um template, basta criar um arquivo xhtml e definir as áreas que serão substituídas quando o template for aplicado. Vamos exemplificar isto construindo um xhtml (vou chamar de meuTemplate.xhtml), informando ao template que o título, o cabeçalho e o conteúdo, serão voláteis, ou seja, irão mudar a cada página:

<head>
    <title>
        <ui:insert name=”titulo”>
          Aqui vai o titulo
        </ui:insert>
    </title>
</head>

<body>
    <ui:insert name=”cabecalho”>
      Aqui vai o cabeçalho
    </ui:insert>
    <ui:insert name=”conteudo”>
      Aqui vai o conteúdo
    </ui:insert>
</body>

Na página em que vamos usar o template, referenciamo-lo da seguinte forma:

<ui:composition template=”meuTemplate.xhtml”></ui:composition>

Redefinindo o valor das áreas voláteis da seguinte forma:

<ui:define name=”titulo”>
  Novo valor do título
</ui:insert>
<ui:define name=”cabecalho”>
  Novo valor do cabeçalho
</ui:insert>
<ui:define name=”conteudo”>
  Novo valor do conteúdo
</ui:insert>

Este é um exemplo muito simples do Facelets para a definição de templates, muita coisa mais sofisticada podemos fazer com estas tags. Saiba que existem outras e espero explorá-las aqui no blog em breve.

Referências:


Grande abraço.