Troca de mensagens com criptografia em Java, usando AES.

O escopo de uma aplicação incluía a troca de mensagens sensíveis como parte de um WebService, e além do uso de HTTPS, deveria ser usada alguma forma de criptografia na parte crítica do serviço.

Logo deveria haver uma forma de criptografia disponível tanto no servidor como nos clientes, inicialmente um serviço em Java e o cliente seria no Android (depois outros surgiriam), com isso tem quer ser usado um algorítimo de chave simétrica, que permitisse recuperar a mensagem original de posse da chave de criptografia usada. Obviamente deveria ser um mecanismo eficiente.

Escolhi o AES por acreditar ser o padrão ideal atualmente, “lançado” em 2001 entrou em estudo pelo governo dos EUA e hoje é o seu padrão para troca de documentos, incluindo os “tops”. Usando mesmo uma chave de apenas 128bits seria extremamente seguro, a chave pode ser de 128bits, 192bits ou 256bits.

Se você está desenvolvendo em Java EE 5 ou no Android (Ou qualquer Java 6, acredito eu, mas não confirmei), ambos já possuem a implementação deste algoritmo, caso a plataforma não possua você pode usar a implementação do Bouncy Castle, geralmente basta o Provider do bcprov-jdk16-*.jar .

O primeiro passo para a criptografia é definir uma chave, ela pode ser gerada automaticamente pelos mecanismos do sistema:

public byte[] key() throws NoSuchAlgorithmException {
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(128);
SecretKey key = keyGen.generateKey();
return key.getEncoded();
}

Esse método retorna o array de bytes de uma chave de 128bits, podemos usar 256bits mas esse algorismo nem sempre está disponível ou requer configurações especificas do JRE.

A criptografia trabalha com valores em Hexadecimal, assim a chave também usa valores em hexa, você pode criar uma chave com um array de hexas do tamanho que deseja da chave, uma chave de 128bits são 8 bytes (128/16), assim:

byte[] key = { 0x0f, 0xad, 0x54, 0x12, 0x00, 0xaf , 0x34, 0xff }

Em posse de uma chave de criptografia basta aplica-la a uma engine de criptografia, junto dos bytes da mensagem a ser encriptada, com o seguinte método:

public byte[] encode(byte[] input, byte[] key) throws NoSuchAlgorithmException, 
InvalidKeyException, IllegalBlockSizeException,
BadPaddingException, NoSuchPaddingException {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(input);
return encrypted;
}

Detalhe para o “AES/ECB/NoPadding” , isso usa o algoritmo AES e não faz o padding da mensagem.

Por trabalhar em hexadecimal, o algoritmo trabalha com blocos de 16 bytes, então a mensagem(seus bytes) devem ter uma tamanho múltiplo de 16 para não haver erros de “BadPaddingException: pad block corrupted, para isso podemos usar os seguintes métodos, que preenchem os espaços que faltam até formar o tamanho necessário com “null”:

public String nullPadString(String original) {
StringBuffer output = new StringBuffer(original);
int remain = output.length() % 16;
if (remain != 0) {
remain = 16 - remain;
for (int i = 0; i < remain; i++) {
output.append((char) 0);
}
}
return output.toString();
}

Então podemos encriptar uma mensagem assim:

String mensagem = "Hello World!";
byte[] enc = encode(nullPadString(mensagem).getBytes(), key);

Para descriptografar a mensagem não tem mistério, basta o seguinte método:

public byte[] decode(byte[] input, byte[] key) throws NoSuchAlgorithmException, 
InvalidKeyException, IllegalBlockSizeException,
BadPaddingException, NoSuchPaddingException {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(input);
return decrypted;
}

A única diferença é o parâmetro passado ao Cipher, para de descriptografar.

Agora que podemos criptografar e decodificar as mensagens, precisamos garantir seu formato ao ser enviado via HTTP/HTTPS.

Novamente, como trabalhamos com Hexadecimal, ele não é simplesmente convertido para String, não sem perda, e a conversão de volta também traria riscos, ainda mais se for em plataformas diferentes.

Precisa-se então converter esses valores hexadecimais para uma representação “por extenso” destes, e que possa ser transformado de volta, e podemos alcançar isto com os seguintes métodos:

