O que é RMI?
Java RMI é um mecanismo para permitir a invocação de métodos que residem em diferentes máquinas virtuais Java (JVM). O JVM pode estar em diferentes máquinas ou podem estar na mesma máquina. Em ambos os casos, o método pode ser executado em um endereço diferente do processo de chamada. Java RMI é um mecanismo de chamada de procedimento remoto orientada a objetos.
Aplicação de objetos distribuídos
Uma aplicação RMI é frequentemente composto por dois programas diferentes, um servidor e um cliente. O servidor cria objetos remotos e faz referências a esses objetos disponíveis. Em seguida, ele é válido para clientes invocarem seus métodos sobre os objetos.
O cliente executa referências remotas aos objetos remotos no servidor e invoca métodos nesses objetos remotos.
O modelo de RMI fornece uma aplicação de objetos distribuídos para o programador. Ele é um mecanismo de comunicação entre o servidor e o cliente para se comunicarem e transmitirem informações entre si. A aplicação de objetos distribuídos tem de prover as seguintes propriedades:
- Localização de objetos remotos: O sistema tem de obter referências a objetos remotos. Isto pode ser feito de duas maneiras. Ou, usando as instalações de nomeação do RMI, o registro RMI, ou passando e retornando objetos remotos.
- Comunicação com objetos remotos: O desenvolvedor não tem de lidar com a comunicação entre os objetos remotos desde que este é tratado pelo sistema RMI.
- Carregar os bytecodes de classe dos objetos que são transferidos como argumentos ou valores.
Todos os mecanismos para carregar o código de um objeto e transmitissão dos dados são fornecidos pela RMI system.40
Interfaces e Classes
Java RMI é um sistema de linguagem individual, a programação de aplicação distribuída em RMI é bastante simples. Todas as interfaces e classes para o sistema de RMI são definidos no pacote java.rmi. A classe de objeto remoto implementa a interface remota, enquanto as outras classes estendem RemoteObject.
A interface remota
Uma interface remota é definida pela extensão da interface Remote que está no pacote java.rmi. A interface que declara os métodos que os clientes podem invocar a partir de uma máquina virtual remoto é conhecido como interface remota. A interface remota deve satisfazer as seguintes condições:
- Deve estender-se a interface Remote.
- Cada declaração de método na interface remota deve incluir a exceção RemoteException (ou uma de suas superclasses), em sua cláusula lançada.
A classe RemoteObject
Funções do servidor RMI são fornecidos pela classe RemoteObject e suas subclasses Remote Server, Activatable e UnicastRemoteObject. Aqui está uma breve descrição de como lidar com as diferentes classes:
- RemoteObject fornece implementações dos métodos toString, equals e hashCode na classe java.lang.Object.
- As classes UnicastRemoteObject e Activatable cria objetos remotos e os exporta, ou seja, essas classes fazem os objetos remotos usados por clientes remotos.
A classe RemoteException
A classe RemoteException é uma super-classe das exceções que o sistema RMI joga durante uma invocação de método remoto. Cada método remoto que é declarado em uma interface remota deve especificar RemoteException (ou uma de suas superclasses), em sua cláusula throws para garantir a robustez das aplicações no sistema RMI.
Quando uma chamada de método remoto tiver um erro, a exceção RemoteException é lançada. Falha de comunicação, erros de protocolo e falha durante a triagem ou unmarshalling de parâmetros ou valores de retorno são algumas das razões para o fracasso da comunicação RMI. RemoteException é uma exceção que deve ser tratada pelo método chamador. O compilador confirma que o programador de ter lidado com essas exceções.
Implementação de um simples sistema RMI
Este é um sistema de RMI simples com um cliente e um servidor. O servidor contém um único método hello (Olá), que retorna uma String para o cliente.
Para criar o sistema RMI todos os arquivos tem que estar compilados. Em seguida, o outline e stub, que são mecanismos de comunicação padrão com objetos remotos, são criadas com o compilador RMIC. [Este sistema RMI contém os seguintes arquivos:
- Hello.java: A interface remota.
- HelloClient.java: A aplicação cliente no sistema RMI.
- HelloServer.java: O aplicativo de servidor no sistema RMI.
- Quando todos os arquivos são compilados, executando o seguinte comando irá criar o stub e o skeleton: RMIc HelloServer
Em seguida, as duas classes serão criados, HelloServer_Stub.class e HelloServer_Skel.class, onde a primeira classe representa o lado do cliente do sistema RMI e o segundo arquivo representa o lado do servidor do sistema RMI.
Listagem 1: Hello.java
import java.RMI.Remote;
import java.RMI.RemoteException;
/*
Classname: Hello
Comment: The remote interface.
*/
public interface Hello extends Remote {
String Hello() throws RemoteException;
}
Listagem 2: HelloClient.java
import java.RMI.Naming;
import java.RMI.RemoteException;
/*
Classname: HelloClient
Comment: The RMI client.
*/
public class HelloClient {
static String message = "blank";
// The Hello object "obj" is the identifier that is
// the Hello interface.
static Hello obj = null;
public static void main(String args[])
{
try {
obj = (Hello)Naming.lookup("//"
+ "kvist.cs.umu.se"
+ "/Hello");
message = obj.Hello();
System.out.println("Mensagem no servidor RMI de: \""
+ message + "\"");
}
catch (Exception e) {
System.out.println("HelloClient exception: "
+ e.getMessage());
e.printStackTrace();
}
}
}
Listagem 3: HelloServer.java
import java.RMI.Naming;
import java.RMI.RemoteException;
import java.RMI.RMISecurityManager;
import java.RMI.server.UnicastRemoteObject;
/*
Classname: HelloServerDemo
Purpose: The RMI server.
*/
public class HelloServerDemo extends UnicastRemoteObject
implements Hello {
public HelloServerDemo() throws RemoteException {
super();
}
public String Hello() {
System.out.println("Invocation to Hello was succesful!");
return "Hello World from RMI server!";
}
public static void main(String args[]) {
try {
// Creates an object of the HelloServer class.
HelloServer obj = new HelloServer();
// Bind this object instance to the name "HelloServer".
Naming.rebind("Hello", obj);
System.out.println("Ligado no registro");
}
catch (Exception ex) {
System.out.println("error: " + ex.getMessage());
e.printStackTrace();
}
}
Saída:
Mensagem do servidor RMI de: Joe
Ligado no registro
Listagem 4: Programa para implementar Calculadora usando RMI - Calcutator.java
import java.RMI.Remote;
import java.RMI.RemoteException;
public interface Calcutator extends Remote
{
public long add(long a, long b) throws RemoteException;
}
Listagem 5: CalculatorImple.java
import java.RMI.RemoteException;
import java.RMI.server.UnicastRemoteObject;
public class CalculatorImple extends UnicastRemoteObject implements Calculator
{
protected CalculatorImple() throws RemoteException
{
super();
}
public long add(long a, long b) throws RemoteException
{
return a+b;
}
}
Listagem 6: CalculatorServer.java
import java.RMI.Naming;
public class CalculatorServer
{
CalculatorServer()
{
try
{
Calcutator c = new CalculatorImple();
Naming.rebind("RMI://127.0.0.1:1020/CalculatorService", c);
}
catch (Exception e)
{
e.printStackTrace();
}
}
public static void main(String[] args)
{
new CalculatorServer();
}
}
Listagem 7: CalculatorClient.java
import java.RMI.Naming;
public class CalculatorClient
{
public static void main(String[] args)
{
try
{
Calculator c = (Calculator) Naming.lookup("//127.0.0.1:1020/CalculatorService");
System.out.println("Adição : "+c.add(20, 15));
}
catch (Exception e)
{
System.out.println(e);
}
}
}
Passos para executar esses programas:
Primeiro de tudo, colocar todas essas quatro classes dentro da pasta bin do JDK. Vamos supor que a nossa pasta JDK está dentro da pasta java na unidade E:, agora com o prompt de comando aberto executamos o seguinte:
cd e:
cd Java \ jdk1.6.0_23 \ bin
javac Calculator.java
javac CalculatorImple.java
javac CalculatorServer.java
javac CalculatorClient.java
rmic CalculatorImple
iniciar registro RMI
java CalculatorServer
Abrir outro prompt de comando e novamente ir para mesmo caminho e: \ java1 \ jdk1.6.0_23 \ bin
java CalculatorClient
O resultado será:
Adição: 35
Conclusão
Neste artigo, vimos como podemos usar diferentes métodos em diferentes JVM e combiná-los para usar como um único aplicativo. RMI é útil em um aplicativo do servidor onde se quer comunicar com diferentes JVM.RMI usa serialização marshal e unmarshal, reforçando verdadeiro polimorfismo orientado a objetos.
Artigo traduzido e originalmente publicado em: http://mrbool.com/rmi-remote-method-invocation-in-java/28575