Usando Borland DELPHI para implementar aplicações CORBA Página 1 de 10 USANDO BORLAND DELPHI PARA IMPLEMENTAR APLICAÇÕES CORBA por Simone Vey Dutra e César Bridi Introdução A Arquitetura CORBA Criando uma Aplicação CORBA em Delphi Criando um Servidor CORBA em Delphi Criando Clientes CORBA O Cliente Delphi Early Binding O Cliente Delphi Late Binding Clientes em Outras Linguagens Conclusão Referências Introdução A indústria da computação tem evoluído radicalmente nas últimas décadas. Os computadores pessoais tomaram conta do ambiente de trabalho em todas as corporações e sua integração, visando o processamento distribuído, se tornou uma necessidade. Os sistemas que devem rodar nesse ambiente também possuem características diferenciadas que são atendidas com o uso da tecnologia de orientação a objetos no processo de desenvolvimento de software. A união de duas tecnologias tão importantes como sistemas distribuídos e orientação a objetos deu origem ao que hoje conhecemos como objetos distribuídos. O padrão CORBA - Common Object Request Broker Architecture - do grupo OMG (Object Management Group) propõe uma arquitetura de software para suportar objetos distribuídos e garantir a interoperabilidade entre diferentes plataformas de hardware e sistemas operacionais. Esta capacidade é obtida através do uso de uma interface comum e um mecanismo de passagem de informações implementado em diferentes linguagens de programação, entre elas o Borland Delphi. O objetivo deste trabalho é apresentar os recursos disponíveis no Borland Delphi 5 Enterprise para o desenvolvimento de aplicações CORBA. A implementação do padrão CORBA utilizada foi o VisiBroker da Inprise. A Arquitetura CORBA CORBA (Common Object Request Broker Architecture) é uma arquitetura padrão para objetos distribuídos. A arquitetura CORBA define e implementa a estrutura necessária à comunicação entre aplicações distribuídas em diferentes plataformas, sistemas operacionais e linguagens de programação. Com CORBA, uma aplicação cliente não precisa conhecer os Usando Borland DELPHI para implementar aplicações CORBA Página 2 de 10 detalhes de implementação do objeto que obterá de um servidor. Esta capacidade é fornecida pela utilização de uma interface comum, compartilhada para a passagem de informações. Há vários fatores que destacam o CORBA das outras tecnologias de distribuição. O principal deles é que CORBA é um padrão aberto, isto é, sua especificação está constantemente sendo revisada e atualizada pelo OMG (Object Management Group). O OMG é um grupo internacional composto de centenas de empresas e organizações que decidem como evoluir a especificação CORBA. O elemento chave da tecnologia CORBA é o ORB (Object Request Broker), que gerencia o acesso de e para objetos em uma aplicação, comunica estes objetos com outros, monitora suas funções, descobre suas localizações e controla a comunicação com outros ORBs. Basicamente, o ORB é o principal mecanismo para simplificar o desenvolvimento de aplicações padrão CORBA. A simplificação é o resultado de três características: independência de localização e interoperabilidade entre plataformas e linguagens. Independência de localização significa que um ORB trata todos os objetos como se fossem locais, mesmo que estejam em sistemas remotos. Interoperabilidade entre plataformas significa que objetos criados em uma plataforma de hardware/software podem executar em qualquer outra plataforma que suporte CORBA. Por fim, interoperabilidade entre linguagens significa que objetos escritos em uma linguagem podem interagir com aplicações escritas em outra linguagem, graças a uma interface comum chamada IDL (Interface Definition Language). IDL é uma linguagem que define as interfaces dos objetos, mas não suas implementações. Os objetos podem ser escritos em qualquer linguagem (C,C++, Java, Delphi) devido a esta facilidade do padrão CORBA. CORBA também inclui mecanismos para comunicação entre objetos através de uma rede. O protocolo GIOP (General Inter-ORB Protocol) especifica formatos de mensagens e representações de dados que garantam a interoperabilidade entre ORBs. O protocolo IIOP (Inter-ORB Protocol) define detalhes específicos para usar GIOP sob TCP/IP. Criando uma Aplicação CORBA em Delphi O ponto de partida para aplicações CORBA é a interface que as aplicações compartilham quando trocam informações. Esta interface comum que define que informações estão sendo trocadas é a IDL. A IDL tem sua própria linguagem, apesar da sua sintaxe ser similar a Java e C++. Seu propósito é definir a interface para os objetos que serão passados entre aplicações CORBA. A implementação e o uso destes objetos são feitos na linguagem específica escolhida. A única condição é que esta linguagem possua recursos para mapear a arquitetura CORBA. É aqui que o Delphi entra. Aplicações CORBA podem ser implementadas em Delphi através do editor Type Library para criar facilmente interfaces IDL, através do MIDAS para conectar-se a dados CORBA e através do utilitário IDL2PAS para transformar código IDL em fontes Pascal. A seguir serão apresentados os passos básicos para criação de uma aplicação CORBA em Delphi. A aplicação demonstra um sistema de leilão, onde o servidor mantém as informações de um determinado produto e os clientes competem entre si fazendo lances na tentativa de comprar o produto. Para cada lance realizado com sucesso, a aplicação cliente atualiza a tela para exibir o valor do maior lance, que servirá de referência para os próximos lances. O Visibroker, implementação da Inprise para o padrão CORBA, é o ORB usado na aplicação. Usando Borland DELPHI para implementar aplicações CORBA Página 3 de 10 Criando um Servidor CORBA em Delphi O primeiro passo será criar o servidor que irá implementar o objeto CORBA. Como já foi mencionado, objetos CORBA são definidos pela IDL. Os desenvolvedores Delphi não precisam conhecer IDL para criar os seus objetos, pois isso pode ser feito usando o editor Type Library. Este utilitário permite a criação visual dos objetos e suas interfaces. Para criar o servidor, inicie uma nova aplicação Delphi e salve o form e o projeto. No nosso caso, chamamos estes arquivos de Cmain.pas e CServer.dpr. A partir do menu principal do Delphi, selecione File| New, e então selecione o item CORBA Object na página Multitier. O assistente CORBA Object será exibido: Figura 1 - Criando a interface CORBA. Neste exemplo, o objeto a ser definido foi denominado Leilao. O objeto servidor será uma instância compartilhada porque todos os clientes farão acesso ao mesmo objeto leilão. O objeto é criado para executar em uma única thread, uma vez que a requisição de apenas um cliente será processada em um determinado momento. Clique OK para criar a nova unit e salvar o arquivo. Isso irá criar o núcleo da interface do objeto CORBA. O editor Type Library permite a especificação de todas as informações necessárias à definição da interface do objeto CORBA (a partir do menu principal do Delphi, selecione View | Type Library). Usando Borland DELPHI para implementar aplicações CORBA Página 4 de 10 Figura 2 - O editor Type Library. Para este exemplo, criaremos um objeto servidor para o nosso Leilão Online, o qual manterá informações sobre o autor e o valor do último lance aceito. Adicionaremos uma propriedade para o nome do produto que está sendo leiloado e métodos para realizar um novo lance e verificar as informações do lance atual. Uma interface foi gerada automaticamente para o nosso objeto CORBA. Métodos e propriedades podem ser adicionados com um clique do botão direito no nome da interface ou clicando os botões "New Method" ou "New Property". Foram adicionados os métodos EfetuaLance, GetValorAtual, GetClienteAtual e GetDataAtual e a propriedade NomeProduto. A definição dos parâmetros para os métodos (nome, tipo, natureza, default) é feita posicionando o cursor sobre o nome do método. Concluída a definição da interface, um clique no botão "Refresh Implementation" sincronizará o código fonte com o objeto CORBA. Finalmente o editor Type Library pode ser fechado e o arquivo fonte pode ser salvo (CSrvObj.pas, no exemplo). Agora temos a interface do nosso objeto servidor definida e o núcleo do código Pascal no qual podemos adicionar funcionalidades ao objeto. O editor Type Library criou alguns arquivos, como o arquivo de stub Cserver_TLB.pas. Uma vez que este arquivo é gerado automaticamente, nenhum trabalho adicional é necessário. Este arquivo define as classes stub e skeleton para o objeto servidor, bem como várias outras classes que podem ser utilizadas, como a classe do object factory do CORBA. Resumidamente, o núcleo CORBA foi criado a partir da interface definida através do editor Type Library e o arquivo TLB foi criado para possibilitar a obtenção da referência de objeto para o servidor. O arquivo fonte do servidor (CSrvObj.pas) foi preenchido a partir do editor Type Library com os métodos e propriedades que foram definidos. Agora é necessário codificar a implementação do objeto. Precisamos de variáveis private para armazenar o valor do lance atual, o nome do cliente e o nome do produto que está sendo leiloado. Também precisamos inicializar estas variáveis no construtor do objeto. Finalmente precisamos implementar o http://www.inf.ufrgs.br/procpar/disc/dsitec08/trabalhos/sem2000-1/cb_svd/ 22/10/2007 Usando Borland DELPHI para implementar aplicações CORBA Página 5 de 10 código que provê funcionalidade aos métodos que foram criados. O código completo, com comentários, está disponível aqui. O que foi gerado pelo Delphi é apenas o núcleo do código; o resto precisa ser codificado para dar à interface do objeto uma implementação. Agora temos o servidor para o nosso objeto. Para usá-lo, tudo que precisamos fazer é adicionar a unit CSrvObj à cláusula uses de todos os forms de um projeto. Feito isso, o código de inicialização para o objeto será disparado quando o form for usado. Assim, o servidor será iniciado e um objeto será criado ficando disponível para o uso. Criando Clientes CORBA Nosso servidor já foi implementado e pode fornecer objetos de acordo com a necessidade dos vários clientes que buscam uma instância do TLeilao. Agora vamos criar clientes para acessar e usar este objeto. Em CORBA há dois métodos de um cliente obter uma instância de um objeto servidor. O primeiro é conhecido como early binding ou static binding. Isso significa que o cliente tem conhecimento do tipo de objeto CORBA com o qual irá se comunicar, ou seja, outro arquivo, conhecido como stub, será usado para controlar a passagem dos dados entre o cliente e o servidor – processos conhecidos como marshaling e unmarshaling, respectivamente. A complexidade destes processos ficam por conta do stub, que torna-os mais fáceis de implementar. O outro método para acessar o objeto servidor a partir do cliente é conhecido como late binding ou dynamic binding. O dynamic binding é também referenciado por DII (Dynamic Invocation Interface). Isso significa que o cliente não tem conhecimento prévio do objeto servidor e que nada sabe sobre a estrutura dos objetos que pode acessar. Cabe ressaltar que o stub de cliente não é usado, uma vez que o cliente não conhece a estrutura dos objetos do servidor em tempo de projeto. A vantagem da DII é que os clientes podem ser criados sem que seja preciso regerá-los quando um objeto do servidor é alterado, ou seja, o código do cliente permanece constante apesar das alterações do objeto servidor usado por ele. Isso é feito através de uma construção CORBA conhecida como Repositório de Interfaces. Este repositório mantém informações sobre o que está disponível para o cliente e permite que o cliente use os serviços disponíveis. Um obstáculo a este método é que, comparado ao early binding, ele é mais complexo, mais lento e requer mais trabalho do desenvolvedor. Para este exemplo, serão criados um cliente early binding e um cliente late binding, com o objetivo de usá-los com o servidor CORBA criado anteriormente. Por ser mais fácil, o cliente early binding será criado primeiro. O editor Type library cria um stub na forma de um arquivo TLB. Quando criamos o cliente, precisamos adicionar este arquivo à seção uses do form, a fim de termos uma referência à estrutura do objeto servidor. Também precisamos adicionar CorbaObj à seção uses para executar as ligações necessárias à comunicação através do ORB. A figura abaixo representa o nosso cliente: Usando Borland DELPHI para implementar aplicações CORBA Página 6 de 10 Figura 3 - Cliente CORBA. O Cliente Delphi Early Binding Como mencionado anteriormente, o cliente early binding usa o arquivo gerado pelo editor Type Library para obter uma referência ao objeto CORBA que o nosso servidor irá criar. O código do cliente tem que acessar e usar este objeto como é apresentado aqui. No cliente, implementamos todos os métodos a partir do objeto servidor. Podemos fazer isso porque conhecemos a estrutura do objeto servidor através da interface ILeilaoOnline. Alguns passos devem ser seguidos antes de executar este cliente. O ORB Smart Agent deve estar rodando em algum lugar da rede – no servidor ou qualquer outra máquina. Para fazer isso, execute osagent -C a partir da linha de comando. O -C na linha de comando determina que o osagent irá executar na barra de tarefas, de modo a deixar a sua execução aparente enquanto estiver testando. Uma vez que o ORB Smart Agent esteja; rodando, inicie o servidor. Uma vez iniciado o servidor, é uma boa idéia garantir que os objetos do servidor estão disponíveis para todos os clientes. O utilitário VisiBroker osfind pode ser usado para isso. Execute osfind a partir da linha de comando na máquina cliente para exibir uma lista dos objetos disponíveis na subrede da máquina. Isso verificará se o cliente tem acesso aos objetos do servidor necessários. O passo final é executar vários clientes. Estes podem automaticamente obter uma referência ao servidor incluindo o arquivo gerado pelo editor Type Library e, assim, ter acesso a todas as funções do servidor. No nosso exemplo, podemos disparar vários clientes a partir de diferentes máquinas e fazer sucessivos lances para o servidor. O Cliente Delphi Late Binding Como descrito anteriormente, o cliente late binding não tem conhecimento da estrutura dos objetos do servidor disponíveis em tempo de projeto e deve usar uma facilidade chamada Repositório de Interfaces para constatar o que está disponível. Neste exemplo, iremos implementar este cliente e descrever os requisitos, benefícios e obstáculos do uso deste método. Usando Borland DELPHI para implementar aplicações CORBA Página 7 de 10 Antes de começar a escrever o cliente, há alguns requisitos a serem atendidos. Primeiramente, a interface para o objeto deve ser registrada com um repositório de interface. Para fazer isso, devemos primeiro ter um arquivo IDL. Este pode ser criado facilmente retornando ao editor Type Library e selecionando Export to CORBA IDL. Isso é feito pressionando o último botão à direita da barra de ferramentas. Neste caso, a opção CORBA IDL deve ser selecionada. Figura 4 - Exportando para CORBA IDL. Isso criará o arquivo IDL correspondente ao objeto servidor definido anteriormente. O nome do arquivo será o mesmo do projeto Delphi. Esta IDL deve então ser registrada com um Repositório de Interfaces. O osagent e o servidor devem estar executando, antes do repositório de interface ser iniciado. O Repositório de Interfaces pode ser iniciado executando irep <nome_do_repositório> a partir da linha de comando. A aplicação Interface Repository é então disparada. Uma vez aberta, selecione File Load a partir do menu principal e selecione o arquivo IDL exportado acima. Feito isso, nossa interface está registrada. Para verificar que a interface foi registrada com o Interface Repository, clique no botão "Lookup" depois de carregar a IDL. Figura 5 - Interface Repository. Usando Borland DELPHI para implementar aplicações CORBA Página 8 de 10 O único passo que falta neste ponto é criar o cliente que irá acessar o Repositório de Interfaces e usar um objeto armazenado lá. Para começar, usamos o mesmo form do exemplo early binding e iniciamos um novo projeto Delphi. Uma vez que não vamos usar o stub gerado, a referência ao arquivo Cserver_TLB pode ser removida da cláusula uses. O código fica um pouco diferente, pois não temos mais o stub do cliente para nos dar uma referência direta à interface. Usamos a classe TAny, um tipo de interface CORBA para DII, para obter a referência do repositório de interface para o nosso objeto servidor. Neste caso, obteremos uma instância do object factory, que obterá uma referência ao objeto servidor. Isso é feito para imitar o processo do cliente não DII mostrado anteriormente. Excetuando-se o código adicional necessário para obter as referências ao nosso objeto servidor através do object factory, o código para o cliente late binding permanece quase idêntico ao cliente early binding. O código para o segundo cliente está disponível aqui. Revisando, os passos necessários para executar o servidor e os dois tipos de clientes na mesma máquina são os seguintes: l Iniciar o ORB Smart Agent l Iniciar o servidor l Executar o Interface Repository l Carregar a interface para o Interface Repository l Executar o cliente early binding l Executar o cliente late binding Neste exemplo, mostramos como implementar os dois tipos de clientes CORBA através do Delphi. Entretanto, a importância do CORBA está no fato de que clientes e servidores podem ser escritos em qualquer linguagem com interface IDL. No próximo exemplo, veremos como compartilhar as informações da IDL com outras linguagens. Clientes em Outras Linguagens Quando criamos o cliente dynamic binding, precisamos exportar a IDL para o nosso objeto servidor, para que o Repositório de Interfaces tivesse uma referência para os objetos que estão disponíveis. Este arquivo IDL pode também ser usado por qualquer outra linguagem compatível com o padrão CORBA para fornecer uma interface para o nosso objeto servidor. Ferramentas como JBuilder e C++ Builder podem ser usadas para criar clientes ou servidores baseados neste arquivo IDL. Neste exemplo, usaremos JBuilder. Em JBuilder, criamos uma nova aplicação com um único frame. No project manager, adicionamos o arquivo IDL salvo anteriormente. O arquivo aparecerá na lista de arquivos do projeto JBuilder. Clique com o botão direito no arquivo IDL e selecione Build. Isso executa o arquivo IDL através do precompilador IDL2JAVA. O precompilador IDL2JAVA converte o arquivo IDL em classes de stub do Java. Os arquivos Java gerados podem então ser usados para criar servidores CORBA para implementar estes objetos ou clientes CORBA para acessar os objetos. Projete o frame para que ele pareça com o cliente Delphi criado anteriormente. Usando Borland DELPHI para implementar aplicações CORBA Página 9 de 10 Figura 6 - Cliente JAVA. O código do cliente early binding Java será similar ao cliente Delphi; teremos variáveis para o object factory e um objeto servidor que será obtido a partir daquele factory. O código para este cliente está disponível aqui. Como pode ser visto, declaramos o object factory e a interface no nosso arquivo fonte. No construtor para o frame, um método diferente do Delphi é executado para conectar ao ORB e obter uma referência de objeto. A aplicação Java obtém uma referência ao objeto servidor através do uso de arquivos Helper automaticamente gerados. Fazendo isso, uma referência de objeto é obtida e usada da mesma maneira do cliente Delphi. Os arquivos Helper e outros arquivos CORBA são gerados a partir do utilitário IDL2JAVA, que foi executado quando o arquivo IDL foi compilado. O JBuilder usa este método para criar os arquivos stub e skeleton, podendo ser comparado ao uso do editor Type Library no Delphi. Uma vez obtida a referência de objeto, o código para o frame em si é similar à aplicação Delphi. O servidor CORBA Delphi não sabe que linguagem está sendo usada pelas requisições, pois clientes Delphi e Java fazem chamadas virtualmente idênticas ao objeto servidor através de seus arquivos stub. Nosso cliente Java poderia estar rodando em uma máquina UNIX localizada em um continente diferente do nosso servidor Delphi. Se a subrede CORBA ou osagents estiverem configurados corretamente, estes processos independentes podem conversar entre si como se estivessem na mesma máquina. Conclusão Não há dúvidas de que o CORBA continuará a ganhar espaço no cenário da computação distribuída devido a três fatores: flexibilidade, independência de linguagem e um amplo conjunto de capacidades para necessidades de distribuição. O Delphi combina estes fatores com desenvolvimento RAD, tornando a programação CORBA mais simples e fácil ao desenvolvedor, sem sacrificar as capacidades do CORBA. Como foi visto nos exemplos, Delphi é uma plataforma ideal para implementar servidores e clientes para vários tipos de aplicações. Os técnicos da Inprise também ampliaram as capacidades disponíveis no CORBA através do uso da tecnologia MIDAS. O MIDAS permite que seus usuários criem com facilidade queries complicadas através do Delphi e recuperem os resultados da query de datasets remotos usando CORBA como formato de transferência. Esta tecnologia é especialmente poderosa, Usando Borland DELPHI para implementar aplicações CORBA Página 10 de 10 pois os desenvolvedores não precisam criar objetos complicados para obter estes resultados. O MIDAS automatiza esta tarefa, criando classes stub e skeleton automaticamente. A tecnologia MIDAS está disponível em várias ferramentas da Inprise e continuará a ser uma peça chave no desenvolvimento CORBA RAD. Além disso, o utilitário IDL2PAS, disponível a partir do VisiBroker 3.3 para Delphi, permite que os desenvolvedores Delphi tenham acesso a todas as características CORBA, não havendo limites às implementações possíveis a partir da estrutura fornecida pelo Delphi. Em síntese, isso representa o melhor dos dois mundos: desenvolvimento RAD para tarefas CORBA padrão, como as apresentadas nos exemplos, e desenvolvimento CORBA granular através do IDL2PAS para implementações mais específicas e complicadas. Referências* Borland Home Page Borland Delphi 5 Borland JBuilder VisiBroker: CORBA Technology from Inprise New VisiBroker 3.3 For Delphi Radically Simplifies Corba Development MIDAS Home Page Java and CORBA - a smooth blend The Java Tutorial Using the Delphi 4 CORBA Implementation Visão Geral do CORBA - UFRJ *disponíveis em Julho/2000.