/I write code in .*?/gi


16
jul 11

Acessando classes java em jruby

Java and Ruby

Java and Ruby

Integrar é preciso.

Em um ambiente de produção moderno não há muito espaço para a uniformidade tecnológica. É quase certo que você terá de tudo um pouco ao entregar uma solução.

Por uma necessidade destas eu estou precisando integrar umas aplicações em java com ruby. Está sendo pra lá de divertido!

Minha classe java

Para poder mostrar como fazer, vamos antes criar uma classe bem simples em java para ser consumida em jruby.

package e7r;

/**
* Simple calculator class to be used inside jruby
*/
public class Calculator {

  /**
* Adds two integer numbers
* @param a First value
* @param b Second value
* @return The sum of two values
*/
  public int sum(int a, int b) {
    return a + b;
  }

}

É uma calculadora muito simples. Na verdade ela somente adiciona dois valores.

Para compilar e gerar o jar basta seguir os passos abaixo:

# two steps to create a jar manually

javac Calculator.java
jar cvf SmallestJar.jar Calculator.class

Eu não tinha nem idéia de como criar um jar até ler o post Creating an executable jar file.

Mais fácil impossível!

Preparando o script jruby

Basicamente você pode consumir uma classe java de três formas:

  • Diretamente (nomes completos de pacotes a cada uso)
  • Incluindo a classe no object
  • Incluindo um pacote dentro de um módulo ruby

Ganhando “super-poderes”

Existe um passo comum a todas elas para permitir o acesso às classes java no ruby:
require ‘java’
Ao efetuar este require você terá uma série de métodos auxiliares que deixarão a sua vida muito mais simples para efetuar a integração.

Chamando um jar

OK! Efetuamos o require do java, e temos tudo o que precisamos para consumir uma classe, agora precisamos indicar o jar onde nossa classe está.

Isto é feito pelo comando require. Você não precisa colocar a extensão .jar, ele automáticamente procurará tanto arquivos .rb quanto .jar, sendo que o seu jar deve ou estar no CLASSPATH ou na árvore de diretórios do consumidor.

Logo, requires como  ‘lib/SimplestJar’ ou ‘../../SimplestJar’ são válidos.

Importante, você somente precisa dar require nos jars que contém classes que você consome diretamente. As dependências serão automaticamente carregadas!

Consumindo a classe

Diretamente (nomes completos de pacotes a cada uso)

É a forma favorita dos masoquistas de plantão.

Para acessar uma classe java, você precisa iniciar a chamada com o módulo Java:: seguido do caminho completo nos pacotes até a classe.

Como desenvolvedores java tem punhos de aço (principalmente os da ASF) você pode se preparar para usar namespaces muuuito longos.

Incluindo a classe no object

Mesmo quando no irb, estamos em um contexto de uma classe. (É só digitar self.class para descobrir de quem).

Assim, você pode uma única vez fazer esta inclusão e em diante a classe estará disponível diretamente pelo nome dela.

Para fazer a inclusão utilize o comando include_class usando o Java:: seguido do caminho completo até a classe.

Incluindo o pacote em um módulo ruby

Sempre é bom poder organizar as coisas.

Neste projeto que estou fazendo, eu quero simplificar os trezentos mil pacotes em uns quatro ou cinco módulos. Não há razão alguma justificável para termos mais.

Para isso dentro do módulo você pode usar o método import_package para vincular as classes java ao seu módulo ruby.

O fonte completo

#
# First you must require java to gain some special powers
# Remember that this works only with jruby!
#
require 'java'

#
# Then require your jar file. Note that you can't do something like
# import SmallestJar.*. You must require each jar by yourself.
#
require 'SmallestJar'

# Some ways of consuming java classes inside jruby

#
# 1. Let's do it the hard way: using full package name every time
# - remember to always start with a Java:: and then the package namespace
# - some namespaces like org, com, etc. are mapped directly
#

calculator = Java::e7r.Calculator.new
puts calculator.sum(10, 20)

#
# 2. Let's do it the messy way: including the package in the current context
#

include_class Java::e7r.Calculator
calculator = Calculator.new # look mama, no namespaces
puts calculator.sum 10, 20