public String fromHex(byte[] hex) {
StringBuffer sb = new StringBuffer();
for (int i=0; i < hex.length; i++) {
sb.append( Integer.toString( ( hex[i] & 0xff ) + 0x100, 16).substring( 1 ) );
}
return sb.toString();
}

public byte[] toHex(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}

Então para enviar uma mensagem podemos proceder da seguinte forma (contando que ambos possuem a mesma chave):

String mensagem = "Hello World!";
byte[] enc = encode(nullPadString(mensagem).getBytes(), key);
String msgParaEnviar = fromHex(enc);

Enviamos então via http a string msgParaEnviar, e ao recebe-la procedemos a decodificação:

byte[] msgEnc = toHex(msgRecebida);
byte[] msg = decode(msgEnc,key);
String mensagem = new String(msg).trim();

Assim temos a mensagem nas duas pontas, o trim é necessário devido ao “padding”.

Veja o código da Classe de Criptografia que uso.

Hello World em JavaFX: Faça um streaming com a busca do twitter.

Não tem HelloWorld mais na moda que o Twitter.

Este artigo sera um tutorial sobre o básico do JavaFX, vai tratar a sintaxe, como construir uma interface básica e acessar um webservice. O Objeto final será um client para busca do twitter, atualizando automaticamente.

Não será um stream propriamente dito pois a API de Streaming do twitter requer autenticação, então para manter mais simples usará atualizações agendas para busca de novos itens. Não vou tratar de nenhuma ferramenta especifica, apenas do código em si, a parte de compilar e rodar fica a cargo da sua IDE. Vamos começar?

O primeiro passo é criar nosso projeto, que se chamará , muito criativamente, Searchr. Vou trabalhar apenas no pacote homônimo, searchr. Vamos primeiro o ponto de entrada na nossa aplicação, que será o Main, então temos o arquivo searchr/Main.fx , lembre-se de configurar sua IDE para usa-lo como ponto inicial.

O primeiro ponto de um aplicativo JavaFx é um objeto “Stage”, cada Stage representa uma janela. É importante notar que a janela é aberta no momento que criamos o Stage, assim que ele é construído. Cada Stage possui então um Scene, que é o conteúdo da janela, aonde vamos colocar nossos elementos gráficos.

O ponto de partida da aplicação é a função “run()”, quando temos o “run” lá criamos nosso stage e iniciamos qualquer outro processo necessário ao inicio da aplicação. Veja como colocamos então uma janela com um texto dentro:

// Main.fx, após imports
var stage: Stage ;
def scene: Scene = Scene {
fill: Color.WHITE
content: [ Text { content: “Hello JavaFx” } ]
}

function run() {
stage = Stage {
title: “Hello JavaFx”
width: 350
height: 500
scene: scene
}
}

Explicando tudo, na sintaxe do javafx temos duas formas de declarar uma variável, como sendo realmente variável ou definitiva, sendo preferível ser definitiva. O formato é então nomeDaVariavel: Tipo.

Temos então a construção de um objeto Scene, veja que na sintaxe declarativa iniciamos cada propriedade no momento da criação do objeto. Nesse caso criei o scene com “fill” branco e um array no conteúdo.

Uma lista é tratada como visto no content do Scene, entre colchetes, com elementos separados por virgula. Criei ainda um texto com conteúdo “Hello JavaFX”. Mais sobre listas mais tarde.

Em seguida declarei um função, nesse caso a principal “run”, aonde começa o programa, quando chega nesse ponto crio a janela que conterá minha UI. Vamos começar a explorar alguns elementos básicos de UI agora.

Minha ideia do aplicativo é extremamente simples, um campo de texto, um botão “Search” e em baixo a lista dos tweets.

Para organizar tudo, criarei um container vertical, o Vbox, e o coloco na cena (Scene). Com conteúdo vazio.

def container: VBox = VBox { spacing: 5, content: [] } ;
def scene: Scene = Scene {
fill: Color.rgb(51,51,51)
content: [ container ]
}

Crio agora a caixa de texto onde vai entrar a busca. E o botão para fazer o busca.

