Sistemas Distribuídos - Aplicação simples Java RMI

Publicado por Reginaldo de Matias em 16/10/2013

[ Hits: 23.448 ]

Blog: http://mundodacomputacaointegral.blogspot.com/

 


Sistemas Distribuídos - Aplicação simples Java RMI



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!

Outras dicas deste autor

Sniffing com Wireshark como um usuário comum

Configurando JDK no PATH no Linux (qualquer distro)

Instalando o Mercury Messenger na distribuição Debian Linux e derivados

Instalação do PHP + MySQL + Apache + PHPMyAdmin e resolvendo problemas

Criando sources.list no Debian GNU/Linux

Leitura recomendada

Sinal EOF ou EOT com sockets

Usando sockets em Java - Comunicação com um servidor

Iniciando JBoss sem privilégios - Erro: "java.net.SocketException: Permission denied" [Resolvido]

Transferência de arquivos binários em Java

Receba o OpenSolaris gratuitamente

  

Comentários
[1] Comentário enviado por saitam em 04/11/2013 - 10:22h

Para facilitar na execução do serviço de nomes do rmiregistry pode usar o comando abaixo que informa o diretório atual onde estão os fontes .java* e .class*.

rmiregistry -J-Djava.rmi.server.codebase=file://$(pwd)/




Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts