Computação em nuvem (cloud computing)

Cloud computing, ou computação em nuvem, é uma tecnologia onde o processamento e armazenamento de informações digitais é feito em computadores remotos, interligados pela internet.

O problema da computação local

Tradicionalmente, o processamento e o armazenamento são feitos no seu próprio computador. Neste modelo, seus dados estavam fisicamente gravados no seu computador, ou seja, os dados estão gravados localmente. Caso seu computador (ou notebook) apresente algum defeito, é bem possível que esses dados sejam perdidos. E sim, os computadores falham com frequência. Se seus dados são importantes, mantenha cópias de segurança em computadores diferentes.

Os problemas dessa abordagem são os seguintes:

  • O processamento está limitado ao poder computacional do próprio computador. Mais processamento exige um computador mais potente.
  • A recuperação de desastres é complicada. Se a máquina falhar, você tem de reinstalar todos os softwares e recuperar os dados de cópias de segurança (backup>
  • A probabilidade de perda de dados é real e constante.

Computação em nuvem

Nesse novo modelo computacional os dados estão na internet, disponíveis de forma transparente para o usuário. Você não precisa saber onde os seus arquivos estão armazenados fisicamente, porque o importante é que eles estejam disponíveis a qualquer hora, em qualquer dispositivo, seja no computador, tablet, celular e nos smartwatches, que começam a se popularizar. É uma tecnologia muito prática e segura.

Computação em nuvem (fonte: Wikipedia)
Computação em nuvem (fonte: Wikipedia)

Os serviços em nuvem têm uma versão grátis (e limitada). Inclua aí o OneDrive, o Dropbox, o Box e o Google Drive para armazenamento. Caso precise de mais espaço, é só adquirir a versão paga, através de uma subscrição anual. Assim, seus dados estarão disponíveis em qualquer computador ou dispositivo móvel.

Aplicativos

A computação em nuvem ficou em evidência com o GMail, o primeiro serviço de e-mail que dava 1 GB de armazenamento para os usuários. Antes dele já existiam outros, mas a proposta de 1 GB era impressionante (para época). A partir daí, virou um caminho sem volta. Os serviços que não conseguiram disponibilizar ao menos 1 GB de espaço simplesmente fecharam.

Os aplicativos mais importantes em um computador pessoal doméstico são o editor de texto e planilha de cálculo. E estão disponíveis na web. Você pode usá-los sem precisar instalar nada na sua máquina. Google Docs, Office 365 e Zoho são os mais conhecidos e têm versões grátis (sim, limitadas). Também têm versões pagas que são usadas em empresas. Para o usuário comum, em casa, a versão grátis é mais que suficiente.

O Evernote é outro aplicativo que não abro mão. Você pode usá-lo para guardar todas as anotações importantes e organizar o cotidiano.

Essas são algumas das possibilidades da computação em nuvem. Há outras, claro.

  • Video – serviços como Youtube, Metacafe, Vimeo, Netflix e iTunes revolucionaram a distribuição de conteúdo audiovisual através do que chamamos de streaming.
  • Música – novamente, os CDs estão rareando pelo mesmo motivo. Deezer, Spotify e iTunes são opções bem em conta para ouvir música.

Esses são os serviços destinados aos usuários domésticos. Para empresas a situação é um pouco diferente. A demanda é outra e a solução são as nuvens corporativas, sejam elas públicas ou privadas. Praticamente todas as grandes empresas de tecnologia já oferecem o serviço. A primeira e principal é a Amazon, com seu fantástico AWS.

Conclusão

A computação em nuvem é relativamente nova, mas já tem muitas opções e pontos positivos. Merece atenção, tanto para usuários doméstico como corporativo. As oportunidades são enormes. A economia e praticidade proporcionada pela nuvem é um ponto a favor, enquanto a infraestrutura de internet (ao menos no Brasil) é um ponto negativo. Nesse sentido ainda precisamos evoluir um pouco. Para começar, minha sugestão é usar o Evernote e o Dropbox em sua versão grátis. Depois, o céu é o limite.

Curso de Hadoop

Muito têm sido falado sobre big data. Mas o que é, de fato, e o que pode trazer de benefício para sua empresa? Mais que isso, como podemos extrair valor dos dados armazenados na empresa? Essa é a proposta do big data, que veremos neste curso de Hadoop.

Curso de Hadoop

Este é um curso prático sobre Apache Hadoop, a implementação mais conhecida para soluções de Big Data e chegaremos a um nível intermediário no uso das ferramentas, suficiente para programar e configurar um ambiente de produção. Para tanto, temos roteiros de implantação do cluster e os passos necessários para criar soluções para as principais demandas de big data.

Hadoop
Apache Hadoop

O início do treinamento indica o caminho para começar a usar as ferramentas e tem um nível básico de dificuldade. Depois de vencida a barreira inicial, os alunos terão contato com Linux e Java em nível intermediário, chegando ao final do curso com conhecimento suficiente para fazer o planejamento da infraestrutura do cluster.

As aulas mostram quais os problemas que podemos resolver com Hadoop, como as análises de grandes volumes de dados, sempre utilizando dados públicos. Também veremos quais problemas o Hadoop não resolve e qual a ferramenta adequada nesse caso. No final teremos um projeto completo, onde iremos juntar todas as partes e criar uma solução big data integrada com bancos de dados relacionais.

Quando decidimos por adotar uma solução de big data, alguns critérios devem ser observados:

  • Estratégia para implementação – como a empresa deve ser preparada para a adoção do big data?
  • Métricas para comparação – como vamos comparar e decidir se a infraestrutura de big data trouxe resultados?
  • Análise de dados – que tipo de informação pode ser extraída do conjunto de dados?
  • Relatórios – como apresentar os resultados analisados?

O curso está disponível na Escola Linux, que disponibiliza vários outros cursos. O nosso curso de Hadoop está neste link.

Ementa

  • Big Data
  • Apache Hadoop 2.x
  • MapReduce
  • Instalação/administração do cluster
  • HDFS
  • YARN

Aulas

    As aulas estão divididas assim:

  • Aula 00: conceitos sobre big data e Hadoop
  • Aula 01: configuração do ambiente de desenvolvimento
  • Aula 02: Apache Hadoop MapReduce
  • Aula 03: instalação e configuração do cluster
  • Aula 04: O sistema de arquivos HDFS
  • Aula 05: YARN
  • Aula 06: Sqoop / Projeto final

O aluno

O público alvo esperado é composto por programadores, analistas de BI/ETL/DW, profissionais de infra-estrutura, gerentes de projeto, DBAs e Administradores de dados.

É interessante, mas não necessário, ter conhecimentos básicos sobre Linux e programação Java, pois os exemplos usam essa linguagem.

Depois do curso, o aluno estará apto a instalar um cluster Hadoop, administrar o sistema de arquivos, criar programas MapReduce e integrar sua aplicação com um banco de dados relacional.

Link para o curso

O curso está disponível aqui.

PrimeFaces

Como usar GraphicImage no Primefaces

PrimeFaces

Neste exemplo temos uma alternativa para usar o GraphicImage no PrimeFaces com JSF 2 para mostrar uma imagem gravada no banco de dados.

O GraphicImage é um componente prático porque elimina a necessidade de servlets ou outros artifícios para carregar a imagem.

Um ponto importante é que o GraphicImage não funciona com @ViewScope, que é muito usado nas aplicações com JSF 2. Ele funciona apenas com @SessionScope e @RequestScope. Para resolver esse problema, criei o ImagemProdutoBean, um managed bean com @RequestScope.

Código-fonte

O projeto completo está disponível no GitHub. Além do GraphicImage, o projeto mostra exemplos de outros componentes PrimeFaces, além de soluções simples para problemas comuns de aplicações web.

Persistência

No nosso exemplo vamos criar a classe Produto com o atributo byte[] foto, que deve ter a anotação @Lob. Em alguns bancos de dados temos que definir um tamanho desse arquivo, como é o caso do HSQLDB, que é usado no exemplo. No MySQL não é necessário.


public class Produto {
{...}
@Lob
@Column(length = 1024 * 1024 * 5)
private byte[] especificacaoFabricante;
@Lob
@Column(length = 1024 * 1024 * 5)
private byte[] foto;
{...}
}

JSF

A página produto.xhtml vai mostrar a imagem através do managed bean imagemProdutoBean.


{…}

id=”uploadfotoProduto” /> id=”uploadfotoProduto” /> actionListener=”#{produtoBean.salvar}” icon=”ui-icon-disk”
update=”messages” />

{…}

 

Managed bean

Precisamos de 2 managed beans. O primeiro, ProdutoBean, é para a página XHTML e tem escopo @ViewScoped. O segundo, ImagemProdutoBean é somente para a imagem e pode ser @RequestScoped ou @SessionScoped. Eu prefiro o @RequestScoped, mas fica a critério de cada um.

Observe o método salvar(), que deve ter uma condição para não apagar a imagem já gravada, no caso em que o usuário está fazendo a edição do registro.

Para esse exemplo, o ajax do upload está desabilitado. Para habilitar o ajax, você pode usar essa dica.


@ViewScoped
@ManagedBean
public class ProdutoBean {

{…}

private UploadedFile foto;
private Produto produto;

public void setFoto(UploadedFile foto) {
this.foto = foto;
}

public UploadedFile getFoto() {
return foto;
}

public boolean isExisteFoto() {
try {
return getProduto().getFoto().length > 0;
} catch (Exception e) {
return false;
}
}

public void salvar() {
try {
//
if (getEspecificacaoFabricante() != null
&& getEspecificacaoFabricante().getSize() > 0) {
byte[] dados = IOUtils.toByteArray(getEspecificacaoFabricante()
.getInputstream());
getProduto().setEspecificacaoFabricante(dados);
}
//
if (getFoto() != null && getFoto().getSize() > 0) {
byte[] dados = IOUtils.toByteArray(getFoto().getInputstream());
getProduto().setFoto(dados);
}
//
getProdutoService().salvar(getProduto());
infoMsg(MENSAGEM_SUCESSO_GRAVACAO);
} catch (Exception e) {
errorMsg(e);
}
}

}

GraphicImage no Primefaces

Essa é a abordagem mais simples para mostrar uma imagem no PrimeFaces. E pode ser usada no sistema todo.

Um detalhe é que o PrimeFaces executa duas vezes o método getConteudoImagem() e somente da segunda vez é que a imagem deve ser carregada.

 

package net.marcoreis.ecommerce.controlador;

import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseId;

import net.marcoreis.ecommerce.entidades.Produto;
import net.marcoreis.ecommerce.negocio.GenericService;

import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.StreamedContent;

@ManagedBean
@RequestScoped
public class ImagemProdutoBean extends BaseBean {
private static final long serialVersionUID = -7524476303834771432L;
private Produto produto;

@PostConstruct
public void init() {
produto = new Produto();
}

public StreamedContent getConteudoImagem() {
try {
FacesContext context = FacesContext.getCurrentInstance();
if (context.getCurrentPhaseId() == PhaseId.RENDER_RESPONSE) {
return new DefaultStreamedContent();
}
String idS = getParametro(“id”);
Long id = Long.parseLong(idS);
produto = (Produto) new GenericService()
.findById(Produto.class, id);
InputStream is = new ByteArrayInputStream(produto.getFoto());
DefaultStreamedContent dsc = new DefaultStreamedContent(is);
return dsc;
} catch (Exception e) {
return new DefaultStreamedContent();
}
}

}

Problema no wifi do Lumia 520

O Lumia 520 é o smartphone de entrada da Nokia e tem sido um grande sucesso de venda. Comprei o meu na blackfriday pela internet e esperei ansiosamente pela chegada. O problema é que quando chegou não consegui acessar a internet pelo wifi, problema que outros usuários também tiveram. Se estiver tendo problemas para acessar o wifi, mesmo configurando todos os parâmetros corretamente, provavelmente o procedimento abaixo irá resolver a questão.

E um smartphone não serve de nada sem internet. No site de suporte da Microsoft encontrei a solução para o problema.

Vá para o menu Configurações, opção sobre e lá embaixo, no final da tela, pressione o botão restaurar configuração de fábrica

Pronto. Agora é só esperar alguns minutos até que o telefone volte à configuração original. Em seguida, configure a conexão wifi que vai funcionar.

Processamento de texto com Java

Processamento de texto com Java

Java oferece um conjunto completo de funcionalidades para manipulação de caracteres e este artigo mostra de forma concisa e prática algumas dessas facilidades. Atualmente, Java e Python têm sido bastante usadas para processamento de texto, quando tratamos de cenários com um grande volume de dados.

Seguem alguns exemplos de projetos escritos em Java e que fazem processamento de grande quantidade de dados, textuais ou não:

  • Lucene
  • Hadoop
  • Mahout
  • Storm
  • OpenNLP

Introdução

O processamento de texto é uma área que vem crescendo, principalmente impulsionado pelas redes sociais, onde os dados não são estruturados como em um banco de dados relacional. Dados não tabelados, que anteriormente eram ignorados, têm hoje uma grande importância no mundo corporativo. O cruzamento de informações está se mostrando uma área lucrativa, por exemplo, no mundo financeiro. Mas todas as corporações podem se beneficiar. A análise do que está sendo produzido em uma organização pode revelar padrões, e essa informação muitas vezes não está gravada em tabelas.

Para ilustrar, vamos criar uma aplicação de exemplo que faz processamento de uma grande quantidade de dados. Esta aplicação vai utilizar os dados da Wikipedia, que disponibiliza uma versão grátis do seu conteúdo. A versão mais recente está disponível aqui.

Modelo de página da Wikipedia:


  <page>
    <title>Anno Domini</title>
    <ns>0</ns>
    <id>226</id>
    <revision>
      <id>35978308</id>
      <parentid>35629623</parentid>
      <timestamp>2013-06-03T14:20:50Z</timestamp>
      <contributor>
        <username>Albmont</username>
        <id>117075</id>
      </contributor>
      <comment>XXXXX</comment>
      <text xml:space="preserve">XXXXXX</text>
      <sha1>tf6la5j11avof8kav9wfj3l7yni7f9x</sha1>
      <model>wikitext</model>
      <format>text/x-wiki</format>
    </revision>
  </page>

O arquivo compactado deve ter aproximadamente 1GB e, após descompactado, deve ter algo em torno de 4GB. Ele contém todas as páginas da Wikipedia em português, mas apenas a última revisão, sem o histórico de alterações. Lembre-se que a Wikipedia é colaborativa e todos podem alterar as páginas livremente. Podemos fazer o download da versão completa, com o histórico de versões e outras opções aqui.

No final do texto de cada atributo “text” de uma página da Wikipedia há uma seção onde estão as categorias do artigo. Cada artigo tem uma ou várias categorias. Uma categoria é na verdade outra página, seguindo o modelo de hiperlinks.

Exemplo:


[[Categoria:Geomática]]
[[Categoria:Astronomia|Cronologia ]]
[[Categoria:Efemérides]]
[[Categoria:Calendários]]

2. O projeto

O projeto com o código-fonte está disponível no Github e utiliza as seguintes tecnologias:

  • XML (SAX)
  • StringBuilder
  • JDBC
  • Expressões regulares
  • Maven
  • MySQL

3. SAX

Com a API Simple API for XML, ou SAX, podemos construir um parser mais rápido e que utiliza menos memória que o DOM, Document Object Model, outra API bastante popular para XML. Dessa forma, é melhor usar SAX para arquivos grandes. O DOM carrega todo o conteúdo do arquivo em memória, e nesse caso estamos trabalhando com um arquivo de 4GB.

Para analisar um documento XML com SAX precisamos implementar ao menos os métodos:

  • startElement() e endElement(): métodos chamados no começo e fim de cada elemento do documento XML.
  • characters(): método chamado com o conteúdo de cada elemento, indicando a posição inicial e final de cada elemento.

O processamento é feito em quatro etapas:

  • Primeiro, as páginas são extraídas do XML com SAX.
  • Em seguida cada item é inserido no banco de dados através de JDBC.
  • Processar cada página e extrair as categorias.
  • Inserir as categorias no MySQL.

Cada item do XML é uma página da Wikipedia. Nesta aplicação vamos usar apenas alguns dos atributos. O script para geração das tabelas no MySQL com os atributos que precisamos está logo abaixo.

4. Scripts

O scripts abaixo são para o MySQL.


CREATE TABLE `PaginaWikipedia` (
  `id` int(11) NOT NULL DEFAULT '0',
  `title` varchar(255) DEFAULT NULL,
  `timestamp` datetime DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `text` longtext,
  `model` varchar(255) DEFAULT NULL,
  `format` varchar(255) DEFAULT NULL,
  `comment` longtext,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
)


CREATE TABLE `Categoria` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `descricao` text,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`)
)

5. Código-fonte

As classes Java que representam essas tabelas estão logo abaixo. Crie os getters e setters para PaginaWikipedia e CategoriaWikipedia. O código completo está no repositório do Github.

O que cada classe faz:

  • PaginaWikipedia: encapsula os atributos de cada artigo do XML.
  • CategoriaWikipedia: encapsula as categorias que vão ser extraídas das páginas através de expressões regulares.
  • DAOPaginaWikipedia: contém os métodos de acesso aos dados para a PaginaWikipedia.
  • DAOCategoriaWikipedia: o mesmo para a CategoriaWikipedia.
  • WikipediaSAXParserToJDBC: é responsável pela análise do XML e extração dos elementos que precisamos para criar nossa base de dados.
  • CategorizadorCategoria: utiliza expressões regulares para recuperar as categorias de cada página.
  • pom.xml: arquivo do Maven, com as bibliotecas e demais configurações.


public class PaginaWikipedia {
    private Long id;
    private String title;
    private Date timeStamp;
    private String userName;
    private String text;
    private String model;
    private String format;
    private String comment;
}


public class CategoriaWikipedia {
    private Long id;
    private String descricao;

    public CategoriaWikipedia(String descricao) {
  this.descricao = descricao;
    }
}


package net.marcoreis.wikipedia;

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Timestamp;

import org.apache.log4j.Logger;

public class DAOPaginaWikipedia {
    private static Logger logger = Logger.getLogger(DAOPaginaWikipedia.class);
    private Connection conexao;
    private String pwd = "";
    private String user = "root";
    private String url = "jdbc:mysql://localhost:3306/db_wikipedia";
    private String driver = "com.mysql.jdbc.Driver";

    public DAOPaginaWikipedia() {
  try {
      Class.forName(driver);
      conexao = DriverManager.getConnection(url, user, pwd);
  } catch (Exception e) {
      throw new RuntimeException(e);
  }
    }

    public void inserir(PaginaWikipedia pagina) {
  try {
      String sql = "insert into PaginaWikipedia (id, title, timestamp, username, text, model, format, comment) values (?,?,?,?,?,?,?,?)";
      PreparedStatement pstmt = conexao.prepareStatement(sql);
      pstmt.setLong(1, pagina.getId());
      pstmt.setString(2, pagina.getTitle());
      Date data = new Date(pagina.getTimeStamp().getTime());
      pstmt.setTimestamp(3, new Timestamp(data.getTime()));
      pstmt.setString(4, pagina.getUserName());
      pstmt.setString(5, pagina.getText());
      pstmt.setString(6, pagina.getModel());
      pstmt.setString(7, pagina.getFormat());
      pstmt.setString(8, pagina.getComment());
      int qtd = pstmt.executeUpdate();
      if (qtd != 1) {
    logger.error("Registro nao incluido -> " + pagina.getId());
      }
      pstmt.close();
  } catch (Exception e) {
      logger.error(e);
  }
    }

    public ResultSet findAll() {
  try {
      String sql = "select id, text from PaginaWikipedia";
      PreparedStatement pstmt = conexao.prepareStatement(sql,
        ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
      pstmt.setFetchSize(Integer.MIN_VALUE);
      ResultSet rs = pstmt.executeQuery();
      return rs;
  } catch (Exception e) {
      throw new RuntimeException(e);
  }
    }

    public void fechar() throws SQLException {
  conexao.close();
    }
}


package net.marcoreis.wikipedia;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.apache.log4j.Logger;

public class DAOCategoriaWikipedia {
    private static Logger logger = Logger
      .getLogger(DAOCategoriaWikipedia.class);
    private Connection conexao;
    private String pwd = "";
    private String user = "root";
    private String url = "jdbc:mysql://localhost:3306/db_wikipedia";
    private String driver = "com.mysql.jdbc.Driver";

    public DAOCategoriaWikipedia() {
  try {
      Class.forName(driver);
      conexao = DriverManager.getConnection(url, user, pwd);
  } catch (Exception e) {
      throw new RuntimeException(e);
  }
    }

    public void inserir(CategoriaWikipedia categoria) {
  try {
      String sql = "insert into Categoria (descricao) values (?)";
      PreparedStatement pstmt = conexao.prepareStatement(sql);
      pstmt.setString(1, categoria.getDescricao());
      pstmt.executeUpdate();
      pstmt.close();
  } catch (Exception e) {
      logger.error(e);
  }
    }

    public void fechar() {
  try {
      conexao.close();
  } catch (SQLException e) {
      throw new RuntimeException(e);
  }
    }

}


public class WikipediaSAXParserToJDBC extends DefaultHandler {
    private static String nomeArquivo = System.getProperty("user.home")
      + "/dados/ptwiki-20130817-pages-articles-multistream.xml";
    private static Logger logger = Logger
      .getLogger(WikipediaSAXParserToJDBC.class);
    private PaginaWikipedia pagina;
    private StringBuilder content = new StringBuilder();
    //Formato da data no dump da Wikipedia
    private SimpleDateFormat sdf = new SimpleDateFormat(
      "yyyy-MM-dd'T'HH:mm:ss'Z'");
    private int paginasIndexadas;
    private DAOPaginaWikipedia dao = new DAOPaginaWikipedia();

    public void startElement(String uri, String localName, String qName,
      Attributes attributes) throws SAXException {
  if (qName.equals("page")) {
      pagina = new PaginaWikipedia();
      content.setLength(0);
  } else if (qName.equals("title")) {
      content.setLength(0);
  } else if (qName.equals("timestamp")) {
      content.setLength(0);
  } else if (qName.equals("username")) {
      content.setLength(0);
  } else if (qName.equals("text")) {
      content.setLength(0);
  } else if (qName.equals("model")) {
      content.setLength(0);
  } else if (qName.equals("format")) {
      content.setLength(0);
  } else if (qName.equals("comment")) {
      content.setLength(0);
  } else if (qName.equals("id")) {
      content.setLength(0);
  }
    }

    public void characters(char[] ch, int start, int length)
      throws SAXException {
  content.append(String.copyValueOf(ch, start, length).trim());
    }

    public void endElement(String uri, String localName, String qName)
      throws SAXException {
  if (qName.equals("page")) {
      dao.inserir(pagina);
      paginasIndexadas++;
      // pagina = null;
      logAndamento();
  } else if (qName.equals("title")) {
      pagina.setTitle(content.toString());
  } else if (qName.equals("timestamp")) {
      try {
    Date timestamp = sdf.parse(content.toString());
    pagina.setTimeStamp(timestamp);
      } catch (ParseException e) {
    logger.error(e);
      }
  } else if (qName.equals("username")) {
      pagina.setUserName(content.toString());
  } else if (qName.equals("text")) {
      pagina.setText(content.toString());
  } else if (qName.equals("model")) {
      pagina.setModel(content.toString());
  } else if (qName.equals("format")) {
      pagina.setFormat(content.toString());
  } else if (qName.equals("comment")) {
      pagina.setComment(content.toString());
  } else if (qName.equals("id")) {
      if (pagina.getId() == null)
    pagina.setId(new Long(content.toString()));
  }
    }

    private void logAndamento() {
  if (paginasIndexadas % 10000 == 0) {
      logger.info("Parcial: " + paginasIndexadas);
  }
    }

    public static void main(String[] args) {
  new WikipediaSAXParserToJDBC().parse();
    }

    public void parse() {
  try {
      SAXParserFactory factory = SAXParserFactory.newInstance();
      factory.setNamespaceAware(true);
      SAXParser parser = factory.newSAXParser();
      parser.parse(new File(nomeArquivo), this);
  } catch (Exception e) {
      logger.error(e);
  }
    }
}


package net.marcoreis.wikipedia;

import java.sql.ResultSet;
import java.util.Collection;
import java.util.HashSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.log4j.Logger;

public class CategorizadorWikipedia {
    private static Logger logger = Logger
      .getLogger(CategorizadorWikipedia.class);
    private Pattern pattern = Pattern.compile("\[\[Categoria\:(.*?)\]\]");
    private DAOCategoriaWikipedia daoCategoria = new DAOCategoriaWikipedia();
    private DAOPaginaWikipedia daoPagina = new DAOPaginaWikipedia();
    private Collection<string> categorias = new HashSet<string>();

    public void criarCategorias() {
  try {
      int quantidadePaginasAnalisadas = 0;
      ResultSet rs = daoPagina.findAll();
      while (rs.next()) {
    String texto = rs.getString("text");
    Matcher matcher = pattern.matcher(texto);
    //
    while (matcher.find()) {
        String categoria = matcher.group(1);
        //
        if (categoria.contains("|")) {
      String subCategorias[] = categoria.split("\|");
      for (String subCategoria : subCategorias) {
          if (subCategoria.length() > 0)
        categorias.add(subCategoria.trim());
      }
        } else {
      categorias.add(categoria.trim());
        }
    }
    quantidadePaginasAnalisadas++;
      }
      logger.info("Quantidade de paginas analisados: "
        + quantidadePaginasAnalisadas);
      rs.close();
      daoPagina.fechar();
  } catch (Exception e) {
      logger.error(e);
  }
    }

    public static void main(String[] args) {
  CategorizadorWikipedia c = new CategorizadorWikipedia();
  c.criarCategorias();
  c.inserirCategorias();
    }

    private void inserirCategorias() {
  int quantidadeCategoriasCriadas = 0;
  for (String categoria : categorias) {
      daoCategoria.inserir(new CategoriaWikipedia(categoria));
      quantidadeCategoriasCriadas++;
  }
  logger.info("Quantidade de categorias criadas: "
    + quantidadeCategoriasCriadas);
  daoCategoria.fechar();
    }
}

pom.xml


<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>net.marcoreis</groupId>
  <artifactId>wikipedia-offline</artifactId>
  <version>0.1.beta</version>
  <dependencies>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.17</version>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.26</version>
    </dependency>
  </dependencies>

  <properties>
    <version.compiler.plugin>2.3.1</version.compiler.plugin>
    <version.surefire.plugin>2.10</version.surefire.plugin>
    <maven.compiler.target>1.6</maven.compiler.target>
    <maven.compiler.source>1.6</maven.compiler.source>
  </properties>
</project>

6. Processamento de texto

Esta é uma aplicação baseada em processamento de grandes quantidades de texto e que utiliza muitos objetos do tipo String. As Strings são classes fundamentais em Java, tanto que têm implementação levemente diferente das demais, pois tem seus próprios literais e operadores. Em uma aplicação típica, boa parte da memória e do processamento é usado com Strings, por isso é importante entender seu funcionamento.

A classe java.lang.String tem algumas características importantes que devem ser levadas em consideração.

  1. String é uma implementação imutável de CharSequence. Cada objeto String é uma cadeira de caracteres única.
  2. String é “thread safe”, o que gera um pouco mais de overhead.
  3. String é uma classe final, não permite subclasses.

Uma curiosidade: se o programador criar uma String com valor “marco” e depois criar novamente outra String com o mesmo valor, serão dois objetos em memória, mesmo que tenham a sequência de caracteres “marco”. Se isso acontecer em uma escala de milhões de objetos, pode haver impacto na performance da aplicação. Por isso, funcionalidades que criam muitas Strings devem ser tratadas com cuidado.

StringBuilder

Ao contrário da String, StringBuilder é uma implementação mutável de CharSequence. Ela contém um array de caracteres que pode ser redimensionado através de métodos como append(). Após adicionar o conteúdo, podemos usar o toString() para construir uma String baseada nos valores acumulados. Essa foi a classe escolhida para ser utilizada em WikipediaSAXParserToJDBC porque é mais eficiente para esse tipo de aplicação, onde há muita concatenação de Strings. No nosso exemplo, há uma reutilização do buffer, ao invés da criação de novos objetos em memória.

Para termos noção da diferença na utilização das duas abordagens foi criada a classe WikipediaSAXParserToJDBCComString, que faz a mesma coisa que WikipediaSAXParserToJDBC, mas utiliza String no lugar de StringBuilder. Seguem logo abaixo alguns testes realizados com as duas classes. Para repetir os tester você deve fazer um drop/create table na tabela PaginaWikipedia.

Testes

Para incluir 10000 registros com WikipediaSAXParserToJDBCComString:


20:14:41,455  INFO WikipediaSAXParserToJDBCComString:102 - Inicio
20:18:01,276  INFO WikipediaSAXParserToJDBCComString:92 - Parcial: 10000

Para incluir os mesmos 10000 registros com WikipediaSAXParserToJDBC:


20:18:42,847  INFO WikipediaSAXParserToJDBC:102 - Inicio
20:20:43,576  INFO WikipediaSAXParserToJDBC:92 - Parcial: 10000

A diferença de tempo é sensível entre as duas classes. Se utilizarmos String para o processamento a execução leva 3:20 minutos, enquanto que com StringBuilder leva 2:01 minutos. A diferença também pode ser visualizada através do profiler do VisualVM.

Na figura 1 o método characters, onde é feita a concatenação do conteúdo de cada elemento XML, é o segundo na lista de consumo de tempo da CPU quando utiliza String, ocupando por 42% do tempo de processamento, isso considerando a inclusão de 10000 registros.

Snapshot da CPU, processando os dados com String
Snapshot da CPU, processando os dados com String

Na figura 2 o método characters aparece apenas na sexta posição, ocupando a CPU por 683ms quando se utiliza StringBuilder, também considerando a inclusão de 10000 registros.

Snapshot da CPU, processando os dados com StringBuilder
Snapshot da CPU, processando os dados com StringBuilder

7. Considerações sobre performance

Para inclusão dos registros no banco de dados há muita atividade no disco. Em contrapartida, o processador fica bastante tranquilo. Conclusão: incluir registros no banco de dados é bastante custoso para o disco.

Com o processamento das expressões regulares praticamente não há atividade de disco, em compensação o processamento é bastante elevado. Concluímos assim que o processamento de expressões regulares é muito custoso para o processador, mas não para o disco.

8. Referência

Expressões Regulares
Java Regex Tutorial
Java Regular Expression Tutorial with Examples
Text Processing with Java
Working with Text

Como usar um POJO no selectOneMenu sem o converter

java
java
Aqui está um exemplo de como usar um POJO no selectOneMenu sem o converter. Assim, a gente economiza uma classe e já faz as associações no controlador, usando diretamente os objetos do JPA.


<?xml version="1.0" encoding="ISO-8859-1"?>
<!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:h="http://java.sun.com/jsf/html"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:p="http://primefaces.org/ui">

<h:head>
  <title>e-commerce</title>

  <style>
.ui-widget,.ui-widget .ui-widget .ui-panel-title {
  font-size: 90% !important;
}
</style>
</h:head>

<h:body>
  <h:form>
    <p:messages id="messages" />

    <p:spacer height="6px" />

    <p:panel header="Produto" style="margin-left: 30%; margin-right: 30%;">
      <p:panelGrid columns="2">

        <p:outputLabel value="Nome:" />
        <p:inputText value="#{categoriaBean.categoria.nome}" />

        <p:outputLabel value="Categoria:" />
        <p:selectOneMenu value="#{categoriaBean.categoria.id}">
          <f:selectItems value="#{categoriaBean.categorias}" var="item"
            itemLabel="#{item.nome}" itemValue="#{item.id}" />
        </p:selectOneMenu>

      </p:panelGrid>

      <f:facet name="footer">
        <p:commandButton value="Salvar" ajax="false" icon="ui-icon-disk" />
      </f:facet>
    </p:panel>

  </h:form>

</h:body>

</html>


package net.marcoreis.ecommerce.controller;

import java.util.Collection;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.persistence.EntityManager;

import net.marcoreis.ecommerce.entidades.Categoria;
import net.marcoreis.ecommerce.util.JPAUtil;

@ManagedBean
@RequestScoped
public class CategoriaBean {
    private Categoria categoria;
    private Collection<categoria> categorias;

    public void setCategoria(Categoria categoria) {
  this.categoria = categoria;
    }

    public Categoria getCategoria() {
  return categoria;
    }

    @PostConstruct
    public void init() {
  categoria = new Categoria();
  carregarCategorias();
    }

    public void carregarCategorias() {
  EntityManager em = JPAUtil.getInstance().getEntityManager();
  categorias = em.createQuery("from Categoria").getResultList();
  em.close();
    }

    public Collection<categoria> getCategorias() {
  return categorias;
    }
}

Lista de podcasts

java

O que é visualização de dados

Visualização de dados

A visualização de dados (data visualization) é uma área da computação que estuda maneiras de representar dados visualmente. Mais que isso, uma interface visual atraente pode estimular a atenção e imaginação da audiência. A idéia é comunicar os principais pontos de um conjunto complexo de dados de uma forma simples para o usuário.

Data visualization - Tag Cloud
Data visualization – Tag Cloud

É mais fácil para o ser humano identificar padrões em elementos visuais. Com os dados organizados visualmente podemos identificar informações ocultas, tendências, anomalias e exceções. Como consequência, passamos a mensagem de forma rápida. Estamos preparados para identificar certas propriedades como localização, tamanho, área, forma, cor e orientação. Ao invés de informar valores individuais como em tabelas, com uma representação visual podemos entender diversos valores de uma só vez, porque nossa percepção está mais atenta aos contrastes e padrões visuais já conhecidos.

A visualização de dados é bastante utilizada em ferramentas de business intelligence. Com isso as pessoas têm interesse de ver e interagir com a informação. Dados, por definição, são difíceis de entender. Por exemplo, um relatório com linhas e colunas é bem chato de ler, além de ser complexo para entender. Podemos utilizar ferramentas para resumir e mostrar graficamente esses dados e possibilitar que o usuário chegue a suas conclusões e tome decisões mais rápidas e acertadas na sua área de atuação.

A internet contribuiu para essa mudança (ou evolução). Um gráfico é mais interessante e informativo para o usuário do que centenas de palavras e, eventualmente, algumas imagens. O mundo está gerando cada vez mais informação e as técnicas de visualização de dados podem agilizar a análise desse conteúdo. De fato, estamos vivendo a era da informação e parece ser o momento certo para pensar sobre análise de dados.

Hoje há muitas ferramentas disponíveis tanto para a visualização como para a análise de dados. Abaixo, vemos algumas possibilidades para essa nova realidade, que é bastante promissora.

Many Eyes

O Many Eyes é um site da IBM para visualização de dados onde você pode enviar seu dataset e escolher o tipo de gráfico que será gerado. Na visualização abaixo, temos os dados do turismo na Austrália em Março/2013. Os países mais importantes nesse período foram a Nova Zelândia, China, Reino Unido e Estados Unidos.

Data visualization - turismo na Austrália
Data visualization – turismo na Austrália

Bitly

O Bitly é um encurtador de links (que eles chamam de bitmarks) e agora tem uma plataforma para análise de mídia social. O exemplo abaixo mostra as relações entre links onde ligações mais finas representam menos cliques. Pelo gráfico, podemos concluir que há pouca ligação entre “Química” e “Artes”, enquanto que há uma forte ligação entre “Tecnologia” e “Educação”.

Data visualization - Bitly
Data visualization – Bitly

Referências

Data-Driven Documents
Visual.ly
Many Eyes
Scientific American
Big Data Viz
Twitter (#dataviz)

Curso de big data

Curso de big data

Big data
Big data

Big data é o assunto do momento no setor de TI e a demanda por profissionais especializados está aumentando. Uma boa maneira de entrar nesse mercado é se matricular em um curso de big data. Não é exatamente o tipo de treinamento fácil de ser encontrado no Brasil, mas há algumas opções grátis e online. Os principais temas abordados nesses cursos envolvem, além do big data, machine learning, inteligência artificial, estatística e análise de dados.

O termo big data é usado quando nos referimos à grande quantidade de informação gerada atualmente pela humanidade. Redes sociais, dispositivos móveis, sensores, o governo e empresas privadas produzem uma infinidade de dados diariamente e a análise desses dados é uma ótima oportunidade para a TI. Ao mesmo tempo, é o seu maior desafio. Trata-se de muitos petabytes de dados não-estruturados gerados diariamente, incluindo textos, planilhas, vídeos e imagens. O desenvolvimento de ferramentas analíticas está evoluindo rapidamente com o objetivo de extrair dessa montanha de dados informações úteis para o mercado corporativo.

A educação, principalmente no mercado de TI, deve ser vista como uma ação contínua, onde a conclusão da faculdade é apenas um passo na formação do profissional. Novas tecnologias surgem frequentemente, sempre com o intuito de resolver os problemas cada vez mais complexos da sociedade e a universidade não consegue se atualizar com a mesma velocidade. Para aprender as novas ferramentas que trabalham com big data o profissional pode se basear em livros, artigos científicos e cursos.

Logo abaixo está disponível uma lista de cursos de big data e temas correlatos. Nesses cursos, mais do que aprender sobre big data, o profissional vai aprender sobre tecnologias avançadas.

Udacity

Há alguns anos, Sebastian Thrun e Peter Norvig da Universidade de Stanford ofereceram o curso “Introduction to Artificial Intelligence” online e gratuitamente. Mais de 190.000 alunos se matricularam e esse sucesso, logo depois, se transformou no Udacity. Hoje há mais de 200 cursos disponíveis e 1,3 milhão de alunos matriculados.

Big Data University

A Big Data University é um portal educacional que conta com usuários avançados de Hadoop, big data e DB2 dispostos aprender, contribuir com material de cursos ou oportunidades de emprego na área. O site conta com cursos grátis e pagos.

Coursera

A Coursera é uma empresa que oferece mais de 100 cursos online nas áreas de Ciências Humanas, Ciências Sociais, Matemática, Ciência da Computação, etc. Esses cursos são disponibilizados em associação com grandes universidades.

Referências

27 ways to learn online
Big Data, Trying to Build Better Workers
Começando a Aprender sobre Big Data
A Surge in Learning the Language of the Internet

Microsoft e Hadoop: usando Big Data na XBox Live

logo-hadoop
hadoop
Microsoft e Hadoop estão juntos numa ferramenta de Big Data chamada HDInsight que está rodando no Windows Azure. A empresa está utilizando Hadoop na análise de peta bytes de dados gerados pelo Halo 4 na XBox Live para aperfeiçoar a experiência do usuário.

A equipe de desenvolvedores do Halo 4 tinha a tarefa de descobrir as preferências dos jogadores para dar suporte ao torneio online. Para isso, tinham que analisar os dados disponibilizados no Windows Azure. Essa análise foi feita com o Hadoop e, como resultado, o serviço gera estatísticas usadas para classificar os melhores jogadores. Além disso, as estatísticas alimentam uma campanha por e-mail para aumentar a retenção dos usuários, entre outros benefícios.

O estudo de caso completo está disponível aqui.

Benefícios

Aumentar a agilidade e o tempo de resposta

Foi construído um sistema de configuração que pode ser ligado e desligado sem afetar a produção. Um cluster do Hadoop pode ser levantado em minutos, processar os dados e retornar as informações para a área de negócios em poucas horas.

Ajudar a equipe do Halo 4 a lançar atualizações semanais

Com os dados processados diariamente, é possível identificar tendências, como quais as características do jogo que são mais usadas e gerar atualizações semanais, tudo isso baseado nas preferências dos usuários, com o objetivo de atrair novos jogadores.

Ajudar a identificar fraudes

Com o Hadoop, os desenvolvedores podem focar mais em análise, já que o HDFS já resolve o problema do armazenamento de forma transparente. Com a análise, a equipe pode descobrir padrões de fraude em algumas partidas, notificando os jogadores das suspeitas e até mesmo removendo-os dos torneios.

Contribuir com a retenção dos jogadores

A solução fornece diversos relatórios para a equipe de marketing, que envia e-mails personalizados para cada tipo de jogador logo após os torneios. Novos jogadores, por exemplo, são notificados sobre características do jogo que ainda não conhecem.

Usar ferramentas conhecidas para simplificar tomada de decisões

A Microsoft começou a expandir o uso do Hadoop através do HDInsight Service para outras áreas. Para usar os dados gerados pelo Hadoop não é necessário ser um especialista. Os dados podem ser facilmente exportados para outras ferramentas já conhecidas como Excel e SharePoint.

Strata 2013

Neste vídeo, Dave Campbell, da Microsoft, explica como o Halo 4 está usando tecnologias Big Data.

Conclusão

O Apache Hadoop está evoluindo rapidamente e as possibilidades de uso ainda estão sendo descobertas. A equipe do Halo 4 está usando para remodelar a forma como se joga, fornecendo dados para várias áreas diferentes, como marketing, negócio e design, mas essas idéias podem ser usadas em qualquer organização.

Não é uma ferramenta que substitui as tecnologias atuais, mas sim que agrega valor a um custo relativamente baixo. No caso do BI, podemos processar rapidamente grandes bases de dados e fornecer informações para tomada de decisão mais ágil.