def input: TextBox = TextBox { promptText: “Search…” , action: doSearch, columns: 30};
def button: Button = Button { text: “Search”, action: doSearch };

Veja que temos ai um “action”, aponto ele para uma função “doSearch”, que tem a mesma assinatura que a propriedade “action”, que é uma função sem argumentos e que não retorne nada.

function doSearch(): Void {}

Deixo a função para mais tarde, veja que o tipo de retorno vem depois da declaração. Posso ainda definir assim:

def doSearch = function(): Void {}

Vou colocar esses elementos na mesma linha usando o Hbox, e já o incluo no container vertical.

def searchBar: HBox = HBox { spacing: 5, content: [ input, button] }
def container: VBox = VBox { spacing: 5, content: [ searchBar ] }

Vou declarar agora uma classe para generalizar a interface de cada linha que será o resultado da busca. Será um CustomNode, que é um elemento personalizado.

class SearchLine extends CustomNode {

public-init var profileUrl: String ;
public-init var user: String ;
public-init var text: String;
public var width: Number ;

override function create(): Node {
return HBox {
spacing: 5
content: [
ImageView {
image: Image {
url: profileUrl
, width: 54
, height: 54
, backgroundLoading: true
, placeholder: Image {
url: “{__DIR__}placeholder.png”
width: 54
height: 54
}}
}
Text {
content: “{user}: {text}”
wrappingWidth: bind width – 60
fill: Color.WHITESMOKE
}
]
}
}
}

Temos ai vários elementos para explorar, a declaração da Classe é básica. Temos então os atributos “public-init” que só podem ser alterados na construção do objeto. Width não é public-init pois pode mudar conforme o tamanho da janela mude, você verá mais tarde.

Tenho então que sobreescrever (o override) a função create da classe CustomNode, onde devo retorna o elemento customizado.

Nesse casso fiz uma linha HBox , com uma image e o texto do tweet. Vejam que na imagem defino a URL de onde deve ser carregada, informo para carregar em background, para não travar a UI, e defino uma imagem temporária (placeHolder).

Ai temos algo interessante, uma variável especial __DIR_ indica o diretório do aplicativo. E temos a string. Em Java FX não concatenamos como em Java, mas sim usando a expressão dentro de chaves, como:

def soma = “Soma de {a} + {b} = {a +b}”;

Em seguida temos o elemento texto, novamente com uma string com variáveis, e um limite de largura, aonde haverá quebra automática de linha. E um BIND.

Um bind é uma ligação entre uma variável ou propriedade e uma outra variável ou expressão, assim quando uma muda a outra é atualizada. Quando width mudar, a largura do texto irá acompanhar. Podemos ainda ter casos mais complexo, como expressões e loops, como veremos até o final.

Vamos criar agora o container dos tweets, esse será um pouco mais complexo, pois exibirá apenas parte dos tweets, e terá rolagem, mas isso vai explorar boas partes da linguagem. Então vamos por partes, primeiro a lista em si:

def tweetList: VBox = VBox { spacing: 5 , content: bind for ( tweet in tweets) {
SearchLine{
profileUrl: tweet.profileImage
user: tweet.user
text: tweet.text
width: bind scene.width -15
  } } }

Veja que interessante, eu liguei o conteúdo da lista a um loop, que gera a SearchLine. E garanti que o tamanho do texto vai bater com o tamanho da tela. Vamos definir esses itens faltosos logo:

class Tweet {
public var profileImage :String;
public var user: String ;
public var text: String ;
}
var tweets: Tweet[];

Essa classe vai conter cada tweet, como sendo nosso model. E temos a lista onde armazenamos os tweet achados.

Agora temos um detalhe, que é que não podemos exibir a lista toda por conta do espaço, então criamos um ClipView. Ele funciona contendo o conteúdo, mas exibindo apenas parte dele. Veja:

def clip: ClipView = ClipView {
clipY: 0
clipX: 0
node: tweetList
height: bind scene.height – 30
width: bind scene.width
}

Temos ai nosso ClipView, começando exibindo o começo apenas, contendo o VBox anterior, a altura será sempre o da janela menos 30 (mais ou menos o tamanho da barra de busca), e a largura será o da janela.

