Programação com Objetos Distribuídos e Componentes



Documentos relacionados
Invocação de Métodos Remotos

SISTEMAS DISTRIBUÍDOS

Chamadas Remotas de Procedimentos (RPC) O Conceito de Procedimentos. RPC: Programa Distribuído. RPC: Modelo de Execução

Objetos Distribuídos - Programação Distribuída Orientado a Objetos. Luiz Affonso Guedes

Java 2 Standard Edition. Fundamentos de. Objetos Remotos. Helder da Rocha

Laboratório de Computação VI JAVA IDL. Fabricio Aparecido Breve

Como foi exposto anteriormente, os processos podem ter mais de um fluxo de execução. Cada fluxo de execução é chamado de thread.

Invocação de Métodos Remotos RMI (Remote Method Invocation)

Java RMI - Remote Method Invocation. Programação com Objetos Distribuídos (C. Geyer) Java-RMI 1

MIDDLEWARE Aplicativos RMI, RPC e eventos Camadas Protocolo Requesição-Respostal Middleware Representação Externa dos Dados Sistemas Operacionais

Uma Introdução à Arquitetura CORBA. O Object Request Broker (ORB)

SISTEMAS DISTRIBUIDOS

THREADS EM JAVA. George Gomes Cabral

INE Sistemas Distribuídos

Adriano Reine Bueno Rafael Barros Silva

Sistemas Distribuídos

Sistemas Distribuídos

Sistemas Paralelos e Distribuídos /2004 Curso: Matemática /Informática Sistemas Distribuídos /2004 Curso: Ensino da Informática

Capítulo VI CORBA. Common Object Request Broker Architecture. [Cardoso2008] Programação de Sistemas Distribuídos em Java, Jorge Cardoso, FCA, 2008.

Programação Concorrente em java - Exercícios Práticos Abril 2004

Sistemas Distribuídos RPC x RMI. Edeyson Andrade Gomes

Considerações no Projeto de Sistemas Cliente/Servidor

Num sistema de objectos distribuídos, dois conceitos são fundamentais.

Orientação a Objetos

1.6. Tratamento de Exceções

Sistemas Distribuídos

Sistemas Distribuídos

Introdução a Java. Hélder Nunes

UNIVERSIDADE. Sistemas Distribuídos

Sistemas Distribuídos


Tutorial RMI (Remote Method Invocation) por Alabê Duarte

Bancos de dados distribuídos Prof. Tiago Eugenio de Melo

CORBA. Common Object Request Broker Architecture. Unicamp. Centro de Computação Rubens Queiroz de Almeida

UNIVERSIDADE. Sistemas Distribuídos

Hardware (Nível 0) Organização. Interface de Máquina (IM) Interface Interna de Microprogramação (IIMP)

Sistemas Distribuídos Capítulos 3 e 4 - Aula 4

Introdução ao Modelos de Duas Camadas Cliente Servidor

Sistemas Distribuídos. Professora: Ana Paula Couto DCC 064

Sistemas Distribuídos

OBJETOS DISTRIBUÍDOS E INVOCAÇÃO REMOTA

3 Um Framework Orientado a Aspectos para Monitoramento e Análise de Processos de Negócio

Princípios de Sistemas Distribuídos. Tecnologias utilizadas em sistemas distribuídos Aula 5

Prof. Marcos Ribeiro Quinet de Andrade Universidade Federal Fluminense - UFF Pólo Universitário de Rio das Ostras - PURO

Threads e Concorrência em Java (Material de Apoio)

Processos e Threads (partes I e II)

Java. Marcio de Carvalho Victorino

Programação distribuída e paralela (C. Geyer) RPC 1

SISTEMAS OPERACIONAIS CAPÍTULO 3 CONCORRÊNCIA

Curso de Java. Orientação a objetos e a Linguagem JAVA. TodososdireitosreservadosKlais

PROGRAMAÇÃO ORIENTADA A OBJETOS -TRATAMENTO DE EXCEÇÕES. Prof. Angelo Augusto Frozza, M.Sc. frozza@ifc-camboriu.edu.br

Tabela de Símbolos. Análise Semântica A Tabela de Símbolos. Principais Operações. Estrutura da Tabela de Símbolos. Declarações 11/6/2008

Sistemas distribuídos:comunicação

Java 2 Standard Edition Como criar classes e objetos

Comunicação. Parte II

Sistemas Distribuídos. Professora: Ana Paula Couto DCC 064

BANCO DE DADOS DISTRIBUÍDOS e DATAWAREHOUSING

CORBA Common Object Request Broker Architecture. Carolina de Oliveira Cunha Lenita Martins Ambrosio Victor da Fonseca Santos

EXERCÍCIOS SOBRE ORIENTAÇÃO A OBJETOS

3 SCS: Sistema de Componentes de Software

Sistemas Operacionais

3. Comunicação em Sistemas Distribuídos

A ) O cliente terá que implementar uma interface remota. . Definir a interface remota com os métodos que poderão ser acedidos remotamente

Sistemas Distribuídos

FBV - Linguagem de Programação II. Um pouco sobre Java

(Aula 17) Threads em Java

Para construção dos modelos físicos, será estudado o modelo Relacional como originalmente proposto por Codd.

Threads em Java. Sistemas Operacionais - Laboratório Professor Machado

IMPLEMENTAÇÃO DE SOCKETS E THREADS NO DESENVOLVIMENTO DE SISTEMAS CLIENTE / SERVIDOR: UM ESTUDO EM VB.NET

Sistemas Distribuídos

Especificação do 3º Trabalho

Java Threads. Introdução

Programação Orientada a Objetos em Java. Threads Threads Threads. Threads

Programação Concorrente em Java. Profa Andréa Schwertner Charão DLSC/CT/UFSM

Guia de Fatores de Qualidade de OO e Java

Desenvolvimento Cliente-Servidor 1

UFG - Instituto de Informática

Java para Desenvolvimento Web

Notas da Aula 4 - Fundamentos de Sistemas Operacionais

Exemplos práticos do uso de RMI em sistemas distribuídos

MODELO CLIENTE SERVIDOR

Análise e Desenvolvimento de Sistemas ADS Programação Orientada a Obejeto POO 3º Semestre AULA 03 - INTRODUÇÃO À PROGRAMAÇÃO ORIENTADA A OBJETO (POO)

SISTEMAS OPERACIONAIS ABERTOS Prof. Ricardo Rodrigues Barcelar

Sistemas Operacionais Processos e Threads

Notas da Aula 15 - Fundamentos de Sistemas Operacionais

Sistemas Operacionais

Grupo I [6v] Considere o seguinte extracto de um programa de definição de uma calculadora apenas com a função soma de dois valores reais

Conteúdo. Disciplina: INF Engenharia de Software. Monalessa Perini Barcellos. Centro Tecnológico. Universidade Federal do Espírito Santo

Aula 30 - Sockets em Java

IFPE. Disciplina: Sistemas Operacionais. Prof. Anderson Luiz Moreira

5.1 Exemplos de uso Mediante a instanciação de componentes específicos, o OiL pode ser configurado

Sistemas Operacionais. Prof. André Y. Kusumoto

Informática UFRGS. Programação com Objetos Distribuídos (C. Geyer) C# Remote V0 1

BACHARELADO EM SISTEMAS DE INFORMAÇÃO EaD UAB/UFSCar Sistemas de Informação - prof. Dr. Hélio Crestana Guardia

CURSO DE PROGRAMAÇÃO EM JAVA

5 Mecanismo de seleção de componentes

Transcrição:

