Erro 104: Connection reset by peer

Já me deparei com esse erro algumas vezes durante meus anos de experiência com web e quase sempre ele traz consigo uma confusão tremenda pois à nível de protocolo HTTP, ele pode siginificar uma infinidade de coisas. Entretanto, quando estamos falando de sites dinâmicos que rodam no lado do servidor, como ASP.NET, as causas são mais simples (e infelizmente mais comuns do que se imagina) de serem mitigadas e não devem causar espanto em programadores de qualquer nível, bastando um pouco de atenção aos detalhes.

O que é?

O browser cliente estava conectado com o servidor e por algum motivo esta conexão foi interrompida subitamente, seja por decisão de um lados ou uma falha no meio de comunicação.

O que tem a ver com meu código?

Quando você desenvolve código que derruba a pilha de memória do processo que está executando sua aplicação, esse erro ocorre pois o servidor não esperava por isso e o processo é encerrado.

Como resolvo?

Basta reescrever o código que está causando o estouro da pilha. Simples assim. Ok, como eu não sou tão sádico, aqui vão algumas dicas para ajudar a tornar esta tarefa mais fácil:

Em primeiro lugar, qual foi a última alteração que você realizou no código antes desse problema começar a acontecer? Qualquer coisa, por mais inofensiva que pareça pode ocasionar isso, principalmente aqueles códigos que você escreveu e colocou direto no ar, sem testar, porque eram muito triviais.

Enumere as alterações que fez e uma a uma, e vá revisando seu código. Você deve revisar principalmente os algoritmos que envolvem um ou mais casos abaixo:

  • algoritmos recursivos (i.e. métodos que chamam eles mesmos)
  • laços de repetição (principalmente while, que é mais fácil de dar problema)
  • sobrecarga de operadores (muito úteis para objetos, mas perigosos também)
  • palavra reservada “goto” (evite usar, afinal não estamos programando em Assembly…)
  • tratamento de erros (try/catch) que tentam refazer a tarefa que deu errado

Essas dicas cobrem mais de 90% dos casos mais comuns de “Connection reset by peer” causados por mau funcionamento de código.

Como prevenir?

Pode parecer óbvio, mas para alguns programadores não é: teste. Nunca mande nada para produção sem testar antes, e de preferência, de forma unitária, isto é, somente o método que foi alterado, de forma independente do restante do sistema. Obviamente se você usar TDD, será muito fácil identificar os problemas logo que eles são desenvolvidos e antes de ir para o ar, pois esse tipo de erro não passaria nos testes automatizados.

Espero ter ajudado, e se alguém salvou o seu pescoço por causa desse post, não me importo se agradecerem nos comentários!

Ciclo de palestras na FAQI e demais projetos

ion>Post com minha participação na Jornada Acadêmica da FAQI Porto Alegre e resumo dos demais projetos.

Nesta segunda e terça-feira tive a oportunidade de conhecer a FAQI de Porto Alegre, graças ao contato do Prof. João Moreira, coordenador do curso de Análise e Desenvolvimento de Sistemas da instituição. Nos conhecemos na minha última visita à FAQI Gravataí, onde palestrei sobre Cloud Computing, palestra esta que eu e meu colega da RedeHost, Cristiano, temos ministrado em mais de uma dezena de instituições pelo Rio Grande do Sul afora. Desta vez não foi diferente, nossa presença na instituição foi para estreitar ainda mais os laços entre RedeHost e FAQI, enquanto empregadores e educadores.

Eu apresentando a RedeHost pro pessoal

Com esta palestra, provavelmente terá encerrado minha participação em eventos acadêmicos este ano, uma vez que estamos chegando em dezembro, e com ele, o recesso das instituições de ensino. Não que isto signifique o encerramento de minhas atividades relacionadas à ensino, já estão engatilhados novos cursos de desenvolvimento, em cima de plataformas mais tradicionais, como o curso recém organizado de C# Nível 2 que deve estreiar na Facensa no verão e principalmente, minhas estréia como ministrante de cursos em cima de mobilidade, com plataformas como Android, Windows Phone 7 e iOS (bom, quem acompanha o blog sabe do que estou falando!). Embora oficialmente eu não tenha fechado com nenhuma instituição (estou no aguardo de algumas confirmações), considero que 2012 será um grande ano para meus estudos nestas plataformas e que conseguirei alguns bons contratos enquanto instrutor.

2ª dia de palestra na FAQI

E por fim, hoje estive conversando com o Prof. Heitor Boeira, coordenador do curso de Análise e Desenvolvimento de Sistemas da FAQI Gravataí, para montarmos a agenda de cursos de extensão de 2012, desta vez focados em Linux e Virtualização, com os instrutores e colegas Diego Voltz e Cristiano Diedrich. Em contrapartida, a FAQI finalmente fechou conosco o tão aguardado convênio educacional, onde colaboradores da RedeHost terão desconto nos cursos de gradução e pós-graduação na instituição. Com isso, nossos profissionais terão mais um benefício oferecido pela empresa e mais uma motivação para estudarem. Outras parcerias estão em vias de serem fechadas, mas é cedo para comentar ainda…

Hoje o post foi curto, nada de tutorial ou algo do gênero, apenas o uso deste espaço para divulgar meu trabalho. Tenha uma boa semana!

Criando uma app Android com banco de dados SQLite

Android + SQLite

Este post é antigo, caso queira ler um tutorial novo com exemplo completo de CRUD usando SQLite em Android, consulte este post aqui!

Hoje o post irá tratar de um assunto muito importante: persistência de dados. Todas as aplicações que lidam com um grande volume de dados devem ter algum mecanismo de persistência, geralmente um banco de dados, para garantir a segurança, confiabilidade e integridade dos mesmos. O Android possui um mecanismo nativo, chamado de SQLite (o mesmo utilizado pelo Corona SDK, iOS e muitas outras plataformas móveis) que provê funcionalidades de banco de dados para suas aplicações. Iremos ver algumas dessas funcionalidades neste post, de uma maneira bem simples, mas que servirá como base para estudos futuros.

Veremos neste artigo:

Banco de dados no Android

Para cumprir com muitas das atividades oferecidas pelos celulares modernos, como busca de contatos, eventos, e tarefas, o sistema operacional e as aplicações estar aptos a manter e rastrear grandes quantidades de dados. A maior parte destes dados está estruturado como uma planilha, na forma de linhas e colunas. Cada aplicação Android é como uma ilha por si só, e cada aplicação somente consegue ler e escrever dados criados por ela mesma, mas muitas vezes é necessário compartilhar dados além de suas fronteiras. Existem classes e interfaces Java para que o Android possa se comunicar com a base de dados relacional SQLite. Estes recursos suportam uma implementação de SQL rica o suficiente para qualquer coisa que você queira em uma aplicação mobile, incluindo facilidades como cursores.

Caso esteja buscando por acesso remoto à banco de dados, dê uma olhada nesse post.

Base de Dados SQLite

Dados são melhores armazenados em um formato de base de dados relacional se ela puder incluir muitas instâncias de um mesmo tipo de dado. Pegue uma lista de contatos, por exemplo. Existem muitos contatos, todos com os mesmos tipos de informação (endereço, telefone, etc). Cada “linha” de dados armazena informações sobre uma pessoa diferente, enquanto cada “coluna” armazena um atributo específico de cada pessoa: nomes em uma coluna, endereços em outra coluna, e telefone em uma terceira.

Android usa a engine de base de dados SQLite, uma auto-contida, engine transacional que não requer um processo de servidor para funcionar. Ele é usado por muitas aplicações e ambientes além de Android, e é desenvolvido por uma grande comunidade.

O processo que inicia a operação de base de dados, como um SELECT ou UPDATE, faz o trabalho necessário de leitura e escrita no disco que contém a base de dados visando completar a requisição. Com SQLite, a base de dados é um simples arquivo no disco. Todas as estruturas de dados formando uma base de dados relacional – tabelas, views, índices, etc. – estão contidas neste arquivo.

SQLite não é um projeto do Google, embora o Google contribua com o mesmo. SQLite tem um time internacional de desenvolvedores dedicados a melhorar as capacidades do software e sua confiabilidade. Alguns desses desenvolvedores trabalham full time no projeto.

Confiança é a característica chave do SQLite. Mais de metade do código do projeto é devotado à testes. A biblioteca é desenvolvida para lidar com muitos tipos de falhas de sistema, como pouca memória, erros de disco, e falhas de energia. Em nenhum caso a base de dados pode ficar em um estado irreparável: isto é uma grande preocupação em um telefone onde muitos dados críticos são armazenados em bases de dados. Se a base de dados fosse suscetível a corrupção de arquivos, o telefone estaria em sérios apuros quando a bateria acabasse…

Este post irá tratar dos percalços para se criar uma aplicação muito simples que consuma dados no SQLite e não se aterá à sintaxe SQL propriamente. Muito pouco de orientação à objetos e arquitetura de software será usado aqui, mantendo toda a lógica de acesso à dados em uma única classe chamada ContextoDados.java como segue (ela ainda não está completa, iremos construindo-a ao longo do post):

Estrutura Básica da classe ContextoDados

Em nosso exemplo, a classe ContextoDados encapsula completamente toda a lógica SQL necessária para trabalhar com a base de dados. Todas as outras classes na aplicação não possuem acesso aos dados diretamente, usando ContextoDados como um acesso central ao banco. Esta é uma prática de programação interessante que pode ser aplicada nas suas aplicações Android que utilizem base de dados.

Antes de aprofundarmo-nos nos detalhes da aplicação em si, é importante entender o funcionamento da classe ContextoDados. Esta classe herda de SQLiteOpenHelper, e sobrescreve (override) os métodos onCreate e onUpgrade. O método onCreate é automaticamente chamado quando a aplicação roda pela primeira vez; sua tarefa é criar a base de dados. Como novas versões da aplicação podem ser lançadas, a base de dados pode ser atualizada também, uma tarefa que dispara o método onUpgrade. Quando você entrega uma nova versão da base de dados, você também deve incrementar a versão, como irei explicar rapidamente a seguir.

E por fim, o método ExecutarComandosSQL é um método para facilitar a execução de comandos SQL múltiplos, que apenas chama os comandos nativos do Android para execução de comandos SQL.

A classe ContextoDados utiliza uma string constante (que fica no arquivo strings.xml): R.string.ContextoDados_onCreate com o scripts de criação do banco de dados. Esta string está abaixo e não passa de um SQL comum, que você já deve estar acostumado e que poderia estar em variáveis String normais:

Lendo dados da base

Existem muitas maneiras de ler dados de uma base SQL, mas todos eles fazem uma sequência básica de operações:

  1. Cria um comando SQL que descreve os dados que você deseja retornar
  2. Executa o comando na base de dados
  3. Mapeia os dados SQL resultantes em uma estrutura de dados que a linguagem que você está utilizando possa entender.

Este processo pode ser muito complexo no caso de um software de mapeamento objeto relacional, ou relativamente simples quando escrevendo as consultas diretamente em sua aplicação. A diferença é a fragilidade. Ferramentas complexas de ORM protegem seu código das complexidades inerentes às bases de dados e o mapeamento de objetos, movendo esta complexidade para eles mesmos. O resultado é um código mais robusto face às alterações na base, mas ao custo de mais complexidade na configuração e manutenção do ORM.

A iniciativa de escrever consultas diretamente na sua aplicação trabalha bem somente para projetos bem pequenos que não irão mudar muito com o passar do tempo. Aplicações com código de base de dados são muito frágeis devido às alterações da mesma, pois todo o código que referenciava um elemento alterado deve ser examinado e potencialmente reescrito.

Uma técnica “meio-termo” é capturar toda a lógica de base de dados em um grupo de objetos cujo único propósito é traduzir as requisições da aplicação em requisições de banco de dados e entregar os resultados de volta para a aplicação. Esta opção é a utilizada em nossa aplicação de teste utilizando a classe ContextoDados.java.

Android nos dá a habilidade de personalizar cursores, e eu usarei essa característica para reduzir dependências de código escondendo toda a informação sobre uma operação de dados específica dentro d eum cursor personalizado. Cada cursor personalizado é uma classe dentro da classe ContextoDados, no nosso caso, somente o ContatosCursor.

Desta forma, criei um método RetornarContatos, cuja função é retornar um ContatosCursor preenchido com contatos da base de dados. O usuário pode escolher (através de um simples parâmetro) para ordenar os contatos por Nome crescente ou decrescente (este código vai dentro da classe ContextoDados criada anteriormente):

Tela de listagem

Como o foco deste post não é a criação de um layout ideal para exibição de dados, criei um bem simples que utiliza um TextView para mostrar os dados do banco concatenando strings. O código XML abaixo mostra como deve ser codificado o layout main.xml e a imagem mostra como ele deve se parecer:

E o código Java a seguir mostra o início da codificação da Activity principal, que mantém o nome padrão de MainActivity.java (este código vai dentro do corpo da classe MainActivity):

Neste trecho de código podemos ver as chamadas aos métodos CarregarLista (mostrado abaixo) e mais a seguir implementaremos o CarregarInterfaceCadastro:

Este código nada mais faz do que concatenar strings em um TextView para simular uma listagem de dados vindos do banco. Com o código que vimos até agora, já é possível listar os dados que já estão no banco, mas provavelmente você irá querer escrever também, que veremos na próxima parte!

Escrevendo no Banco de Dados

Voltando ao ContextoDados, o trecho de código a seguir insere um novo registro no banco de Contatos e serve como exemplo para futuras inserções em outras tabelas (este código vai dentro da classe ContextoDados):

Cadastro.xml - Como deve se parecer

E agora devemos criar o layout para a tela de cadastro, que chamei de cadastro.xml. A seção a seguir mostra o código XML para o layout, e a imagem à direita, como ele deve se parecer se tudo estiver correto:

Note que neste layout temos alguns EditTexts e dois botões. O botão de cancelar apenas retorna à tela inicial, com a listagem tosca de contatos. Já o botão de salvar, deve invocar o método de inserir novo registro, da classe ContextoDados. O código restante da MainActivity está abaixo, para que você possa copi-colar:

O código é auto-descritivo, mas caso tenha alguma dúvida, não hesite em perguntar pelos comentários.

Conclusões

Este post mostrou o básico de seleção e inserção de dados, com uma exibição bem tosca, longe de ser a ideal para uma base de dados. Você pode realizar o download dos fontes completos do projeto no link abaixo. Posts futuros devem cobrir outros aspectos da persistência de dados, como deleção e atualização, bem como listagem profissional dos dados usando ListViews personalizadas e dicas de boas práticas com SQLite.

Mas isto fica pra próxima!

* OBS: curtiu o post? Então dá uma olhada no meu livro de Android clicando no banner abaixo pra aprender a criar outros tantos apps incríveis!

Criando apps para empresas com Android