APÊNDICE A EXEMPLO DE APLICAÇÃO Para ilustrar os três métodos de distribuição de objetos apresentados nesta dissertação iremos, a seguir, mostrar um exemplo de implementação de uma aplicação. São apresentadas as implementações, tanto do lado cliente quanto do lado servidor, em CORBA, DCOM e Java. Esse exemplo consiste de um objeto servidor, nomeado como StockMarket, que quando questionado sobre um determinado item de produto responde informando o seu preço, sendo essa requisição atendida pelo seu método get_price( ). A linguagem de implementação utilizada nesse exemplo é o Java, pois ela é a única que utiliza o Java/RMI e tanto o CORBA quanto o DCOM podem ter seus objetos escritos em Java. Cada uma das implementações define uma interface IStockMarket. Elas apresentam o método get_price( ) que retorna um valor real indicando o preço do item de produto passado como parâmetro para o método. Esse exemplo é composto de: 1) Arquivos que definem as interfaces escritas em IDL e Java. 2) Arquivos que mostram como clientes invocam métodos das interfaces através da aquisição de referências para o objeto servidor. 3) Arquivos que mostram a implementação do objeto servidor. 4) Arquivos que mostram a implementação do programa principal. 217
1. INTERFACES IDL O arquivo IDL DCOM, na Tabela A.1, mostra que o servidor DCOM implementa a interface IStockMarket como herdeira de IDispatch, que por sua vez é herdeira de IUnknown, assim, a interface IStockMarket herda também os métodos de IUnknown. A interface IDispatch juntamente com o arquivo que descreve o objeto (SimpleStocks do tipo TypeLibrary), possibilta a sua invocação dinâmica. A IDL DCOM também associa a interface IStockMarket com a classe de objetos StockMarket, mostrada no bloco coclass. Nota-se também que cada interface está associada a um Universally Unique Identifier (UUID) nomeado pelo DCOM com CLSID. O arquivo IDL CORBA, na Tabela A.1, mostra a interface StockMarket com o seu método get_price( ). Quando o compilador IDL compila arquivo IDL ele gera arquivos stubs e skeletons e gera também informaçôes sobre cada método da interface armazenando-as no Repositório de Interface. Essas informações possibilitarão a invocação dinâmica, pois o cliente pode, em tempo de execução, questionar o Repositório de Interface e obter a informação sobre a interface e seus métodos. O Java não faz uso de uma IDL específica para definir interfaces. As interfaces são descritas num arquivo <.java> utilizando a própria linguagem Java. A Tabela A.1 mostra a interface StockMarket como herdeira de java.rmi.remote, pois todo o servidor de objeto remoto no Java/RMI, assim como seus métodos, deve ser herdeiro das classes java.rmi.remote e java.rmi.remoteexception. 218
2. IMPLEMENTAÇÃO DO CLIENTE O cliente DCOM passa a acessar os métodos do objeto servidor após adquirir o primeiro ponteiro para o objeto, como mostrado na Tabela A.2, através do statement : <IStockMarket market = (IStockMarket) new simplestocks.stockmarket( );> A palavra chave new instancia o objeto DCOM StockMarket, isto é, chama a função CoCreateInstance( ) passando como parâmetro o CLSID. CoCreateInstance( ) retorna o ponteiro de IUnknown sendo então realizado um casting para IStockMarket. O casting faz com que seja chamada a função Queryinterface requisitando um ponteiro para IStockMarket. Caso a interface não seja suportada a ClassCastException indicará uma exceção. O cliente CORBA deve primeiramente inicializar o ORB como mostrado no statement <ORB orb = ORB.init( );> da Tabela A.2. Após, ele deve instanciar o objeto CORBA e obter a sua referência que é dada pelo statement <StockMarket market = StockMarketHelper.narrow(root.resolve(name));> da Tabela A.2, onde o contexto de nomeação ( root ) e nome do componente ( name ) é obtido através do serviço de nomeação. O cliente Java/RMI primeiramente aciona o gerenciador de segurança antes de realizar qualquer chamada remota, como mostrado no statement <System.setSecurityManager( )>, Tabela A.2. Após o cliente instancia o objeto servidor através de um chamada a função Naming.Lookup( ), como mostrado no statement < StockMarket)Naming.lookup("rmi:localhost/NASDAQ");>. Uma vez o cliente tendo adquirido para um objeto servidor remoto um ponteiro válido, no caso do DCOM ou uma referência de objeto válida, no caso do CORBA ou Java/RMI, ele passa a chamar os métodos desse objeto remoto como se ele residisse no seu espaço de endreçamento. 219
3. IMPLEMENTAÇÃO DO OBJETO SERVIDOR Para o exemplo mostrado na Tabela A.3, o pacote definido em <com.ms.com> contem todas as classes necessárias para implementar o COM utilizando a linguagem Java. No DCOM o objeto servidor implementa a interface IStockMarket que foi definida no IDL (StockMarketLib.IDL). A classe StockMarket e o método get_price( ) são declarados como públicos de maneira que possam ser acessados fora do pacote. O CLSID é declarado como privado, sendo utilizado pelo COM para instanciar o objeto através da função CoCreateInstance( ) quando o cliente DCOM executar o comando new. O método get_price( ) é capaz de retornar uma exceção (ComException). Para o exemplo mostrado na Tabela A.3, o pacote definido em <org.omg.corba> contem todas as classes necessárias para implementar o CORBA. No CORBA o objeto servidor é herdeiro da classe _StockMarketImplBase que é uma classe do tipo skeleton gerada pelo compilador IDL CORBA. A classe StockMarketImpl e o método get_price( ) são declarados como público de maneira que possam ser acessados fora do pacote. A classe StockMarketImpl implementa todas as operações declaradas no arquivo CORBA IDL (StockMarket.IDL). É necessário prover um construtor, para a classe do objeto servidor CORBA StockMarketImpl, que tenha como argumento uma variável do tipo string, no exemplo, name. Desta forma, todos os serviços CORBA associarão o nome, dado por name, ao servidor de objeto CORBA StockMarketImpl. Para o exemplo mostrado na Tabela A.3, o pacote definido em <java.rmi> contem todas as classes necessárias para implementação em Java. O objeto servidor Java/RMI é herdeiro da classe UnicastRemoteObject.class que possuí a definição de todos os métodos remotos do Java/RMI e implementa a interface StockMarket. A classe StockMarketImpl e o método get_price( ) são 220
declarados como público de maneira que possam ser acessados fora do pacote. A classe StockMarketImpl implementa todas as operações declaradas no arquivo de interface Java/RMI (StockMarket.Java). É necessário prover um construtor, para a classe do objeto servidor Java/RMI que tenha como argumento uma variável do tipo string, no exemplo, name. Este nome, dado por name, é registrado no RMIRegistry como um nome público sendo utilizado para estabelecer uma ligação e uma associação do nome ao objeto servidor. O método get_price( ) é capaz de retornar uma exceção (RemoteException). 221
4. PROGRAMA PRINCIPAL No programa principal CORBA, mostrado na Tabela A.4, primeiramente é iniciado o ORB (ORB.init( );) e o adaptador de objeto básico (orb.boa_init( );) responsável por connectar a implementação do objeto servidor ao ORB. Desta forma, pode-se instanciar o objeto utilizando o statement <StockMarketImpl stockmarketimpl = new StockMarketImpl("NASDAQ");>. NASDAQ é o nome que identifica o objeto sendo utilizado por todos os serviços CORBA. O statement <boa.obj_is_ready(stockmarketimpl);> informa ao ORB que o objeto está pronto para ser invocado. O trecho de código, mostrado a seguir, ilustra a utilização do serviço de nomeação que possibilita ao cliente encontrar o objeto: <org.omg.corba.object object = orb.resolve_initial_references("nameservice"); NamingContext root = NamingContextHelper.narrow( object ) ; NameComponent[ ] name = new NameComponent[1]; name[0] = new NameComponent("NASDAQ", ""); root.rebind(name, stockmarketimpl);> O statement <boa.impl_is_ready( );> garante que o programa principal aguarde num loop, isto é, sleep on a thread e não finalize até que seja executado um shutdown. No programa principal Java/RMI, mostrado na Tabela A.4, primeiramente, antes de realizar qualquer chamado, é iniciado o security manager e após através do statement <StockMarketImpl stockmarketimpl = new StockMarketImpl("NASDAQ");> é instanciado o objeto. O programa principal permanece até ocorrer um shutdown. 222
Não foi apresentado o programa principal utilizando o DCOM pois é o mesmo do Java/RMI. 223
TABELA A.1 INTERFACES IDL IDL DCOM IDL CORBA Definição de Interface Java/RMI 224 [ uuid (7371a240-2e51-11d0-b4c1-44455354000), version (1.0) ] library SimpleStocks importlib ( stdole32.tlb ); [ uuid (BC4C0AB0-5A45-11d2-99C5-00A2414C655), dual ] interface IStockMarket : IDispatch HRESULT get_price( [in] BSTR p1, [out, retval] float * rtn); [ uuid (BC4C0AB3-5A45-11d2-99C5-00A2414C655), ] coclass StockMarket interface IStockMarket, ; ; Module SimpleStocks interface StockMarket float get_price (in string symbol); ;, package SimpleStocks; import java.rmi.*; import java.util.*; public interface StockMarket extends Java.rmi.Remote float get_price ( StringSymbol) throws RemoteException; Arquivo: StockMarketLib.idl Arquivo: StockMarket.idl Arquivo: StockMarket.java FONTE: Gopalan (1999, p.3)
225 TABELA A.2 IMPLEMENTAÇÃO DO CLIENTE Cliente DCOM Cliente CORBA Cliente Java/RMI StockMarketClient import simplestocks.*; public class StockMarketClient public static void main(string[ ] args) try IStockMarket market = (IStockMarket) new simplestocks.stockmarket( ); System.out.println( "The price of MY COMPANY is " + market.get_price("my_company") ); StockMarketClient import org.omg.corba.*; import org.omg.cosnaming.*; import SimpleStocks.*; public class StockMarketClient public static void main(string[ ] args) try ORB orb = ORB.init( ); NamingContext root = NamingContextHelper.narrow( orb.resolve_initial_references("nameservice") ); StockMarketClient import java.rmi.*; import java.rmi.registry.*; import SimpleStocks.*; public class StockMarketClient public static void main(string[ ] args)throws Exception if(system.getsecuritymanager( ) == null) System.setSecurityManager(new RMISecurityManager( )); (continua)
TABELA A.2 CONCLUSÃO catch (com.ms.com.comfailexception e) System.out.println( "COM Exception:" ); NameComponent[ ] name = new NameComponent[1] ; name[0] = new NameComponent("NASDAQ",""); StockMarket market = (StockMarket)Naming.lookup("rmi:localhost/NASD AQ"); 226 System.out.println( e.gethresult( ) ); System.out.println( e.getmessage( ) ); StockMarket market = StockMarketHelper.narrow(root.resolve(name)); System.out.println("Price of MY COMPANY is " + market.get_price("my_company")); catch( SystemException e ) System.err.println( e ); System.out.println( "The price of MY COMPANY is " + market.get_price("my_company") ); Arquivo: StockMarketClient.java Arquivo: StockMarketClient.java Arquivo: StockMarketClient.java FONTE: Gopalan (1999, p.4)
TABELA A.3 IMPLEMENTAÇÃO DO OBJETO SERVIDOR Objeto DCOM Objeto CORBA Objeto/RMI Java StockMarketServer StockMarketServer StockMarketServer import com.ms.com.*; import org.omg.corba.*; package SimpleStocks; import simplestocks.*; import SimpleStocks.*; import java.rmi.*; import java.rmi.server.unicastremoteobject; public class StockMarket implements IStockMarket public class StockMarketImpl extends _StockMarketImplBase public class StockMarketImpl extends private static final String CLSID = UnicastRemoteObject implements StockMarket 227 "BC4C0AB3-5A45-11d2-99C5-00A02414C655"; public float get_price( String symbol ) public float get_price( String symbol ) public float get_price( String symbol ) float price = 0; float price = 0; for(int i = 0; i < symbol.length( ); i++) float price = 0; for( int i = 0; i < symbol.length( ); i++ ) for( int i = 0; i < symbol.length( ); i++ ) price += (int) symbol.charat( i ); price += (int) symbol.charat( i ); price += (int) symbol.charat(i); price /= 5; return price; price /= 5; (continua)
TABELA A.3 CONCLUSÃO 228 price /= 5; return price; public StockMarketImpl( String name ) super( name ); return price; public StockMarketImpl( String name ) throws RemoteException try Naming.rebind( name, this ); catch( Exception e ) System.out.println( e ); Arquivo: StockMarket.java Arquivo: StockMarketImpl.java Arquivo: StockMarketImpl.java FONTE: Gopalan (1999, p.5)
TABELA A. 4 PROGRAMA PRINCIPAL Programa Principal CORBA Programa Principal Java/RMI StockMarketServer Main import org.omg.corba.*; import org.omg.cosnaming.*; import SimpleStocks.*; StockMarketServer Main import java.rmi.*; import java.rmi.server.unicastremoteobject; import SimpleStocks.*; 229 public class StockMarketServer public static void main(string[ ] args) try ORB orb = ORB.init( ); BOA boa = orb.boa_init( ); StockMarketImpl stockmarketimpl = new StockMarketImpl("NASDAQ"); boa.obj_is_ready( stockmarketimpl ); org.omg.corba.object object = orb.resolve_initial_references("nameservice"); (continua) public class StockMarketServer public static void main(string[ ] args) throws Exception if(system.getsecuritymanager( ) == null) System.setSecurityManager(new RMISecurityManager( )); StockMarketImpl stockmarketimpl = new StockMarketImpl("NASDAQ");
TABELA A. 4 CONCLUSÃO NamingContext root = NamingContextHelper.narrow( object ) ; NameComponent[ ] name = new NameComponent[1]; name[0] = new NameComponent("NASDAQ", ""); root.rebind(name, stockmarketimpl); 230 boa.impl_is_ready( ); catch( Exception e ) e.printstacktrace( ); Arquivo: StockMarketServer.java Arquivo: StockMarketServer.java FONTE: Gopalan (1999, p.7)