• Nenhum resultado encontrado

Processamento Distribuído com RPC e RMI

No documento 14785589987745587 (páginas 65-89)

Exercícios de fixação

Questão 1 - C

Justificativa: Em linguagem Java uma tarefa independente pode ser definida pela extensão da classe Thread ou pela implementação da interface Runnable, e quando há necessidade de sincronização utiliza-se a palavra-chave synchronized.

Questão 2 - B

Justificativa: Os métodos getInputStream, getOutputStream e close pertencem à classe Socket, enquanto start inicia uma Thread. O método accept pertence ao ServerSocket e serve para receber uma conexão na porta especificada na inicialização do mesmo.

Questão 3 - D

Justificativa: As ferramentas para criação de aplicativos RPC cuidam da geração dos stubs para garantir a transparência da comunicação em rede. O par de stubs faz a transformação de chamadas e respostas nas mensagens necessárias.

Questão 4 - C

Justificativa: Em termos do servidor, o elemento responsável pela interceptação das chamadas é comumente denominado skeleton, e deve receber a chamada, ativar o componente de software responsável pelo processamento do pedido, e retornar com a resposta solicitada.

Questão 5 - A

Justificativa: A utilização de Socket e ServerSocket de forma plana não constituiria um sistema RPC. Nas arquiteturas do tipo RPC deve haver uma IDL

(Interface Definition Language) que permita a aplicativos como o rpcgen gerar os stubs para a comunicação com o skeleton do servidor.

Questão 6 - B

Justificativa: Tanto no uso de RMI quanto no uso de CORBA, JEE, ou qualquer outro recurso que precise ser acessado a partir de uma localização externa ao programa que fornece este recurso, é comum o uso de serviços de nomes e diretórios.

Questão 7 - C

Justificativa: A transformação dos dados para o formato de envio é denominada marshalling, enquanto o processo inverso, na recepção, é denominado unmarshalling.

Questão 8 - A

Justificativa: O passo inicial para o desenvolvimento de um sistema com uso de RMI é a definição da interface remota, o que equivaleria à definição da IDL utilizada no RPC, porém restrita ao universo Java. Esta interface deverá ser descendente da interface Remote.

Questão 9 - D

Justificativa: A alternativa III está incorreta, pois seria ainda necessário criar um aplicativo (main) que registre uma instância da classe criada em II, bem como o rmiregistry deverá estar em execução para que este aplicativo consiga também executar.

Questão 10 - E

Justificativa: No caso do Java, as ações de registro e localização são feitas pelo JNDI, o qual apresenta uma interface única entre os diversos serviços de diretório, gerenciando inclusive o acesso a recursos como RMI, CORBA, DAP, LDAP e JEE.

Introdução

Com as necessidades corporativas em termos de processamento, cooperação, transações e segurança, começam a aparecer diversas plataformas de objetos distribuídos.

A principal plataforma utilizada originalmente era o CORBA, arquitetura aberta que permite às mais diversas plataformas acessarem seus componentes de forma remota.

No mundo Java surgem os EJBs (Enterprise Java Beans), objetos distribuídos com acesso irrestrito às tecnologias Java, e que mantém compatibilidade com tecnologias legadas através de uma camada de comunicação compatível com CORBA.

Objetivo:

1. Compreendeu os objetos distribuídos e uso de CORBA;

Conteúdo

Objetos distribuídos

Em termos de orientação a objetos, uma Interface define um conjunto bem- definido de métodos públicos que viabilizam o acesso e uso externo.

Uma referência a um objeto trata-se de um ponteiro de memória, onde o acesso ao estado do objeto é feito através de sua interface, que deve ser a única parte visível do objeto.

A forma como a interface é implementada não se torna relevante para o sistema como um todo, pois define apenas uma fronteira que viabiliza a troca de mensagens entre objetos distintos.

Quando os objetos estão em máquinas distintas e oferecem suas interfaces para acesso através da rede, isso define a base do conceito de objetos distribuídos.

