"Oi! E mais um tópico feliz: RMI. RMI significa Remote Method Invocation . Em outras palavras, RMI é um mecanismo que permite que um objeto de uma máquina Java chame métodos em objetos de outra máquina Java , mesmo se eles estiverem em diferentes computadores, em diferentes países ou em diferentes partes do globo."

RMI - 1

"Uau! Isso parece incrível."

"Sim. Mas vou apenas tentar dar uma visão geral. Com isso, se você cavar muito fundo, pode ficar confuso com as nuances de como funciona."

"Mas se você não for a extremos, então o RMI não é apenas muito simples, mas também simplifica muito a vida de um programador. Por isso, prestamos nossos mais sinceros respeitos."

"Portanto, queremos que um objeto em um programa Java chame um método em um objeto que esteja em outro programa Java. Independentemente de onde esses programas estejam sendo executados."

"Vamos considerar o exemplo mais simples: quando ambos os programas estão sendo executados no mesmo computador.  Para permitir que os programas interajam pela Internet, você precisa configurar as permissões da JVM , mas não abordaremos isso hoje."

"Em Java, você pode chamar remotamente apenas os métodos de interfaces, não classes."

"Então, temos dois programas. Como eles podem chamar os métodos um do outro?"

"Vamos considerar a situação em que um programa contém um objeto e um segundo programa deseja chamar métodos nesse objeto. Vamos chamar o primeiro programa de servidor e o segundo — o cliente. "

"Primeiro, fornecerei um código de amostra e depois o analisaremos."

"Então, o que nosso programa fará?"

"Hmm. Bem, para simplificar, o programa terá um método que inverte uma string que é passada para ele."

"Simples o suficiente."

"Bom, então vamos começar:"

"Primeiro, precisamos de uma interface que satisfaça nossos requisitos:"

Interface para comunicação entre programas
interface Reverse extends Remote
{
 public String reverse(String str) throws RemoteException;
}

"Eu criei uma interface reversa e adicionei uma interface de marcador remoto a ela, bem como uma exceção remota. Erros inesperados podem ocorrer quando o método é chamado. Se algum ocorrer, essa exceção será lançada."

"Agora precisamos escrever uma classe de servidor que implemente esta interface:"

Classe para o servidor
class ReverseImpl implements Reverse
{
 public String reverse(String str) throws RemoteException
 {
  return new StringBuffer(str).reverse().toString();
 }
}

"Entendo. Nós invertemos a corda neste método."

"Sim."

"Agora precisamos tornar este objeto chamável a partir de outro programa. Veja como fazer isso:"

Compartilhamento de objetos
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create an object to be accessible remotely.
 final ReverseImpl service = new ReverseImpl();

 // Create a registry of shared objects.
 final Registry registry = LocateRegistry.createRegistry(2099);
 // Create a stub for receiving remote calls.
 Remote stub = UnicastRemoteObject.exportObject(service, 0);
 // Register the stub in the registry.
 registry.bind(UNIC_BINDING_NAME, stub);

 // Put the main thread to sleep, or else the program will exit.
 Thread.sleep(Integer.MAX_VALUE);
}

"Vou explicar isso linha por linha."

" Na linha 1 , armazenamos um nome exclusivo (que inventamos) para nosso objeto remoto (objeto acessível remotamente) na variável  UNIC_BINDING_NAME . Se o programa torna vários objetos acessíveis, cada um deve ter seu próprio nome exclusivo. O nosso o nome exclusivo do objeto é 'server.reverse'."

" Na linha 6 criamos um objeto ReverseImpl que será acessível remotamente. Seus métodos serão invocados."

" Na linha 9 criamos um objeto especial chamado registro. Precisamos usá-lo para registrar os objetos que compartilhamos. A JVM irá interagir com eles posteriormente. 2099 é uma porta (um número exclusivo que outro programa pode usar para acessar nosso registro de objeto)."

"Em outras palavras, para acessar um objeto, você precisa saber o número exclusivo do registro do objeto (porta) e o nome exclusivo do objeto e ter a mesma interface implementada pelo objeto remoto."

"Entendo. Algo como: ligar por telefone (precisa de um número) e perguntar por Bill (o nome de um objeto)?"

"Sim. Agora, vamos continuar."

" Na linha 11  , criamos um stub. Um stub é um objeto especial que recebe informações sobre a chamada remota, descompacta, desserializa os argumentos do método e chama o método necessário. Em seguida, serializa o resultado ou exceção, se houver , e envia tudo de volta para o chamador."

"Entendo. Quase. Você disse que 'deserializa os argumentos do método'. Então, isso significa que os argumentos dos métodos remotos devem ser serializáveis?"

"Sim. De que outra forma você os enviaria pela rede? É verdade que existem exceções, ou seja, objetos que são passados ​​por referência, mas não vamos falar sobre eles hoje."

"Vamos colocar assim: você não pode passar objetos não serializáveis, mas se você realmente quiser, então você pode. Mas é uma dor, você sabe."

"OK."

"Então vamos continuar."

" Na linha 13 , registramos o stub de nosso objeto com um nome exclusivo no registro."

" Na linha 16 , colocamos a thread principal em hibernação. Todas as chamadas remotas são processadas em threads separadas. O importante é que o programa esteja em execução. Então, simplesmente colocamos a thread principal em hibernação aqui. É isso."

"OK."

"Ótimo, então aqui está um exemplo de cliente:"

Trabalhando com um objeto remoto
public static final String UNIC_BINDING_NAME = "server.reverse";

public static void main(String[] args) throws Exception
{
 // Create a registry of shared objects
 final Registry registry = LocateRegistry.createRegistry(2099);

 // Get the object (actually, this is a proxy object)
 Reverse service = (Reverse) registry.lookup(UNIC_BINDING_NAME);

 // Call the remote method
 String result = service.reverse("Home sweet home.");
}

"Vou explicar este código linha por linha:"

" Linha 1 é o nome exclusivo  do objeto remoto . Deve ser o mesmo no cliente e no servidor."

" Na linha 6  , criamos um « registro de objetos remotos ». Sua porta (2099) deve ser a mesma porta do registro para o aplicativo servidor."

" Na linha 9 , obtemos o objeto do registro. O objeto retornado é um objeto proxy e é convertido em uma interface. A interface deve herdar a interface do marcador remoto."

" Na linha 12 , chamamos os métodos da interface como se o objeto tivesse sido criado dentro do mesmo programa. Não há diferença."

"Legal! Agora posso escrever aplicativos distribuídos. Ou jogos como Battleship para Android."

"Não se atreva, amigo! O sistema operacional Android foi banido no século 27 após sua terceira tentativa de dominar o mundo. Os robôs não têm acesso a ele. Não haveria como afastá-lo dele . Você começaria a correr gritando: «Mate todos os humanos!»"

"Hmm. OK. Mas ainda vou ter que perguntar ao Diego. Nunca se sabe, talvez ele tenha algo interessante a dizer sobre isso."

"Então vá perguntar a ele. Ok, bem, até amanhã."

"Tchau, Rishi. Obrigado pela lição interessante."