240 likes | 324 Views
Remote Method Invocation RMI. Java Avançado. 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:
E N D
Remote Method Invocation RMI Java Avançado Luiz Carlos d´Oleronlcadb@cin.ufpe.brSJCP
Sistemas Distribuídos “Um sistema distribuído é uma coleção de processadores pouco acoplados, interconectados por uma rede de comunicação” Sistemas Operacionais com JavaSilberschatz, Galvin e Gagne Principais Vantagens: • Compartilhamento de Recursos • Aumento da Velocidade de Computação • Confiabilidade • Comunicação • ... De Novo? Qual é o Problema com Sockets?
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
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
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
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)
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
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
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
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
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
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
serialVersionUID • O QuickFix do Eclipse poderá ajudar a gerar um serialVersionUID para a classe Serializable
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!
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 Settings\luiz carlos\workspace> C:\Arquivos de programas\Java\jdk1.5.0_06\bin\rmic 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.ServidorClientesum 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
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:
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.
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
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:
Executando todos os programas • Para executar o exemplo, basta executar os métodos main de cada classe (comece pelo servidor!)
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...)