Características de objetos distribuídos: • Interagem através da rede;

• Atuam de forma colaborativa;

• Apenas a interface do objeto pode ser acessada e de forma remota; • A interface define os serviços oferecidos;

• Para referenciar o objeto é necessário o endereço de rede; • Comunicam-se segundo o padrão de desenvolvimento Proxy.

As soluções que implementam objetos distribuídos geralmente têm uma estrutura que consiste de:

• Serviço de registro de objetos: serviço que mapeia um nome a um objeto para que possa ser localizado pelas aplicações que querem usar seus serviços;

• Interface de comunicação: documento ou classe que declara a interface (métodos, parâmetros, tipos de retorno etc.) que podem ser chamados no objeto. É o principal instrumento de interoperabilidade;

• Infraestrutura de comunicação: barramento que utiliza um protocolo comum, stubs que encapsulam código de rede do cliente e skeletons que encapsulam servidores;

• Formato de dados comuns usado na comunicação.

Alguns exemplos de arquiteturas de objetos distribuídos são:

• CORBA, tecnologia de objetos distribuídos, definida pelo OMG (http://www.omg.org) que utiliza para comunicação o protocolo IIOP; • DCOM, tecnologia da Microsoft para objetos distribuídos;

• JEE, tecnologia Java para objetos distribuídos baseada no protocolo RMI- IIOP;

• DDObjects, framework de objetos distribuídos utilizado pelo Delphi; • Pyro, framework de objetos distribuídos que utiliza Python;

Objetos distribuídos

Objetos distribuídos normalmente são utilizados em soluções corporativas, sendo instanciados em pools do lado servidor e acessados remotamente por clientes, os quais podem ser também outros servidores. Em termos gerais, objetos locais e distribuídos diferem em vários aspectos.

- Ciclo de vida: criação, migração e exclusão de objetos distribuídos são diferentes de objetos locais.

- Referência: referências remotas a objetos distribuídos são mais complexas do que os ponteiros simples para endereços de memória.

- Latência do pedido: uma solicitação de objetos distribuídos é mais lenta do que a invocação de métodos locais.

- Ativação do objeto: objetos distribuídos podem não estar sempre disponíveis para servir uma solicitação de objeto em qualquer instante.

- Comunicação: há diferentes primitivas de comunicação disponíveis para solicitações de objetos distribuídos.

- Falha: objetos distribuídos têm muito mais pontos de falha que objetos típicos locais.

- Segurança: distribuição aumenta a vulnerabilidade a ataques, exigindo ferramentas próprias de autenticação e uso.

CORBA

Criado pelo OMG (Object Management Group), o CORBA (Common Object Request Broker Architecture) trata de uma arquitetura padrão com o objetivo de estabelecer e simplificar a troca de dados entre sistemas distribuídos heterogêneos baseados em objetos.

O grande diferencial do CORBA frente a outros sistemas de objetos distribuídos é a preocupação em garantir a interoperabilidade, pois as suas interfaces de exposição de serviços seguem uma sintaxe independente, e plataformas como Java e dotNet apresentam ferramentas próprias para gerar os stubs de forma automatizada, deixando a comunicação transparente ao programador, segundo o padrão Proxy.

Essa interface de exposição de serviços é denominada CORBA-IDL e segue uma sintaxe muito parecida com a da linguagem C, como pode ser observado no exemplo da tela: module Finance { struct CustomerDetails { string name; short age; }; interface Bank { CustomerDetails getCustomerDetails; (in string name);

}; };

Esses arquivos em CORBA-IDL formam um repositório, ou catálogo, de como os serviços devem ser utilizados pelas mais diversas linguagens.

No vocabulário do CORBA, um ORB (Object Request Broker) trata de um componente de software que funciona como um mediador entre o cliente ou servidor e o canal de comunicação especificamente, o qual utiliza IIOP (Internet Inter-ORB Protocol) como protocolo padrão.

Atenção

Em termos práticos, o uso de ORB pelo CORBA define um midleware mais estratégico e mais sofisticado conceitualmente que outros midlewares, como RPC e MOM. Entre as características de um ORB encontram-se:

• Serviços de gerenciamento do ciclo de vida, incluindo criação, cópia, movimentação e deleção de alguns componentes;

• Serviço de persistência, incluindo a possibilidade de utilização de banco de dados;

• Sistema de eventos, que permitem aos componentes especificarem quais eventos deverão ser notificados;

• Controle de concorrência;

• Serviços transacionais, permitindo desfazer alterações não confirmadas;

• Serviço de nomes e diretórios para localização de componentes (COS Naming, ou Common Object Service Naming Services); • Opcionalmente um ORB pode apresentar também serviços de segurança e Time Stamp.

RMI-IIOP

A principal arquitetura de objetos distribuídos comercial do Java é o JEE (Java Enterprise Edition) com seus componentes, denominados EJBs (Enterprise Java Beans), e essa arquitetura utiliza um protocolo de comunicação denominado RMI-IIOP. Mas qual o motivo para se utilizar uma camada IIOP, se a comunicação remota padrão para serviços distribuídos do Java é o RMI?

A resposta é simples: o uso de IIOP, pelo fato do CORBA-IDL garantir a interoperabilidade com diversas linguagens, permite a ferramentas como Delphi e C++ utilizarem os serviços oferecidos pelo Java na plataforma JEE. O Java apresenta ferramentas para transformação direta do código-fonte das interfaces

RMI-IIOP em CORBA-IDL, facilitando ainda mais a disponibilização para outras plataformas. Inicialmente, deve ser criada a interface remota, da mesma forma que o RMI.

Porém, para que a implementação esteja compatível com o CORBA, segundo o protocolo IIOP, deve ser utilizado um descendente de PortableRemoteObject.

A partir desta implementação do objeto remoto, podem ser gerados o Stub e o Skeleton com o comando “rmic -iiop exemplormi.CalcRemoteCORBA”, e opcionalmente pode ser gerada a IDL através do comando “rmic -iiop -idl exemplormi.CalcRemoteCORBA”, o que irá gerar um arquivo IDL com o conteúdo a seguir, permitindo a chamada do objeto remoto a partir de outras ferramentas, como Delphi e C++, segundo os princípios de interoperabilidade defendidos no contexto de arquiteturas orientadas a serviço.

/**

* Generated by rmic -idl. Do not edit

* Quinta-feira, 20 de Agosto de 2015 09h58min41s BRT */ #include "orb.idl" #ifndef __exemplormi_ICalcRemote__ #define __exemplormi_ICalcRemote__ module exemplormi { interface ICalcRemote { long add( in long arg0, in long arg1 ); long sub( in long arg0, in long arg1 ); };

#pragma ID ICalcRemote "RMI:exemplormi.ICalcRemote:0000000000000000" };

#endif

É através desse arquivo IDL, criado pelo rmic, que ferramentas de apoio a tecnologias, como Visual Studio dotNet, podem gerar os clientes CORBA de forma simplificada.

Java Enterprise Edition

A arquitetura JEE é baseada em componentes denominados Enterprise Java Beans, os quais são instanciados em pools de objetos no servidor, disponibilizando através de fábricas registradas as interfaces de acesso remoto ou local a esse pool.

Como descrito anteriormente, essa arquitetura define uma forma de interoperabilidade com tecnologias legadas com suporte à CORBA através do uso de RMI-IIOP para a camada de comunicação.

Um Enteprise JavaBean (EJB) é um componente que pode ser implantado em um servidor de aplicações e utilizar seus serviços de forma declarativa ou não.

O servidor oferece o container que executa o componente;

O container gera os interceptadores que isolam esse componente dos

seus clientes locais ou remotos;

O deployer (instalador da aplicação) pode configurar os serviços que

desejar e o código para chamá-los será gerado nos interceptadores durante a implantação;

 Um EJB é um objeto distribuído, mas não é um objeto remoto. No

entanto, seu interceptador pode ser um, caso utilize RMI-IIOP.

Atenção

Embora as anotações incluídas na versão JEE5 tenham simplificado muito a construção de aplicativos corporativos com Java, na versão J2EE a arquitetura do framework ficava mais acessível ao programador, permitindo entender a filosofia básica

do JEE.

Em termos gerais, os EJBs são instanciados em pools no servidor, sendo acionados através de interfaces locais ou remotas, criadas a partir de fábricas próprias.

A figura seguinte mostra o funcionamento da arquitetura JEE. Nenhum EJB pode ser acessado diretamente. Para os clientes remotos, estes devem acessar a fábrica remota (EJBHome) e solicitar uma interface de acesso ao Pool de EJBs de forma remota, a qual será um EJBObject, enquanto para os clientes locais devem utilizar a fábrica local (EJBLocalHome) para a criação de interfaces de acesso similares, mas que trabalham localmente, sendo derivadas de EJBLocalObject.

(figura representativa da arquitetura JEE)

O modelo de criação de interfaces, em ambos os casos, segue o padrão Abstract Factory, enquanto a comunicação de EJBObject segue o padrão Proxy com protocolo RMI-IIOP, e os pools de EJBs seguem o padrão Fly Weight. Além desses, vários outros padrões de desenvolvimento estão presentes no JEE. Como as fábricas são únicas para cada classe de EJB específica, elas são nomeadas e acessadas via JNDI, o que denota a presença de um padrão

Singleton implícito. Os padrões de desenvolvimento presentes na arquitetura J2EE podem ser observados na figura em questão.

Existem três tipos de EJBs:

• SessionBean, para processos de negócios síncronos; • EntityBean, para persistência;

• Message Driven Bean (MDB), para processos de negócios assíncronos;

O único tipo de EJB que não segue o modelo de ativação descrito, com o uso de fábricas de interfaces, é o MDB, pois ele é ativado através do JMS, conforme visto em aulas anteriores desta disciplina.

Quanto aos EntityBeans, foram substituídos pelo JPA (Java Persistence Architecture) no JEE5 devido a questões de performance.

Finalmente, os SessionBeans podem ser divididos em dois tipos distintos: - Stateless, os quais não guardam estado entre transações sucessivas; - Stateful, que ao contrário dos primeiros, guarda estado entre transações.

O código seguinte demonstra a criação de um EJB Stateless, segundo a sintaxe anotada do JEE5, bem como suas interfaces (local e remota). Observa-se que, com o uso de anotações, a codificação das fábricas foi suplantada, tornando-se responsabilidade do Application Server.

Para que este EJB seja utilizado a partir de um Servlet, por exemplo, bastaria acrescentar um atributo anotado do tipo CalculadoraLocal, como no código abaixo:

Chamada de JEE por ferramentas CORBA

É possível utilizar o J2EE (Java 2 Enterprise Edition) para gerar EJBs acessíveis a partir de outras plataformas com suporte a CORBA. Nessa versão do JEE os componentes não são anotados, sendo sua programação levemente mais trabalhosa que as versões a partir do JEE5.

// Interface remota que utiliza o protocolo RMI-IIOP public interface Logger extends EJBObject

{

void logString(String message) throws RemoteException; }

// Fábrica de interfaces remotas

public interface LoggerHome extends EJBHome {

Logger create() throws RemoteException, CreateException;}

O exemplo aqui utilizado está disponível na documentação da Oracle, no endereço

iiop/interop.html. Inicialmente devem ser criados a interface remota do EJB e também a fábrica de interfaces remotas.

Após a definição desses componentes, o EJB em si deve ser criado, nesse caso um SessionBean.

Para efetuar o deploy deste EJB seria necessário ainda a configuração nos arquivos XML corretos. Com relação à interoperabilidade via IIOP, o passo seguinte seria a geração dos arquivos IDL através do programa rmic.

Chamada de JEE por ferramentas CORBA

Com relação à interoperabilidade via IIOP, o passo seguinte seria a geração dos arquivos IDL através do programa rmic, conforme o modelo abaixo:

rmic -idl -noValueMethods –classpath

$J2EE_HOME/lib/j2ee.jar:<diretorio_codigo_fonte>

-d <diretório_geracao_idl> ejbinterop.Logger ejbinterop.LoggerHome Serão gerados os seguintes arquivos, lembrando que apenas dois são específicos para esse EJB (Logger.idl e LoggerHome.idl), sendo os demais apenas arquivos padrão de suporte à comunicação com o J2EE:

java/lang/Ex.idl java/lang/Exception.idl java/lang/Object.idl java/lang/Throwable.idl java/lang/ThrowableEx.idl javax/ejb/CreateEx.idl javax/ejb/CreateException.idl javax/ejb/EJBHome.idl javax/ejb/EJBMetaData.idl javax/ejb/EJBObject.idl

javax/ejb/Handle.idl javax/ejb/HomeHandle.idl javax/ejb/RemoveEx.idl javax/ejb/RemoveException.idl ejbinterop/Logger.idl ejbinterop/LoggerHome.idl

Com uma ferramenta adequada o arquivo-cliente pode ser gerado, como por exemplo, o código abaixo que foi gerado em C++ pelo ORBacus 4.0.5. Os comentários gerados foram suprimidos para evitar uma quantidade maior de linhas no exemplo. #include <fstream.h> #include <OB/CORBA.h> #include <OB/OBORB.h> #include <java/lang/Exception.h> #include <java/lang/Throwable.h> #include <javax/ejb/CreateException.h> #include <javax/ejb/RemoveException.h> #include <ejbinterop/Logger.h> #include <ejbinterop/LoggerHome.h>

void run(CORBA::ORB_ptr orb, const char* logger_home_url) {

cout << "Looking for: " << logger_home_url << endl;

CORBA::Object_var home_obj = orb->string_to_object(logger_home_url); ejbinterop::LoggerHome_var home =

ejbinterop::LoggerHome::_narrow(home_obj.in()); assert(!CORBA::is_nil(home));

ejbinterop::Logger_var logger = home->create(); CORBA::WStringValue_var msg =

new CORBA::WStringValue((const CORBA::WChar*)L "Message from a C++ client");

cout << "Logging..." << endl; logger->logString(msg); logger->remove();

cout << "Done" << endl; }

int main(int argc, char* argv[]) {

int exit_code = 0; CORBA::ORB_var orb; try {

if (argc != 2) {

cerr << "Usage: Client <corbaname URL of LoggerHome>" << endl; return 1;

}

orb = CORBA::ORB_init(argc, argv);

CORBA::ValueFactory factory = new java::lang::Throwable_init;

orb -> register_value_factory(java::lang::Throwable::_OB_id(),factory); factory -> _remove_ref();

factory = new java::lang::Exception_init;

orb -> register_value_factory(java::lang::Exception::_OB_id(),factory); factory -> _remove_ref();

factory = new javax::ejb::CreateException_init;

orb -> register_value_factory(javax::ejb::CreateException::_OB_id(),factory); factory -> _remove_ref();

factory = new javax::ejb::RemoveException_init;

orb -> register_value_factory(javax::ejb::RemoveException::_OB_id(), factory);

factory -> _remove_ref(); run(orb, argv[1]);

} catch(const CORBA::Exception& ex) { cerr << ex._to_string() << endl; exit_code = 1;

}

if (!CORBA::is_nil(orb)) { try {

orb -> destroy();

} catch(const CORBA::Exception& ex) { cerr << ex._to_string() << endl; exit_code = 1;

} }

return exit_code; }

Embora o código seja um pouco extenso, ele é gerado automaticamente a partir dos arquivos IDL, o que significa que não envolve grande custo em termos de desenvolvimento.

Por fim, a classe gerada pode ser compilada em algum compilador C++, e o cliente pode ser chamado passando o endereço onde pode ser acessada a fábrica de interfaces do SessionBean, como no exemplo seguinte:

Client corbaname:iiop:1.2@localhost:1050#ejbinterop/logger

Esse tipo de solução é um grande elemento de interoperabilidade com tecnologias legadas, apresentando-se como solução bastante viável na integração com mainframes.

public class LoggerEJB implements SessionBean { public LoggerEJB() {}

public void ejbCreate() {} public void ejbRemove() {} public void ejbActivate() {} public void ejbPassivate() {}

public void setSessionContext(SessionContext sc) {} public void logString(String message) {

System.out.println(new Date() + "::" + message); }

}

Atividade proposta

Como atividade de fixação, efetue uma pesquisa acerca de padrões de desenvolvimento e como os mesmos são aplicados em arquiteturas de objetos distribuídos como o JEE e o CORBA.

Referências

McHale, C. CORBA explained simply, 2007

http://www.ciaranmchale.com/download/corba-explained- simply.pdf

Exercícios de fixação

Questão 1

Qual o padrão de desenvolvimento utilizado na forma de comunicação com objetos distribuídos? a) Front Control b) Flyweight c) DAO d) Proxy e) Request Dispatcher Questão 2

