
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
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.