Um caso especial sobre o ClipView, é que é pannable. Ou seja, basta “segurar” e arrastar para rolar. Podemos definir ele como “pannable: false” e adcionar um ScrollBar também ou eventos de mouse, mas ai fica para outra oportunidade.

Agora é só inserir o clip no container:

def container: VBox = VBox { translateX: 10, translateY: 5, spacing: 5, content: [ searchBar, clip ] }

Adcionei ainda um posicionamento em X e Y para haver um espaço na janela. Feito a UI, agora é hora de mágica! Vamos ao acesso ao webservice.

Vou usar uma classe chamada AtomTask(podia ser RssTask, FeedTask, ou mesmo genérico HttpRequest), que recupera atom de tempos em tempos. Trabalhamos na função doSearch que definimos antes:

var current: AtomTask ;

function doSearch(): Void {
if(current != null) { current.stop(); }
current = AtomTask {
interval: 1m
location: “http://search.twitter.com/search.atom?q={input.text}”
onFeed: function(feed: Feed) {
delete tweets;
}
onEntry: function(item: Entry) {
insert Tweet {
profileImage: item.links[1].href
text: item.title.text
user: item.authors[0].name
} into tweets ;
}
};
current.start();
input.text = “”;
}

Crio uma variável para conter a Tarefa corrente. Ao fazer a busca, paro a tarefa anterior, e crio uma nova. Defino o intervalo de 1 minuto (é um tipo do JavaFx chamado Duration), a location de acordo com o conteúdo do input.

O evento onFeed é chamado assim que recebemos o Atom, ai eu limpo o array de tweets.

O evento onEntry recebe cada alemento achado no Atom, para cada um eu insiro um novo Tweet no array de tweets.

