Olá Pessoal. Estou iniciando o desenvolvimento no mundo móvel e me deparei com uma situação desafiadora. Como transmitir dados de um cliente móvel para um servidor Java. A única solução que eu tinha achado era através de sockets. Porém, eu consegui achar uma solução que usasse RMI.
Portanto, para quem enfrenta o mesmo problema que eu, vou postar um minitutorial sobre como conseguir tal facenha.
RMI, Invicação de Métodos Remotos, demonstra um cenário aonde é possível acessar métodos de um objeto que não estão localizados na máquina ou dispositivo aonde se está rodando a aplicação. Para quem deseja saber um pouco mais sobre RMI, acesse o tutorial Introdução ao RMI aqui do GUJ.
A solução RMI para J2ME (MIDP 2.0) foi proposta pelo projeto Arcademis, e a solução para o SW foi feita pelo mesmo projeto, por mim, porém apenas recompilando o código alterando as classes de sockets e outras coisinhas… Créditos totais ao pessoal do Arcademis!
Para começar, efetue o download das três APIS que seguem no fim do tutorial:
arcademis_J2SE.jar: API para o servidor J2SE ou EE
arcademis_J2ME.jar: API para o cliente J2ME
arcademis_SW.jar: API para o cliente SuperWaba
Para testes, a seguinte aplicação vai ser desenvolvida: um cliente pede ao servidor os seus dados (nome do SO, versão, etc) e ele retorna uma string contendo esses dados. Vamos começar implementando a interface remota:
/*
* SystemInformatation.java
* ------------------------
* Interface de um objeto Remoto para retornar informações sobre o sistema
* operacional de um host
*/
package rmi;
import arcademis.*;
public interface SystemInformation extends Remote {
String getInformation() throws ArcademisException;
}
Em seguida, vamos implementar essa interface remota
/*
* SimpleSystemInformatation.java
* ------------------------------
* Implementação da Interface Remota SystemInformatation para obter
* informações do sistema operacional de um host
*/
package rmi;
import rme.server.RmeRemoteObject;
public class SimpleSystemInformation extends RmeRemoteObject
implements SystemInformation {
public SimpleSystemInformation() {
}
public String getInformation() {
String info = "";
info += "Sistema Operacional: " + System.getProperty("os.name");
info += "\nArquitetura: " + System.getProperty("os.arch");
info += "\nVersão SO: " + System.getProperty("os.version");
info += "\nUsuário: " + System.getProperty("user.name");
return info;
}
}
Se vc entende um pouco da arquitetura do RMI, sabe que essa comunicação exige que vc tenha compilado os stubs e skeletons da implementação da interface remota, pois eles vão servir de elo de ligação e sincronização. Para esse projeto, vc vai ter que efetuar isso no braço. Não é nada complicado. Adiaremos esse passo.
Agora vamos implementar o servidor. Adicione o jar do servidor ao classpath do seu projeto e mãos a obra!
/*
* Servidor.java
*/
import rme.RmeConfigurator;
import rme.naming.NameServer;
import rme.naming.RmeNaming;
import rmi.SimpleSystemInformation;
public class Servidor{
/* No construtor, inicia-se o serviço de registro de Objeto Remoto. TimeOut de 3 seg */
public Servidor() throws Exception {
System.out.println("Executando o serviço de registro de objeto remoto...");
NameServer.main(new String[0]);
Thread.sleep(3000);
System.out.println("Serviço OK!");
}
public void execute() {
try {
RmeConfigurator mc = new RmeConfigurator();
mc.configure();
SimpleSystemInformation infoObj = new SimpleSystemInformation();
System.out.println("Registrando objeto Remoto...");
RmeNaming.bind("rmeTeste",infoObj);
System.out.println("Registrado!");
infoObj.activate();
}
catch (Exception e)
{
System.err.println("Erro " + e);
e.printStackTrace();
System.exit(2);
}
System.out.println("Esperando por ação...");
}
// Gerando os stubs e skeletons
public static void main(String args[]) {
String localPath = new java.io.File("").getAbsolutePath() + "/src";
rme.rmec.RmeC.main(new String[] {"-d", localPath,
"rmi.SimpleSystemInformation"} );
}
}
Observe que o servidor possui um método main, mais ele só serve para gerarmos os stubs e skeletons. Coloquei ele aí para facilitar apenas isso. Aquela classe RmeC é a responsável pela geração dos stubs e skeletons. Simples, execute do jeito que está ali, que se o seu projeto tem uma pasta de fontes chamada src, ele vai pro local certo! Só tome cuidado com o último parâmetro: deve ser o nome da classe que possui a implementação da interface remota (sem o .java) e precedido da hierarquia de pacotes. Nesse caso, a classe está dentro do pacote rmi.
Agora faça alguma interfacizinha bem bonitinha e inicie o servidor:
try {
new Servidor().execute();
} catch (Exception ex) {
System.err.println("Erro ao instanciar o servidor!");
}
Pronto. Servidor rodando. Agora vamos implementar o cliente. A única diferença da implementação entre J2ME e SW é o jar que vc inclui no seu classpath e os imports. O código é exatamente o mesmo!
Copie pro projeto de app móvel as classes de interface remota e o Stub da implementação remota, no caso teste, os arquivos SystemInformation.java e SimpleSystemInformation_Stub.java. O importante é que elas estejam no mesmo pacote que estavam no servidor, senão dá erro!
Agora, finalmente, a implementação do cliente:
/*
* RMIClient.java
* --------------
* Cliente de uma aplicação cliente-servidor utilizando RMI
*/
import rme.RmeConfigurator;
import rme.naming.RmeNaming;
public class RMIClient {
/* Método do cliente que chama a execução do método remoto */
public String getSystemInfo(String host) throws Exception {
SystemInformation info = null;
try {
System.out.println("Configurando...");
RmeConfigurator conf = new RmeConfigurator();
conf.configure();
System.out.println("Procurando por objeto remoto...");
info = (SystemInformation)RmeNaming.lookup("rmeTeste");
}
catch( Exception e )
{
e.printStackTrace();
throw new Exception("Erro ao procurar o objeto remoto!\n" + e);
}
try {
// Executando a chamada remota
return info.getInformation();
}
catch( Exception ex ) {
ex.printStackTrace();
throw new Exception("Erro ao realizar a chamada remota!\n" + ex);
}
}
}
Pronto! Agora faça a chamada do cliente em alguma outra interfacizinha bonita pelo código abaixo:
RMIClient client = new RMIClient();
try {
System.out.println(client.getSystemInfo("127.0.0.1"));
} catch (Exception e) {
e.printStackTrace();
}
Abaixo, seguem os jars…
Um abraço a todos, algum problema é só postar!
Até a próxima, pessoal!