Java Avançado

             Luiz Carlos d Oleron
                   lcadb@cin.ufpe.br
                               SJCP

 Remote Method Invocation
          RMI
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
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
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
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
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
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
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
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
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
Definindo a Remote Interface




  Luiz Carlos   d Oleron – lcadb@cin.ufpe.br
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
Codificando Remote Class




  Luiz Carlos   d Oleron – lcadb@cin.ufpe.br
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
serialVersionUID
• O QuickFix do Eclipse
  poderá ajudar a gerar um
  serialVersionUID para a
  classe Serializable




           Luiz Carlos   d Oleron – lcadb@cin.ufpe.br
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
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
Gerando o Stub no Eclipse




  Luiz Carlos   d Oleron – lcadb@cin.ufpe.br
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
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
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
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
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
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

Sistemas distribuídos com RMI

  • 1.
    Java Avançado Luiz Carlos d Oleron lcadb@cin.ufpe.br SJCP Remote Method Invocation RMI
  • 2.
    Sistemas Distribuídos “Um sistemadistribuí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çõesque 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 - RemoteMethod 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 - RemoteMethod 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 classeque 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 – Passoa 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 RemoteInterface • 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
  • 11.
    Definindo a RemoteInterface 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
  • 13.
    Codificando Remote Class 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 QuickFixdo 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 Stubno Eclipse Luiz Carlos d Oleron – lcadb@cin.ufpe.br
  • 19.
    Criando o RemoteServer • 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 RemoteServer • 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 osprogramas • 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 umServidor 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