Em seguida eu inicio a tarefa, e limpo a caixa de texto. Assim como mágica ( #NOT ), o aplicativo está pronto. Agora você pode roda-lo usando webstart, através do jnlp que sua IDE criou(ou não), ou como applet no seu site.

Claro que esta extremamente simples, mas já serve para os principais conceitos do JavaFx, o código final esta no github, no streaming de search de twitter.

InputStream remoto em Java – baixando arquivos

Passei essa semana por esse problema em um projeto no trabalho.

O caso era realizar o download de um arquivo, no android. O problema era que apesar da conexão estar certa, o arquivo era salvo errado, os bytes estavam errados apesar do tamanho esta quase certo.

Acontece que usei um algorimo básico para baixar escrever no arquivo, primeiro fazia a coneão HTTP:

URL urlCn = new URL(url.toString().trim());
HttpURLConnection conn = (HttpURLConnection) urlCn.openConnection();
conn.setDoInput(true);

E em seguida criava o arquivo: 

File file = new File(“downloads”, name ); 
if(!file.exists()) {
    try {
      file.createNewFile();
      isNew = true;
    } catch (IOException e) {
      e.printStackTrace();
      return;
    }
}

Então chegava a problemática hora de escrever o conteúdo do arquivo, eu estava usando um algorimo básico, que sempre funciona com InputStreams locais.

int bSize = 1 * 1024 ;
FileOutputStream fos = null;
BufferedInputStream bis = new BufferedInputStream(is,bSize);

try {
   fos = new FileOutputStream(file);
   byte[] buffer = new byte[bSize];
   while(bis.read(buffer) > 0) {
      fos.write(buffer);
   }
   fos.flush();
   fos.close();
   bis.close();
} catch (FileNotFoundException e) {
   e.printStackTrace();
} catch (IOException e) {
   e.printStackTrace();

O algorismo lê, a cada “bSize” e escreve no arquivo, para não ocupar muita memória. 

A pegadinha esta em que nem sempre o InputStream da conexão me retorna a quantidade de bytes que eu pedi, mas eu sempre estava escrevendo o buffer inteiro. Logo se num buffer de 1k, o Stream só me deu 512B, eu estava escrevendo o resto de lixo (bytes da escrita antiga). 

A correção foi alterar o trecho para o código a seguir:

   int len1 = 0;
   while((len1 = bis.read(buffer)) > 0 ) {
      fos.write(buffer, 0,len1);
   }

E todos viveram felizes para sempre. 

A experiência de fazer um cliente para twitter em JavaFX

Ainda em JavaFx, minha segunda aplicação esta se saindo bem, estou gostando do resultado. 

Este texto não é só propaganda(mas também é :), vou analisar a criação, negativos e positivos. Mas primeiro, a apresentação:

O TwitterFlow é um cliente para twitter que conta com alguns dos principais recursos que deve-se ter já funcionando:

  • Ele tem múltiplas contas
  • Escreve em qualquer uma das contas (doh)
  • Atualiza automaticamente (ou não, claro)
  • Faz buscas
  • Retweet, Reply, links…

Para oferecer algo um pouco além do “basicão”, que os clients legais costumam ter:

  • Envia fotos 
  • Encurtar URLs 
  • Salva buscas
  • Busca por menções(ret e rep) de qualquer usuário
  • Segue usuários sem precisar “follow” de verdade (não lembro mais por que)
  • Atualiza qualquer coisa automaticamente 
  • Manter mais de uma janela, cada uma aconpanhando um fluxo
  • Paginação 
  • Se “esconde” na bandeja do sistema
  • Exibe alertas na bandeja quando há novos tweets

Acho que é só isso por enquanto… 

 

JavaFx, multiple accounts, Twitter Client

 

 

A tarefa de construção de UIs no JavaFx é muito boa, e mesmo um “nada-designer-e-preguiçoso”  como eu consegui fazer algo razoável.

Os principais dificuldades foram as já esperadas: Quando fora da UI, não consegui bons resultados com as classes fornecidas pelo SDK.

Fiz o controle de threads e temporização na mão, e em Java. Foi uma cascata nessa parte na verdade, primeiro usei as classes mais “abstratas” do JavaFx,  a RssTask. Depois Passei a usar o HttpRequest mesmo junto com Timer e TimerTask. Depois usei o Timer e TimerTask com URLConnection (estas já são do Java), e como já estava aqui larguei o Timer e usei Threads e Runnables mesmo.

O resultado esta com Threads bem legais até, sem dores de cabeça e boa performance, sem overhead. 

Na parte de UI apenas algumas ressalvas, escrevi um campo de password baseado no campo de texto, e um Spinner do zero. Ainda faltam matar os Swings do TextArea e (mais complicado) FileChooser, mas acho que o FileChoose já tem pronto por ai.

Quanto às chamadas de serviço, a API do Twitter é uma maravilha. Mesmo. A do twitpic abstraí através do twitipic4j. E os encurtadores de URLs também não podiam ser mais simples. Para cuidar do JSon usei a fornecida no próprio json.org , que sempre me ajuda. Já que estou nos créditos, todas as imagens (exceto os avatares, óbvio) são do Iconset do Oxygen. (Links no final)

Mas um pouco na API , tem uma complicação na verdade. Depois de todo o mimimi de segurança e todos os problemas em digitar sua senha em aplicativos, o twitter esta introduzindo autenticação por OAuth (parecido com grandes sites fazem), e com novas apps só tem seus nomes aparecendo no tweet se usarem OAuth (antigas continuam ok). Então aparece apenas API por hora. 

Uma parte que rendeu uma boa Gambiarra foi para fazer os links no tweet. Bom, como não é simples HTML e não posso simplesmente usar <a>, nem inserir eventos em partes especificas de uma string. A primeira POG foi dividir o conteúdo nos espaços e ver se são possíveis links (http, @ ou #). Se for uso um elemento devido, senão uso o Text padrão. E fazer uma sequence com isso.

O primeiro problema dessa abordagem foram parenteses e pontuação, por exemplo o conteúdo “bla bla (http://g.com)” sairia errado. Isso já rendeu bons IFs. O segundo é que cada palavra era na verdade um elemento de UI, o “tweet” em sí era um “float” desses elementos. Imagine a confusão!

A solução atual é diferente, eu busco pelos links no conteúdo os guardo em uma sequencia, depois ele são inseridos numa área especifica da UI. Salvei bastante memória assim, até melhorou o layout, mas perdi um pouco em design já que não tenho “cores” no tweet (apenas na área dos links).

Falando em memória, essa sempre foi uma preocupação. Chances para Leaks , o fato da tecnologia ainda ser nova e fama de Java como devorador de memória me deixavam bastante preocupado.

De fato é muito fácil “torrar” memória na construção UI, principalmente por que estou sempre lidando com sequencias e binds, mas tenho feito um esforço bom para mante-la sobre controle e tem ficado tudo bem.  Reduzi a passagem de objetos entre diferentes camadas da aplicação, para evitar de esquecer referencias, e reutilizei os objetos que consegui.

O modelo de threads ajudou bastante a controlar a memória, um “pool” para as imagens também reduziu bastante.  A lista de tweets é mantida somente em um lugar, e quem a recebe sempre se livra da referência. A gambiarra dos links quando desfeita também liberou bastante coisa.

Mas é um trabalho eterno, ainda pode melhorar muito.

Não gosto de fazer comparações, pois sei que são muito diferentes e todo um blá blá blá(…), mas sempre achei que os clientes  twitter consumissem bem pouco. Estava enganado. Tirando os pertencentes aos browsers (twitterfox, Opera Twitter widget, etc), a maioria consome muita memória. Talvez eu só tenha escolhido os maiores consumidores para testar.

Nos clients em Adobe AIR, ( Twhirl, Spaz e TweetDeck que eu vi) é fácil começarem nos 70, 80, subir para 90 e 100MBs (e até continuar), o TweetDeck, um client completíssimo, é assustador nisso. Não posso falar que é culpa do AIR (provavelmente não é), já que o DestroyTwitter (que eu usaria fácil, gostei muito) usa bem menos(visual mais simples, talvez), entre 55~65Mbs.

Nos feitos em JavaFx, como o TwitterFx e o TweetBox, o consumo também é muito alto, tanto ou maior que os em AIR. O TwitterFlow (o meu) também não está ideal ainda, mas fica parecido com o DestroyTwitter, durante o uso normal ao longo do dia fica entre uns 60~70Mbs, mas se for abrindo mais janelas e mais fluxos, passa fácil para 70~80MBs. 

Não testei nenhuma aplicação nativa, nem para Windows, nem Linux  e nem Mac (informações são bem vindas!), mas imagino que esses se saiam bem melhor (por favor!).

Voltando para a aplicação, usei melhor os recursos de binds, triggers e sequences do JavaFx, facilitando manter a conformidade , normalização e sincronismo dos dados. Salvo as configurações usando a API  de Storage local, que é encriptada e “sandboxada” para cada app.

A parte de integração com o Desktop (lançar navegador e bandeja) ainda esta na gambiarra, ambas usam a classe de Desktop do Java. O lançar navegador usa o BareBonesBrowserLauncher.

Ainda quero implementar pelo menos OAuth, manutenção de cada usuário e , claro, memória e performance. E o que mais der na telha! 

Enfim, o aplicativo, links e código em http://kenai.com/projects/twitterflow. Opiniões são bem vindas, para mal ou bem :) 

JavaFx – O bom, o ruim e o feio.

Até agora ficou claro que JavaFx não pegou, não existem muitas aplicação “de verdade” rodando, e só entusiastas mesmo tem construído algo. Nesse batalha de RIA parece que o Adobe AIR realmente largou na frente.

No meio de minha segunda aplicação na tecnologia, resolvi fazer essa análise, com vantagens, desvantagens e considerações.

Vou começar pela vantagem mais óbvia: É Java. Ou melhor, roda na JVM e pode ser escrito em Java. Isso quer dizer que se o JavaFx não supre algum requisito do aplicativo, você pode “descer” para java nessa parte. Isso implica também que você pode fazer uso de uma comunidade gigantesca que disponibiliza milhares de bibliotecas para completar sua aplicação. Além é claro dos recursos e classes da JRE.

Aplicações JavaFx podem ser lançadas como applets ou através do Java WebStart. Lançando como applet você ainda tem a opção de arrastar o applet para fora do browser para te-lo como uma app independente. Ambos os modos permitem criar um icone na área de trabalho para o aplicativo.

Isso levanta a questão óbivia de performace: No geral o tempo de carregamento tanto de um applet como do JWS é um pouco lento, o startup da JVM ainda é um pouco lento. Mas após lançado o aplicativo a performace é muito boa, e o consumo de memória não é o monstro que todos esperam do Java, com alguns cuidados é possível manter o usso de memoria baixo, mais até que Apps em Adobe Air, por exemplo.

Falando em recursos da JVM, o primeiro grande problema em JavaFx é que é “Single Threaded”, isso quer dizer que toda sua aplicação roda em uma Thread só, na EDT (na interface). E o único meio de usar threads é recorrendo a Java. Algumas classes do JavaFx internamente rodam em threads, como HTTP, mas se você quer criar threads, a classe da thread será feita em Java. O JavaFX tem classes para thread próprias, mas tem quer alidas a classes java.

Resumindo, se quer thread use as classes de Java (como Timer) ou crie as classes usando Java e as classes async do JavaFx.

E qual a diferença entre escrever em Java e JavaFx? A linguagem usada no JavaFx é o javafx script, é uma linguagem híbrida entre Orientação a Objetos e Funcional (mas bem mais OO que funcional), com uma sintaxe declarativa. Isso quer dizer que: É uma ótima sintaxe. É bem mais flexível, mais enxuta e de leitura fácil, lembra muito JSon(e javascript), mas é bem diferente. Tem funções como classes de primeiro nível e variáveis finais.

Você pode receber uma função(definida pela assinatura) como parâmetro. Tem ainda os “bind”, que permitem conectar duas ou mais variáveis, com ou sem reciprocidade. Quando você “bind” uma variável a outra é como se cadastrasse um Listener para quando esta mudar, o outra é atualizada. Você pode ainda disparar eventos quando o conteúdo de uma variável é alterado.

Isso tudo torna a linguagem muito boa para criação de interface gráfica, e aí esta a maior vantagem do JavaFx: É focado em interfaces. Não posso nem comparar ao swing ou mesmo mesmo swt, é muito mais fácil e flexível. Você pode usar ferramentas gráficas, pode usar o inkscape por exemplo, é bem fácil fazer os elementos da forma e cor que quiser, e adicionar funções a eles. Além, é claro, de contar com os controles mais comuns. Efeitos, transições, animações e layouts não faltam. E, aceita CSS em vários níveis.

Bom, ai esta um grande problema na verdade: Ainda faltam muitos componentes “comuns”, como por exemplo a absurda ausência de campos para password e selects drop down. O workaround (ou gambiarra) é que é possivel fazer o “wrap” de componentes swing, o que é feio. Não são muitos elementos que faltam, mas esses dois são uma grande decepção.

Mas isso também demonstra que o JavaFx traz utilitários para várias tarefas comuns à aplicativos conectados, por exemplo: o RssTask (e AtomTask) que atualiza a aplicação a cada atualização dos mesmo, verificando em períodos definidos, tem parsers para Json e Xml bem fáceis de usar, baseados em SAX. O utilitário de HTTP também é muito bom, gráficos tem de montão, além de media, incluindo um conversor de diversos formatos. Além de uma API de persistência para os dados da aplicação.

Enfim, na minha opinião, JavaFX é uma tecnologia muito boa mas ainda imatura. Claro que, principalmente por pode recorrer ao Java, pode ser usado em aplicações “reais”, mas ainda tem muito o que implementar e corrigir. Nos aplicativos que fiz costumo deixar tudo sobre fluxos e telas ao JavaFx, e nas próprias classes do JavaFx usar as classes Java para certos trabalhos, como threading e pools.

Para terminar, confiram alguns links legais, para conferir algumas aplicações:

Extraindo thumbnail de preview de videos no android

Totalmente aleatório, mas deu um trabalho absurdo achar a solução e colocar para funcionar, então é melhor registrar aqui para não esquecer. 

Resumindo:  SurfaceView é velho e não funciona bem e o VideoView ainda é bugado. Olhando ainda no source code das aplicações(a Gallery2Avtivity) que vem no android elas estão desatualizados no repositório e não funcionam na ultimo SDK, tendo sua ultima atualização a meses atras.

Enfim, a solução foi a seguinte, pegar uma classe que consta nos source projeto mas não entrou no SDK, a MediaMetadataRetriever e coloca-la em seu projeto, e TEM que ser no pacote “android.media”, então fica assim a class android.media.MediaMetadataRetriever.

Para extrair o thumb do video, segue o trexo de código:

MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setMode(MediaMetadataRetriever.MODE_CAPTURE_FRAME_ONLY);
  retriever.setDataSource(context,uri); // URI do video 
Bitmap t = retriever.captureFrame();
thumb.setImageBitmap(t);
} catch(IllegalArgumentException ex) {
ex.printStackTrace();
} catch (RuntimeException ex) {
ex.printStackTrace();
} finally {
try {
retriever.release();
} catch (RuntimeException ex) { }
}

É isso ae, partiu. 

Configurando Java FX no Netbeans no Linux

Uma nova tecnologia promissora a entrar no mercado é o Java FX da SUN para o mercado de RIA, na área em que temos o Silverlight da Microsoft e o Flash/Flex da Adobe, e esta disponível no Java 6.

 

Java Fx

 

Ele pode rodar como os antigos applets diretos do browser, mas muito mais leves e rápidos, além de usar uma linguagem script muito mais prática para interfaces, deixando as desvantagens que levaram os applets a falharem no passado. Além de outras evolução do Update N, que tornaram a Maquina java mais modular e leve, com um “boot” mais rápido.

Interessante recurso também é a possibilidade de arrastar um applet para o desktop e utiliza-lo como stand-alone, transformando-o em uma aplicação desktop padrão. Há também o Java Fx Mobile, que virá em breve nos dispositivos embarcado.

Sendo principalmente uma tecnologia para interfaces ricas, possui ainda diversas ferramentas para integrar gráficos gerandos em diversas tecnologias direto ao Java Fx Script, com isso podemos por exemplo desenhar uma interface direto em vetor, com o Inkscape ou outro, e passar para o JavaFx Script, entre outras possibilidades.

Até o momento o suporte oficial é apenas ao Windows e ao Mac, mas como os bons usuários Linux não tardou um método para fazer funcionar, com a limitação de recursos de vídeo. Então, vamos colocar o ambiente para funcionar no Netbeans 6.5.1 com o JavaFX 1.1.1 no Linux.

O Método completo pode ser lido aqui, em inglês. Sequindo este vai resultar nestes arquivos, baixe-os e descompacte.

Em seguida, abra o Netbeans e use o menu Ferramentas > Plugins, na aba Baixados clique em Adcionar Plugins e selecione todos os arquivos do download e em seguida, com todos selecionados, em Instalar.

Basta reiniciar o Netbenas e pronto, o ambiente esta funcionando, pode agora usar os Samples que acompanham para ver o Java Fx em ação, e estudar essa nova tecnologia.

 

Netbeans com JavaFx no Linux

 

 

REST Server em segundo lugar!

Como publiquei no começo do mês de março, o RestServer foi nomeado ao innovation awards do phpclasses.org, o que já havia me deixado bem feliz, e esta semana saiu o resultado, e o pacote ficou em segundo! Yay. 

O pacote foi atualizado inclusive, com algumas melhorias internas e um exemplo bem melhor, pode-se conferir na página do RestServer ou no GITHUB.

Em primeiro lugar esta um outro pacote legal, o Online Zip Modifier, para edição e manutenção de arquivos ZIP "on the fly". 

Estou mega feliz com isso, e vou tentar agregar mais funções ao pacote para fazer valer a pena!

Obrigado a todos que votaram.

Pedra Papel ou Tesoura? Meu primeiro aplicativo para celular J2ME

Para meus estudos de J2ME, o primeiro aplicativo que concluí foi um jogo de pedra, papel ou tesoura: o Jan Ken Pon

Nele você joga contra um adversário que também tenha o jogo instalado, através de bluetooth. Basta que o oponente tenha o jogo que o aplicativo é lançado em ambos os celulares quando você o desafia ou é desafiado. Além de guardar o score de cada oponente.

Já é até um pouco antigo, mas estava esperando ser publicado no GetJar.com para "lançar" oficialmente.

Nele pude aprender melhor como funciona o bluetooth e os recursos de persistência mobile(RMS), usei o framework bluetooth Marge para o trabalho, que é muito bom. Também pude usar o *chato* (para ser gentil) do Push Registry, para lançar o aplicativo sob requisição.

Divirta-se.