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:
-
Crie uma interface definindo o contrato de cliente / servidor.
-
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.