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

Publicado por Reginaldo de Matias em 16/10/2013

[ Hits: 23.511 ]

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

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

Sniffing com Wireshark como um usuário comum

Questões de conhecimentos básicos de Linux - LPIC 1

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

Conceitos básicos e história do Linux

Leitura recomendada

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

Sinal EOF ou EOT com sockets

Transferência de arquivos binários em Java

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

Controle de banda no Debian Sarge

  

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