Em um projeto aqui na empresa, estava precisando acessar o webservice do SugarCRM. O problema aconteceu quando descobri que o estilo de binding dele era rpc/encoded e que os projetos em Java mais atuais não estavam dando suporte a isso, alguns exemplos são : Axis2 e CXF.
Então foi que pensei, deixa eu ver se tem jeito de fazer isso em Ruby, e descobri que era até meio ridiculo…
require('md5')
require 'soap/wsdlDriver'
@wsdl = "http://localhost/settech_orcamentos/soap.php?wsdl"
@soap = SOAP::WSDLDriverFactory.new(@wsdl).create_rpc_driver
resultado = @soap.login({:user_name=>"login",:password=>MD5.new("password"),:version=>"5.1.0a"},"SugarCRM")
puts resultado.id
Isso porque o Ruby faz o parse do wsdl em tempo de execução e cria uma classe para você naquele momento, na verdade um proxy, e permite que todos os metodos sejam acessados. Ainda conta a ferramenta wsdl2ruby para fazer algo similar ao wsdl2java.
Com isso em mãos, resolvi fazer o mix de Java com Ruby, usando o Java como linguagem, mas também como plataforma para execução de código, nesse caso o Ruby através da sua implementação em Java, JRuby. Isso oferece um potencial incrível pois, por exemplo, podemos usar o potencial do Ruby para fazer algo que Java não seja muito bom ou até querer manter um código em Java que seja dinâmico, sim é permitido acessar as API’s do Java através do Ruby. Abaixo segue o código que fiz. A primeira parte em Ruby e a segunda em Java. As variaveis no código Ruby que estão com $, foram compartilhadas do código em Java para o Ruby
require('java')
include_class('br.com.settech.sugarsoap.Result')
include_class('br.com.settech.sugarsoap.helper.ContextSoapComunication')
require 'soap/wsdlDriver'
require 'MD5'
module IntegracaoSugarCRM
class SugarCRM
def initialize(name_value_pairs)
@name_value_pairs = name_value_pairs
@params = Array.new
end
def params
@name_value_pairs.each {|name_value_pair| @params.push({:name=>name_value_pair.name,:value=>name_value_pair.value})}
@params
end
end
class Integrador
def initialize
if not $context
@soap = SOAP::WSDLDriverFactory.new($info.url_wsdl).create_rpc_driver
end
end
def login
result = @soap.login({:user_name=>$info.login,:password=>MD5.new($info.password),:version=>$info.version},$info.app_name)
ContextSoapComunication.new(Result.new(result.error.number,result.error.description,result.id),@soap)
end
def logout
#logout aqui
end
#Usa as variaveis definidas no codigo java.
def executa_metodo
params = SugarCRM.new($name_value_pairs).params
result = $context.driver.set_entry($context.login_id,$which_module,params)
Result.new(result.error.number,result.error.description,result.id)
end
end
end
if not $context
IntegracaoSugarCRM::Integrador.new.login
else
IntegracaoSugarCRM::Integrador.new.executa_metodo
end
public class JRubyIntegrationTest {
private ContextSoapComunication contextSoapComunication;
private BSFHelper helper;
@Before
public void testCreateLogin() throws BSFException,IOException{
helper = new BSFHelper();
SugarInfo sugarInfo = new SugarInfo("login","password","SugarCRM","5.1.0a","http://localhost/settech_orcamentos/soap.php?wsdl");
helper.declareBean("info",sugarInfo);
this.contextSoapComunication = (ContextSoapComunication)helper.evalFile("C:\\ambiente\\ruby_project\\IntegracaoSugarCRM\\lib\\integrador.rb");
this.contextSoapComunication.loginId();
}
@Test
public void testExecuteJRubyCode() throws BSFException,IOException{
NameValuePairCreator lista = new NameValuePairCreator();
this.helper.declareBean("which_module",ModuleTypes.OPPORTUNITIES);
this.helper.declareBean("name_value_pairs",lista.addNameValuePair("lead_source","Self Generated").addNameValuePair("name","Projeto integracao2").addNameValuePair("amount","53500.55").nameValuePairList());
this.helper.declareBean("context",this.contextSoapComunication);
Result result = (Result)helper.evalFile("C:\\ambiente\\ruby_project\\IntegracaoSugarCRM\\lib\\integrador.rb");
System.out.println(result.createdId());
helper.finalize();
}
}
Para acessar o script através do Java, uso o projeto BSF(Bean Scripting Framework), ideal para quem, como eu, está no Java 5 ainda. A classe BSFHelper foi extraída do site ociweb.com. A única ressalva que faço, é que para usar um script que faça uso do require ou algo parecido, devemos forncer ao BSF a localização das bibliotecas. Para fazer isso, coloque o seguinte código:
System.getProperties().put("jruby.lib",jrubyBase+"\\lib");
System.getProperties().put("jruby.home",jrubyBase);
Bom, por hoje é isso, desculpem o tamanho do post, mas queria mostrar algo que foi realmente útil para mim e acho que pode ser para vocês também.
Estudando Ruby, nós do Java ou .NET, vemos umas coisas que nos parecem meio estranhas. Por exemplo, todo metodo retorna algo, mas para que eu quero que meu metodo setter retorne alguma coisa?. Bem, inicialmente pode não fazer sentido, mas se parar e der uma olhada, verá que não faz diferença nenhuma para seu código se seu metodo pessoa.setNome(”Alberto”) retornar uma referencia para ele mesmo(this).
Você usa o retorno se quiser, querendo pode fazer algo besta, mas na minha opinião muito mais legivel,
pessoa.setNome("Alberto").setSobreNome("Souza").qqCoisaAqui(...);
É isso que venho colocando na minha cabeça, aprender uma linguagem nova é muito legal, mesmo que não coloquem em produção, não custa nada dar uma olhada, ver uma forma diferente de fazer algo.
