quinta-feira, 31 de março de 2016

Padrão Singleton "Double-checked" e Padrão Singleton "Instantâneo"

Padrão Singleton é bastante conhecido e usado como solução para diversas finalidades, onde por questão de controle, segurança e uso da memória desejamos ter apenas uma única instância de uma determinada classe, o que seria o exemplo de uma classe de configurações gerais de um sistema, não poderíamos ter um sistema estável sem garantir que existe apenas uma instancia com essas configurações.

Então abaixo vou mostrar um código de implementação de um singleton “Double-checked” que garante a unicidade da classe mesmo em um ambiente multithread e logo depois vou fazer algumas explicações.

public class MeuSingletonSincronizado{
     
      ... //outros atributos da classe

      private volatile static MeuSingletonSincronizado instance; //uso da palavra reservada volatile
     
      private MeuSingletonSincronizado (){
           
... //algo que preciso ser feito no construtor
     
}
     
      public static MeuSingletonSincronizado getInstance(){
           
            if(instance == null){ //primeira checagem
                 
                  synchronized (MeuSingletonSincronizado.class){
                       
                        if(instance == null){ //segunda checagem
                            
                             instance = new MeuSingletonSincronizado();
                       
                        }
                       
                  }
                 
            }
           
            return instance;
      }
     
      ... //outros métodos da classe

}

Vamos às considerações... Primeiro, o uso do modificador volatile na variável que guarda a instância do nosso singleton faz com que o java sinalize ao processador que este atributo sempre vai ser lido e escrito diretamente da memória principal ignorando o cache, evitando valores diferentes em ambientes multi-threads.


Porque usar a dupla checagem? Quando usamos esse modelo, observe que só sincronizamos a classe no método que retorna a instância enquanto houver a possibilidade de essa instância ser nula, depois disso, não há necessidade dessa sincronização. Isso faz com que ganhemos performance e segurança de que só haverá uma instância da classe.

Já na opção instantâneo, o que muda é que inicializamos a instância do singleton no momento da declaração da variável. O problema é que dependendo do que o seu singleton fizer e da quantidade de classes do tipo singleton que você codificar isso pode trazer um consumo maior de memória, pois o objeto será instanciado no momento que a classe for lida pela JVM mesmo que não venha a ser usada...

public class MeuSingletonSincronizado{
     
      ... //outros atributos da classe

      Private final volatile static MeuSingletonSincronizado instance = new MeuSingletonSincronizado();
     
      private MeuSingletonSincronizado(){}// construtor
     
     
      public static MeuSingletonSincronizado getInstance(){
                 
            return instance;

      }
     
      ... //outros métodos da classe

}

terça-feira, 29 de março de 2016

Paginação de dados com Hibernate e Primefaces

     Esse post sobre paginação com hibernate, considero que você já tenha seu DAO, ManagedBean, o Bean e a página XHTML feita, e quer apenas mudar a forma como os dados são trazidos do banco, melhorando dessa forma o desempenho do sistema.

Para fazermos paginação com o Hibernate, precisamos preparar a camada View (Páginas XHTML) para lidar com essa paginação. No caso do primefaces, isso é bem simples. Vamos analisar como fica o componente <p:dataTable> de forma a trabalhar com a paginação:

<p:dataTable id="carroTable" paginator="true" rows="20" lazy="true" paginatorAlwaysVisible="false" paginatorPosition="bottom" var="carro" value="#{pesquisaCarroBean.lazyCarros}" rowsPerPageTemplate="10,20,50"
emptyMessage="Nenhum carro encontrado." style="margin-top: 20px" >

      ...

<p:dataTable>

         A propriedade paginator=”true” indica que haverá um paginação, e mesmo que não fizéssemos a parte de paginação na camada  Model, o primefaces conseguiria paginar os dados trazidos para esse dataTable, porém, mesmo a exibição estando paginada, todos os dados estariam carregados em memória. Daí a importância de fazermos realmente a paginação dos dados, mudando a forma como esses dados são trazidos do banco de dados, que é o que vamos ver mais a frente nesse post.

         A propriedade paginatorAlwaysVisible=”false” serve para que o paginador aparece apenas quando houver dados suficientes para serem paginados. O paginatorPosition=”bottom” informa a posição que a paginação será exibida. A propriedade rows=”20” indica quantas linhas serão exibidas por default, já a propriedade rowsPerPageTemplate=”10,20,50” é responsável por permitir a customização da quantidade de linhas visualizadas.

         Porém, a propriedade lazy=”true” é quem realmente faz o componente do primefaces entender que haverá uma paginação real dos dados. Com isso, podemos passar para a camada Model.

       Precisamos criar uma classe responsável por fazer o meio de campo entre o componente do primefaces que será paginado e o método responsável por buscar a consulta paginada usando o hibernate. Vamos começar criando a classe LazyCarro, que criei dentro de um novo pacote chamado lazy_model dentro da minha hierarquia de pacotes. Segue o código:

public class LazyCarro extends LazyDataModel<Carro> implements Serializable{

      private static final long serialVersionUID = 1L;
     
      private CarroDAO carroDAO;
     
      public LazyCarro(CarroDAO carroDAO) {
            this.carroDAO = carroDAO;
      }
     
      @Override
      public List<Carro> load(int first, int pageSize,
                  String sortField, SortOrder sortOrder, Map<String, Object> filters) {
           
           
            List<Carro> carros = carroDAO.buscarTodosPaginado(first, pageSize);
           
            this.setRowCount(carroDAO.pegarQuantidadeDeCarros().intValue());
           
            return carros;
      }
     
}

        Essa classe estende a classe LazyDataModel do primefaces, e tem uma implementação bem simples. Preste bastante atenção quanto ao método load que deve ser sobrescrito, que deve ser o segundo e não o primeiro. Note que os dois métodos que chamamos do carroDAO (buscarTodosPaginado(first, pageSize) e pegarQuantidadeDeCarros()) precisam ser criados, então vamos adicioná-los a classe CarroDAO.

public List<Carro> buscarTodosPaginado(int primeiroDigito, int segundoDigito){
      return em.createQuery("FROM Carro", Carro.class)
                  .setFirstResult(primeiroDigito)
                  .setMaxResults(segundoDigito)
                  .getResultList();
}

public Long pegarQuantidadeDeCarros(){
      return em.createQuery("SELECT count(c) FROM Carro c", Long.class)
.getSingleResult();
}

Agora que já temos tudo feito na camada model, vamos a camada Controller que é responsável por fazer a ligação entre a View e a Model. Na classe PesquisaCarroBean vamos adicionar o objeto do tipo LazyCarro que será inicializado no método init que possui a anotação @PostConstruct e também o seu método getter para que a página XHTML possa ter acesso.

@ManagedBean
@ViewScoped
public class PesquisaCarroBean implements Serializable{
private LazyCarro lazyCarros;
      ...
public LazyCarro getLazyCarros() {
      return lazyCarros;
}
      ...
@PostConstruct
public void init(){
      lazyCarros = new LazyCarros(new CarroDAO);
...
}
      ...
}

         Pronto, com isso já temos uma consulta paginada. Caso apareça um erro informando e o “Lazy loading não foi implementado”, sugiro que verifique o método load que você sobrescreveu na classe LazyCarro, checando os parâmetros com estes:

load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters){...}


Qualquer dúvida, pode deixar nos comentários que tentarei ajudar no que for possível...

quinta-feira, 24 de março de 2016

Calendar do Primefaces em Português

       O primefaces é uma biblioteca fantástica, porém não sei por que eles não já deixaram padrão a parte de tradução dos componentes pelo menos para as principais linguagens distribuindo os aqruivos junto com o .jar. Já que não vem por padrão, cabe a nós fazermos essa configuração que é bastante simples.

         Primeiro vamos criar um arquivo chamado locale-primefaces.js Java com o seguinte código:

PrimeFaces.locales['pt'] = {
    closeText: 'Fechar',
    prevText: 'Anterior',
    nextText: 'Próximo',
    currentText: 'Começo',
    monthNames:['Janeiro','Fevereiro','Março','Abril','Maio','Junho''Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
    monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun', 'Jul','Ago','Set','Out','Nov','Dez'],
    dayNames: ['Domingo','Segunda','Terça','Quarta','Quinta','Sexta','Sábado'],
    dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
    dayNamesMin: ['D','S','T','Q','Q','S','S'],
    weekHeader: 'Semana',
    firstDay: 0,
    isRTL: false,
    showMonthAfterYear: false,
    yearSuffix: '',
    timeOnlyTitle: 'Só Horas',
    timeText: 'Tempo',
    hourText: 'Hora',
    minuteText: 'Minuto',
    secondText: 'Segundo',
    ampm: false,
    month: 'Mês',
    week: 'Semana',
    day: 'Dia',
    allDayText : 'Todo o Dia'
};


         Guarde esse arquivo na pasta js dentro de resources em webapp:


Adicione as suas páginas ou no seu template a chamada ao arquivo:

<h:outputScript library="js" name="locale-primefaces.js"/>

Agora, basta nos componentes <p:calendar> usar a propriedade locale e informar o valor “pt” como mostrado abaixo:

<p:calendar id="dataDevolucao" value="#{novoAluguelBean.aluguel.dataDevolucao}" pattern="dd/MM/yyyy HH:mm" mask="true" locale="pt" />



Links úteis:

Formatação de campos de valor Monetário

        Trabalhar com valores monetários em páginas WEB é meio chato, porém vou mostrar duas maneiras de facilitar esse trabalho, uma é do próprio primefaces, e outra é com JQuery, que funciona em qualquer aplicação web, bastando configurar corretamente.

         Primeiro vamos a solução com primefaces, que é uma biblioteca de extensão que deve ser adicionada ao projeto. Vamos então configurar no arquivo pom.xml o seguinte:

<dependencies>
    ...   
    <dependency>
        <groupId>org.primefaces.extensions</groupId>
        <artifactId>primefaces-extensions</artifactId>
        <version>4.0.0</version>
    </dependency>
    ...
</dependencies>

         Depois, temos que adicionar na página xhtml o namespace da extensão do primefaces no topo da página:

xmlns:pe="http://primefaces.org/ui/extensions"

         E então podemos usar a biblioteca de extensão para formatarmos os componentes que guardarão valores monetários.

<pe:inputNumber id="valor" value="#{meuManagedBean.valor}" symbol=" R$" 
symbolPosition="s" decimalSeparator="," thousandSeparator="." decimalPlaces="2/>

Caso dê algum erro de conversão, você pode adicionar o seguinte componente:

<pe:inputNumber id="valor" value="#{meuManagedBean.valor}" symbol=" R$"
symbolPosition="s" decimalSeparator="," thousandSeparator="." decimalPlaces="2>

<f:convertNumber maxFractionDigits="2" minFractionDigits="2"/>

</pe:inputNumber>

Agora vamos fazer a biblioteca JQuery-MaskMoney. Basta fazer o download da biblioteca no link http://plentz.github.io/jquery-maskmoney, lá tem o arquivo zip para baixar. Então crie o diretório “js” dentro da pasta resources em webapp como mostra a imagem a seguir:



Se você trabalha com templates do facelets basta adicionar isso no cabeçalho do template, se não, terá que adicionar nas paginas que irá precisar. Dentro do header coloque:

<h:outputScript library="js" name="jquery.maskMoney.js"/>

      Dentro do body, no final crie a função:

<script>

function configurarMoeda(objeto){
$(objeto).maskMoney({decimal: ",", thousands: ".", allowZero: true, symbolStay: "R$"});
       }
      
</script>
        
         Então basta chamar no componente que deseja usar da seguinte forma:
 
<p:inputText id="valorUnitario" value="#{meuManagedBean.valorUnitario }" 
onfocus="configurarMoeda(this);">
        <f:convertNumber maxFractionDigits="2" minFractionDigits="2"/>
<p:inputText>


     Se você não trabalha com primefaces, no link do download do JQuery-MaskMoney você vai encontrar ajuda para usar a biblioteca. Abraços!
            
ATENÇÃO! <pe:inputnumber> foi removido das extensões do PF e agora faz parte do pacote principal, então nas versões mais recentes, simplesmente substitua <pe:inputNumber> por <p:inputNumber>.

Links úteis: