quarta-feira, 5 de dezembro de 2012

keytool: java.lang.IllegalArgumentException: unknown format type at

Salve galera..

Ai vai um negócio muito louco! Ao tentar gerar o fingerprint do keystore debug para uma aplicação android, e ter acesso ao google maps, tinha como retorno a seguinte mensagem:

 keytool: java.lang.IllegalArgumentException: unknown format type at

Para gerar o fingerprint devemos usar a versão 6 do jdk. Se geramos com a versão 7 do jdk não teremos problemas com a geração, mas ela não vai validar na página do google, apresentando a seguinte mensagem:

A digital inserida n�o � v�lida. Pressione o bot�o Voltar no navegador e insira uma digital certificada v�lida.

Então, para corrigir o primeiro erro temos que alterar, no painel de controle em Opções Regionais e Idiomas

Padrões e Formatos: Estados Unidos
Local: Estados Unidos


Com isso passa a funcionar. Sei que isso é muito tosco estranho, mas é a solução que encontrei.

Até a próxima!

sexta-feira, 16 de novembro de 2012

Task List

Salve galera!

Através desse post estou divulgando o lançamento de um novo produto da Mobile Mind. Um produto simples, porém muito útil, chamado "Task List", que tem uma simples missão: Ser uma lista de tarefas. 


Por se tratar de um serviço voltado a produtividade, sua usabilidade é extremamente simples, para que você não perca muito tempo lançando uma tarefa.

Onde e por que usar o Task List?

Você está fazendo aquela planilha chata, cheia de cálculos e então lembra que deve mandar um e-mail importante, mas você não pode fazer isso no momento. Então você abre o navegador e em poucos segundos lança a tarefa para lembrar mais tarde.
Você está almoçando e tem aquela ideia que vai revolucionar o mundo. Então você pega seu celuar ou tablet e escreve sua ideia para mais tarde dar continuidade.

Simples assim, a sincronização entre os dispositivos e o site é automática. Você ainda pode usar  a função reminder, para que o aplicativo avise você sobre sua tarefa. Abaixo algumas telas do serviço:

Nova Tarefa Android
 Lista de Tarefas Android

 Opções de Tarefa Android

 Configurações
Função Alarme Android
Lista de Tarefas Web

Nova Tarefa Web


Oficialmente a versão ainda não está liberada, mas é possível testar a versão beta que ainda está  em fase de ajustes e pequenas correções. O uso do serviço não tem custo algum. Você apenas deve se cadastrar em http://www.mobilemind.com.br/taskLis. 

A aplicação para android você pode baixar no Google Play, no link Task List.

Se você quiser receber novidades sobre esse e outros produtos da Mobile Mind, você pode se cadastrar no site http://www.mobilemind.com.br para receber novidades.

A Mobile Mind espera que esse produto possa tornar sua vida um pouco mais fácil.

Até a próxima!

segunda-feira, 29 de outubro de 2012

Import external jar in grails application

Salve galera,

Dica útil!! Para adicionar um jar externo em um projeto grails, basta colocar o jar na pasta lib do projeto, e depois executar o comando

grails compile --refresh-dependencies 

E fico por aqui! Até a próxima

MongoDB com Autenticação

Salve galera,

Vamos ver como configurar o banco de dados MongoDB com autenticação.

 Siga os comando abaixo:

mongo
use admin
db.addUser('username','password')
use myDataBase
db.addUser('username','password')

Atenção! é necessário a criação do banco admin. Altere o usuário e senha por seus respectivos valores, e o myDataBase pelo nome do seu banco de dados.

Agora edite o arquivo mongod.conf. Geralmente ele fica em /etc/mongod.conf, mas caso você não tenha esse arquivo, aqui vai um configurado:

dbpath=/lib/data/db
logpath=/var/logs/mongod.log
logappend=true
bind_ip=127.0.0.1
port=27017
auth=true 

O que define que o banco irá solicitar autenticação é o parametro

auth=true

Agora você apenas precisa reiniciar o serviço do banco:

service mongod restart


Ou se você está rodando o mongod apartir do console:

mongod --config /caminho_doarquivo/mongod.conf


E era isso pessoal, espero que ajude.

Install MongoDB on CentOS

Salve galera,

Uma pequena dica de instalação do MongoDB no CentOS.

 Criae o arquivo /etc/yum.repos.d/10gen.repo:


64 bits

[10gen]
name=10gen Repository 

baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/x86_64
gpgcheck=0
enabled=1


32 bits

[10gen]
name=10gen Repository
baseurl=http://downloads-distro.mongodb.org/repo/redhat/os/i686
gpgcheck=0
enabled=1

depois
yum install mongo-10gen mongo-10gen-server

O arquivo de configuração será criado em /etc/mongod.conf

O serviço

   service mongod start
   service mongod stop
   service mongod restart


Referência:
http://docs.mongodb.org/manual/tutorial/install-mongodb-on-redhat-centos-or-fedora-linux/

quarta-feira, 24 de outubro de 2012

Grails exclude dependency

Salve galera,

Aqui vai uma dica de como remover uma dependência indesejada de um projeto Grails, na hora de gerar o .war.

