Professional Documents
Culture Documents
Helder da Rocha
www.argonavis.com.br 1
Sumrio
RMI/RPC e Java em ambientes distribudos Java IDL (~25%)
Arquitetura CORBA e mapeamento Java-IDL Construo de uma aplicao distribuda com Java IDL
Diferenas entre Java RMI e RMI sobre IIOP Construo de uma aplicao distribuda com RMI-IIOP Passagem de parmetros por valor e por referncia
Sockets, JMS (modelo alternativo de comunicao), EJB (arquitetura de componentes baseada em RMI-IIOP), Servlets / JSP (tecnologias baseadas em HTTP)
exemplos.zip (requer Ant). Cria diretrio exemplos. Configure arquivo build.properties e use o Ant para montar e rodar os exemplos. extras.zip (usados em demonstraes). 3
RMI e RPC
RMI e RPC so tcnicas usadas para isolar, dos clientes e servidores, os detalhes da comunicao em rede
Utilizam protocolos padro, stubs e interfaces Lidam com diferentes representao de dados
Dificuldades em RPC
Para dar a impresso de comunicao local, implementaes de RPC precisam lidar com vrias dificuldades, entre elas
Marshalling e unmarshalling (transformao dos dados em um formato independente de mquina) Diferenas na forma de representao de dados entre mquinas
Implementaes RMI tem ainda que decidir como lidar com particularidades do modelo OO:
Como implementar e controlar referncias dinmicas remotas (herana e polimorfismo) Como garantir a no duplicao dos dados e a integridade do encapsulamento? Como implementar a coleta de lixo distribuda? Como implementar a passagem de parmetros que so objetos (passar cpia rasa, cpia completa, referncia remota)?
Java
RMI-IIOP RMI-JRMP JRMP
IIOP
Java IDL
Tecnologia Java para objetos distribudos baseada na arquitetura CORBA
Permite desenvolver aplicaes ou componentes distribudos em Java capazes de se comunicarem com aplicaes ou objetos distribudos escritos em outras linguagens
Arquitetura CORBA
Common Object Request Broker Architecture
Especificao da OMG - Object Management Group Padro para interoperabilidade de objetos distribudos
Componentes
IIOP - Internet Inter ORB Protocol ORB - Object Request Broker OMG IDL - Interface Definition Language COS - CORBA Object Services (opcionais)
Principais caractersticas
1998-2002, Helder da Rocha
Transparncia de localidade: no precisa saber onde esto objetos Independncia de plataforma: objetos podem estar distribudos em plataformas diferentes Neutralidade de linguagem: objetos se comunicam mesmo escritos em linguagens diferentes 8
IDL
ORB
ORB
Stub (lado-cliente)
Transforma os parmetros em formato independente de mquina (marshalling) e envia requisies para o objeto remoto atravs do ORB passando o nome do mtodo e os dados transformados
Esqueleto (lado-servidor)
Recebe a requisio com o nome do mtodo, decodifica (unmarshals) os parmetros e os utiliza para chama o mtodo no objeto remoto Transforma (marshals) os dados retornados e devolve-os para o ORB 9
OMG IDL
OMG Interface Definition Language
a linguagem que CORBA usa para definir interfaces usadas por clientes para acessar objetos remotos Qualquer implementao de objeto CORBA deve ter uma
10
Mapeamento IDL
IDL serve apenas para descrever interfaces
No serve para ser executada Nenhuma aplicao precisa da IDL (no faz parte da implementao - design puro)
Mapeamentos Java-IDL-Java
Os mapeamentos Java-IDL-Java so definidos na especificao CORBA e usados para pelas ferramentas do J2SDK:
idlj (compilador IDL): gera classes Java a partir de IDL rmic -iiop -idl: gera IDLs a partir de interfaces Java
12
COS Naming
Objeto/A Objeto/B
IOP
ORB
IOP esqueleto A
stub A
Internet
esqueleto B
ORB
ORB
14
5. Implementar o cliente
Obter o contexto do servio de nomes (COS Naming) Obtm o objeto remoto atravs de seu nome Converter objeto para tipo de sua interface: XXXHelper.narrow(obj)
15
idl to java
idl to C++
preciso implementar
5 2
Stub Stub Stub *.java Stub Stub Skel *.cpp
3
HelloImpl.cpp void sayHello { printf("Hello"); } HelloServer.cpp
HelloClient
COS Naming
HelloServer
ORB
esqueleto
HelloImpl
(obj remoto)
16
Compilao do IDL
O IDL pode ser compilado para gerar todas as classes necessrias (cliente e servidor) ou apenas um dos lados
> idlj -fclient hello.idl > idlj -fserver hello.idl > idlj -fall hello.idl
(s classes essenciais para o cliente) (s classes essenciais para o servidor) (todas as classes)
module hello { module corba { interface HelloRemote { string sayHello(); void sayThis(in string msg); }; }; };
hello.idl
Resultado
hello/ corba/ _HelloRemoteStub.java HelloRemotePOA.java HelloRemoteHelper.java HelloRemoteHolder.java HelloRemote.java HelloRemoteOperations.java
17
public String sayHello() { return nome; } public void sayThis(String toSay) { nome = toSay; } }
18
public class HelloServer { public static void main (String[] args) { try { ORB orb = ORB.init(args, System.getProperties()); POA rootPOA = POAHelper.narrow( orb.resolve_initial_references("RootPOA") ); rootPOA.the_POAManager().activate(); HelloImpl hello = new HelloImpl(); Inicializa objeto Transforma hello.setORB(orb); hello.initPOA(); objeto em org.omg.CORBA.Object ref = rootPOA.servant_to_reference(hello); referncia HelloRemote helloRef = HelloRemoteHelper.narrow(ref); org.omg.CORBA.Object objRef = Obtm orb.resolve_initial_references("NameService"); referncia do NamingContextExt ncRef = NamingContextExtHelper.narrow(objRef); NameService ncRef.rebind(ncRef.to_name( "hellocorba" ), helloRef); Liga objeto System.out.println("Remote object bound to 'hellocorba'."); a nome no orb.run(); e roda ORB } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException)e; System.out.println("" + e); }}} 19
1998-2002, Helder da Rocha
Cliente
package hello.corba; import org.omg.CORBA.*; import org.omg.CosNaming.*;
public class HelloClient { public static void main (String[] args) { try { ORB orb = ORB.init(args, null); org.omg.CORBA.Object objRef = orb.resolve_initial_references("NameService");
} catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException)e; System.out.println("User Exception " + e); } } }
20
Para executar
Inicie o ORB
> orbd -ORBInitialPort 1900 -ORBInitialHost localhost &
Rode o servidor
> java hello.corba.HelloServer -ORBInitialPort 1900 -ORBInitialHost localhost & Remote object bound to 'hellocorba'.
Rode o cliente
> java hello.corba.HelloClient -ORBInitialPort 1900 -ORBInitialHost localhost & Hello, World! Goodbye!
21
Principais caractersticas
Centralizada: cliente tem que saber em que servidor est o objeto remoto (no transparente quanto localizao) Independente de plataforma: por ser 100% Java (no suporta comunicao com objetos escritos em outras linguagens) Suporta transferncia de bytecode: objetos remotos podem ser transferidos fisicamente para o cliente (por ser 100% Java) Suporta coleta de lixo distribuda Suporta passagem de parmetros por valor e por referncia 22
Comunicao RMI
Interface Remote
Abstrao da interface do objeto remoto Usada para gerar stubs e esqueletos
ObjetoRemoto void m() {...} java.rmi.Remote ObjRemote void m(); Comunicao aparente JRMP Cliente srv.m(); stub lookup()
Stub (lado-cliente)
Esqueleto (lado-servidor)
1998-2002, Helder da Rocha
RMIRegistry
RMIRegistry
Recebe a requisio, desserializa os parmetros e chama o mtodo no objeto remoto. Depois serializa objetos retornados. Servidor registra o objeto usando java.rmi.Naming.bind() Cliente recupera o objeto usando java.rmi.Naming.lookup() 23
Registrar os objetos remotos no RMIRegistry usando Naming.bind() Definir um SecurityManager (obrigatrio p/ download de cd. remoto)
5. Implementar o cliente
Definir um SecurityManager e conectar-se ao codebase do servidor Recuperar os objetos remotos usando (Tipo)Naming.lookup()
24
java.rmi.server.UnicastRemoteObject
extends HelloClient.java
2
HelloImpl.java HelloImpl_Skel HelloImpl_Stub
HelloServer.java
Stub
Skel
3 6
1998-2002, Helder da Rocha
Java compiler
RMIC
HelloClient HelloImpl_Stub
lookup()
RMIRegistry
bind()
HelloServer HelloImpl
JRMP
HelloImpl_Skel
(obj remoto)
25
Interface Remote
Interface de comunicao entre cliente e servidor
Stub e objeto remoto implementam esta interface de forma que cliente e esqueleto enxergam a mesma fachada
public String sayHello() throws RemoteException ; public void sayThis(String toSay) throws RemoteException; }
26
27
28
Servidor e rmi.policy
package hello.rmi; import java.rmi.*; import javax.naming.*;
public class HelloServer { public static void main (String[] args) { if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); try { Associando o objeto com HelloRemote hello = new HelloImpl(); um nome no RmiRegistry Naming.rebind("hellormi", hello); System.out.println("Remote object bound to 'hellormi'."); } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException)e; System.out.println("" + e); } } }
rmi.policy
grant { permission java.net.SocketPermission "*:1024-65535", "connect, accept, resolve"; permission java.net.SocketPermission "*:80", "connect, accept, resolve"; permission java.util.PropertyPermission "*", "read, write"; };
29
Cliente
package hello.rmi; import java.rmi.*; import javax.naming.*; public class HelloClient { public static void main (String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { HelloRemote hello = (HelloRemote) Naming.lookup("hellormi"); System.out.println(hello.sayHello()); hello.sayThis("Goodbye, Helder!"); System.out.println(hello.sayHello());
1998-2002, Helder da Rocha
30
Execuo
Inicie o RMIRegistry
> rmiregistry &
Rode o servidor
Rode o cliente
> java hello.rmiop.HelloClient -Djava.rmi.server.codebase=file:///aulaj2ee/cap03/build/ -Djava.security.policy=../lib/rmi.policy Hello, World! Goodbye!
1998-2002, Helder da Rocha
Voc pode rodar esta aplicao no usando o Ant. Mude para o subdiretrio* exemplos/ e monte uma aplicao semelhante a esta com
> ant buildrmi
31
Necessidade de RMI-IIOP
Queremos programar em Java
No queremos aprender outra linguagem (IDL) No queremos escrever linhas e linhas de cdigo para transformar, registrar e localizar objetos CORBA (queremos transparncia)
Soluo: RMI sobre IIOP Principal benefcio: comunicao com mundo CORBA Desvantagens: limitaes de CORBA
No faz download de bytecode No faz Distributed Garbage Collection - DGC 32
Principais caractersticas
Transparncia de localidade: no precisa saber onde esto objetos Independncia de plataforma: objetos podem estar distribudos em plataformas diferentes Neutralidade de linguagem possvel: pode se comunicar com objetos escritos em linguagens diferentes (gera IDL) Suporta passagem de parmetros por valor e por referncia Sem suporte transferncia de bytecode Sem suporte coleta de lixo distribuda
Comunicao RMI-IIOP
Interface Remote
Abstrao da interface do objeto remoto Usada para gerar stubs e esqueletos
ObjetoRemoto void m() {...} java.rmi.Remote ObjRemote void m(); Comunicao aparente IIOP Internet IIOP Cliente srv.m(); stub
Stub (lado-cliente)
Transforma parmetros (serializados) em formato independente de mquina e envia requisio pela rede atravs do ORB ORB do cliente passa dados via IIOP para ORB do servidor
ORB
ORB
Esqueleto (lado-servidor)
Recebe a requisio do ORB e desserializa os parmetros Chama o mtodo do objeto remoto Transforma os dados retornados e devolve-os para o ORB 34
5. Implementar o cliente
Definir um SecurityManager e conectar-se ao codebase do servidor Recuperar objetos usando JNDI e PortableRemoteObject.narrow()
6. Compilar
35
2
HelloImpl.java HelloImpl_Tie _HelloImpl_Stub
HelloClient.java
HelloServer.java
Stub
Skel
3 6
1998-2002, Helder da Rocha
Java compiler
JNDI (CosNaming)
IDL
RMIC
HelloClient _HelloImpl_Stub
lookup()
bind()
HelloServer HelloImpl
(obj remoto)
ORB
IIOP
ORB
HelloImpl_Tie
36
Interface Remote
Declara os mtodos que sero visveis remotamente Indntica interface usada em RMI sobre JRMP
package hello.rmiop; import java.rmi.*; public interface HelloRemote extends Remote {
1998-2002, Helder da Rocha
public String sayHello() throws RemoteException ; public void sayThis(String toSay) throws RemoteException; }
37
38
Resultados
_HelloRemote_Stub.class _HelloImpl_Tie.class - este o esqueleto!
Para gerar, opcionalmente, uma (ou mais) interface IDL compatvel use a opo -idl
> rmic -iiop -idl hello.rmiop.HelloImpl
1998-2002, Helder da Rocha
Resultado
HelloRemote.idl
#include "orb.idl" Tipos definidos em orb.idl module hello { (equivalem a wstring) module rmiop { interface HelloRemote { ::CORBA::WStringValue sayHello( ); void sayThis(in ::CORBA::WStringValue arg0 ); }; }; };
39
Servidor e rmi.policy
package hello.rmiop; import java.rmi.*; import javax.naming.*;
public class HelloServer { public static void main (String[] args) { if (System.getSecurityManager() == null) System.setSecurityManager(new RMISecurityManager()); try { HelloRemote hello = new HelloImpl(); Context initCtx = new InitialContext(System.getProperties()); initCtx.rebind("hellormiop", hello); System.out.println("Remote object bound to 'hellormiop'."); } catch (Exception e) { if (e instanceof RuntimeException) throw (RuntimeException)e; Associando o objeto com System.out.println("" + e); um nome no servio de nomes } } }
Informaes de segurana e servio de nomes e contexto foram inicial passadas na linha de comando
rmi.policy
grant { permission java.net.SocketPermission "*:1024-65535", "connect, accept, resolve"; permission java.net.SocketPermission "*:80", "connect, accept, resolve"; permission java.util.PropertyPermission "*", "read, write"; };
40
Cliente
package hello.rmiop; import java.rmi.*; import javax.naming.*;
public class HelloClient { public static void main (String[] args) { if (System.getSecurityManager() == null) { System.setSecurityManager(new RMISecurityManager()); } try { Context initCtx = new InitialContext(System.getProperties()); Object obj = initCtx.lookup("hellormiop"); HelloRemote hello = (HelloRemote) javax.rmi.PortableRemoteObject.narrow(obj, hello.HelloRemote.class); System.out.println(hello.sayHello()); hello.sayThis("Goodbye, Helder!"); System.out.println(hello.sayHello());
} catch (Exception e) { if (e instanceof RuntimeException) No basta fazer cast! O objeto retornado throw (RuntimeException)e; um objeto CORBA (e no Java) cuja raiz System.out.println("" + e); no java.lang.Object mas org.omg.CORBA.Object } } }
41
RMI-IIOP e JNDI
2. Procura objeto pelo nome a partir do contexto inicial
JNDI
Cdigo do Cliente
4. Delega 5. Delega
ctx.lookup()
3. Obtm stub
Stub RMI-IIOP
1998-2002, Helder da Rocha
Skeleton RMI-IIOP
6. Delega 1.Servidor associa nome ao objeto remoto
Mquina #1
obj.sayHello()
ctx.bind() ctx.rebind()
Mquina #3
42
Execuo
Inicie o ORB
> orbd -ORBInitialPort 1900 -ORBInitialHost localhost &
Rode o servidor
> java hello.rmiop.HelloServer -Djava.rmi.server.codebase=file:///cursos/j433/exemplos/build/ -Djava.security.policy=../lib/rmi.policy -Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory -Djava.naming.provider.url=iiop://localhost:1900 Remote object bound to 'hellormiop'.
Rode o cliente
> java hello.rmiop.HelloClient <mesmas propriedades -D do servidor> Hello, World! Goodbye!
Defina as propridades no cdigo ou crie um arquivo rmi.properties (melhor!) Use um script shell, .bat ou o Ant
43
Objetos serializveis
Objetos (parmetros, tipos de retorno) enviados pela rede via RMI ou RMI-IIOP precisam ser serializveis
Objeto serializado: objeto convertido em uma representao binria (tipo BLOB) reversvel que preserva informaes da classe e estado dos seus dados Serializao representa em nico BLOB todo o estado do objeto e de todas as suas dependncias, recursivamente Usado como formato "instantneo" de dados Usado por RMI para passar parmetros pela rede Como criar um objeto serializvel (da forma default*) Acrescentar "implements java.io.Serializable" na declarao da classe e marcar os campos no serializveis com o modificador transient Garantir que todos os campos da classe sejam (1) valores primitivos, (2) objetos serializveis ou (3) campos declarados com transient
* possvel implementar a serializao de forma personalizada implementando mtodos writeObject(), readObject(), writeReplace() e readResolve(). Veja especificao.
44
Questes
O que acontece quando voc chama um mtodo de um objeto retornado por um mtodo remoto?
45
... e remotamente?
46
Ponto x y 3 4
c1
HelloImplStub
setCirculo()
Ponto x y 3 4
Ponto x 30 y 40
47
Ponto x 30 y 40
c2
c c2.setOrigem(hello.createPonto(300, 400)); // Circulo local; Ponto local! d c2.getOrigem().setX(3000); // altera objeto Ponto local!
1998-2002, Helder da Rocha
hello
Ponto x 30 y 40
c2
48
Desvantagens
Objetos cuja interface formada pelos seus componentes (alterao nos componentes no refletida no objeto remoto) Objetos grandes (demora para transferir)
Soluo: passagem por referncia RMI simula passagem por referncia atravs de stubs
1998-2002, Helder da Rocha
Em vez de devolver o objeto serializado, devolvido um stub que aponta para objeto remoto (objeto devolvido, portanto, precisa ser "objeto remoto", ou seja, implementar java.rmi.Remote) Se cliente altera objeto recebido, stub altera objeto remoto
Como implementar?
Basta que parmetro ou tipo de retorno seja objeto remoto Objetos remotos so sempre retornados como stubs (referncias) 49
PontoRImpl
x y
3 4
c c2.setOrigem(hello.createPonto(300, 400)); // CirculoR remoto; PontoR remoto d c2.getOrigem().setX(3000); // altera PontoR remoto (que acaba de ser criado)
1998-2002, Helder da Rocha
hello c3
HelloImplStub CirculoRStub
PontoRImpl
PontoRImpl
PontoRStub
setX()
x 3000 y 400
x y
3 4
50
51
Concluso
Java oferece trs opes nativas para implementar sistemas de objetos distribudos Use RMI sobre JRMP se
Sua aplicao 100% Java e sempre vai ser 100% Java Voc no precisa de um sistema de nomes distribudo e hierrquico Os seus objetos nunca mudam de servidor Quiser usar recursos exclusivos do RMI (activation, DGC, download)
Prefere o modelo de desenvolvimento Java RMI (deseja especificar suas interfaces em Java e no em IDL) Quer usufruir da melhor escalabilidade do modelo CORBA Precisa garantir interoperabilidade com sistemas CORBA
Exerccio
Considere o seguinte arquivo IDL:
module exercicio { interface Sorte { long numero(); }; }; Nmero retorna um valor aleatrio entre 1 e 10000:
Math.ceil(Math.random()*10000)
Escreva uma interface Java (ou use a que foi gerada na fase 1) Implemente objeto remoto, cliente e servidor Inicie os ORBs (ou RMI daemons + Registry) e rode a aplicao
Fontes
[1] Sun
Ponto de partida para tutoriais e especificaes sobre Java IDL (documentao do J2SDK 1.4) [2] Sun Microsystems. RMI-IIOP Tutorial. http://java.sun.com/j2se/1.4/docs/guide/rmi-iiop/ Ponto de partida para tutoriais e especificaes sobre RMI-IIOP (documentao do J2SDK 1.4)
[3]
Ed Roman et al. Mastering EJB 2, Appendixes A and B: RMI-IIOP, JNDI and Java IDL http://www.theserverside.com/books/masteringEJB/index.jsp
Contm um breve e objetivo tutorial sobre os trs assuntos
[4] [5]
Jim Farley. Java Distributed Computing. O'Reilly and Associates, 1998. Esta a primeira
edio (procure a segunda). Compara vrias estratgias de computao distribuda em Java.
Helder da Rocha, Anlise Comparativa de Dempenho entre Tecnologias Distribudas Java. UFPB, 1999, Tese de Mestrado. [6] Qusay H. Mahmoud Distributed Programming with CORBA (Manning)
http://developer.java.sun.com/developer/Books/corba/ch11.pdf Breve e objetivo tutorial CORBA
[7] Qusay
H. Mahmoud Distributed Java Programming with RMI and CORBA http://developer.java.sun.com/developer/technicalArticles/RMI/rmi_corba/ Sun, Maio 2002.
Artigo que compara RMI com CORBA e desenvolve uma aplicao que transfere arquivos remotos em RMI e CORBA [8] David Flanagan et al. Java Enterprise in a Nutshell, 2nd. edition. Abril 2002 (O'Reilly). Oferece tutoriais sobre as principais tecnologias Java para ambientes distribudos, incluindo RMI, RMI-IIOP e Java IDL
54
www.argonavis.com.br
Ministrado pela primeira vez no Java Open Brasil 1998 em Braslia, DF
hlsr@uol.com.br
Minicurso Java em Ambientes Distribudos, 1998 jav400 - Curso Programao distribuda em Java, 1999 jav433 - Minicurso Java RMI x CORBA x RMI-IIOP, 2000
55