Programação com Objetos Distribuídos e Componentes Cláudio F. R. Geyer, Luciano Cavalheiro da Silva, Patrícia Kayser Vargas, Juliano Malacarne Resumo Universidade Federal do Rio Grande do Sul Instituto de Informática Av. Bento Gonçalves, 9500 Bloco IV Cx. Postal 15064 91501-970 Porto Alegre E-mail: {geyer, lucc, kayser@inf.ufrgs.br, juliano@direcao.com http://www-gppd.inf.ufrgs.br Este texto é uma introdução à programação com objetos distribuídos (POD). A abordagem dessa introdução pode ser caracterizada por dois aspectos: conceitos e técnicas básicas de POD e alguns dos ambientes de POD mais importantes nos dias atuais. Inicialmente, os principais conceitos e questões da programação com objetos distribuídos são descritos. O primeiro ambiente apresentado é a linguagem Java via a plataforma JDK da Sun, abordando-se somente os principais recursos para POD, como threads e RMI. A seguir descreve-se o modelo CORBA para POD e a tecnologia DCOM da Microsoft. Por último, introduz-se a tecnologia JavaBeans da Sun, proposta para o desenvolvimento padrão de componentes. 1. Introdução É inegável a crescente importância dos ambientes paralelos e distribuídos tanto no meio acadêmico quanto comercial. O uso de redes locais e da Internet está amplamente difundido mesmo para uso doméstico. Mas para que tais recursos físicos sejam aproveitados da melhor forma possível é preciso fornecer suporte adequado de software. Existem diversos aspectos relacionados ao controle em ambientes distribuídos. Por ambiente distribuído entende-se um conjunto de processadores interligados por uma rede de interconexão e sem memória compartilhada. Enquanto em um ambiente centralizado a comunicação entre processos ocorre através de variáveis ou arquivos compartilhados, a ausência de memória compartilhada exige que a interação entre processos em processadores distintos seja feita através de troca de mensagens. Segundo Tanenbaum, um sistema distribuído é "uma coleção de computadores independentes que parecem ao usuário como um único computador". Essa definição implica hardware formado por máquinas autônomas e software fornecendo a abstração de uma máquina única. O uso de sistemas distribuídos possui uma série de vantagens em relação ao processamento seqüencial, dentre as quais destaca-se: (a) aproveitamento de máquinas potencialmente ociosas, além de ser mais barato interconectar vários processadores do que adquirir um supercomputador; (b) algumas aplicações são distribuídas por natureza e portanto mais facilmente implementadas nesse tipo de ambiente; (c) em caso de falha de uma máquina, o sistema como um todo pode sobreviver, apresentando apenas uma degradação de desempenho; (d) é possível ter um crescimento incremental, pois o poder computacional pode ser aumentado através da inclusão de novos equipamentos; (e) sistemas distribuídos são mais flexíveis do que máquinas isoladas, por isso muitas vezes são utilizados até mesmo que não se esteja buscando desempenho. Porém, também existem algumas desvantagens ainda segundo Tanenbaum: (a) pouco software de alto nível disponível para sistemas distribuídos; (b) dificuldades para evitar acesso indevido (segurança); (c) a rede de interconexão pode causar problemas de não conexão ou não dar vazão à demanda.

2 Uma vez que a programação distribuída é mais complexa que a programação seqüencial, diversos trabalhos são desenvolvidos tanto com o objetivo de explorar o paralelismo e a distribuição de forma implícita ou automática, quanto com o intuito de tornar a expressão do paralelismo mais simples. Dentre os diversos tópicos relacionados aos sistemas distribuídos, esse texto irá se deter em aspectos relacionados ao programação com o uso de objetos distribuídos. O uso de objetos distribuídos tem crescido com a popularização da linguagem orientada a objetos Java que possui uma série de facilidades para a programação distribuída. A computação com objetos distribuídos é um paradigma que permite que objetos sejam distribuídos através de uma rede heterogênea e permite que os componentes interajam como se estivessem unificados. Os objetos podem estar distribuídos em diferentes computadores através de uma rede, embora parecendo como se eles estivessem locais dentro de uma aplicação. Uma das preocupações nesse tipo de ambiente é simplificar a programação facilitando ao programador a expressão da concorrência entre objetos e da distribuição dos mesmos. Outros aspectos importantes estão relacionados às diferentes formas de otimizar a execução do sistema buscando aumento de desempenho. O restante desse texto é composto de diversas partes independentes (cada uma tem uma numeração de seção própria): - Conceitos Básicos de Programação com Objetos Distribuídos; - Java Threads - concorrência e sincronização; - Java RMI - comunicação por chamada remota de método; - Introdução a CORBA; - Introdução a DCOM; - Introdução a JavaBeans.

3 Índice Programação com Objetos Distribuídos e Componentes...1 Resumo...1 1. Introdução...1 2. Conceitos Básicos de Programação com Objetos Distribuídos...5 2.1. Programação Distribuída...5 2.2. Objetos...5 2.3. Distribuição...6 2.4. Concorrência...6 2.5. Sincronização...8 3. Java Threads - concorrência e sincronização...10 3.1. Introdução...10 3.2. Java Thread...10 3.3. Criação de threads...10 3.4. Sincronização...12 3.5. Controle de threads...15 3.6. Endereços...15 3.7. News Groups...16 4. Java RMI - comunicação por chamada de método remoto...17 4.1. Introdução...17 4.2. Conceitos básicos...17 4.3. Recursos básicos...18 4.4. Comunicação entre os componentes...18 4.5. Diferenças entre RMI e chamada local de método...18 4.6. Camadas de software do sistema RMI (exemplo Hello)...19 4.7. Passos do uso de RMI...21 4.8. Segurança do RMI...22 4.9. Outros aspectos...22 4.10. Pacote java.rmi...22 4.11. Pacote java.rmi.registry...23 5. Introdução a CORBA...24 5.1. Introdução...24 5.2. O que é CORBA...24 5.3. Histórico CORBA...24

4 5.4. Arquitetura CORBA...25 5.5. IDL...25 5.6. ORB...26 5.7. ID s Globais e Protocolos...28 5.8. Serviços CORBA...28 5.9. Facilidades CORBA...29 5.10. Objetos de Negócio...29 5.11. Endereços...29 6. Introdução a DCOM...31 6.1. Introdução...31 6.2. Visão geral de DCOM...31 6.3. Características do DCOM...31 6.4. Exemplo Counter em DCOM/Java...32 6.5. Obtenção de DCOM...36 6.6. DCOM X CORBA X RMI...36 6.7. Resumo...37 7. Introdução a JavaBeans...38 7.1. Introdução...38 7.2. Conceitos Básicos de JavaBeans...38 7.3. Principais Recursos de Programação (Classes JavaBeans)...39 7.4. Enterprise JavaBeans...42 8. Bibliografia...44 -

5 2. Conceitos Básicos de Programação com Objetos Distribuídos 1 2.1. Programação Distribuída A programação distribuída está presente em muitos problemas resolvidos através do computador. Para esses problemas as soluções são mais naturalmente representadas na forma de atividades paralelas, atuando de forma cooperativa ou competitiva, que colaboram cada uma com uma parcela da solução final. Um programa concorrente é composto de dois ou mais programas seqüenciais, que são executados de forma concorrente, e denominados processos paralelos distribuídos. Essa execução concorrente pode ser feita através do compartilhamento de um único processador por todos os processos (multiprogramação), ou através da execução de cada processo em elementos processadores exclusivos (multiprocessamento ou processamento distribuído, se esses processadores compartilham ou não memória, respectivamente). Processos que cooperam para atingir os resultados desejados interferem, mutuamente, na sua execução, através da troca de informações necessária para a cooperação. Além disso, há situações em que os processos devem se sincronizar, para respeitar as dependências entre resultados a serem produzidos e consumidos, acomodando assim diferentes velocidades relativas de execução. Tanto a comunicação como a sincronização de processos são efetuadas por mecanismos baseados em compartilhamento de memória ou troca de mensagens. A programação distribuída reduz a complexidade das aplicações. No contexto da programação distribuída, algumas questões são de grande importância, tais como: distribuição, concorrência e sincronização. O modelo para programação distribuída baseado em objetos oferece basicamente: - paralelismo de alta granularidade: permitindo (desde que exista mais de um processador) que mais de uma parte da aplicação esteja executando em um mesmo instante de tempo; - cooperação entre processos: possibilitando comunicação e sincronização entre partes da aplicação. 2.2. Objetos A exploração de paralelismo depende da divisão de um problema em um conjunto de partes que podem ser executadas em paralelo visando o máximo de proveito dos recursos. Normalmente, essa tarefa não é simples, se não existirem mecanismos adequados, nas linguagens de programação, para expressar essa solução. A programação concorrente orientada a objetos estuda como tais mecanismos podem ser implementados aproveitando-se das vantagens de programar no paradigma de objetos, e dessa forma implementar tais programas como uma coleção de objetos. Objetos podem representar naturalmente essas entidades paralelas já que, por definição, apresentam propriedades de encapsulamento e autonomia. Entretanto, é preciso analisar alguns aspectos dessa integração de concorrência com objetos, já que isso implica a incorporação de 1 Essa seção foi inicialmente desenvolvida por alunos da disciplina Programação com Objetos Distribuídos, ministrada no 1 o semestre de 2000 no curso PPGCC da UFRGS, a partir das notas de aula e outras referências.

6 conceitos bastante estabelecidos (como processos, sincronização, exclusão mútua, etc) dentro das técnicas embutidas nas linguagens orientadas a objetos. Um objeto remoto é uma unidade de processamento e distribuição criada e executada fora do contexto do objeto que o criou. Um objeto desse tipo é visível fora do objeto que o criou, podendo ser compartilhado por outros objetos. Assim, objetos podem, dinamicamente, tornar-se clientes de objetos que foram criados por outros. 2.3. Distribuição Sistemas de computação distribuída podem ser utilizados por muitos tipos de aplicações. As razões que levam a distribuir uma aplicação se enquadram em quatro categorias: decremento do tempo do processamento total, tolerância a falhas, especializações funcionais de um sistema, e aplicação inerentemente distribuída. Existem basicamente duas características que distinguem a programação distribuída da programação seqüencial: o uso de múltiplos processadores e a cooperação entre os processadores. Um dos requisitos para programação distribuída é a habilidade de distribuir a execução de diferentes partes de um programa em diferentes processadores. Objetos Passivos Em alguns modelos, dados compartilhados são encapsulados em objetos passivos, ou seja, objetos que atendem a requisições de serviço e não possuem fluxo de controle próprio. Os dados armazenados pelo objeto são acessíveis apenas através do conjunto de operações definidas pela classe de objeto, o qual é uma instância de tipos abstratos de dados. 2.4. Concorrência Em se tratando de concorrência, objetos são unidades autônomas de execução e distribuição, interagindo periodicamente com outros objetos através de chamadas de métodos. Os objetos podem apresentar concorrência internamente, para possibilitar a execução de várias tarefas simultaneamente. Objetos que não são remotos, i.e., que são criados e executados dentro do contexto de algum objeto, podem ser de natureza passiva ou ativa. Objetos Passivos Os objetos do tipo passivo têm seu código incorporado ao objeto que os criou, e executam apenas chamadas de métodos; nos intervalos entre chamadas, permanecem sem executar nenhuma tarefa. Objetos Ativos Os objetos ativos, depois de criados, passam a executar uma seqüência de comandos particulares, ao mesmo tempo em que continuam atendendo chamadas de métodos, quando solicitados. Esses comandos particulares são, basicamente, tarefas necessárias à manutenção do estado interno do objeto, que distinguem objetos ativos dos passivos. Outra forma de concorrência é a execução concorrente de métodos. Como objetos remotos podem ser compartilhados por vários clientes, pode ser que, num determinado momento, pedidos para a execução de métodos sejam atendidos enquanto um (ou mais métodos) está sendo executado. Cada pedido de execução de método causa a ativação de uma Thread para atender esse pedido,

7 utilizando como dados locais os parâmetros da chamada e as variáveis locais ao método (e de demais funções chamadas em sequência). Essa Thread começa a executar o método e é destruída quando o resultado da execução do método é devolvido ao objeto cliente. Linguagens orientadas a objetos concorrentes trazem os benefícios da orientação a objeto, pois permitem modularizar um problema em pequenos problemas, baseando-se em dados antes de funções, para ambientes multiprocessadores. Abaixo serão apresentadas algumas considerações sobre concorrência. Objetos Concorrentes Objetos, na maioria das linguagens e sistemas existentes, são estáticos ou passivos, isto é, somente um objeto é executado a cada instante. Diante desta limitação, surge o conceito de objetos concorrentes que consistem de operações (métodos), armazenamento local de dados e de um processador. Este conceito é simples, pois a alocação do processador é função da implementação e não da linguagem de programação. Um objeto concorrente torna-se ativo quando recebe uma mensagem invocando um método. Três elementos em objetos concorrentes merecem atenção especial: mensagens, classes e metaobjeto. Mensagens Objetos concorrentes interagem entre si trocando mensagens. Em objetos seqüenciais, mensagens são restritas a simples chamadas síncronas de procedimentos. Em objetos concorrentes, o mecanismo de passagem de mensagens assíncronas deve ser incluído a fim de permitir a exploração da concorrência. Classes Classes em linguagens orientadas a objetos seqüenciais servem para a criação de instâncias e compartilhamento de código. Em uma implementação distribuída, o que é natural para objetos concorrentes, o compartilhamento de código em tempo de execução através da hierarquia de classes deve ser reconsiderado. Em objetos concorrentes, é mais efetivo para cada objeto ter seu próprio código. Isto permite que uma instância migre para diferentes nodos do sistema distribuído, tornando fácil a implementação. Meta-objetos Em objetos seqüenciais existe apenas um objeto controlador para todo o sistema. Assim, o nível meta pode ser acessado e alterado por um objeto, suspendendo a execução dos demais. Além disso, a utilização de um controlador único diminui o grau de paralelismo do sistema. Em objetos concorrentes, um objeto não pode suspender a execução de outros objetos, devendo se constituir em uma entidade independente do sistema. Deste modo cada objeto deve possuir seu próprio controlador. Em multiprocessadores convencionais, objetos se comunicam ou por compartilhamento de memória ou por troca de mensagens. Mas em ambientes orientados a objeto, a comunicação é

8 sempre através de troca de mensagens, pois compartilhar dados entre objetos violaria o princípio do encapsulamento. Existe um questionamento sobre a validade de violar o paradigma de objeto em nível físico a fim de maximizar a performance. No entanto, o programador não poderia ter acesso a este nível. Tipos de mensagens As linguagens orientadas a objeto utilizam três tipos de comunicação: - Síncrona: a comunicação síncrona usa chamadas remotas a procedimentos. Isto é muito fácil de implementar, mas algumas vezes causa desperdício de tempo por causa do requerimento de um send e um receive para fazer o rendezvous. Sistemas síncronos são mais previsíveis e fáceis de testar. - Assíncrona: a comunicação assíncrona elimina a espera por sincronização e pode aumentar o volume de atividades concorrentes. No entanto, é menos previsível, conseqüentemente difícil de programar e testar. Um programa pode usar comunicação assíncrona se seus objetos podem permanecer processando sem esperar por alguma resposta para suas mensagens. - Invocação (chamada com resposta no futuro): invocação, ou método futuro, é uma variação da comunicação assíncrona, pois o chamador também continua executando, enquanto uma variável futura aloca um local para o resultado. O sender processa até acessar a variável futura. Se o resultado tiver retornado, o sender continua; se não, ele bloqueia e fica esperando o resultado. Aceitação de mensagens Objetos recebem mensagens implicitamente ou explicitamente. Aceitação implícita significa que o sistema aceita mensagens automaticamente, e os usuários não podem controlar o seu recebimento. Em um sistema implícito, uma tarefa de baixa prioridade pode interromper uma tarefa de alta prioridade. Para controlar isto, o programador pode atribuir propriedades às mensagens, mas isto torna o programa mais complexo. A aceitação explícita permite que os objetos controlem o momento em que receberão e processarão as mensagens. Isto é mais flexível, pois esquemas de prioridade são definidos em uma lista de mensagens e o objeto pode respondê-las. No entanto, isto aumenta o overhead em tempo de execução, pois o sistema precisa priorizar a fila de mensagens e, em função disto, o programador assume maior responsabilidade sobre o controle do processamento de mensagens. 2.5. Sincronização Uma sincronização correta coordena as atividades paralelas para que executem eficientemente, consistentemente e previsivelmente. Muita coordenação reduz a concorrência, pouca conduz a um indeterminismo indesejável. O esquema de herança complica a sincronização, pois quando uma subclasse herda de uma classe base, o programa precisa, algumas vezes, redefinir a sincronização do método herdado. Este é o aspecto mais complicado na integração de concorrência em linguagens orientadas a objeto. Se uma única classe centralizada controlar explicitamente a recepção de mensagens, todas as subclasses precisarão reescrevê-la cada vez que um novo método for adicionado a classe. A

9 subclasse não poderá simplesmente herdar o código de sincronização, pois a classe de mais alto nível não consegue invocar o novo método.

10 3. Java Threads - concorrência e sincronização 3.1. Introdução Este texto aborda dois grandes tópicos da programação concorrente em Java: - expressão da concorrência em Java através dos objetos Thread; - sincronização dos objetos Thread. 3.2. Java Thread Uma thread Java é um fluxo de controle, ou processo leve, dentro de um programa. Um objeto do tipo Thread equivale a um bloco de controle de processo contendo dados, métodos e prioridades. Um objeto Thread oferece métodos especiais como: - public final void setpriority(int newpriority): altera a prioridade da thread; - public void start(): inicia a execução de uma thread; - public void interrupt(): interrompe a execução de uma thread. As threads Java são escalonadas pelo escalonador da máquina virtual de Java, conforme esquema de escalonamento preemptivo, baseado em prioridades. As aplicações de threads são várias como: - entrada e saída assíncrona; - tratamento assíncrono de requisições assíncronas em sistemas cliente/servidor; - processos de serviço em retaguarda (background); por exemplo, coletores de lixo (garbage collectors); - sistemas reativos que precisam tratar certos eventos rapidamente usando escalonamento baseado em prioridades; - servidores de tempo; - processamento paralelo: uso do poder de computação das máquinas multiprocessadoras. 3.3. Criação de threads As threads Java (ou somente threads a seguir) podem ser criadas por dois métodos. - método A: -- estender a classe Thread definindo uma nova subclasse; -- reescrever o método run(); -- criar um objeto da nova subclasse; -- iniciar a execução da thread via o método start().

11 - método B: -- definir uma classe C que implementa a interface Runnable; -- criar um objeto O da classe C; -- criar um objeto do tipo Thread (classe) passando o objeto O como parâmetro; --iniciar a execução da thread via o método start(). Um exemplo de criação pelo método A é dado a seguir: public class MyThread extends Thread { private String whoami; private int delay; public MyThread(String name, int d) { whoami = name; delay = d; public void run() { try { sleep(delay); catch(interruptedexcetion e) { System.out.println( Hello, this is +whoami+! ); public class TestThreads { public static void main(string[] args) { MyThread t1, t2, t3; t1 = new MyThread( First, 1000); t2 = new MyThread( Second, 500); t3 = new MyThread( Third, 2000); t1.start(); t2.start(); t3.start();

12 Uma provável saída (impressão) da execução do programa acima seria: Hello, this is second! Hello, this is First! Hello, this is Thirst! No caso de criação de thread com interface Runnable, usa-se o fato de que a classe Thread também é implementada como Runnable. Runnable é uma interface do ambiente Java. O esqueleto do código de uma classe que implementa Runnable está abaixo: class ThreadBody implements Runnable {... public void run() { // código do corpo da thread Um exemplo de criação de thread usando a interface Runnable é dado a seguir. No mesmo, se passa o objeto Runnable (ThreadBody) como argumento da criação de um objeto Thread: Thread t = new Thread (new ThreadBody()); t.start(); Uma vantagem significativa desse método é o que com o mesmo a classe thread do usuário (ThreadBody no caso acima) pode estender uma outra superclasse diferente da classe Thread do ambiente Java. 3.4. Sincronização O conceito geral de sincronização de threads Java segue o modelo clássico de monitores. Um monitor consiste de estruturas de dados e de uma coleção de procedimentos que operam sobre as estruturas do monitor. No modelo clássico, somente uma thread (ou processo) pode executar um procedimento do monitor em um momento, o que oferece exclusão mútua automática no acessos aos dados do monitor. O mesmo modelo ainda oferece as variáveis condicionais, sobre as quais pode-se executar as primitivas wait e signal. A primitiva wait bloqueia um processo de forma incondicional e libera um outro processo para executar um procedimento do monitor. A primitiva signal acorda um processo bloqueado pela primitiva wait. Cada variável condicional possui uma lista (eventualmente uma fila FIFO) de processos bloqueados. O modelo acima é aplicado em Java com algumas diferenças importantes. Qualquer objeto Java pode ser visto como um monitor. Os processos do modelo clássico são implementados pelas threads Java, as quais chamam (executam) os métodos do objeto monitor. Entretanto, a exclusão mútua automática deve ser explicitada pelo programador. Na sua forma básica, um objeto Java permite que várias threads possam estar executando seus métodos ao mesmo tempo. A implementação da exclusão mútua pode ser obtida com o uso do modificador de método

13 synchronized. Blocos (trechos de comandos) de exclusão mútua, dentro de um método, com granularidade mais fina que o objeto, podem ser implementados com semântica similar via o comando synchronized. As primitivas clássicas wait e signal são implementadas via os métodos wait e notify/notifyall. Entretanto variáveis de condição propriamente ditas não existem. Elas podem ser emuladas através de objetos de qualquer tipo, os quais devem obrigatoriamente ser referenciados na especificação dos blocos de exclusão mútua (comando synchronized). O modificador de método synchronized torna o mesmo parte do monitor. Não é necessário que todos os métodos de uma classe sejam modificados com synchronized. Os eventuais métodos sem synchronized não respeitam a exclusão mútua, isto é, uma thread pode estar executando um método synchronized enquanto várias outras podem estar executando métodos não synchronized do mesmo objeto. O método wait() inclui a thread em execução na lista de espera do monitor e permite a execução de outra thread dentro do monitor. A thread deve estar de posse do monitor, o que no caso básico (objeto monitor) significa que a thread está executando um método synchronized do objeto. O método notify() acorda uma thread da lista de espera do monitor. A escolha de qual thread a acordar é não determinística, ou em outras palavras, dependente de implementação do ambiente de execução Java. Observe-se que a condição de somente uma thread no monitor continua válida. A escolha de qual thread continua em execução, devido à exclusão mútua, é também não determinística. O método notifyall() acorda todas as threads da lista de espera do monitor. Como no caso do método notify(), a escolha de qual thread continua a execução é não determinística. A seguir é dado um exemplo simples do uso de sincronização. O problema é a codificação de uma classe que implementa uma fila no conceito de ordem FIFO: First In, First Out. A fila deve oferecer dois métodos públicos: - inclusão (append): inclui um elemento no fim (tail) da fila; - retirada (get): retira um elemento do início (head) da fila. Em caso de fila usada em programas monothreads as situações de exceção podem ser tratadas da seguinte forma: - se a fila está vazia em retirada: retorna um aviso; - se a fila está cheia em inclusão: idem. No caso de uso em programas multithread, pode-se oferecer soluções mais interessantes como fazer o usuário ou cliente (processo, thread) esperar em caso de exceção. Na situação de fila vazia em retirada, a thread cliente espera até haver alguma inclusão. Para simplificação do exemplo abaixo, para o caso de fila cheia considera-se que o buffer usado para armazenar os elementos da fila é ilimitado. Deve-se prever a concorrência possível entre diversas threads no acesso à fila. Essa concorrência permite que várias threads estejam inserindo e excluindo elementos ao mesmo tempo. Isto pode levar o objeto fila a um estado inconsistente, como ponteiros apontando para elementos

14 inexistentes. Esse problema, de exclusão mútua, pode ser resolvido de modo simples com o uso do modificador synchronized nos métodos append e get. Um segundo problema a ser resolvido é o de bloquear o cliente que chama o método get() quando a fila está vazia. Isto pode ser resolvido com o uso da primitiva wait() sobre o próprio objeto servidor (implicitamente no código abaixo). O terceiro problema, relacionado ao segundo, é o acordar o mesmo cliente quando algum elemento for incluído na fila. O uso da primitiva notify() resolve o mesmo. Uma extensão do problema geral é a de, considerando que o buffer é limitado, por exemplo a N elementos, bloquear o cliente que tenta incluir um elemento quando a fila está cheia. A solução da extensão é deixada a cargo dos leitores. Um esqueleto de código do problema básico, considerando somente a exclusão bloqueio em caso de fila vazia, está abaixo: classe Queue { Element head, tail; // first and last element of the queue // structure: element and pointer (next) // inserts element at the end of the queue public synchronized void append(element p) { if (tail == null) else head = p; tail.next = p; p.next = null; tail = p; notify(); // if queue is empty: simple case // first element is the new element // last elem. points to new element // next of last element is null // last element is the new element // notify someone that 1 element arrived mútua e o public synchronized Element get() { try { while (head = null) // if queue is empty? wait(); // wait for an element catch (InterruptedException e) { return null; Element p = head; // save first element head = head.next; // take out of queue if (head == null) // queue is empty?

15 tail = null; // last element null return p; 3.5. Controle de threads O ambiente Java ainda oferece um conjunto de métodos para controle de threads. Esses métodos são em geral chamados por outra thread (objeto) fazendo referência a uma segunda thread (objeto). Por exemplo, em thread a sobre thread b: b.stop(); Alguns desses métodos, em princípio os mais importantes, são brevemente descritos a seguir: Método start() stop() isalive() suspend() resume() sleep(long ml) Descrição inicia execução da thread principal (run) do objeto; JVM chama o método run() força a própria thread a terminar sua execução testa se a thread foi iniciada e ainda não terminou suspende a thread até ser reativada (resume()) reativa thread suspensa anteriormente a thread é colocada em espera ( dormindo ) por ml milisegundos; a thread não abandona o monitor (synchronized) Tabela 1 - Métodos de controle de threads 3.6. Endereços Alguns endereços de sites relacionados com Java estão indicados a seguir: Descrição site da Sun sobre Java notas técnicas tutorial Java tutor Java Java ensina Java Endereço http://java.sun.com http://java.sun.com/jdc/tecdocs/newsletter/in dex.html http://javasoft.com/docs/books/tutorial/index. html http://www.mercury.com/java-tutor/ http://www.neca.com/~vmis/java.html

16 outro tutorial Java http://www.phrantic.com/scoop/onjava.html Tabela 2 - Sites sobre Java 3.7. News Groups Alguns nomes de news groups relacionados a Java estão indicados a seguir: comp.lang.java.announce comp.lang.java.api comp.lang.java.beans comp.lang.java.databases comp.lang.java.gui comp.lang.java.help comp.lang.java.machine comp.lang.java.programmer comp.lang.java.security comp.lang.java.softwaretools comp.lang.java.tech

17 4. Java RMI - comunicação por chamada de método remoto 4.1. Introdução Este texto introduz os conceitos do pacote RMI, um tópico importante da programação distribuída com Java. Alguns dos principais tópicos abordados nesse texto são: - conceitos básicos de RMI: lado servidor e lado cliente; - exemplo Hello; - roteiro de desenvolvimento; - segurança; - pacote RMI. 4.2. Conceitos básicos RMI, ou "Remote Method Invocation" (Invocação Remota de Método) é um mecanismo que permite a chamada de métodos de objetos remotos (distribuídos). O nome ou sigla RMI é bastante associado ao mecanismo proprietário do ambiente Java. Entretanto, ele pode ser usado para outros mecanismos em geral, como CORBA e DCOM (apesar de, nesses ambientes, serem empregados outros termos), ou mesmo como o termo genérico para chamada remota de método. O objetivo principal é o de oferecer comunicação entre objetos distribuídos de forma similar à comunicação entre objetos locais. Isto simplifica a programação de sistemas distribuídos. RMI apresenta características similares às de RPC (chamada remota de procedimento), um conceito mais antigo de comunicação, mas também introduz diferenças importantes. Outras características do RMI são: - tratamento automático/implícito da heterogeneidade entre máquinas; - modelo cliente/servidor; - comunicação bidirecional; - argumentos de entrada; - valor de retorno. As duas últimas características têm sintaxe idêntica e semântica similar às de chamada local de método. Existem entretanto diferenças sensíveis entre RPC e RMI. Em RPC é realizada a chamada de um procedimento de um módulo servidor (e não de um objeto). A identificação do módulo é freqüentemente implícita na chamada. Só há um procedimento com determinado nome no módulo. O procedimento usa os dados (contexto) do módulo e não de um objeto. O cliente não pode acessar diferentes instâncias do mesmo tipo de servidor, como é possível no modelo OO (orientação a objetos), em especial com RMI, sendo que cada instância tem um estado (dados, contexto) próprio.

18 Em RMI, é realizada a chamada de um método de um objeto específico, o qual é sempre explicitado na chamada. Vários objetos podem ter o mesmo método (nome, argumentos e valor de retorno). Os objetos têm dados (contexto) locais ou próprios. Os objetos (e não os métodos) são registrados no sistema de RMI. 4.3. Recursos básicos As principais características do uso de RMI são descritas nessa seção. O objeto servidor deve ser registrado com nomes dados pelo usuário (programador), em um servidor de nomes próprio do RMI, denominado rmiregistry. Opcionalmente pode-se usar outros servidores de nomes via a API JNDI. O cliente precisa localizar os objetos remotos (servidores), obtendo como resultado referências a esses objetos. Para isto o cliente deve acessar o mesmo rmiregistry, via o nome associado ao objeto servidor, para obter a referência. Em outras palavras, no caso básico, o programador do objeto cliente precisa conhecer esses nomes dados pelo programador do objeto servidor. A comunicação entre objetos é deixada totalmente a cargo do RMI, ou seja, é transparente ao programador e similar à comunicação local. Eventualmente, em uma aplicação pode ser necessária a carga de classes de objetos que foram passados pela rede. Isto é implementado via o uso de servidores WEB e protocolos como HTTP, FTP,... 4.4. Comunicação entre os componentes Um aspecto importante da comunicação entre os componentes do sistema RMI é a passagem de parâmetros e resultados entre duas máquinas, principalmente se as duas são heterogêneas. Os tipos primitivos (por exemplo, int, boolean, double,...) são passados por valor na sua forma normal (lembrar que a forma normal dos tipos primitivos Java é única para qualquer ambiente - hardware e SO). Os objetos remotos (isto é, objetos que implementam a interface remota) são passados como referências remotas, apenas para permitir que o receptor possa chamar os métodos dos objetos remotos. Isto nada mais é do que dizer que o objeto servidor não é (implicitamente) passado (ou copiado) para a máquina do objeto cliente. A transferência da referência é realizada implicitamente no momento da busca do servidor pelo cliente. Todos os outros objetos são serializados e então passados por valor (isto é, uma cópia do objeto é transferida). Serialização é um mecanismo de transformação de um objeto Java em uma seqüência de bytes, de modo que o mesmo possa ser transferido pela rede ou gravado em um arquivo. 4.5. Diferenças entre RMI e chamada local de método Diferentes tipos de falhas podem ocorrer em um sistema distribuído, afetando a programação. Por exemplo, a falha pode atingir somente o servidor e não o cliente, o qual continua sua execução, podendo ficar bloqueado à espera de uma resposta do servidor. Alguns métodos, como hashcode, equals, e tostring, são sensíveis a contextos distribuídos, podendo apresentar comportamento diferente.

19 4.6. Camadas de software do sistema RMI (exemplo Hello) No lado do servidor os métodos remotos devem ser especificados em uma interface remota que estende a classe java.rmi.remote do pacote RMI. Os objetos remotos são instâncias de classes que implementam a interface remota; essas classes devem ser definidas como subclasses de java.rmi.server.unicastremoteobject, uma classe do pacote RMI. Opcionalmente, pode-se estender qualquer classe e chamar o método estático UnicastRemoteObject.exportObject(objeto). O programa servidor (pode ser o main) deve criar um objeto remoto da classe acima, associar esse objeto a um nome simbólico e incluir essa associação no rmiregistry. Métodos remotos e construtores de objetos remotos podem disparar exceções do tipo RemoteExceptions; elas devem ser declaradas e tratadas. Para ilustrar esses conceitos, será usado o clássico e simples exemplo do Hello World. O mesmo será desenvolvido de forma gradativa. Uma implementação desse problema no paradigma clienteservidor pode ser: o cliente faz uma chamada ao servidor que imprime o string Hello World. A interface do servidor é a seguinte: // todos os arqs em um pacote package hello; // importa pacote de classes RMI import java.rmi.*; // interface do objeto servidor public interface Hello extends Remote { // um único método sayhello public String sayhello() throws java.rmi.remoteexception; A implementação da classe do servidor é simples, pois o mesmo tem um único método que imprime o string Hello World. Conforme dito acima, a complexidade adicional vem dos requisitos de uso do rmiregistry e do tratamento obrigatório de eventuais exceções. O código da classe servidor é: package hello; import java.rmi.*; import java.rmi.server.*; // herda a UnicastRemoteObject e implementa a interface Hello public class HelloImpl extends UnicastRemoteObject implements Hello{ // implementa o construtor public HelloImpl() throws RemoteException{

20 super(); // implementa o método sayhello public String sayhello() throws RemoteException { return Hello, World! ; // método main da classe servidora public static void main (String args[]) { try { // cria objeto HelloImpl HelloImpl h = new HelloImpl(); //registra o objeto Naming.rebind( hello, h); catch (Exception e) { System.out.println( HelloImpl.main: + e); O lado do cliente é diferente da versão seqüencial em 3 aspectos: questões de segurança, busca do servidor e tratamento das eventuais exceções. Em geral, um cliente que queira utilizar classes de um servidor remoto deve estabelecer um gerenciador de segurança, por exemplo, o RMISecurityManager, fornecido pelo ambiente Java (por exemplo, o JDK da Sun). O cliente referencia o objeto remoto usando seu nome simbólico para procurá-lo no rmiregistry. A partir desse momento, o cliente pode chamar métodos de um objeto remoto da mesma maneira que ele chama métodos de objetos locais. Deve entretanto tratar as exceções do tipo RemoteException dos métodos remotos. O código da classe cliente é: package hello; import java.rmi.*; public class HelloClient { public static void main (String args[]) { System.setSecurityManager (new RMISecurityManager());

21 try { Hello h = (Hello) Naming.lookup( rmi://ijui.inf.ufrgs.br/hello ); //chama um método remoto String message = h.sayhello(); System.out.println(message); catch (Exception e) { System.out.println( Exception in main : + e); 4.7. Passos do uso de RMI Os passos necessários ao desenvolvimento e execução de clientes e servidores remotos com comunicação por RMI são: 1) Escrever arquivos Java para: interface remota; classe que implementa a interface remota (servidor); classe que chama o método remoto (cliente). 2) Compilar os arquivos.java com javac (ou outra ferramenta de desenvolvimento Java) 3) Gerar arquivos stubs e skeletons com o compilador RMI rmic rmic < classe que implementa a interface remota> Alguns cuidados devem ser tomados com relação a diretórios e caminhos (paths) em caso de uso da opção de pacote (package: agrupar todos os fontes de uma aplicação). 4) Iniciar o registry daemon na máquina remota Se o sistema for de tipo Unix (Solaris da Sun, por exemplo) executa-se: rmiregistry & Se for Windows 95/97/Me/NT/2000: start rmiregistry 5 ) Iniciar o servidor na máquina remota Se o RMISecurityManager foi criado, é preciso indicar a política de controle, normalmente através de um arquivo especial (policy). Um exemplo de política totalmente aberta (cuidado!) para testes é gerar um arquivo policy com conteúdo: grant { // Allow everything for now permission

22 java.security.allpermission; ; 5 ) Iniciar o servidor na máquina remota Um exemplo de chamada é: java -Djava.security.manager=myHome\mySources\policy hello.helloimpl O arquivo \myhome\mysources\policy contém a política. 6) Iniciar o programa cliente na máquina cliente java hello.helloapp 4.8. Segurança do RMI Um programa (normalmente o cliente) que queira utilizar classes de uma máquina remota deve estabelecer um gerenciador de segurança, por exemplo: System.setSecurityManager (new RMISecurityManager()); O RMISecurityManager não permite que classes remotas (entre outras): - utilizem novas classes; - manipulem threads; - saiam da Máquina Virtual Java. Outros gerenciadores de segurança podem ser obtidos por construção estendendo-se o RMISecurityManager. Um exemplo seria a implementação da autenticação de chaves públicas. 4.9. Outros aspectos Um aspecto importante da programação com RMI é a chamada Integridade Referencial. Quando duas (ou mais) referências ao mesmo objeto são passadas em uma mesma chamada remota, na máquina receptora elas apontarão para a mesma (única) cópia do objeto. Entretanto, se o mesmo for feito em duas chamadas, haverá duas cópias do objeto na máquina receptora. Um outro aspecto importante é a clássica semântica de chamada RPC em caso de falhas. O programador de RMI pode ter certeza de que cada chamada é executada somente uma vez em caso de sucesso. Em caso de falhas (rede, servidor), há certeza de que a chamada foi executada ou uma única vez ou nenhuma. 4.10. Pacote java.rmi O pacote java.rmi deve ser usado por programas clientes e servidores. Ele contém diversas classes. A interface Remote deve ser usada na implementação das interfaces dos servidores. A classe Naming é usada para associação, desassociação e procura de objetos remotos. A classe RMISecurityManager é encarregada de testes de segurança em classes carregadas de

23 máquinas remotas, por exemplo, os stubs para os clientes. A classe RemoteException estende a java.lang.exception tendo subclasses, como por exemplo: - ConnectException - AccessException - NoSuchObjectException Elas devem ser pegas num bloco catch ou declaradas em uma cláusula throws. O pacote java.rmi.server é necessário somente para uso em servidores. Entre as classes mais importantes encontra-se a RemoteObject que estende java.lang.object e implementa métodos com semântica especial remota, como equals(), tostring(), hashcode(). A classe RemoteServer oferece métodos para controle da máquina cliente e do stream de saída para log das chamadas. Ela possui a subclasse UnicastRemoteObject, a qual usa sockets TCP para comunicação. Nessa classe, as referências remotas não permanecem válidas após reinícios (falha - start) do servidor e oferece uma única cópia do objeto (sem replicação). A classe java.rmi.activation.activatable é uma classe abstrata que oferece suporte para objetos persistentes e que são ativados pelo sistema (automaticamente). 4.11. Pacote java.rmi.registry O pacote java.rmi.registry oferece basicamente as interfaces e classes da implementação do servidor de nomes usado em programação RMI. Ele entretanto pode ser usado para outras finalidades, em especial para o desenvolvimento de servidores de nomes mais evoluídos do que o atual oferecido pelo ambiente JDK (Sun). Um registro (servidor de nomes do RMI) é um objeto remoto que mapeia nomes para objetos remotos. Um registro pode ser usado em uma máquina virtual com outras classes de servidores ou sozinho. O pacote oferece duas interfaces para recuperação e registro de objetos através de um simples nome: - interface java.rmi.registry.registry; - interface java.rmi.registry.registryhandler: abandonado em novas versões. A interface java.rmi.registry.registry oferece métodos para procura, associação, reassociação, desassociação e listagem do conteúdo de um registro. A classe java.rmi.naming (faz parte do pacote java.rmi) usa a interface remota Registry para o uso de nomes baseados em URL.

24 5. Introdução a CORBA 5.1. Introdução Este texto contém uma introdução aos principais conceitos do padrão CORBA. Os principais tópicos a serem abordados são: - conceitos básicos de CORBA: definição, histórico, arquitetura,... - IDL: linguagem para declaração de interfaces; - arquitetura do ORB: barramento de comunicação entre objetos; - serviços CORBA; - facilidades e objetos de negócio. 5.2. O que é CORBA CORBA, ou Common Object Request Broker Architecture, é um padrão proposto pelo OMG (Object Management Group). CORBA pode ser visto como um conjunto de middlewares: - independentes de plataforma; - que permitem tratamento de sistemas e aplicações heterogêneas; - que usam a orientação a objetos. 5.3. Histórico CORBA Em abril de 1989 a OMG foi criada por 11 companhias, como 3Com Corporation, American Airlines, Canon, Inc., Data General, Hewlett-Packard, Philips Telecommunications N.V., Sun Microsystems e Unisys Corporation. Em 1990 a OMG publica o Object Management Architecture Guide (OMA Guide), e em outubro de 1991 publica a especificação do CORBA 1.0, que contém: - IDL (linguagem de declaração de interfaces); - mapeamento para linguagem C; - uma API de serviços. Em fevereiro de 1992, a versão CORBA 1.1 é publicada, a qual foi muito difundida, eliminando ambiguidades da anterior e propondo novas interfaces. Em 1992 saiu uma revisão do OMA, e em dezembro de 1993 a CORBA 1.2, novamente eliminando ambiguidades. Em 1995 são adicionadas as Common Facilities. A versão CORBA 2.0 é anunciada em agosto de 1996, apresentando diversos protocolos para interoperabilidade entre diferentes ORBs, como GIOP, IIOP, DCE CIOP, além dos mapeamentos para Smalltalk e C++. Os mapeamentos para COBOL e Ada são introduzidos com a versão CORBA 2.1 em agosto de 1997, e em fevereiro de 1998 os para Java, junto com a interconexão para o padrão DCOM da Microsoft.

25 A versão CORBA 3.0 está em desenvolvimento há vários anos, e pode ser caracterizada como uma série de especificações mais ou menos independentes. As principais entre elas se referem a: - integração com Java e Internet; - qualidade da gerência de serviços; - componentes distribuídos. 5.4. Arquitetura CORBA A arquitetura CORBA, OMA, é organizada em diversos módulos: - application objects: -- desenvolvidos pelos usuários CORBA; - ORB: -- CORBA TM barramento que interliga todos os elementos; - common object services: -- coleção de serviços em nível de sistema; -- empacotados em interfaces especificadas em IDL; -- aumentam e complementam a funcionalidade do ORB; -- OMG: define mais de 15 padrões de serviços; CORBA common facilities: -- coleção de serviços para uso direto pelos objetos de aplicações; - domain interfaces: 5.5. IDL -- serviços para uso direto pelos objetos de aplicações de certos domínios; -- podem combinar facilities e services. A IDL é uma linguagem neutra de especificação de interfaces, usada no desenvolvimento de objetos servidores para a declaração dos métodos ou serviços. A descrição IDL de um componente/objeto CORBA estabelece uma relação contratual entre este e seus cliente e servidor, definindo a interface pela qual estes poderão interagir, no entanto sem fixar detalhes de implementação dos objetos. Ela é independente de linguagem de programação (C++, Java, Smalltalk,...). Atualmente oferece uma série de mapeamentos como C, C++, Ada, Smalltalk, COBOL e Java. Em particular, a IDL é usada para especificação de: - atributos de componentes; - classes pais (herança); - exceções; - eventos tipados (sinais).

26 A sintaxe da IDL pode ser caracterizada como um subset de C++ mais diversas palavras chaves para programação distribuída. A estrutura geral de um arquivo IDL é ilustrada a seguir: module <identificador> // define um escopo de nomes, equivalente a { <declarações de tipos de dados>; <declarações de constantes>; <declarações de exceções>; // namespaces em C++ ou packages em Java interface <identificador> [:<herança opcional>] { <declarações de tipos de dados>; <declarações de constantes>; <declarações de exceções>; [<tipo>] <identificador de método> (<parâmetros>).. [raises <exception>] [context]; [<tipo>] <identificador de método> (<parâmetros>).. [raises <exception>] [context]; interface <identificador> [:<herança opcional>].. 5.6. ORB O ORB (Object Request Broker), barramento que faz a ligação entre todos os módulos da OMA, possui diversas vantagens e características, das quais as mais importantes são introduzidas a seguir. O ORB permite chamadas estáticas e dinâmicas: - estáticas: ligações em tempo de compilação; - dinâmicas: ligações em tempo de execução.

27 Outros middlewares, em geral, oferecem somente chamadas estáticas. No ORB, as ligações para definição de serviços e chamadas são especificadas ou codificadas em linguagem de alto nível, como C++ mais IDL. Outros middlewares em geral permitem somente uma API de baixo nível como sockets, sem distinção entre especificação e implementação da interface. O sistema tem recursos para ser auto descritivo, via metadados para descrição de serviços (interfaces), usáveis em tempo de execução, e gerados automaticamente por precompiladores. Outros middlwares, em geral, não oferecem metadados. O ORB oferece transparência entre o local e o remoto, quanto a diversos itens como: - transporte, localização e ativação de objetos; - ordenação de bytes (arquitetura); - SO; - concorrência: processo único, multiprocessos em uma máquina, multiprocessos em rede. O ORB também suporta segurança e transações, via informações de segurança e de transações embutidas nas mensagens. As mensagens do ORB podem ser polimórficas, onde o efeito da chamada depende do objeto que atende. Ele é consistente com a tendência de especificação dos sistemas atuais, onde há separação entre especificação e implementação. Também permite tornar aplicações desenvolvidas em linguagens de outro paradigma, como COBOL, em objetos. Os mecanismos de chamada do ORB são similares aos de RPC (chamada remota de procedimento), mas entre os dois existem diferenças sensíveis como: - RPC: 1 único serviço (função); os dados são únicos; - ORB: 1 chamada: 1 função de 1 objeto que possui várias funções; cada objeto possui dados próprios (permitindo múltiplos dados ou estados). A estrutura interna do ORB é bastante complexa, podendo inicialmente ser dividida em duas grandes partes: o ORB cliente e o ORB servidor. A estrutura do ORB oferece independência sobre o servidor, pois esse pode ser implementado em outra linguagem, SO, máquina,... Um objeto pode ser servidor e cliente ao mesmo tempo. No lado do cliente, os principais componentes são: - stubs IDL para o cliente: implementam as chamadas estáticas do cliente para o servidor; - DII: é interface de chamada dinâmica, com a qual o cliente pode determinar métodos a chamar durante a execução; - repositório de interfaces: suporta obtenção e modificação de interfaces de componentes registrados; - interface ORBI: possui algumas API s para serviços locais; - recursos para chamadas estáticas e dinâmicas. As chamadas estáticas são mais fáceis de programar, mais rápidas e autodocumentáveis. As dinâmicas oferecem mais flexibilidade e são mais difíceis de programar. O servidor não distingue entre chamada estâtica e dinâmica.

28 No lado do servidor, os principais componentes são: - stubs IDL do servidor (skletons pela OMG): são as interfaces estáticas, havendo um stub para cada serviço; - interface de skeleton dinâmica (DSI): suporte ao mecanismo de ligação dinâmica, para servidores sem IDL skeletons compilados; - adaptador de objetos (Basic Object Adaptor - BOA): situado no topo dos serviços de comunicação do ORB, aceita requisições para objetos; é responsável (dinâmico) por instanciação de objetos, requisição de serviços, atribuição de ID s aos objetos (referências), registro de classes e objetos no RI,...; BOA: é o adaptador mínimo, padrão, definido no CORBA 2.0; os servidores podem suportar mais de um adpatador; - repositório de implementações: é um BD de informações sobre classes, objetos e ID s, e também informações associadas às implementações de ORB s. 5.7. ID s Globais e Protocolos Os ID's globais foram introduzidos no CORBA 2.0. São ID s únicos para todos os ORB s. O formato básico é composto de strings, em 3 níveis de nomes, gerados a partir de pragmas IDL ou outros métodos. Existem diversos protocolos de interconexão entre diferentes ORB s. O IIOP é um dos mais práticos, pois é um Internet Inter-ORB Protocol, especificado no CORBA 2.0 e baseado em TCP/IP. Todo ORB CORBA deve implementar o IIOP. Existem diversos protocolos inter-orb s específicos, chamados ESIOPS (Environment Specific Inter-ORB Protocols), para redes específicas. O GIOP (General Inter-ORB Protocol) é descrito por um conjunto de 7 mensagens e representações comuns de dados, ou CDR: Common Data Representation. Ele mapeia dados OMG-IDL em representação plana para uso em mensagens de redes, tratando: diferentes representações de hardware. O IIOP é a implementação do GIOP sobre TCP/IP. O IOR (Interoperable Object Reference) permite transmissão de referências de objetos entre ORB s distintos. 5.8. Serviços CORBA Os serviços CORBA são uma coleção de serviços empacotados com IDL, aumentando a funcionalidade do ORB. Por exemplo, serviços para criar um componente, nomeá-lo e introduzí-lo no ambiente. Os serviços são agrupados em diversos grupos (mais de 15). Alguns desses grupos de serviços (ou somente serviços) são: - serviço de vida (life cycle): operações de criação, cópia, movimento, exclusão de componentes; - serviços de persistência: operações (e serviços) para armazenamento persistente em diversos servidores de armazenamento como BD de objetos, BD relacionais, arquivos simples; - serviço de nomeação: operações para busca de componentes; permite uso de nomes de outros serviços de nomes como: ISO X.500, OSF DCE, Sun NIS, Novell NDS, Internet LDAP; - serviço de eventos: registro de interesse em evento por componente;

29 - serviço de controle de concorrência: gerente de locks (obtenção de locks,...); - serviços de externalização: envio ou recepção de dados por mecanismo tipo stream; - serviço de consultas: superset de SQL: baseado na especificação SQL3 e na Object Query Language (OQL) do Object Data Management Group (ODMG); - serviço de licença: operações para contabilizar uso de componentes; - serviço de propriedades: associação de valores a componentes; - serviço de tempo: sincronização de tempo em um ambiente distribuído; - serviço de segurança: segurança em ambiente distribuído; autenticação, lista de controle de acesso, confidencialidade (privacidade), delegação de credenciais entre objetos; - serviço de trader: yellow pages para objetos; objetos publicam seus serviços e pedem trabalho; - serviços de coleção: criação e manipulação de coleções de objetos do mesmo tipo. Um aspecto importante na escolha de um fornecedor CORBA é a verificação de quais serviços são implementados, em especial os mais importantes como o serviço de nomeação. 5.9. Facilidades CORBA Facilidades CORBA são serviços de uso direto pelos objetos de aplicação, em nível superior de semântica, por exemplo, em um nível de negócios. Elas podem ser horizontais ou verticais. O estudo de algumas das principais facilidades atualmente é realizado por força tarefa de serviço ORB ou por força tarefa de domínios de objetos de negócios. Alguns exemplos de facilidades em estudo são: - agentes móveis; - workflow; - firewalls; - frameworks para objetos de negócios. 5.10. Objetos de Negócio Objetos de negócio CORBA podem ser vistos como descrições de conceitos de negócios independentemente de aplicações (usuários/sistemas). Alguns exemplos de conceitos seriam: cliente, ordem, competidor, dinheiro, pagamento, carro, paciente,... Esses conceitos seriam reconhecíveis por usuários finais (não-técnicos), enquanto que os objetos de sistema (nãonegócios) seriam somente por programadores. Uma aplicação seria uma combinação de objetos de negócios em ambiente próprio, específico. Um objeto de negócio também deve ter uma interface e cooperaria com outros objetos de negócio para a realização de uma tarefa. 5.11. Endereços Alguns endereços de sites relacionados com CORBA estão indicados a seguir:

30 Site da OMG BEASystems: Object Broker and Iceberg; um dos CORBA mais antigos Borland/Visigenic: VisiBroker for Java; also for C++; líder em CORBA/Java IBM: SOM and Component Broker Slides sobre desenvolvendo aplicações distribuídas com CORBA Slides: apresentação de CORBA IONA: Orbix and Orbix Web; líder em ambientes CORBA; portado para mais de 20 sistemas operacionais Javasoft: Java IDL; CORBA/Java ORB embutido na versão 1.2 de Java; ambiente de desenvolvimento e um serviço de nomes CORBA-compliant ORBacus: ORB para C++ e Java; subset público (free) http://www.omg.org http://www.beasys.com http://www.visigenic.com/prod http://www.software.ibm.com/objects/som objects http://www.cs.wustl.edu/~schmidt http://hegel.ittc.ukans.edu/projects/corba/li nks/index.html http://www.iona.ie http://www.javasoft.com www.orbacus.com Tabela 1 - Sites sobre CORBA

31 6. Introdução a DCOM 6.1. Introdução Este texto contém uma introdução aos principais conceitos do padrão, ou tecnologia, DCOM da Microsoft (MS). Os seguintes aspectos (não exatamente uma súmula) serão abordados: - Visão geral de DCOM; - Características COM/DCOM; - Arquitetura DCOM; - Exemplo em Java; - Onde conseguir DCOM; - Diferenças entre DCOM, CORBA e RMI (Java). 6.2. Visão geral de DCOM DCOM (Distributed Component Object Model) é um produto comercial da Microsoft (MS), podendo ser caracterizado como uma extensão distribuída de COM (Component Object Model), também da MS. DCOM implementa o ORPC (Object Remote Procedure Call) para realizar as chamadas remotas. Um servidor COM é capaz de criar múltiplas instâncias de múltiplas classes de objetos. DCOM é a base da MS para implementação de componentes e aplicações para a Internet. Um exemplo é o ActiveX, um objeto DCOM. O MTS, Microsoft Transaction Server, usado normalmente em plataformas NT, pode ser visto como o DCOM para empresas. A ferramenta Visual J++ é o ambiente Java da MS, cuja primeira versão é de 1996. Basicamente ele é mais integrado com DCOM que o Visual C++. Clientes Java podem, usando DCOM, chamar componentes COM escritos em outras linguagens sem usar RMI. DCOM tem funções equivalentes às de CORBA, mas tem também grandes diferenças com relação a CORBA. Sua linguagem de definição de interface, também chamada IDL, é baseada na IDL do DCE. A implementação usual da IDL gera dois stubs (proxy/stub), para cliente e servidor respectivamente. O cliente faz a chamada ao objeto proxy que comunica-se com o stub afim de que este realize a chamada do método implementado em um objeto do servidor. Após compilado o objeto passa pôr um processo de registro afim de associar a identificação de classes (CLSID) ao caminho para o objeto no servidor de componentes. A IDL do DCOM não suporta múltipla herança de interfaces, mas suporta delegação (containment/delegation), onde as interfaces internas são chamadas via a externa, e agregação (aggregation), onde as interfaces internas são chamadas diretamente. 6.3. Características do DCOM Em COM, é possível referenciar classes particulares de objetos via CLSIDs. CLSIDs garantem unicidade e nomeação de forma descentralizada para objetos e classes (tamanho de 128 bits). Um objeto COM suporta múltiplas interfaces. O cliente COM interage com um objeto COM obtendo um ponteiro para uma das interfaces do objeto e invocando métodos através deste ponteiro.

32 DCOM estende COM para suportar comunicação entre objetos em máquinas diferentes de forma transparente. DCOM substitui comunicação local com um protocolo de rede, podendo-se usar qualquer protocolo de transporte, incluindo TCP/IP, UDP, IPX/SPX e NetBios. Entre as plataformas disponíveis encontra-se Windows 95/98/NT 4.0, Apple (Macintosh), Sun Solaris, AIX, MVS e Linux. É possível realizar a troca da localização de objetos sem necessidade de recompilação. Virtualmente qualquer linguagem pode ser usada para criar componentes COM. Os objetos DCOM residem dentro de executáveis e DLLs. DCOM usa o mecanismo de segurança do Windows NT. Preve-se que muitas implementações UNIX de DCOM incluirão um mecanismo de segurança compatível com o do Windows NT. DCOM detecta falhas da rede e de hardware do lado cliente. Se a rede se recupera antes do timeout, DCOM reestabelece a conexão automaticamente. 6.4. Exemplo Counter em DCOM/Java O exemplo nessa seção é uma aplicação simples denominada counter, usado em diversas seções do livro do Orfali sobre CORBA/Java. É um aplicação do modelo cliente/servidor. O servidor tem a função de incrementar uma variável local. A interface do servidor (S) tem um único método increment(), sem argumentos, e que retorna novo valor da variável interna. O uso de DCOM para Java é mais simples e implícito que para C++. Os passos gerais são: - a criação do arquivo DCOM IDL; - a geração das identificações únicas (via ferramenta especial do Windows NT); - a criação do arquivo biblioteca de tipos (via o compilador MIDL); - a criação de arquivos resumos e interfaces para Java; - a implementação da classe servidora em Java; -- implementar - implements - a interface; - a compilação das classes Java; - o registro das classes Java (via a tool JavaReg); - a implementação do programa cliente (classe Java); -- mais simples que em CORBA; -- uso de interfaces (cria objeto da classe e cast para interface); - compilação do cliente; - registro da máquina remota na máquina cliente; - execução do cliente. No exemplo counter em DCOM/Java, o cliente realiza as seguintes tarefas: - define valor inicial da variável sum; - chama método increment 1000 vezes; - mostra o valor final de sum;

33 - mostra o tempo médio de resposta do S. O código do cliente é : // CountDCOMClient.java import count.*; class CountDCOMClient { public static void main(string args[]) { try { // Bind to the Count Object System.out.println("Creating Count Object"); ICount counter = (ICount)new count.count(); // Set sum to initial value of 0 System.out.println("Setting sum to 0"); counter.set_sum((int)0); // Calculate Start time System.out.println("Incrementing"); long starttime = System.currentTimeMillis(); // Increment 1000 times for (int i = 0 ; i < 1000 ; i++ ) { counter.increment(); // Calculate stop time; print out statistics long stoptime = System.currentTimeMillis(); System.out.println("Avg Ping = + ((stoptime - starttime)/1000f) + " msecs"); System.out.println("Sum = " + counter.get_sum()); catch(exception e) { System.err.println("System Exception"); System.err.println(e);

34 O código da IDL está abaixo: // Count.idl [ ] uuid(1689cb21-2ade-11d0-892e-00a024638502), version(1.0) library Counter { [ object, uuid(1689cb22-2ade-11d0-892e-00a024638502), pointer_default(unique), oleautomation ] interface ICount : Iunknown ; { import "oaidl.idl"; ; HRESULT set_sum([in] int val); HRESULT get_sum([out, retval] int* retval); HRESULT increment([out, retval] int* retval); importlib("stdole32.tlb"); [ uuid(1689cb23-2ade-11d0-892e-00a024638502), ] coclass Count { [default] interface ICount; ; O código da classe servidora é:

35 import com.ms.com.*; import count.*; class Count implements Icount { private int sum; public int get_sum() throws ComException { return sum; public void set_sum(int val) throws ComException { sum = val; public int increment() throws ComException { sum++; return sum; // Count.java: The Count Implementation A compilação da IDL é realizada pela ferramenta midl (forma básica: midl count.idl), de uso geral no DCOM, isto é, para qualquer linguagem de programação (C++, Java,...). A midl produz vários arquivos biblioteca de tipos (.TLB), que são usadas como entradas para geração de classes. Após, é preciso registrar a biblioteca gerada pelo MIDL com a ferramenta javatlb (por exemplo, javatlb /U:T count.lib). A javatlb produz comandos de importação para clientes e a tabela summary.txt, que contém um resumo das classes e interfaces. A compilação do cliente e servidor é realizada com o uso do MS Visual J++, via comandos como: - jvc... Count.java - jvc... CountDCOMClient.java A execução pode ser feita com o jview (JVM do MS VJ++). Por exemplo, o cliente seria disparado com o comando jview CountDCOMClient. Se o servidor está em máquina remota, é preciso registrar a máquina remota servidora no cliente com o uso do javareg: javareg /register /class: Count... Alguns resultados de desempenho encontrados no [Orfali 1998] são 3,8 msecs para servidor remoto, o que é um pouco mais lento que o VisiBroker para Java com IIOP (CORBA), também conforme o [Orfali 1998].

36 6.5. Obtenção de DCOM DCOM é fornecido com os sistemas Microsoft Windows NT 4.0 (2000), 98 e Millenium. Para Microsoft Windows 95, pode ser obtido no site da MS: http://www.microsoft.com/com/ Para plataformas UNIX, existe a empresa Software AG, que forneceria versões para os sistema Solaris, Linux e HP/UX entre outros. 6.6. DCOM X CORBA X RMI Algumas diferenças básicas entre os produtor DCOM, CORBA e Java/RMI são listadas nessa seção. Indentificação da Interface: - DCOM: Identifica a interface através do conceito de Interface IDs (IID) e identifica a implementação do objeto servidor usando o conceito de CLSID, que são encontrados no registry; - CORBA: Identifica a interface através do nome da mesma e identifica a implementação do objeto servidor pelo mapeamento do seu nome no Repositório de implementação; - Java/RMI: Identifica interface através do nome da mesma e identifica a implementação do objeto servidor através do seu mapeamento para URL no Registry (rmiregistry). Localização (ativação) do objeto servidor: - DCOM: Quando um objeto cliente necessita localizar/acessar um objeto servidor, ele pode utilizar a função CoCreateInstance(); - CORBA: Quando um objeto cliente necessita localizar/acessar um objeto servidor, ele se liga com um serviço de nomes ou de negócios; - Java/RMI: Quando um objeto cliente necessita uma referência do objeto servidor, ele tem que fazer um lookup() no URL name do objeto servidor remoto. Handle do objeto servidor: - DCOM: O handle do objeto que o cliente usa é um ponteiro para a interface; - CORBA: O handle do objeto que o cliente usa é a referência do objeto; - Java/RMI: O handle do objeto que o cliente usa é a referência do objeto. Implementação da ativação do objeto servidor: - DCOM: A responsabilidade da ativação de uma implementação de um objeto é do Service Control Manager (SCM);

37 - CORBA: A responsabilidade da ativação de uma implementação de um objeto é do Object Adapter (OA) - ou do Basic Object (BOA) ou do Portable Object Adapter (POA); - Java/RMI: A responsabilidade da ativação de uma implementação de um objeto é da Java Virtual Machine (JVM). Passagem de argumentos: - DCOM: Permite definir estruturas complexas e arrays na IDL e passá-los como parâmetros de métodos. Tipos complexos que ultrapassam as fronteiras da interface devem ser declarados na IDL; - CORBA: Tipos complexos que ultrapassam as fronteiras da interface devem ser declarados na IDL; - Java/RMI: Qualquer objeto Java serializável pode ser passado como parâmetro entre os processos. Linguagens de programação: - DCOM: Desde que a especificação seja em nível binário, várias linguagens de programação como C++, Java, Object Pascal (Delphi), Visual Basic e até mesmo Cobol podem ser utilizadas para codificar objetos DCOM; - CORBA: Pela sua especificação, diversas linguagens de programação podem ser usadas para codificar objetos CORBA, desde que existam bibliotecas ORB e compiladores IDL para tais linguagens; - Java/RMI: Depende fortemente da Java Object Serialization, portanto estes objetos só podem ser codificados na linguagem Java. 6.7. Resumo Em resumo, DCOM é um produto que satisfaz pelo que se propõe a fazer, oferece uma programação fácil e independente do local físico, e pode ser usado com qualquer protocolo de rede e integrado com qualquer plataforma de hardware suportada pelos SO Windows.

38 7. Introdução a JavaBeans 7.1. Introdução Este texto contém uma introdução aos principais conceitos do padrão, ou tecnologia, JavaBeans da Sun. Os seguintes aspectos (não exatamente uma súmula) serão abordados: - conceitos básicos de JavaBeans; - principais recursos de programação com JavaBeans; - visão geral da Enterprise JavaBeans. 7.2. Conceitos Básicos de JavaBeans JavaBeans é um modelo de componentes independente de plataforma. Um produto do modelo, ou um Bean, é um componente reusável de software que pode ser visualmente manipulado por uma ferramenta de construção de programas. O modelo oferece portabilidade e suporta interoperabilidade com outras plataformas como OpenDoc e ActiveX. Sua API é uniforme e simples. O modelo deve facilitar e garantir a reusabilidade dos componentes. O modelo estende a noção de "write once, run anywhere" incluindo "reuse everywhere". JavaBeans também tem preocupações com a segurança e a ativação local. Beans podem ser invisíveis (ou não) e suportam multi-threading. Em um ambiente distribuído, os Beans podem se comunicar com outros componentes ou serviços por diversos protocolos, como: - JDBC: para acesso a servidores de banco de dados; - IIOP: para acesso a servidores (objetos) CORBA; - RMI: para acesso a servidores Java. O JDK, ambiente de desenvolvimento básico da Sun, pode ser usado como um framework de componentes. A apresentação visual pode ser realizada com o uso das Java Foundation Classes (AWT, 2D e Swing). As principais características dos Beans são: - eventos: adotando o modelo de delegação de eventos; - propriedades: que permitem a identificação do estado do componente; - introspecção: com o uso das classes de reflexão; - persistência: via a serialização e os arquivos Jar; - customização: pelo emprego de editores de propriedades, wizards.

39 7.3. Principais Recursos de Programação (Classes JavaBeans) O pacote java.beans do JDK contém as classes que dão suporte ao desenvolvimento (principalmente) de Beans e também à execução dos mesmos. No caso de execução de Beans, o pacote permite a criação de Beans e a obtenção de informações sobre o ambiente de execução do bean. O JDK oferece suporte à introspecção. Tais classes são usadas pelas ferramentas para descobrir de um Bean informações como o ícone, os métodos, as propriedades e os eventos associados. Existe um conjunto específico de classes para suporte a propriedades, ajudando no gerenciamento das propriedades do Bean. O pacote também oferece melhor suporte à semântica de applet, agregação / delegação de objetos, serviços e protocolo de Bean-container e drag-and-drop. As propriedades podem ser de vários tipos. Métodos especiais permitem a leitura e a escrita do valor das propriedades simples: public <PropertyType> getxxx(); public void setxxx(<propertytype> value); As propriedades booleanas podem ser testadas e escritas: public boolean isxxx(); public void setxxx(boolean value); As propriedades indexadas (similar a um vetor de propriedades) também podem ser lidas e escritas: public <PropertyType>[ ] getxxx(); public void setxxx(<propertytype>[ ] values); public <PropertyType> getxxx(int index); public void setxxx(int index, <PropertyType> value); As propriedades ainda podem ser classificadas em bound e constrained. Uma propriedade bound dispara um evento quando o seu valor é alterado. O Bean deve prover os seguintes métodos: void addpropertychangelistener (PropertyChangeListener l); void removepropertychangelistener (PropertyChangeListener l); Esses métodos permitem adicionar e remover ouvidores (listener), isto é, cada ouvidor é um outro Bean que será notificado quando o valor da propriedade for alterado. Uma propriedade constrained também informa quando da mudança de seu valor, mas nesse caso deve primeiro validar a mudança em todos os subscritores (ouvidores da VetoableChangeListener interface). Qualquer um desses ouvidores pode interromper a mudança gerando uma

40 PropertyVetoException. Nesse caso, o valor original da propriedade deve ser restaurado. Os métodos para adicionar e excluir ouvidores com direito a veto são; void addvetoablechangelistener (VetoableChangeListener l); void removevetoablechangelistener (VetoableChangeListener l); Freqüentemente se deseja propriedades constrained e bound. Nesses casos, pode-se implementar um protocolo de 2 fases (two-phase commit) para atualização das propriedades. Na primeira fase, verifica-se se todos os ouvidores com direito a veto aceitam a mudança. Em caso positivo, todos os ouvidores normais (listeners) são avisados da mudança. Um outro recurso importante dos Beans é o uso dos eventos. Os eventos servem para sinalizar uma mudança de estado do Bean. Em outras palavras, é uma maneira de informar partes interessadas de que alguma coisa aconteceu. O modelo usado é o modelo de delegação de eventos -> publish-andsubscribe. Nesse modelo, existem diferentes tipos de Beans: - Event Sources; - Event Objects; - Event Listeners. Também existe um tipo de evento para todas as ocasiões: o ActionEvent. Adaptadores de eventos permitem uma indireção na relação entre o notificador e o ouvidor de um evento. Adaptadores de eventos não existem propriamente no JDK, sendo mais exatamente uma técnica de programação, muito útil em certos casos. O livro do Orfali sobre Java/CORBA apresenta uma série de usos (tipos) de adaptadores, como demultiplexing adapters, generic adapters, wiring adapters e outros. A nomeação padrão de eventos multicast é realizada pelos métodos: public void add<eventlistenertype> (<EventListenerType> a); public void remove<eventlistenertype> (<EventListenerType> a); Em eventos com restrição no número de ouvidores, pode-se usar o método: public void add<eventlistenertype> (<EventListenerType> a) throws java.util.toomanylistenersexception; A introspecção é a capacidade de descobrir quais propriedades, eventos e métodos um Bean (um objeto em geral) possui. De modo geral, sua aplicação exige a utilização de uma nomeação padrão. Pode-se prover uma interface BeanInfo para controlar que informações são disponibilizadas pelo Bean. A análise do Bean pode ser efetuada com a ajuda da classe java.beans.introspector. A customização é a personalização da aparência e comportamento de um Bean. Existem editores visuais de propriedades que são muito úteis à tarefa de customização. O armazenamento das alterações do usuário normalmente é feita com o emprego dos mecanismos de persistência. A persistência permite o armazenamento e recuperação do estado de um Bean. A persistência é adquirida através do mecanismo de serialização de Java. A interface Serializable do JDK provê uma serialização padrão, com o uso de mecanismos de entrada e saída normais de Java como:

41 private void writeobject(objectoutputstream out) throws IOException; private void readobject(objectinputstream in) throws IOException; A interface Externalizable deve ser usada quando o programador precisa de controle completo do processo de serialização. O processo de serialização passa pelos seguintes passos: - criar uma stream baseada em arquivos; - determinar o número de Beans de um objeto Container e escrevê-lo na stream; - escrever todos os beans; - descarregar o conteúdo da stream; - liberar o objeto stream. O processo de desserialização, ou recuperação do estado do Bean, pode ser expresso pelos seguintes passos: - criar uma stream de entrada baseada em arquivo; - ler o número de beans da stream; - carregar os beans no Container visual; - liberar a stream. O Java Archiver é uma tecnologia usada para agrupar diversos elementos de software como classes, objetos serializados, imagens, arquivos de ajuda e outros recursos como classes de designtime. O Java Archiver permite compressão de múltiplos arquivos, oferece segurança e autenticação, possui um conteúdo auto-descritivo e é suportado por HTML e browsers. O Manifest file contém a descrição do conteúdo de um arquivo.jar. Um exemplo é dado a seguir: Manifest version 1.0 Name: SmileyBean.class Java-Bean: True Design-Time-Only: False Depends-On: SmileyEventAdapter.class Depends-On: Smiley1.ser Digest-Algorithms: SHA MD5 SHA-Digest: T1D6RjlYFlVXnIk0PozZVBUcY= MD5-Digest: x9nbd8gkzinybh004q3nua= =

42 O livro sobre Java/CORBA do Orfali (2 a edição, 1998) propõe uma série de recomendações para o desenvolvimento de Beans portáveis. Com a relação a eventos, as recomendações são: - usar nomeação padrão; - descrever completamente o estado do evento; - criar uma hierarquia de event listeners; - agrupar eventos relacionados em um único listener; - utilizar eventos padrão AWT quando possível; - prover event adapters. Quanto às propriedades, as recomendações são: - usar nomeação padrão para as propriedades; - reservar os nomes de métodos get e set para propriedades; - utilizar Two-phase commit para atualizar propriedades constrained. A Sun oferece (sw livre) o Beans Development Kit, um kit visual básico para o desenvolvimento de Beans. Entre diversos recursos, alguns dos mais importantes são: - Beans como MIME-viewers através do Java Activation Framework; - suporte para merge de menus e toolbars; - sistema de help online para componentes. 7.4. Enterprise JavaBeans A Sun também propõe a especificação de uma arquitetura de componentes server-side para a plataforma Java baseada na tecnologia de Beans. Essa especificação, denominada Enterprise JavaBeans (EJB) define um padrão para implementar regras de negócio em aplicações multicamadas como componentes reusáveis. Seus maiores benefícios seriam: - produtividade; - escalabilidade; - gerenciamento automático de transações - JTS; - suporte a transações distribuídas; - integração com CORBA; - aceitação da indústria. A maior desvantagem é exigir um desenvolvimento mais complexo. As principais entidades da arquitetura são: - Componentes - JavaBeans: EntityBeans e SessionBeans; - Servidores;

43 - Clientes; - Containers: gerenciamento de transações, segurança e ciclo de vida dos componentes. As SessionBeans têm um ciclo de vida igual ao do cliente (uma SessionBean é uma extensão do cliente). Uma SessionBean é destruída quando o servidor EJB cai, e o cliente deverá estabelecer um novo objeto de sessão. As SessionBeans não representam dados que são armazenados em um banco de dados. Por outro lado, uma EntityBean suporta acesso compartilhado por vários clientes, participa de transações, representa dados em um Banco de Dados (seu ciclo de vida é igual ao de um dado em um Banco de Dados), sobrevive a quedas do servidor e refere-se a um objeto persistente. O processo de desenvolvimento passa pelos seguintes passos: - definir a interface remota EJB; - opcionalmente, gerar CORBA IDL; - compilar a interface; - criar stubs e skeletons IIOP; - implementar a interface; - registrar sua implementação com o servidor; - implementar um objeto Factory e registre-o; - escrever, compilar e executar o cliente.

44 8. Bibliografia Conceitos de POD: 1. Jungblut, Roberta. Estudo sobre Concorrência e Paralelismo em Linguagens Orientadas a Objeto. CPGCC-UFRGS, 1995. 2. Rosa, Fernando Raupp. Programação Distribuída Baseada em Objetos. CPGCC-UFRGS, 1991. 3. Gregory R. Andrews e Fred B. Scheneider. Concepts and Notations for Concurrent Programming. ACM Computing Surveys, 15 (1), pp 3-43. Março de 1983. 4. Celso Gonçalves Jr., Bill Coutinho e Rogério Drumond. Controle de Concorrência em Objetos. Laboratório A_HAND. DCC-IMECC- UNICAMP. Junho de 1994. Java - Threads e RMI: 5. Lea, P. Concurrent Programming in Java - Design Principles and Patterns. Addison-Wesley, 1997. 6. Oaks, S. and Wong, H. Java Threads. O Reilly, 1997. 7. Farley, Jim. Java - Distributed Computing. Ed. O'Reilly, 1998. 8. Arnold, K. and Gosling, J. The Java Language. Addison-Wesley, 1996. 9. Orfali, R. and Harkey, D. Client/Server Programming with JAVA and CORBA. John Wiley, 1998. 2 a ed. 10. Wutka, M. Java - Expert Solutions. Que, 1997. 11. Walnum, Clayton. Java by Examples. Que, 1996. 12. Documentação Java: http://java.sun.com/docs/white/index.html 13. Campione, Mary e Walrath, K. The Java Tutorial. Addison-Wesley, 2a. ed., 1998. 14. Cornell, Gary e Horstmann, Cay. Core Java. Sunsoft Press., 1996. 15. Flanagan, David. Java in a Nutshell. O'Reilly Assoc., 2a. ed., 1997. 16. Grand, Mark. Java Language Reference. O'Reilly Assoc., 2a. ed., 1997. 17. Niemeyer, P. e Peck, Josh. Exploring Java. O'Reilly Assoc., 2a. ed., 1997. 18. Tutoriais sobre RMI no site da Sun: http://java.sun.com CORBA: 19. Orfali, R. and Harkey, D. Client/Server Programming with JAVA and CORBA. John Wiley, 1997. 20. Orfali, R. and Harkey, D. Client/Server Programming with JAVA and CORBA. John Wiley, 1998, 2a ed. 21. OMG 97. CORBA: Architecture and Specification. CORBA 2.0 ORB, IDL, Interface Repository, e Inter-ORB communications. 22. OMG 97. CORBAservices. Disponível no site da OMG. 23. OMG 97 CORBAfacilities. Disponível no site da OMG. 24. Baker, Sean. CORBA Distributed Objects. 25. Siegel, Jon. CORBA Fundamentals and Programming. 26. Mowbray, Thomas J.; Malveau, Raphael C. CORBA Design Patterns. 27. Pope, Alan. The CORBA Reference Guide. Addison-Wesley, 1998. 28. Vogel, Andreas and Duddy, Keith. Java Programming with CORBA. 29. Orfali, Robert; Harkey, Dan; Edwards, Jeri. The Essential Distributed Objects Survival Guide. DCOM: 30. SESSIONS, ROGER. COM and DCOM: Microsoft s vision for distributed objects, Wiley Computer Publishing, 1998. 31. MICROSOFT CORPORATION - DCOM Technical Overview. http://msdn.microsoft.com/library/backgrnd/html/msdn_dcomtec.htm

45 32. MICROSOFT CORPORATION - DCOM Architecture. http://msdn.microsoft.com/library/backgrnd/html/msdn_dcomarch.htm 33. RAJ, GOPALAN SURESH. A Detailed Comparison of CORBA, DCOM and Java/RMI. http://www.execpc.com/~gopalan/misc/compare.html 34. Orfali, R. and Harkey, D. Client/Server Programming with JAVA and CORBA. John Wiley, 1998, 2a ed. JavaBeans: 35. Orfali, R., Harkey, D.: Client-Server Programming with Java and CORBA - 2a. Edição. 36. Tutorial: http://java.sun.com/docs/books/tutorial/javabeans/index.html 37. Especificação (PDF ou PS): http://java.sun.com/beans/spec.html

This document was created with Win2PDF available at http://www.daneprairie.com. The unregistered version of Win2PDF is for evaluation or non-commercial use only.