No arquivo BuildConfig.groovy adicione:
grails.war.resources = { stagingDir, args ->
    delete(file: "${stagingDir}/WEB-INF/lib/slf4j-api-1.5.5.jar")
} 
Simples não? Até a próxima!

segunda-feira, 15 de outubro de 2012

Warning: This jar contains entries whose certificate chain is not validated.

Salve galera,

Mais um erro que me atormenta pela segunda vez.. e como era de se esperar, eu não lembrava o que tinha feito para resolver, pois quando achei a solução da primeira vez, não documentei. Ao assinar um jar, a seguinte mensagem é exibida:

Warning: This jar contains entries whose certificate chain is not validated.

Tive problemas com isso ao publicar um apk no Google Play. Se publicar um apk que gerou essa mensagem de aviso, ao instalar ou atualizar a aplicação no Android, é exibida uma mensagem de erro de assinatura. A solução é alterar a versão do Java, para que a compilação e assinatura do jar seja feita com o jdk6.

e era isso, espero que ajude.

até a próxima!

segunda-feira, 8 de outubro de 2012

Android + Netbeans

Salve galera,

Se você é como eu e não gosta muito do eclipse nem mesmo para desenvolvimento Android, uma alternativa é instalar o plugin do Android para o Netbeans.
A instalação do plugin é bem simples. Vá no menu Ferramentas > Plugins > Definições, adicione uma nova central de instalação, que pode ser:

Agora vá na aba em Plug-ins Disponíveis > Verificar Atualização. Ná lista aparecerá os plug-ins do Android. Então é só selecionar e instalar. Após a instalação, estará concluído! Você já terá uma opção para criar projetos Android.

Até a próxima

sexta-feira, 28 de setembro de 2012

Gerenciador de Senhas

Salve galera,

Aqui vai uma dica de app útil para Android. É uma app bem simples, que criei para suprir uma necessidade própria.. e achei interessantes compartilhar ela no google play.

  Gerenciador de Senhas

"Dificuldades em controlar e lembrar-se de todos os dados de acesso a sites, conta bancaria, e-mails e outros? Esse aplicativo resolve seu problema lembrando você de todas as suas senhas no momento em que você precisa. Mantenha suas senhas seguras e sempre a mão com esse aplicativo. Requer autenticação de acesso para manipular e visualizar as senhas."

A aplicação requer autenticação, para ter a certeza de que é você mesmo que está visualizando as senhas. O campo login não é obrigatório, e depois de um tempo percebi que ele pode ser usado para salvar as letras que compõem a senha da conta bancária.

Como disse, ela é bem simples e útil, e o melhor de tudo..  é gratuíta! Vale a pena testar!!

Segue o link para o download Gerenciador de Senhas.



Até a próxima!


quarta-feira, 26 de setembro de 2012

Glassfish - Secure Admin must be enabled to access the DAS remotely.

Salve galera,

Após a instalação do Glassfish, quando você tentar acessar o painel administrativo remotamente, você vai se deparar com a seguinte mensagem:

Secure Admin must be enabled to access the DAS remotely. 

Como liberar o acesso? 

1º Passo - Entre na pasta bin do glassfish e pare o servidor caso ele esteja rodando. Execute o seguinte comando:

$ ./asadmin stop-domain

2º Passo - Execute o seguinte comando e defina uma senha 

$ ./asadmin change-master-password

3º Passo - Inicie o servidor com o seguinte comando

$ ./asadmin start-domain

4º Passo - Defina uma senha administrativa, para acesso remoto

$ ./asadmin change-admin-password

5º Passo - Faça a liberação para acesso remoto

$ ./asadmin enable-secure-admin 


E agora o acesso remoto está liberado! espero que ajude =D

até a próxima!

sábado, 8 de setembro de 2012

Redimensionar Imagem em Java

Salve galera,

Quem aqui nunca precisou pegar uma imagem de 2000x1800 e colocar em um espaço de 500x500? É exatamente esse problema que esse post vem resolver. Na verdade, precisamos fazer um calculo ninja jedi para conseguir escalar a imagem.
Esse calculo consiste em:
  • Descobrir o que é menor na imagem, se é a altura ou a largura.
  • Caso existir um lado menor, descobir seu percentual em relação ao lado maior.
  • Agora em cima do espaço disponível (500x500)temos que tirar o percentual calculado anteriormente do menor lado da imagem.


Se a imagem já tiver altura igual a largura, nada será feito.

Então aqui está ele, o calculo, pronto para uso.


class ImageResizerService {
 
    public byte[] read(String file) {
        byte[] buffer = new byte[1024];

        InputStream is = new FileInputStream(file);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        while (is.read(buffer) != -1) {
            out.write(buffer);
        }
        try {
            return out.toByteArray();
        }finally {
            is.close()   
            out.close()            
        }
        
    }

    public byte[] read(String file, double requiredWidth, double requiredHeight) {


        BufferedImage imagem = ImageIO.read(new File(file));

        double originalWidth = imagem.getWidth();
        double originalHeight = imagem.getHeight();
        double newWidth = 0;
        double newHeight = 0;
        double diff = 0;

        if (requiredHeight == 0) {
            requiredHeight = requiredWidth;
        }

        if (requiredWidth == 0) {
            requiredWidth = requiredHeight;
        }

        if(originalWidth < requiredWidth && originalHeight < requiredHeight){
            return read(file)
        }

        if(requiredWidth == 0 && requiredHeight == 0){
            return read(file)
        }

        if (originalWidth > originalHeight) {
            diff = originalWidth - originalHeight;
            newWidth = requiredWidth;            
            diff = diff / originalWidth;
            newHeight = newWidth - (newWidth * diff);
        } else if (originalWidth < originalHeight) {
            diff = originalHeight - originalWidth;
            newHeight = requiredHeight;            
            diff = diff / originalHeight;
            newWidth = newHeight - (newHeight * diff);
        } else {

            if (requiredHeight > requiredWidth) {
                requiredHeight = requiredWidth;
            } else if (requiredHeight < requiredWidth) {
                requiredWidth = requiredHeight;
            }

            newHeight = requiredHeight;
            newWidth = requiredWidth;
        }



        int type = BufferedImage.TYPE_INT_RGB;
        boolean isPng = file.toUpperCase().endsWith("PNG")

        if (isPng) {
            type = BufferedImage.BITMASK;
        }


        BufferedImage new_img = new BufferedImage((int) newWidth, (int) newHeight, type);
        Graphics2D g = new_img.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.drawImage(imagem, 0, 0, (int) newWidth, (int) newHeight, null);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        if (isPng) {
            ImageIO.write(new_img, "PNG", out);
        }else{
            ImageIO.write(new_img, "JPG", out);
        }

        try {
            return out.toByteArray();
        } finally {
            out.close();
        }
    }

}


Se esse é o melhor ou mais fácil algoritimo não sei, desenvolvi ele apartir da minha necessidade, e até o momento não tive problemas com "deformação" de imagens. Ah, e notem que caso seja solicitada uma um tamanho maior do que o tamanho da imagem existente, ele não faz nada, pois o objetivo é não perder a qualidade da imagem. E caso o tamanho solicitado seja menor do que a imagem existente mas não obedeça suas proporções, ele manterá a proporção, não obedecendo as medidas silicitadas, sempre nivelando por um dos valores (altura ou largura). Nesse caso, pomos sempre passar ou só largura, ou só altura.

Até a próxima!

Apache mascarando porta do Glassfish

Salve galera,

Uma situação muito comum para quem desenvolve aplicações que executam em um container java, como Glassfish ou Tomcat, é a necessidade de "mascarar" a porta do container atrás de um servidor web tradicional. Vou tentar explicar melhor.
Normalmente, subimos nosso container em uma porta diferente da 80, que é a porta web padrão, como por exemplo na porta 8080. Então para o usuário acessar nossa aplicação, ele precisa conectar em http://www.minhaempresa.com.br:8080/MinhaAplicacaoJava. Isso pode gerar alguns problemas, como o usuário não fixar a url do sistema, ou se confundir na hora da digitação, além de se tornar menos profissional, ao meu ver.
O objetivo proposto no artigo, é poder acessar a aplicação no seguinte endereço:
http://www.minhaempresa.com.br/MinhaAplicacaoJava. Sendo que teremos um servidor web apache rodando na porta 80 e um servidor java Glassfish rodando na porta 8080.

Depois de pesquisar um pouco, percebi que a maneira mais simples e transparente para atingir o objetivo, era instalar um módulo no servidor apache para tal funcionalidade. O nome do módulo é mod_jk.

Vamos  a instalação

Ambiente ondo foi implementado:

  • Glassfish 3.1.2.2 (build 5).
  • CentOS Linux release 6.0 (Final)
  • Java 7 build 1.7.0_01-b08
  • Apache 2.2.15
  • Tomcat Connectors 1.2.37

A única dependência que tive que instalar no linux foram gcc-c++ e httpd-devel, pois deu problema na compilação do conector. Caso você tenha o mesmo problema, aqui mostro como instalar no Centos:
$ yum install gcc gcc-c++ autoconf automake
$ yum -y install httpd-devel
Ubuntu
$ sudo apt-get install libapache2-mod-jk


Para fazer o processo no ubuntu, você pode acessar: http://recklessdeveloper.blogspot.com.br/2011/06/apache-e-glassfish-301-com-modjk-no.html

O conector você pode baixar em: http://tomcat.apache.org/connectors-doc/. Como eu baixei o source, então tive que compilar. A complilação é bem simples. Você deve descompactar os fontes do mod_jk, entrar na pasta e executar os seguintes comandos:
cd native/
$ ./configure --with-apxs=/usr/sbin/apxs
$ make
$ make install


Após a compilação e instalação, você deve criar o arquivo de configuração. No meu caso, ele foi criado em:
$ /etc/httpd/conf/workers.properties


Esse arquivo deve ter o seguinte conteúdo:
worker.list=worker1
worker.worker1.type=ajp13
worker.worker1.host=localhost
worker.worker1.port=8009


Observação: Essa porta não precisa estar liberada externamente caso os dois servidors estejam rodando na mesma maquina.

Agora devemos configurar o httpd.conf:

LoadModule jk_module modules/mod_jk.so

JkWorkersFile conf/workers.properties
JkLogFile /var/log/mod_jk.log
JkLogLevel debug
JkLogStampFormat "[%a %b %d %H:%M:%S %Y]"
JkOptions +ForwardKeySize +ForwardURICompat -ForwardDirectories
JkRequestLogFormat "%w %V %T"
JKMount /MinhaAplicacaoJava/* worker1



Em JkWorkersFile configuramos o arquivo criado anteriormente. Em JKMount configuramos o contexto da nossa aplicação no Glassfish. Você pode adicionar varios pontos de montagem, um para cada aplicação.

Agora precisamos avisar o Glassfish que ele vai ouvir as requisições desse cara. Entre na pasta bin do Glassfish e execute os seguintes comandos:

$ ./asadmin create-http-listener --listenerport 8009 --listeneraddress 0.0.0.0 --defaultvs server jk-connector

$ ./asadmin set configs.config.server-config.network-config.network-listeners.network-listener.jk-connector.jk-enabled=true

$ .asadmin create-jvm-options  -Dcom.sun.enterprise.web.connector.enableJK.propertyFile=domain-dir=/etc/httpd/conf/workers.properties



E pronto. Agora reinicie o Apache e o Glassfish e pode testar. Caso não funcione, verifique o arquivo de logs gerado em /var/log/mod_jk.log.

Até a próxima! vlw

sexta-feira, 24 de agosto de 2012

Download de Arquivos com Grails

Fala galera!

Neste post, vou mostrar com disponibilizar um arquivo para download com Grails, e como disponibilizar a visualização de uma imagem qualquer fora dos recursos do projeto.


    //Model
    class Arquivo{
       String file
    }
  
    //Controller
    def show(){
        def item = Arquivo.get(params.id)    
        def arquivo = grailsAttributes.getApplicationContext().getResource("/images/image-not-found.png").getFile().toString()

        if(item != null){
            def base = '/var/www/htdocs/imagens'
            def file = new File(base, item.file)

            if(file.exists()){
               arquivo = file.getAbsolutePath()
            }                
        }
        response.outputStream << readImage(arquivo)                     
    }

    def download(){
        def item = Arquivo.get(params.id)            

        if(item != null){
            def base = '/var/www/htdocs/arquivos'
            def file = new File(base, item.file)

            if(file.exists()){
                file.getAbsolutePath()                
                response.setContentType("application/octet-stream")
                response.setHeader("Content-disposition", "attachment;filename=${file.getName()}")
                response.outputStream << file.newInputStream()
                return
            }                
        }    
        
        render view: 'link-quebrado'
    }

     public byte[] readImage(String file) {
        byte[] buffer = new byte[1024];

        InputStream is = new FileInputStream(file);
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        while (is.read(buffer) != -1) {
            out.write(buffer);
        }
        return out.toByteArray();
    }

Agora vamos a explicação.

Primeiramente criamos a classe Arquivo, que será reponsável por identificar o arquivo solicitado. Nessa caso, recebemos o arquivo via upload, e disponibilizamos ele para download ou como visualização de imagem.

Disponibilizando uma imagem:

A Closure show é usada para visualização de uma imagem. Nela recuperamos a imagem solicitada, através do id do arquivo. Armazenamos a imagem em um array de bytes, e jogamos ela pra dentro do outputStream. O link será algo mais ou menos assim. Caso a imagem não exista, é disponibilizada uma imagem padrão.


   

Simples?! Isso é Grails!

Disponibilizando um arquivo para download:

A Closure download é usada para fazer o download do arquivo solicitado. Nela recuperamos o arquivo solicitado, lemos seu conteúdo e adicionamos no outputStream. Caso o arquivo não exista, é renderizado uma pagina padrão de link quebrado.

Simples?! Isso é Grails!

E com isso, concluímos os ensinamentos =D

Até a próxima!

Upload de arquivos em Grails - Parte 2

Fala galera!

Nesta poste irei continuar com o assunto upload de arquivos com Grails. No primeiro post vimos como salvar o arquivo no banco de dados, e agora vamos ver como salvar esse arquivo em disco. Como tudo no Grails é simples, isso não poderia ser diferente. Então vamos ao que interessa.  

Importânte: Lebrando que temos que ter o atributo do multipart no g:form para funcionar.
def create(){
  //Todo código de criação aqui

  upload('/var/www/htdocs/imagens')

}

//Closure que salva o arquivo em disco
def upload = { path ->

     def fileName = params.arquivo.originalFilename
     def file = request.getFile("arquivo") //arquivo é o id do componente type=file

     if(!file.empty){
      file.transferTo(new File(path, "${fileName}"))
     }
}

Simples assim! No próximo post, vamos ver como recuperar esse arquivo, disponibilizando ele para download ou em img (no caso de imagens).

Até a próxima!

Upload de arquivos em Grails

Fala galera..

Aqui vai uma útilidade, simples e fácil. Nos últimos dias venho me aventurando com Grails, e já estou bem inclinado a mudar minha linguagem web número 1 de Java para Groovy, usando o Grails! São  inúmeras as facilidades nesse framework, sem contar a linguagem dinâmica e produtiva. Neste poste vou mostrar uma delas. Já perdi algumas horas fazendo essa mesma tarefa em Java, pois precisamos de bibliotecas de terceiros, configuração no web.xml e tudo mais. Com grails não, em poucos mínutos, sem ter ne noção de como funcionava, consegui configurar. Vamos lá!

Primeiramente, na classe de modelo você precisa ter um campo do tipo array de bytes (supondo que você vai gravar a imagem no banco)

class User{
   String name
   byte[] avatar
   
   static constraints = {
       avatar(size:0..131072, nulable: true)
   }
}


Se gerarmos as views automáticamente, o upload já vai estar pronto para o uso, assim:

grails create-controler User
grails generate-all User

Caso o campo seja configurado manualmente em uma tela existente, temos que adicionar na tag g:form o seguinte valor:

enctype="multipart/form-data"


Ex.:


Esse parâmetro é quem faz toda a mágica. Sem ele, nosso upload não vai funcionar.

Aqui o campo para download, que fica na tela:


   



Isso já será o suficiente para fazer o upload de uma imagem. Um detalhe importante, é que na edição do registro, quando não informado nenhum avatar, o valor existente é substituido por nada. Então, o interessantes é testarmos isso no método edit.


def oldAvatar = userInstance.avatar

userInstance.properties = params

if(!userInstance.avatar){
    userInstance.avatar = oldAvatar;
}

E pronto. O avatar já está sendo carregado e salvo no banco de dados. No próximo post, vou mostrar como salvar esse arquivo em disco, caso não queira salvar no banco de dados.


Até a próxima!

terça-feira, 5 de junho de 2012

Alterar senha padrão Glassfish

Salva galera! Aqui vai uma dica de como alterar o passowrd padrão do glassfish após sua instalação. O password padrão é changeit.

 Para alterar, entre no console administrativo do glassfish e dê o seguinte comando

change-master-password

Ele vai pedir a senha atual e a nova senha.

E era isso! até a próxima.

quinta-feira, 10 de maio de 2012

Apache + PHP + .htc

Salve galera,

Na construção de um site, precisei usar alguns recursos avançados de css3. Dito isso, contarei brevemente minha historinha triste. Eu estava bem belo e feliz construindo o site e testando no firefox (normal), após deixar ele do com a cara que eu queria, como todo bom desenvolvedor, comecei a fazer os testes em resoluções diferentes e com navegadores diferentes. Como era de se esperar, e não é novidade pra ninguém, tentem adivinhar em qual deu incompatibilidade?! Alguém? Se alguém "chutou" Internet Explorer, está redondamente certo.

O efeito que eu estava aplicando é como esse, que podemos gerar no site http://css3pie.com/, para arredondar os cantos de uma div e colocar sombra, dando um efeito bacana.

Como tudo tem uma solução, descobri que tem uma gambiarra um pack de arquivos que adicionamos no servidor para funcionar no nosso amigo IE =)

Mas como nada é tão simples quanto deveria, temos que adicionar uma configuração no nosso servidor Apache, para ele reconhecer a extensão .htc, e ai sim corrigir o bug para o IE.

Primeiro temo que baixar o arquivo em:

http://cloud.github.com/downloads/lojjic/PIE/PIE-1.0beta5.zip

Depois temos que colocar o arquivo PIE.htc dentro da pasta onde temos nossos arquivos css.

O próximo passo é configurar o servidor para reconhecer esse arquivo:

No Slackware edite o arquivo /etc/httpd/mime.types, e adiciona a seguinte linha:

text/x-component .htc

No CentOS, edite o arquivo /etc/apache/conf/httpd.conf

AddType text/x-component .htc


Agora só reinicie o Apache e parta para o abraço!
Para testar, podemos usar o código gerado no site http://css3pie.com/.

Ex.:

 

.cssClass{

border: 1px solid #696;
padding: 60px 0;
text-align: center; width: 200px;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
-webkit-box-shadow: #666 0px 2px 3px;
-moz-box-shadow: #666 0px 2px 3px;
box-shadow: #666 0px 2px 3px;
background: #EEFF99;
background: -webkit-gradient(linear, 0 0, 0 bottom, from(#EEFF99), to(#66EE33));
background: -webkit-linear-gradient(#EEFF99, #66EE33);
background: -moz-linear-gradient(#EEFF99, #66EE33);
background: -ms-linear-gradient(#EEFF99, #66EE33);
background: -o-linear-gradient(#EEFF99, #66EE33);
background: linear-gradient(#EEFF99, #66EE33);
-pie-background: linear-gradient(#EEFF99, #66EE33);
behavior: url('PIE.htc');

}





Até a próxima

domingo, 6 de maio de 2012

WP7 Unit - Testes Unitários para Windows Phone

Salva galera,

Através desse poste, gostaria de informar o porte da API de testes unitários desenvolvida para Android, chamada Droid Unit, para sua versão Windows Phone. Ela tem mesmo objetivo que a versão Android, o objetivo de fornecer uma maneira muito simples de realizar testes unitários em aplicações para Windows Phone. Agora podemos realizar os testes da mesma maneira, tanto em aplicativos para Android ou para Windows Phone, e mantermos um bom nível de padronização em portes de apps.

Ela funciona da mesma maneira que a versão Android, inclusive em sua simplicidade. Como na versão para Android, na versão para Windows Phone o projeto está sendo liberado a créditos da Mobile Mind, e também espera obter feedback dos usuários.

Area OpenSource da Mobile Mind:

http://www.mobilemind.com.br/open-source.php

Página do projeto no CodePlex:

http://wp7unit.codeplex.com/

ScreensShot de um caso de teste funcionando



Até a próxima!

Droid Unit - Testes Unitários para Android

Salve galera,

Através desse poste, gostaria de comentar um sobre projeto que dei início a alguns mêses.. mas somente agora liberei como um projeto livre, a créditos da Mobile Mind. Se trata de uma simples e pequena API de testes unitários para o sistema operacional Android, ou para aplicativos desenvolvidos para Android. Essa API, apesar de ser "ridiculamente" simples, tem tudo o que esperamos em um teste unitário:

  • Garantia de consistência do código
  • Nos dá o feedback do que está acontecendo
Bom, poderiamos agregar inúmeras coisas a essa API, e justamente por esse motivo, seu projeto está sendo liberado como Open Source.. Então, se alguém se interessar em melhorar o projeto, ou até mesmo usar a api, fique a vontade, e se possível, dê seu feed back sobre o projeto.

Na página inícial do projeto, tem uma explicação de como a API é usada. É tão simples que pode ser explicada em algumas linhas. Hoje a Mobile Mind está usando ela em vários projetos, e astá satisfeita com seus benefícios.

Área OpenSource Mobile Mind:

http://www.mobilemind.com.br/open-source.php

Página do projeto no Google Code:

http://code.google.com/p/mobilemind-droid-unit/


ScreensShot de um caso de teste funcionando






Até a próxima!

quinta-feira, 3 de maio de 2012

Client Restfull Jersey

Salve galera!

Gostaria de compartilhar a solução de um erro que tive a poucos dias, e que me fez perder algumas horas...

Quando eu tentava converter uma lista no formato JSON em objeto, usando a api Jersey, era apresentado um erro. O formato da mensagem JSON que retornava era:


[{"id":2,"descricao":"RESTAURANTE"},{"id":3,"descricao":"MERCEARIA"}]


O erro era:

[com.sun.istack.SAXParseException2;
 lineNumber: 0; columnNumber: 0; unexpected element (uri:"", 
local:"id"). Expected elements are <{}categoria>]


Ou também:

XMLStreamException: JSON expression can not be empty



A configuração do cliente era:

ClientConfig config = new DefaultClientConfig();
client = Client.create(config);
client.addFilter(new LoggingFilter());
webResource = client.resource(BASE_URI).path(resourceName);


E forma de busca do servidor era:

WebResource resource = webResource;
ClientResponse response = resource.path(java.text.MessageFormat.format("{0}/{1}", new Object[]{max, first})).getRequestBuilder().accept(MediaType.APPLICATION_JSON_TYPE).get(ClientResponse.class);
GenericType> genericType = new GenericType>(){};
List categorias = response.getEntity(genericType);





Então, após algum tempo de pesquisa, descobri que faltava uma linha de código na configuração do cliente:

config.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING,Boolean.TRUE);


E pronto, após adicionar essa configuração, tudo funcionou perfeitamente. Espero que ajude!

Até a próxima!




terça-feira, 24 de abril de 2012

Tag Cloud Computing

Salve galera,

Essa vai para aqueles que querem adicionar uma interessante e atrativa tag de Coud Computing no seu site, mas, assim como eu, não entendem nada de flash. Nesse caso, basta conhecer alguém que saiba, a final, não da pra saber tudo não é?! E o site a seguir com certeza sabe =D

http://www.flashxml.net/tag-cloud.html

É só customizar conforme a necessidade, baixar e usar.

Até a próxima!

Notepad++ com Groovy

Salve galera,

Ai vai uma dica para quem programa em Groovy, e gostaria de usar o Notepad++ para isso. Por padrão, a linguagem Groovy não vem integrada ao Notepad++, mas podemos instalar um "plugin" para ele reconhecer a sintaxe. Para isso temos que baixar o arquivo:

http://notepad-plus.sourceforge.net/commun/userDefinedLang/userDefineLang_Groovy.xml

Renomear para:

userDefineLang.xml

Coloca ele na pasta:

%APPDATA%\Notepad++\

ou 

C:\Users\user\AppData\Roaming\Notepad++


E pronto, a partir de agora ele reconhece a sintaxe do Groovy.

Até a próxima!


Referências:

http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=User_Defined_Language_Files#G
http://sourceforge.net/apps/mediawiki/notepad-plus/index.php?title=Notepad%2B%2B_Install_Folder

terça-feira, 27 de março de 2012

Instalando o VLC no Slackware 13.37

Se baixarmos os fontes diretamente do site oficial do VLC e compilarmos, teremos alguns problemas, pois ele vai reclamar de bibliotecas faltantes, plugins e outras coisas que não lembro.. Então devemos instalar a versão que tem em http://connie.slackware.com/~alien/slackbuilds/vlc/, ai não teremos os mesmos problemas, e nossa vida se torna mais facil. Então, basta baixar a versão correspondente a sua versão do Slackware (a minha é 13.37 64 bits)

$ wget http://connie.slackware.com/~alien/slackbuilds/vlc/pkg64/13.37/vlc-2.0.1-x86_64-1alien.txz

$ installpkg vlc-2.0.1-x86_64-1alien.txz

Pronto, já está instalado e funcionando!

Até a próxima! abrass

Padrão Command

Salve galera!!

Agora escrevendo sobre nossos queridos Design Patterns, ou Padrões de Projetos... como preferirem. Nesse post vou tentar demonstrar um uso bem interessante para o padrão Command. Talvez o objetivo desse padrão seja outro, mas desde que comecei a usar com o objetivo de tratamentos de exceções, achei muito pratico, produtivo, coeso e desacoplado. Hoje uso esse padrão em aplicações web, desktop, mobile.. ou seja, em todos os projetos que coloco a mão, aplico esse padrão... Então, vamos ao que interessa..

Uma pequena introdução:

Objetivo: Encapsular uma solicitação como um objeto, desta forma permitindo que clientes parametrizem diferentes solicitações, enfileirem ou façam o registro (log) de solicitações e suportem operações que podem ser desfeitas.

Problema: Algumas vezes é necessário emitir solicitações para objetos nada sabendo sobre a operação que está sendo solicitada ou sobre o receptor da mesma.

Aplicação: A chave deste padrão è uma classe abstrata Command, a qual declara uma interface para execução de operações. Na sua forma mais simples, esta interface inclui uma operação abstrata Execute.

Fonte: http://pt.wikipedia.org/wiki/Command

Agora na pratica, aplicando ele nos meus problemas

Objetivo: Realizar chamada a métodos que lançam exceções, de maneira que todas sejam tratadas em um unico local.

Problema: Quando se pensa na arquitetura de uma aplicação, ou no design, logo pensamos em como vamos tratar as exceções. Então, criamos super exceções para cada camada, ou apenas para camada DAO, e sub-exceções para exceções mais espacificas. Exemplo:

DAOException - Super-exceção
UniqueKeyViolationException - Sub-exceção
PrimaryKeyViolationException  - Sub-exceção
ValidationException - Sub-exceção

Agora temos todas essas exceções para tratarmos com nossos try catch, por toda camada visual, onde vamos consumir os dados da camada BO => DAO ou DAO. Ainda teremos um pequeno problema se uma nova exceção for adicionada a lista, pois ela precisará ser tratada.

Aplicação:  Criar uma classe Chamada CommandDelegate, onde através de um método executar possamos realizar o tratamento de exceções de toda a aplicação de maneira padronizada.

Vamos ao que interessa.. Código fonte!

Interface Command

/**
 * Interface que representa uma operação que
 * deve ter suas exceções tratadas
 * 
 * @author Ricardo Bocchi
 */
public interface Command {

    /**
     * Encapsula um método que deve ser tratado
     * 
     * @throws Exception 
     */
    void operation() throws Exception;
}

Implementação da classe CommandDelegate

/**
 * Exemplo do padrão Command para o tratamento centralizado de exceções 
 *  
 * @author Ricardo Bocchi
 */
public class CommandDelegate {

    private static final Logger logger = Logger.getLogger(CommandDelegate.class.getName());
    private boolean fail;

    /**
     * Executa uma operação que deve ter tratamento de exceções
     * 
     * @param cmd Operação a ser executada
     */
    public void execute(Command cmd) {

        this.fail = true;

        try {
            cmd.operation();
            this.fail = false;
        } catch (PrimaryKeyViolationException e) {
            //Tratar exceção de violação de chave primaria
        } catch (ValidationException e) {
            //Tratar exceção de validação
        } catch (DAOException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            //Tratar exceção de banco de dados generica
        } catch (Exception e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            //Tratar exceção generica
        }
    }

    public boolean isFail() {
        return fail;
    }
}

Uso

        new CommandDelegate().execute(new Command() {

            @Override
            public void operation() throws Exception {
                dao.executeThrowsOperation()
            }
        });

Esse é o uso mais simples possivel. Ainda podemos identificar os seguintes problemas:

Se ocorrer um erro, como posso parar a execução se as exceções estão sendo "caladas" dentro do CommandDelegate? Para identificar erros, podemos chamar o método isFail(), que retorna se ocorreu algum erro na execução. Poderimos altera o método execute na classe CommandDelegate, para:


    public CommandDelegate execute(Command cmd) {

        this.fail = true;

        try {
            cmd.operation();
            this.fail = false;
        } catch (PrimaryKeyViolationException e) {
            //Tratar exceção de violação de chave primaria
        } catch (ValidationException e) {
            //Tratar exceção de validação
        } catch (DAOException e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            //Tratar exceção de banco de dados generica
        } catch (Exception e) {
            logger.log(Level.SEVERE, e.getMessage(), e);
            //Tratar exceção generica
        }

        return this;
    }

E depois usar assim
        
       CommandDelegate delegate = new CommandDelegate().execute(new Command() {

            @Override
            public void operation() throws Exception {
                dao.executeThrowsOperation()
            }
        });

        if(delegate.isFail()){
          //Ocorreu erro! 
          return;
        }

E se eu precisar passar parametros para o método ou pegar o retorno?
Nesse no caso de parametro, se ele fosse final, não teria problemas. E caso ele não possa ser final, poderiamos criar uma classe Wrapper generica para as chamadas.

Classe Wrapper
    
/**
 * Classe Wrapper
 *  
 * @author Ricardo Bocchi
 */
public class Wrapper {

    public T obj;
}

E usar
   
       Wrapper wrapper = new Wrapper();
     
       CommandDelegate delegate = new CommandDelegate().execute(new Command() {

            @Override
            public void operation() throws Exception {
                wrapper.obj = dao.loadCliente(1);
            }
        });

        if(delegate.isFail()){
          //Ocorreu erro! 
          return;
        }


Então, apresentei aqui um uso interessante para o padrão Command já prevendo algumas complicações que ele geraria. Ainda poderiamos realizar diversas customizações, de modo a facilitar o uso do padrão.

E por hora era isso.. até a próxima! abrass

Site da Mobile Mind no ar

Salve galera... apenas publicando que o site da mais nova empresa de tecnologia, Mobile Mind, está no ar! Segue o link MobileMind.



Para quem está procurandosoluções em tecnologia móvel, é uma boa pedida.

Curtam no face!

Abrasss

segunda-feira, 26 de março de 2012

Slackware 64 bits multilib

Salve galera.. Meus problemas começaram assim que instalei a versão do Slackware 13.37 64 bits. Depois de instalado, percebi que não conseguia executar programas 32 bits.. então descobri que:

"Slackware for the x86_64 architecture (or "Slackware64" for short) is a pure 64-bit Operating System, but easily upgradable to multilib. Out of the box, Slackware64 is only capable of compiling and running 64bit binaries."

Ou seja, ele só roda programas 64 bits. Mas como tudo sempre tem uma solução, ai vai uma dica de como reverter a situação e transformando o Slackware 13.37 64 bits em multilib, para ai sim conseguirmos rodar programas 32 bits.

Primeiro, vamos fazer o download dos pacotes de compatibilidade:

mkdir ~/multilib
$ cd ~/multilib
$ wget -c -r --no-parent http://connie.slackware.com/~alien/multilib/13.37/

Agora vamos atualizar e instalar os novos pacotes

$ cd connie.slackware.com/~alien/multilib/13.37 
$ upgradepkg --reinstall --install-new *.t?z
$ upgradepkg --install-new slackware64-compat32/*-compat32/*.t?z 

E pronto, seu sistema está apto a executar programas 32 bits.

Para mais informações, veja http://alien.slackbook.org/dokuwiki/doku.php?id=slackware:multilib

Até a próxima!

terça-feira, 20 de março de 2012

String Resources WP7

Salve galera! Aqui vai apenas uma dica em como trabalhar com string resource a moda android no WP7.

Android

res/values/string.xml

 
  
    Nome da Aplicação
   

Uso:



WP7

App.xaml



Nome da Aplicação




Uso




Simples não? Até a próxima

Custon Button WP7

Salve galera!! Olhando a data de criação do blog, e a quantidade de postagens existêntes, posso afirmar que não cumpri com o prometido =/. Mas nada está perdido, agora pretendo dedicar um tempo especial para postar novidades e coisas interessantes. Agora de verdade =)
Como não era de de se esperar, vou postar um conteúdo sobre Windows Phone 7 ou conhecido WP7. Alguns dias atrás quebrei a cabeça para fazer um botão personalizado com as seguintes regras.
 
- Deve possuír uma imagem de fundo;
- Quando o botão é pressionado, sua imagem de fundo deve ser alterada;
- Quando o botão é liberado, sua imagem de fundo original deve voltar ao estado original.

E como era de se esperar, foi muito mais facil do que eu imaginava. Tive esse problema, pois estava migrando uma App Androd para WP7. Então, vou postar aqui o componente personalizado na versão android, e depois o equivalente na versão WP7.


res/drawable-hdpi/custon_button.xml - Componente customizado



    




Uso do componente - Agora podemos usar nosso componente em uma View do Android.

 



CustonButton.cs - Classe que controla o componente


using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace MobileMind.Control
{
    /// 
    /// ImageButton control
    /// 
    public class ImageButton : Button
    {
        /// 
        /// Default Constructor
        /// 
        public ImageButton()
        {
            DefaultStyleKey = typeof(ImageButton);
        }

        /// 
        /// Normal State Image Property Dependency
        /// 
        public static readonly DependencyProperty ImageProperty = DependencyProperty.Register("Image", typeof(ImageSource), typeof(ImageButton), null);

        /// 
        /// Normal State Image Property
        /// 
        public ImageSource Image
        {
            get { return (ImageSource)this.GetValue(ImageProperty); }
            set { this.SetValue(ImageProperty, value); }

        }

        /// 
        /// Pressed State Image Property Dependency
        /// 
        public static readonly DependencyProperty PressedImageProperty = DependencyProperty.Register("PressedImage", typeof(ImageSource), typeof(ImageButton), null);

        /// 
        /// Pressed State Image Property
        /// 
        public ImageSource PressedImage
        {
            get { return (ImageSource)this.GetValue(PressedImageProperty); }
            set { this.SetValue(PressedImageProperty, value); }

        }
        
    }
}


App.xaml -  Template do componente














Visible






Collapsed


























Uso do componente Agora podemos usar nosso componente personalizado em alguma Page do WP7.

MainPage.xaml







Basta adaptar para seu código e usar!

Era isso pessoal. Espero que esse exemplo ajude alguém! Até a próxima.