Introdução ao Java RMI

Introdução ao Java RMI

1. Visão geral

Quando duas JVMs precisam se comunicar, o Java RMI é uma opção que temos para fazer isso acontecer. Neste artigo, vamos inicializar um exemplo simples mostrando a tecnologia Java RMI.

2. Criação do servidor

Há duas etapas necessárias para criar um servidor RMI:

  1. Crie uma interface definindo o contrato de cliente / servidor.

  2. Crie uma implementação dessa interface.

2.1. Definindo o Contrato

Em primeiro lugar, vamos criar a interface para o objeto remoto. Essa interface estende a interface do marcadorjava.rmi.Remote.

Além disso, cada método declarado na interface lança ojava.rmi.RemoteException:

public interface MessengerService extends Remote {
    String sendMessage(String clientMessage) throws RemoteException;
}

Observe, porém, que o RMI suporta a especificação Java completa para assinaturas de método, contanto que os tipos Java implementemjava.io.Serializable.

Veremos em seções futuras como o cliente e o servidor usarão essa interface.

Para o servidor, criaremos a implementação, geralmente conhecida comoRemote Object.

Para o cliente,the RMI library will dynamically create an implementation called a Stub.

2.2. Implementação

Além disso, vamos implementar a interface remota, novamente chamada deRemote Object:

public class MessengerServiceImpl implements MessengerService {

    @Override
    public String sendMessage(String clientMessage) {
        return "Client Message".equals(clientMessage) ? "Server Message" : null;
    }

    public String unexposedMethod() { /* code */ }
}

Observe que deixamos de fora a cláusulathrowsRemoteException da definição do método.

Seria incomum para nosso objeto remoto lançar umRemoteException, uma vez que essa exceção é normalmente reservada para a biblioteca RMI para gerar erros de comunicação para o cliente.

Deixar de fora também tem o benefício de manter nossa implementação independente de RMI.

Além disso,any additional methods defined in the remote object, but not in the interface, remain invisible for the client.

3. Registrando o serviço

Depois de criar a implementação remota, precisamos vincular o objeto remoto a um registro RMI.

3.1. Criação de um esboço

Primeiro, precisamos criar um esboço do nosso objeto remoto:

MessengerService server = new MessengerServiceImpl();
MessengerService stub = (MessengerService) UnicastRemoteObject
  .exportObject((MessengerService) server, 0);

Usamos o métodoUnicastRemoteObject.exportObject estático para criar nossa implementação de stub. The stub is what does the magic of communicating with the server over the underlying RMI protocol.

O primeiro argumento paraexportObject é o objeto servidor remoto.

O segundo argumento é a porta queexportObject usa para exportar o objeto remoto para o registro.

Dar um valor de zero indica que não nos importamos com qual portaexportObject usa, o que é típico e escolhido dinamicamente.

Infelizmente, o métodoexportObject() sem um número de porta está obsoleto.

3.2 Creating a Registry

Podemos manter um registro local em nosso servidor ou como um serviço autônomo separado.

Para simplificar, criaremos um local para o nosso servidor:

Registry registry = LocateRegistry.createRegistry(1099);

Isso cria um registro ao qual os stubs podem ser vinculados por servidores e descobertos por clientes.

Além disso, usamos o métodocreateRegistry, pois estamos criando o registro local para o servidor.

Por padrão, um registro RMI é executado na porta 1099. Em vez disso, uma porta diferente também pode ser especificada no método de fábricacreateRegistry.

Mas no caso autônomo, chamaríamosgetRegistry, passando o nome do host e o número da porta como parâmetros.

3.3 Binding the Stub

Consequentemente, vamos vincular nosso stub ao registro. Um registro RMI é um recurso de nomeação como JNDI etc. Podemos seguir um padrão semelhante aqui, vinculando nosso esboço a uma chave exclusiva:

registry.rebind("MessengerService", stub);

Como resultado, o objeto remoto agora está disponível para qualquer cliente que possa localizar o registro.

4. Criando o cliente

Finalmente, vamos escrever o cliente para invocar os métodos remotos.

Para fazer isso, primeiro localizaremos o registro RMI. Além disso, pesquisaremos o stub do objeto remoto usando a chave exclusiva limitada.

E, finalmente, vamos invocar o métodosendMessage:

Registry registry = LocateRegistry.getRegistry();
MessengerService server = (MessengerService) registry
  .lookup("MessengerService");
String responseMessage = server.sendMessage("Client Message");
String expectedMessage = "Server Message";

assertEquals(expectedMessage, responseMessage);

Como estamos executando o registro RMI na máquina local e na porta padrão 1099, não passamos nenhum parâmetro paragetRegistry.

De fato, se o registro estiver em um host ou porta diferente, podemos fornecer esses parâmetros.

Depois de pesquisar o objeto stub usando o registro, podemos chamar os métodos no servidor remoto.

5. Conclusão

Neste tutorial, obtivemos uma breve introdução ao Java RMI e como ele pode ser a base para aplicativos cliente-servidor. Fique ligado para postagens adicionais sobre alguns dos recursos exclusivos do RMI!

O código-fonte deste tutorial pode ser encontrado emon GitHub.