• Nenhum resultado encontrado

Algumas das principais características da linguagem Java são as seguintes:

a) Orientada a Objeto: Java é puramente orientada a objeto, possibilitando que uma classe herde o comportamento de sua superclasse;

b) Robusta: em Java os byte-codes são interpretados antes da execução do programa e possui coleta automática de lixo (garbage collector) evitando erros de gerenciamento de memória; c) Portável: a linguagem Java foi projetada para ser executada em qualquer sistema que implemente a Maquina Virtual Java;

d) Suporta aplicações em ambientes distribuídos;

6.3.4 – API RMI

O pacote para Chamada de Métodos Remotos (RMI – Remote Method Invocation) pertencente à tecnologia Java, fornece um mecanismo que possibilita a chamada de um método que pertence a um determinado objeto, sendo que este objeto pode existir no contexto da mesma máquina, ou de uma diferente. O RMI é em essência, um mecanismo orientado a objeto para Chamada de Procedimentos Remotos (RPC – Remote Procedure Calls).

Existem três elementos bem definidos para suportar a chamada remota de métodos [89]: a) O Cliente, responsável por chamar um método em um objeto remoto;

b) O Servidor, que é o elemento ao qual pertence o mencionado objeto;

c) O Registrador de Objetos, que é um servidor de nomes, o qual relaciona objetos com nomes.

a) Arquitetura RMI

Na Figura 6.11 é apresentado o diagrama da arquitetura RMI. A Skeleton e a Stub são classes geradas ao se compilar o programa do servidor no entorno RMI, por meio do comando rmic. Ambos elementos RMI se comunicam através de uma camada de referência remota e entre eles estabelecem-se os processos de marshaling28 e demarshaling da informação transmitida.

28Marshaling: processo de conversão de um formato criado com determinada linguagem, em um formato de transmissão (on-the-

A transmissão dos dados, via rede, se dá através do protocolo TCP/IP, na camada de transporte, de maneira transparente.

É importante esclarecer que os objetos remotos não viajam de uma máquina para outra, pois as classes geradas encarregam-se do processo de transmissão da informação. Do lado cliente, a camada stub fica responsável por aceitar as chamadas remotas e delegá-las, através da rede, à camada skeleton do lado servidor. A skeleton recebe as chamadas realizadas, via rede, e as entrega para o objeto remoto requisitado.

b) Exemplo RMI

Em uma aplicação RMI com um lado cliente e um lado servidor, deve existir uma interface. Em Java, uma interface fornece um espaço para declarar um método. Desta maneira, uma ou várias classes podem implementar o comportamento definido na interface, resolvendo-se, assim, o problema da linguagem Java não possuir herança múltipla.

Em uma aplicação distribuída, as implementações residem em máquinas virtuais diferentes. Deste modo, os objetos que possuem métodos que podem ser chamados por máquinas diferentes são denominados objetos remotos. Cumpre salientar que um objeto converte-se em remoto ao implementar uma interface remota e, para isso, é necessário que a interface herde o comportamento da classe Remote do pacote RMI. Além disso, cada método definido na interface deve declarar uma exceção remota (RemoteException), além de qualquer outra exceção adicional. A seguir será analisado um exemplo simples com a finalidade de ilustrar como implementar um servidor, um cliente e a interface. Na Figura 6.12 mostra-se o código de uma interface simples, denominada Teste.

Figura 6.11. Diagrama da arquitetura RMI.

Ambiente de Rede Objeto Remoto

SERVIDOR CLIENTE

Objeto Remoto

Stub Camada de Transporte – TCP/IP

O programa do servidor implementa a interface Teste e herda o comportamento da classe

UnicastRemoteObject, pertencente à API RMI. No método principal deve ser criado e registrado

um novo objeto remoto. O método rebind, da classe Naming, relacionará o objeto remoto com nome que tem sido especificado. Na Figura 6.13 pode-se analisar o código fonte do servidor.

/*Interface*/ import java.rmi.*;

//Teste estende a classe Remote public interface Teste extends Remote{

public String IdSensor(String dado) throws RemoteException; }

/* Este programa implementa o Servidor */ import java.rmi.*;

import java.rmi.server.*;

/* A classe Servidor estende a classe UnicastRemoteObject e implementa a interface Teste */ public class Servidor extends UnicastRemoteObject implements Teste {

//Declaração de um método Construtor public Servidor() throws RemoteException { }

public String IdSensor (String dado) throws RemoteException {

System.out.println("Codigo de identificacao enviado pelo cliente: " + dado); return dado;

}

//Método principal

public static void main(String[] args) { try {//tentativa

String nome = "//localhost/RecebeDado"; //Criar um novo objeto remoto

Teste teste = new Servidor(); //Relacionar nome com objeto Naming.rebind(nome, teste);

System.out.println("\n" + " Servidor no Ar" + "\n" + "---"); } catch (Exception problemas) {//Tentou e não conseguiu?

System.err.println("exception: " + problemas); }

} }

Figura 6.12. Exemplo de interface em Java.

No exemplo da Figura 6.14 mostra-se o código para a implementação do programa cliente. Através de uma interface gráfica, um cliente entra com o código de identificação de um sensor, que é declarada como uma string para ser interpretada pelo programa. O método lookup, da classe Naming, solicita e chama a referência do objeto remoto. Logo depois, o valor introduzido pelo cliente é passado como parâmetro para interface .

/*Este programa implementa o Cliente*/ import java.rmi.*;

import java.io.*;

import javax.swing.JOptionPane;

public class Cliente { static public String getNome() {

//Entrar com uma String através de uma interface gráfica simples String id = JOptionPane.showInputDialog

("Entre com o codigo de identificacao do sensor"); return id;

}

//Método Principal

public static void main (String[] args) { //Utilizar o próprio host

String host = "localhost"; try {//tentativa

Teste adq = (Teste)

//Solicitar a referência de um objeto remoto e invocá-la Naming.lookup("rmi://localhost/RecebeDado");

String id_sensor;

//Obter código e passá-lo como parâmetro para a Interface id_sensor = getNome();

adq.IdSensor(id_sensor);

System.out.println("O Dado foi Enviado com Sucesso"); }

catch (Exception remota) {//Tentou e não conseguiu? => Mostre a exceção System.err.println("Erro na Conexao Remota: " + remota.getMessage()); remota.printStackTrace();

System.exit(0); } }

}

Após os programas terem sido escritos, devem ser compilados: o programa que implementa o servidor, o cliente e a interface. Na seqüência deve-se iniciar o registro RMI e compilar-se o programa servidor no ambiente RMI, empregando o comando rmic. Depois dessas etapas, o servidor pode ser executado a fim de colocá-lo no ar, como mostrado na Figura 6.15a. Uma vez no ar, o servidor esperará a petição de um serviço por parte de um cliente e, para isso, deve ser executado o programa cliente, como mostrado na Figura 6.15b.

Neste exemplo, ao executar o programa cliente, aparece uma interface gráfica por meio da qual solicita-se a entrada de um código de identificação de sensor. O valor ingressado será enviado para o servidor. Embora o exemplo apresentado seja básico, através dele é possível notar que, uma vez no servidor, um valor pode passar a fazer parte de uma base de dados, ou pode ser um comando remoto ou um endereço de função IEEE 1451.2.

a) b)