#
# 3. The man's way: Create a module to put the classes (via include_package)
#

module E7R
  include_package 'e7r'
end

calculator = E7R::Calculator.new
puts calculator.sum 10, 20

# EOF
view raw calculator.rb This Gist brought to you by GitHub.

Conclusão

Poder consumir classes java dentro do jruby somente fazem crescer as possibilidade de ter a um lado uma linguagem moderna, flexível e produtiva com toda a estabilidade e escalabilidade do java.

Preciso fazer uns testes destes usando ironruby.


21
out 10

Usando DSL para simplificar os testes unitários

A primeira vez que vi em ação uma DSL for no Café Ágil que teve aqui em Curitiba, quando o Klaus demonstrou como eles testavam um jogo para o Sneer chamado Go. Eu comentei sobre isso no meu post Testando seu software usando DLS.

Naqueles dias eu estava na mais absoluta ignorância sobre o assunto. Agora eu já progredi e estou na ligeira ignorância sobre o assunto, tanto é que estou começando a poder aplicar as idéias nos cenários de teste que faço.

Eu quero compartilhar um teste que simplifiquei ao utilizar (algo que acho que é) uma DSL. Continue reading →


2
set 10

Testando seu software usando DSL

A mais ou menos um ano, eu comecei a estudar formas de automatizar o teste de software. Seguindo indicações de amigos, acabei esbarrando nas UnitTests.

Nesse momento eu vi a luz!

Continue reading →


18
jul 10

Qual a melhor forma de criar a API da minha aplicação web?

É usar ao máximo os padrões. Você pode inventar, mas quanto mais comum for a tecnologia escolhida, mais conectável você vai ser,

Uma das características que eu mais acho fascinante no mundo web é a possibilidade de aplicações criadas em qualquer ambiente se comunicar com quaisquer outras. Isto é fantástico.

Tem muita gente que acha que para ser um aplicativo web só precisa estar na nevem e rodar em um browser. Ledo engano.

Tem muito site por ai que para mim ainda está na era do stand alone, sendo que ao invés de estar sendo executado local, roda em um servidor remoto, mas só isso.

A facilidade de conectividade do e para o aplicativo está na lista das maiores qualidades de um software da era da web.

É algo lindo de ver, e que eu sequer sonhava que existiriam enquanto ficava lá esperando 30 minutos até meu compilador Clipper Summer’86 gerar minhas poderosas aplicações… tadinhas delas.

Um bom aplicativo tem de permitir que qualquer outro possa se conectar nele e interagir com suas regras de negócio, mais ainda, as regras internas do aplicativo podem inclusive chamar um convidado externo para resolver algo que elas não vão resolver.

Recentemente vi um tweet do Fred indicando um post meio antigo, de 2008, chamado Brincando com a API do twitter. Nele o Élcio mostra como você pode criar um script em shell no linux para twittar da linha de comando.

Com o cURL para Windows e um pouco de criatividade, dá para fazer o mesmo em arquivo de lote.

Não só o Twitter tem uma boa API, mas quase todos os serviços maiores da web também possuem.

Porque você acha que eles crescem tanto? Porque são acessíveis para quaisquer consumidores, e deixam que muitos façam softwares para ele.

Eu sou um exemplo. Nunca usei o Twiter, até que encontrei o Chromed Bird. Agora como o Twitter está sempre à mão ali na barra de ferramentas do meu Google Chrome, acabo twittando o dia todo, e ele verdadeiramente me serve como meio dinâmico de comunicação.

Agora falando sobre a arquitetura destas API’s, a grande maioria delas utiliza somente requisições http, podendo sobre elas criar um padrão RESTfull. É a reinveção do PUT/GET/POST/DELETE :)

O bacana seguir um padrão que é realmente web é que você ao prover o serviço sabe que se você enviar uma resposta 307 o cliente irá entender e fazer nova consulta no endereço que você indicou.

Praticamente tudo dos meios já existe e é amplamente suportado. Cabe a você criar a aplicação :)

Importante: a API do Twitter em 16 de agosto de 2010 passará a exigir outra forma de autenticação, data da qual os exemplos do post do Élcio vão parar de fucionar.