Qual o serviço de nomes e diretórios do CORBA? a) CORBA IDL b) LDAP c) DNS d) JNDI e) COS Naming Questão 3

Qual a entidade responsável pela criação do CORBA? a) DoD

b) OMG c) DMSO d) W3C e) IEEE

Questão 4

Qual das opções abaixo NÃO é uma arquitetura de objetos distribuídos? a) CORBA b) JEE c) DDObjects d) COM e) Pyro Questão 5

Para que um servidor RMI possa se tornar compatível com o protocolo IIOP, segundo a especificação RMI-IIOP, a classe de negócios deve ser definida como um descendente de: a) PortableRemoteObject b) UnicastRemoteObject c) MulticastRemoteObject d) HttpServlet e) RemoteException Questão 6

Qual o elemento que viabiliza a compatibilidade com CORBA para os EJBs? a) Descrição de serviços CORBA-IDL

b) Protocolo RMI-IIOP c) Uso da linguagem Java d) Uso do JNDI

e) Padrão Proxy Questão 7

Qual a anotação que deve ser utilizada para efetuar a chamada ao pool de EJBs a partir de um Servlet? a) @Local b) @Remote c) @Stateless d) @Stateful e) @EJB Questão 8

Qual tipo de EJB era utilizado no J2EE para efetuar a persistência de dados? a) Message Driven Bean

b) Stateless SessionBean c) Stateful SessionBean d) EntityBean

e) EntityManager Questão 9

Um descendente de EJBHome deve gerar descendentes de EJBObject para prover acesso remoto ao pool de EJBs, enquanto descendentes de EJBLocalHome devem gerar descendentes de EJBLocalObject para prover acesso local ao mesmo pool. Para tal finalidade é utilizado o padrão de desenvolvimento: a) Proxy b) Flyweight c) Abstract Factory d) Session Facade e) DAO Questão 10

Considere as seguintes afirmativas:

I – A construção de pools de EJBs é baseada no padrão Flyweight. II – A comunicação remota com os EJBs é feita segundo o padrão Proxy.

III – No J2EE tornou-se uma prática comum a adoção de um componente que siga o padrão Service Locator para localizar as fábricas de EJBs.

Quais estão corretas? a) Apenas as afirmativas I e II b) Apenas a afirmativa I c) Apenas a afirmativa II d) Apenas a afirmativa III e) Todas as afirmativas

No documento 14785589987745587 (páginas 65-89)