O documento discute a implementação de sistemas distribuídos em Java utilizando a tecnologia RMI (Remote Method Invocation). Ele explica os principais conceitos como interfaces remotas, classes remotas, stubs, serviço de nomes (RMIRegistry) e passo a passo para desenvolver uma aplicação cliente-servidor remota.
1. Java Avançado
Luiz Carlos d Oleron
lcadb@cin.ufpe.br
SJCP
Remote Method Invocation
RMI
2. Sistemas Distribuídos
“Um sistema distribuído é uma coleção de processadores pouco
acoplados, interconectados por uma rede de comunicação”
Sistemas Operacionais com Java
Silberschatz, Galvin e Gagne
Principais Vantagens:
De Novo? Qual
é o Problema
1. Compartilhamento de Recursos com Sockets?
2. Aumento da Velocidade de Computação
3. Confiabilidade
4. Comunicação
5. ...
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
3. Midleware
• As aplicações que utilizam a rede são complexas
• A complexidade vêm normalmente por uma gama de serviços de
infra-estrutura que são necessários para a execução do sistema
propriamente dito
• Por exemplo: localização, chamadas de métodos, tolerância a
falhas, etc...
• Por que são muito simples, com sockets podemos apenas enviar e
receber dados
• Implementar todas as funcionalidades infra-estruturais utilizando
diretamente sockets pode ser um trabalho custoso, repetitivo e, na
maioria das vezes, complexo
• Para diminuir as responsabilidades das aplicações (e dos
desenvolvedores delas), são utilizados plataformas de software que
realizam funcionalidades de infra-estrutura que são comuns aos
sistemas
• Tais plataformas são conhecidas como Midleware, que são
basicamente, provedores de serviços
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
4. RMI - Remote Method Invocation
• RMI é um Midleware que fornece serviços para criação de
aplicações Java Distribuídas.
• Ele disponibiliza apenas um único serviço, o Serviço de Nomes
• Entretanto, a principal função de RMI é permitir que métodos de
objetos remotos sejam chamados de forma tão transparente
como se os objetos estivessem localmente (tanto quanto
possível)
• Todas as características de uma chamada de método (nome,
lista de parâmetros, valores de retorno e lista de exceções) são
fornecidas por RMI
• As chamadas de RMI são realizadas de forma síncrona
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
5. RMI - Remote Method Invocation
• RMI utiliza Sockets Java por baixo dos panos
• Visto que Sockets usam TCP, RMI utiliza TCP, se beneficiando de
todas as qualidades do protocolo
• Um cliente RMI utilizará um proxy da referencia remota para
chamar os métodos
• O proxy é chamado de STUB
• O STUB não é codificado pelo programador
• Usamos um aplicativo chamado rmic para criar o STUB
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
6. Stubs
• Toda classe que deverá
ter métodos remotamente
chamados por RMI,
deverá ter um Stub
• O cliente possuirá uma
instância do Stub, a qual
receberá as chamadas
do cliente e as enviará
pela rede (usando
Murshaling e
Unmarshaling)
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
7. Serviço de Nomes
• São sistemas capazes de localizar um componente
associado pelo nome desse componente. Exemplos de
serviços de nomes são:
– DNS – Domain Name Service
– JNDI – Java Naming and Directory Interface
– RMIRegistry
– Corba Service Name
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
8. RMIRegistry
• RMIRegistry é o serviço de nomes de RMI
• Utilizamos para localizar instâncias de objetos remotos
Java numa rede
• Existem várias formas de iniciar o RMIRegistry, uma
delas é utilizando o aplicativo rmiregistry.exe, do
diretório bin do jdk
• Existem outras formas melhores, via programação, que
utilizaremos
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
9. RMI – Passo a Passo
• Definindo a Remote Interface
• Codificando Remote Class
• Gerando o Stub
• Criando o Remote Server
• Codificando o Cliente
• Executando todos os programas
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
10. Definindo a Remote Interface
• Tudo que um cliente sabe do objeto remoto é a sua interface.
• Nós definimos uma interface com os métodos que queremos chamar remotamente
• Esta interface, que chamamos de Interface Remota, deverá extender a interface
java.rmi.Remote
• Remote não possui métodos
• Todos os métodos da Interface que criamos (a Interface Remota) deverão declarar
que lançam
java.rmi.RemoteException
• Os métodos da Interface Remota poderão lançar outras exceções, específicas do
método
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
12. Codificando Remote Class
• A classe da referência remota
deverá implementa nossa
Interface Remota
• Além disso, deverá extender
java.rmi.server.
UnicastRemoteObject
• Observe que o objeto remoto
poderá ter outros métodos que
não constem na Interface Remota
• Logicamente, esses métodos não
estarão disponíveis remotamente,
mesmo que sejam public
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
14. serialVersionUID
• Algumas vezes, nos deparamos com o seguinte warning:
The serializable class Cliente does not declare a static
final serialVersionUID field of type long
• O serialVersionUID é utilizado para validar se a classe que a JVM conhece
é compatível com o objeto que vem serializado. Se os serialVersionUID
forem diferentes, será lançada um java.io.InvalidClassException
• Toda classe serializável possui um serialVersionUID, que pode ser
codificado pelo programador ou gerado pelo compilador
• Diferenças entre compiladores podem gerar serialVersionUID
diferentes para a mesma classe
• Então java avisa para você que o melhor é você gerar um
serialVersionUID
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
15. serialVersionUID
• O QuickFix do Eclipse
poderá ajudar a gerar um
serialVersionUID para a
classe Serializable
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
16. Gerando o Stub
• Como já foi dito, o STUB é o representante do objeto remoto
• É o STUB que receberá as chamadas de método do cliente,
enviando elas para o objeto remoto, via rede, usando java sockets
• Entre outras coisas, o Stub é responsável por serializar os
parâmentros, enviá-los via rede, receber o bytes com valores de
retorno ou exceções lançadas e reestruturar tudo em objetos java,
devolvendo para o cliente o resultado
• Codificar o Stub é uma tarefa ingrata, ainda bem que existe um
programa chamado rmic que faz isso para o programador!
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
17. Gerando o Stub
• O rmic é um programa de linha de comando que fica na pasta bin do jdk.
Um exemplo de chamada do rmic é:
C:Documents and Settingsluiz carlosworkspace>
C:Arquivos de programasJavajdk1.5.0_06binrmic
jornada.server.ServidorClientes –v1.2 –keep
• Aonde o –v1.2 é uma flag para definir a versão do protocolo rmi utilzado e –
keep é a flag para manter o código fonte do stub gerado
• Se tudo ocorrer corretamente, será criado no mesmo pacote de
jornada.server.ServidorClientes um stub para ser utilizado por
um cliente remoto chamado
jornada.server.ServidorClientes_Stub
• O Eclipse possui uma ferramenta para executar aplicações externas que
também poderá ser utilizada para chamar o rmic
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
18. Gerando o Stub no Eclipse
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
19. Criando o Remote Server
• Entende-se como Remote Server a classe que irá instanciar e
publicar o Remote Object, usando o RMIRegistry
• É comum fazer com que a própria classe do RemoteObject tenha
as responsabilidades do Remote Server
• Por exemplo, codificando o método main:
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
20. Criando o Remote Server
• A interface
java.rmi.registry.Registry
representa um objeto que possui métodos para armazenar e encontrar referencias remotas ligadas
a nomes
• Normalmente, usamos o método bind (ou rebind) para ligar um nome a uma referencia
remota
• A classe
java.rmi.registry.LocateRegistry
é utilizada para obtermos referencias para Registry s
• java.rmi.registry.LocateRegistry possui vários métodos para formas diferentes de se
obter um Registry
• O acesso a objetos remotos, incluindo Registry s, pode ser dificultado por políticas de
seguranças locais ou de redes.
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
21. Codificando o Cliente
• O cliente é a classe que utilizará os métodos do objeto remoto
• Antes de fazer isso, ele terá que obter a referência para o Stub do
objeto remoto. Para isso, ele utilizará o serviço de nomes de RMI
• No exemplo a seguir, utilizamos o método estático lookup da
classe java.rmi.Naming para localizar o Stub
• Observe que localhost aponta para a máquina local, se o serviço
de nomes estiver sendo executado em outra máquina, será
necessário substituir localhost pelo nome do host ou número IP
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
22. Codificando o Cliente
• Após isso, o cliente poderá chamar os métodos do Objeto Remoto da
mesma forma como eles fossem métodos de uma instância local:
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
23. Executando todos os programas
• Para executar o exemplo, basta executar os métodos
main de cada classe (comece pelo servidor!)
Luiz Carlos d Oleron – lcadb@cin.ufpe.br
24. Exercício
• Crie um Servidor que possua os métodos:
void cadastrarCliente(Cliente)
List<Cliente> listarClientes()
void excluirCliente(int)
void alterarCliente(Cliente)
• Não se esqueça de usar as exceções apropriadas
• Crie um cliente para chamar os métodos remotamente
do servidor
• Utilize o esquema de persistência que preferir
(armazenamento em memória, JDBC, etc...)
Luiz Carlos d Oleron – lcadb@cin.ufpe.br