Segundo definição de RMI na
Wikipédia:
" O RMI (Remote Method Invocation), é uma interface de programação que permite a execução de chamadas remotas no estilo RPC em aplicações desenvolvidas em Java.
É uma das abordagens da plataforma Java para prover as funcionalidades de uma plataforma de objetos distribuídos.
Através da utilização da arquitetura RMI, é possível que um objeto ativo em uma máquina virtual Java, possa interagir com objetos de outras máquinas virtuais Java, independentemente da localização dessas máquinas virtuais."
O objetivo dessa dica é mostrar uma aplicação em que o cliente envia uma mensagem para o servidor e obtém o retorno da mensagem convertida para maiúscula usando RMI. A presente aplicação é composta de duas partes, uma parte cliente e outra servidora. O cliente, nesse caso, deve ser capaz de ler a mensagem e chamar o método imprimir mensagem localizada no servidor.
Para compilar, você deve ter o JDK configurado corretamente no PATH do sistema. Caso não tenha o JDK configurado no PATH do sistema, então, acesse:
Passos para criar uma aplicação Java RMI:
1. Criar uma interface derivada de Remote.
2. Criar uma classe que implemente essa interface. Essa será a classe do objeto remoto.
3. Criar uma classe para aplicação servidor.
4. Criar uma classe para aplicação cliente.
5. Compilar a interface:
javac <arquivo interface>
6. Compilar a classe implementação da interface:
javac <arquivo implementa interface>
7. Gerar o Stubs:
rmic <arquivo implementa interface>
8. Executar o serviço de nomes:
rmiregistry -J-Djava.rmi.server.codebase=file://</caminho absoluto onde se encontra as classes da aplicação RMI/>
Exemplo:
< /home/reginaldo/SistemasDistribuidos/AplicacaoRMI/ExemploSimples/ >
9. Executar aplicação servidor:
java <arquivo servidor>
10. Executar aplicação cliente:
java <arquivo cliente>
Arquivo
Hello.java:
import java.rmi.*;
public interface Hello extends Remote{
void imprimirOla(String oqImprimir) throws RemoteException;
}
Arquivo
HelloServidora.java:
import javax.rmi.PortableRemoteObject;
import java.rmi.*;
import javax.swing.*;
import java.rmi.server.UnicastRemoteObject;
public class HelloServidora extends UnicastRemoteObject implements Hello{
public HelloServidora() throws RemoteException{}
public void imprimirOla(String oqImprimir) throws RemoteException{
JOptionPane.showMessageDialog(null,oqImprimir.toUpperCase(),"Mensagem do Objeto Cliente",JOptionPane.INFORMATION_MESSAGE);
}
}
Arquivo
AplicacaoServidora.java:
import java.rmi.*;
public class AplicacaoServidora{
public static void main(String argv[]){
HelloServidora objetoServidor;
try{
objetoServidor = new HelloServidora();
Naming.rebind("rmi://localhost:1099/HelloServidora",objetoServidor);
System.out.println("ObjetoServidor esta ativo!");
}
catch(RemoteException re){
System.out.println("Erro Remoto: "+re.toString());
}
catch(Exception e){
System.out.println("Erro Local: "+e.toString());
}
}
}
Arquivo
AplicacaoCliente.java:
import java.rmi.*;
import javax.swing.*;
public class AplicacaoCliente{
public static void main(String argv[]){
Hello objetoRemoto;
String dados;
try{
objetoRemoto = (Hello) Naming.lookup("rmi://localhost:1099/HelloServidora");
dados = JOptionPane.showInputDialog(null,"Entre com o dado a ser impresso pelo Objeto Remoto","Entrada de Dados",JOptionPane.QUESTION_MESSAGE);
objetoRemoto.imprimirOla(dados);
}
catch(RemoteException re){
JOptionPane.showMessageDialog(null,"Erro Remoto: "+re.toString(),"Erro Remoto",JOptionPane.WARNING_MESSAGE);
}
catch(Exception e){
JOptionPane.showMessageDialog(null,"Erro Local: "+e.toString(),"Erro Local",JOptionPane.WARNING_MESSAGE);
}
}
}
Para facilitar, criei um script em shell que automatiza os passos:
Arquivo
compila_tudo.sh:
#!/bin/bash
javac Hello.java
javac HelloServidora.java
javac AplicacaoServidora.java
javac AplicacaoCliente.java
Arquivo
executa_rmic.sh:
#!/bin/bash
rmic HelloServidora.java
Arquivo
executa_rmiregistry.sh:
#!/bin/bash
echo "digite o caminho absoluto onde se encontra aplicação RMI: Ex: /home/usuario/aplicacaoRMI/RMISimples/"
read caminho
rmiregistry -J-Djava.rmi.server.codebase=file://$caminho
Arquivo
executa_servidor.sh:
#!/bin/bash
java AplicacaoServidora
Arquivo
executa_cliente.sh:
#!/bin/bash
java AplicacaoCliente
Setando permissão de execução para os scripts shell criados:
chmod +x compila_tudo.sh executa_rmic.sh executa_rmiregistry.sh executa_servidor.sh executa_cliente.sh
Executando os scripts:
./compila_tudo.sh
$ ./executa_rmic.sh
$ ./executa_rmiregistry.sh
No terminal servidor:
./executa_servidor.sh
No terminal cliente:
./executa_cliente.sh
Obs. 1: para a execução correta dos scripts shell, os arquivos
.java* e
.class* devem estar no mesmo diretório da aplicação RMI.
Obs. 2: até o Java 6, não precisava informar os parâmetros no comando
rmiregistry e no Java 7 sem os parâmetros informados, dava erro informando não encontrar a classe
Stub, sendo que estava no mesmo diretório.
Se executar o rmiregistry sem parâmetros e for executar aplicação, o servidor irá exibir o erro abaixo:
"Erro Remoto: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: HelloServidora_Stub"
Para resolver esse erro, deve informar na execução do serviço de nomes assim:
rmiregistry -J-Djava.rmi.server.codebase=file://</caminho absoluto onde se encontra as classes da aplicação RMI/>
Obs. 3: testado no Java versão "1.7.0_03".
Espero que essa dica possa ser útil, em sua primeira aplicação cliente e servidor, usando RMI em Java.
Segue screenshot de execução da presente aplicação simples RMI em funcionamento:
Cliente digitando mensagem
Cliente recebeu mensagem convertida para maiúscula do servidor
Feito!