Tutorial RMI - Remote Method Invocation

 

Java RMI: Conceitos Básicos

 

Java RMI (Remote Method Invocation) permite que objetos Java executando no mesmo computador ou em outros computadores comuniquem entre si por meio de chamadas de métodos remoto. Essas chamadas de métodos são semelhantes àquelas que ocorrem entre objetos de um mesmo programa.

RMI está baseado em uma tecnologia anterior semelhante para programação procedural, chamada de chamada de procedimentos remotos (Remote Procedure Calls, ou RPC), desenvolvida nos anos 80.

Sendo uma extensão de RPC, Java RMI permite comunicação distribuída de um objeto Java com outro. Uma vez que um método (ou serviço) de um objeto Java é registrado em um Servidor de Nomes como sendo remotamente acessível, um cliente pode pesquisar esse serviço e receber uma referência que permita utilizar o mesmo (isto é, chamar seus métodos). A sintaxe usada em chamadas de métodos remotos é idêntica àquela de uma chamada para um método de outro objeto no mesmo programa. Como ocorre em RPC, o empacotamento dos dados é tratado pelo RMI. O programador não precisa se preocupar com a transmissão dos dados sobre a rede. RMI também não exige que o programador domine qualquer linguagem particular para definição de interfaces, porque todo o código de rede é gerado diretamente a partir das classes existentes no programa.

 

Java RMI: Arquitetura

 

A arquitetura de Java RMI é dividida em três camadas:

 

·        A camada de stub/skeleton oferece as interfaces que os objetos da aplicação usam para interagir entre si.

·        A camada de referência remota é responsável por criar e gerenciar referências para objetos remotos;

·        A camada de transporte implementa o protocolo que especifica o formato de solicitações enviadas aos objetos remotos pela rede.

 

arqrmi.gif

Figura 1 – Arquitetura de camadas de RMI.

 

 

 

Java RMI: Exemplo de Uso

 

No desenvolvimento de uma aplicação cliente-servidor usando Java RMI, é essencial que seja definida a interface de serviços que serão oferecidos pelo objeto servidor. A especificação de uma interface remota é equivalente à definição de qualquer interface em Java, a não ser pelos seguintes detalhes:

 

• A interface deverá, direta ou indiretamente, estender a interface Remote.

 

• Todo método da interface deverá declarar que a exceção RemoteException (ou uma de suas subclasses) pode ser gerada na execução do método.

 

O exemplo de definição de interface abaixo relaciona os métodos que serão invocados remotamente usando Java RMI. Este exemplo descreve uma aplicação de Chat onde clientes interagem com o servidor conectando, enviando mensagens e desconectando. O servidor interage com um cliente enviando mensagens de outros clientes.

 

public interface ServidorChat extends Remote {

public String conectar (Cliente c) throws RemoteException;

public void enviar (String mensagem) throws RemoteException;

public void desconectar(Cliente c) throws RemoteException;

}

 

 

Já o código mostrado a seguir descreve a interface de um cliente da aplicação de Chat, a qual contém o método exibir cuja função é mostrar a mensagem propagada pelo servidor da aplicação.

 

public interface Cliente extends Remote {

public void Exibir(String mensagem) throws RemoteException;

}

 

Em seguida, classe ServidorImpl que estende UnicastRemoteObject implementa os métodos remotos conectar, desconectar e enviar definidos na interface servidora citada acima.

 

public class ServidorImpl extends UnicastRemoteObject

implements Servidor {

 

O método remoto conectar possui um vetor dinâmico onde são armazenadas referências para os objetos clientes conectados à aplicação.

 

public String conectar (Cliente c) throws RemoteException {

conectados.addElement(o);

return("Usuario Conectado");

}

 

O método remoto desconectar elimina uma referência remota armazenada no vetor de clientes conectados.

 

public void desconectar (Cliente c) throws RemoteException {

conectados.remove(c);

}

 

O método remoto enviar descrito abaixo obtém uma referência para objetos dos clientes através do vetor de conectados e envia as mensagens para os mesmos.

 

public void enviar (String mensagem) throws RemoteException {

do {

Cliente c =(Cliente) conectados.elementAt(i);

c.exibir(mensagem);

} while (i<conectados.size());

}

O programa principal do servidor da aplicação de Chat é responsável por registrar o objeto remoto do servidor no serviço de nomes de Java RMI, por meio do método Naming.rebind (“Servidor”,s), onde “Servidor” é o nome do objeto servidor e “s” é uma referência para o mesmo.

 

public static void main (String[] args) {

try {

Servidor s= new ServidorImpl();

Naming.rebind("Servidor",s);

} catch (Exception e) {

System.out.println ("Erro no servidor: " + e.getMessage()); }

 

Descreve-se a seguir a implementação da aplicação cliente do sistema de Chat. A principal classe do cliente é denominada ClienteImpl. Essa classe implementa o método “exibir” definido na interface Cliente.

 

public class ClienteImpl extends UnicastRemoteObject

implements Cliente {

 

O método exibir mostra as mensagens recebidas do servidor na tela do cliente.

 

public void exibe(String m) throws RemoteException {

try{

interface.append(m+"\n");

} catch(Exception e ){

System.out.println("Erro"+ e);

}

}

 

O programa principal do cliente é responsável por acessar o Serviço de Nomes de Java RMI e obter uma referência remota para o objeto servidor. Dessa forma, o cliente poderá se conectar, enviar mensagens e se desconectar.

 

public static void main (String[] args) {

Servidor s= (Servidor) Naming.lookup("Servidor");

c.conectar(); // chamada remota

......

c.enviar(mensagem);

......

c.desconectar();

......

}

 

A execução da aplicação cliente-servidor em RMI requer, além da execução da aplicação cliente e da execução da aplicação servidora, a execução do Servidor de Nomes de RMI. O aplicativo rmiregistry faz parte da distribuição básica de Java e é encarregado de executar o Servidor de Nomes. Tipicamente, esse aplicativo é executado como um processo em background que fica aguardando solicitações em uma porta, que pode ser especificada como argumento na linha de comando. Se nenhum argumento for especificado, a porta 1099 é usada como padrão.

Em uma arquitetura de objetos distribuídos, nem sempre a comunicação no estilo cliente-servidor é suficiente para atender aos requisitos de todas as aplicações. É usual que um servidor RMI funcione algumas vezes como cliente, invertendo os papéis com o cliente original. O mecanismo para atingir esse objetivo é chamado de callback. Esta técnica é tipicamente utilizada quando a aplicação cliente requer um retorno do servidor mas não pode permanecer bloqueada aguardando uma resposta. Através dessa técnica, o servidor obtém uma referência para o cliente de forma que possa invocar remotamente um método do mesmo. Assim, quando a execução do serviço solicitado é concluída, o servidor pode  notificar o cliente através da invocação do método disponibilizado pelo mesmo para uso remoto.

 

Agradeço sua atençao e em que eu puder ajudar meu e-mail é:

cristiano@supervix.com.br