4.CORBA_Java.pdf

40
Tecgraf PUC-Rio fevereiro de 2011 Desenvolvendo uma aplicação CORBA utilizando Java

Transcript of 4.CORBA_Java.pdf

Tecgraf PUC-Rio fevereiro de 2011

Desenvolvendo uma aplicação CORBA utilizando Java

Exemplo passo-a-passo

•  Veremos um exemplo, passo-a-passo, de desenvolvimento de aplicações CORBA usando Java

•  Para desenvolver a aplicação, usaremos o Jacorb como ORB tanto para o cliente quanto para o servidor, já que ambos serão desenvolvidos em Java

Passo 1: Jacorb e SDK

•  A última versão do Jacorb pode ser obtida de: •  http://www.jacorb.org

•  Precisaremos também do JDK 1.5 ou superior •  Para fazer build do exemplo, usaremos o Ant:

–  http://ant.apache.org/

Libs do Jacorb

•  antlr-2.7.2.jar •  avalon-framework-4.1.5.jar •  backport-util-concurrent.jar •  idl.jar •  jacorb-2.3.0.jar •  logkit-1.2.jar •  picocontainer-1.2.jar •  wrapper-3.1.0.jar

Passo 2: Escrevendo a IDL

// StockMarket.idl // O módulo StockMarket consiste das definições // úteis para desenvolvimento de aplicações // que lidam com mercado de ações. module StockMarket {

// O tipo StockSymbol é usado para representar os // identificadores das ações typedef string StockSymbol;

// Um StockSymbolList é uma sequência de StockSymbols. typedef sequence<StockSymbol> StockSymbolList;

// A interface StockServer é a interface que fornece // as informações sobre as ações do mercado. interface StockServer {

// getStockValue() retorna o valor de uma // determinada ação do marcado identificada por um // StockSymbol fornecido como parâmetro de entrada. // Se o StockSymbol dado for desconhecido, o resultado // é indefinido. Depois veremos como usar uma exceção // para sinalizar essa condição. float getStockValue(in StockSymbol symbol);

// getStockSymbols() retorna uma sequência com todos os // StockSymbols conhecidos pelo servidor do mercado de // ações. StockSymbolList getStockSymbols(); }; };

Passo 3: Compilando a IDL

•  Para compilar a IDL, usaremos o Ant e o compilador IDL do Jacorb:

<!-- =================================================== --> <!-- Inicializacao --> <!-- ==================================================== --> <target name="init" description="Inicia as propriedades"> <property name="lib" value="lib"/> <property name="idl" value="idl"/> <property name="generated" value="generated"/> <property name="jacorb" value="jacorb"/> </target>

<!-- ==================================================== --> <!-- IDL compiler --> <!-- ==================================================== --> <target name="idl" depends="clean" description="Compila as idls"> <delete dir="${generated}"/> <java classname="org.jacorb.idl.parser" fork="yes"> <classpath> <pathelement location="${lib}/${jacorb}/idl.jar"/> <pathelement location="${lib}/${jacorb}/logkit-1.2.jar"/> </classpath> <arg line="-d ${generated} ${idl}/StockMarket.idl"/> </java> </target>

Arquivos gerados na compilação da IDL

•  Todas as classes estão dentro do pacote StockMarket

–  StockServer.java –  StockServerOperations.java

–  StockServerHelper.java –  StockSymbolHelper.java –  StockSymbolListHelper.java

–  StockServerHolder.java –  StockSymbolListHolder.java

–  StockServerPOA.java –  StockServerPOATie.java –  _StockServerStub.java

} Interface Files

Helper Files

Holder Files

Stubs e Skeleton Files

}}}

Interface Files

•  A interface IDL StockServer é mapeada para: –  uma interface java de assinatura StockServer.java –  uma interface java de operações

StockServerOperations.java •  A interface de assinatura possui o mesmo nome da

interface IDL, estende outras interfaces CORBA e é usada como o tipo referenciado em outras interfaces.

•  A interface de operações possui o nome da interface IDL junto com o sufixo Operations e é uma interface “java pura”, ou seja, possui apenas as declarações das operações e atributos definidos na interface IDL

StockServerOperations.java

package StockMarket;

/** * Generated from IDL interface "StockServer". * * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006 * @version generated at Oct 19, 2010 5:47:22 PM */

public interface StockServerOperations { /* constants */ /* operations */ float getStockValue(java.lang.String symbol); java.lang.String[] getStockSymbols(); }

StockServer.java

package StockMarket;

/** * Generated from IDL interface "StockServer". * * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006 * @version generated at Oct 19, 2010 5:47:22 PM */

public interface StockServer extends StockServerOperations, org.omg.CORBA.Object, org.omg.CORBA.portable.IDLEntity { }

org.omg.CORBA.Object: é a interface raiz para todas as referências a objetos CORBA na linguagem Java, análogo a interface java.rmi.Remote para os objetos remotos RMI. org.omg.CORBA.portable.IDLEntity: interface de “marcação” cuja finalidade é apenas indicar que a classe que implementa essa interface é um tipo IDL que possui uma classe de Helper correspondente.

Stub e Skeleton Files

•  A compilação da IDL StockServer produz a classe _StockServerStub.java que atua como stub do cliente e as classes StockServerPOA.java e StockServerPOATie.java que servem de skeleton do servidor.

•  Veremos depois que o uso das classes de skeleton POA ou POATie depende da estratégia adotada para implementação do servidor: por herança ou por delegação

_StockServerStub.java

package StockMarket;!

/**! * Generated from IDL interface "StockServer".! *! * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006! * @version generated at Oct 25, 2010 3:50:57 PM! */!

public class _StockServerStub!extends org.omg.CORBA.portable.ObjectImpl!implements StockMarket.StockServer {! ...! public float getStockValue(java.lang.String symbol) {! ...! }!

public java.lang.String[] getStockSymbols() {! ...! }!

}!

StockServerPOA.java

package StockMarket;!

/**! * Generated from IDL interface "StockServer".! *! * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006! * @version generated at Oct 25, 2010 3:50:57 PM! */!

public abstract class StockServerPOA!extends org.omg.PortableServer.Servant!implements org.omg.CORBA.portable.InvokeHandler, ! StockMarket.StockServerOperations !{ ! ...!

}!

StockServerPOATie.java

package StockMarket;!

import org.omg.PortableServer.POA;!/**! * Generated from IDL interface "StockServer".! *! * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006! * @version generated at Oct 25, 2010 3:50:57 PM! */!

public class StockServerPOATie!extends StockServerPOA!{! ...!

private StockServerOperations _delegate;!

public StockServerPOATie(StockServerOperations delegate)! {! _delegate = delegate;! }!

public float getStockValue(java.lang.String symbol)! {! return _delegate.getStockValue(symbol);! }!

public java.lang.String[] getStockSymbols()! {! return _delegate.getStockSymbols();! }!}!

Helper Files

•  A compilação da IDL StockServer produz as classes de Helper StockServerHelper.java, StockSymbolHelper.java e StockSymbolListHelper.java

•  As classes de Helper oferecem diversos métodos estáticos úteis na manipulação do tipo correspondente: –  inserir e extrair um objeto do tipo em Any –  obter o repository id –  ler de um stream e escrever para um stream – …

Helper Files

•  A classe de Helper gerada a partir de uma interface IDL, também inclui operações de narrow para converter o tipo genérico org.omg.CORBA.Object para o tipo específico.

•  A exceção IDL CORBA::BAD_PARAM é lançada se a conversão do narrow falhar devido a inconsitência do tipo da referência do objeto.

StockSymbolHelper.java package StockMarket;!

/*! * Generated from IDL alias "StockSymbol".! *! * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006! * @version generated at Oct 19, 2010 5:47:22 PM! */!

public final class StockSymbolHelper { ! ...!

public static void insert (org.omg.CORBA.Any any, java.lang.String s) {! ...! }! public static java.lang.String extract (final org.omg.CORBA.Any any) {! ...! }! public static String id() {! return "IDL:StockMarket/StockSymbol:1.0";! }! public static java.lang.String read (! final org.omg.CORBA.portable.InputStream _in) {! ... ! }! public static void write (! final org.omg.CORBA.portable.OutputStream _out, java.lang.String _s) {! ...! }!}!

StockServerHelper.java

package StockMarket;!

/**! * Generated from IDL interface "StockServer".! *! * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006! * @version generated at Oct 19, 2010 5:47:22 PM! */!

public final class StockServerHelper { !

// Todos os métodos estáticos insert, extract, type, id, read e write! // e mais os métodos de conversão narrow!

...!

public static StockMarket.StockServer narrow(final org.omg.CORBA.Object obj)! {! ... ! }!

public static StockMarket.StockServer unchecked_narrow(! final org.omg.CORBA.Object obj)! {! ...! }!

}!

Holder Files

•  Os métodos definidos nas interfaces IDL que tem passagem de parâmetros nos modos out a inout, requerem o uso de classes de Holder. – Todos os tipos primitivos da IDL possuem as

classes de Holder disponíveis no pacote org.omg.CORBA package

– O compilador IDL gera as classes de Holder para todos os tipos definidos pelo desenvolvedor (exceto aqueles definidos por typedef)

•  A compilação da IDL StockServer produz as classes de Holder StockServerHolder.java e StockSymbolListHolder.java

StockSymbolListHolder.java

package StockMarket; /** * Generated from IDL alias "StockSymbolList". * * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006 * @version generated at Oct 19, 2010 5:47:22 PM */

public final class StockSymbolListHolder implements org.omg.CORBA.portable.Streamable { public java.lang.String[] value;

public StockSymbolListHolder () { }

public StockSymbolListHolder (final java.lang.String[] initial) { value = initial; } public org.omg.CORBA.TypeCode _type () { return StockSymbolListHelper.type (); } public void _read (final org.omg.CORBA.portable.InputStream in) { value = StockSymbolListHelper.read (in); } public void _write (final org.omg.CORBA.portable.OutputStream out) { StockSymbolListHelper.write (out,value); } }

StockServerHolder.java

package StockMarket; /** * Generated from IDL interface "StockServer". * * @author JacORB IDL compiler V 2.3-beta-2, 14-Oct-2006 * @version generated at Oct 19, 2010 5:47:22 PM */

public final class StockServerHolder implements org.omg.CORBA.portable.Streamable{

public StockServer value;

public StockServerHolder() { }

public StockServerHolder (final StockServer initial) { value = initial; } public org.omg.CORBA.TypeCode _type() { return StockServerHelper.type(); } public void _read (final org.omg.CORBA.portable.InputStream in) { value = StockServerHelper.read (in); } public void _write (final org.omg.CORBA.portable.OutputStream _out) { StockServerHelper.write (_out,value); } }

Passo 4: Compilando o código java

•  Para compilar o código Java gerado pela IDL, usaremos o Ant e o compilador javac

<!-- ==================================================== -->! <!-- Java Compiler -->! <!-- ==================================================== -->! <target name="javac" depends="idl" description="Compila o codigo java">! <!-- Cria o diretorio para compilacao -->! <mkdir dir="${build}" />!

<!-- Compila os fontes do src e do gerenerated -->! <javac destdir="${build}"! debug="on"! encoding="iso-8859-1">! <src path="${generated}"/>! <src path="${src}"/>! </javac>! </target>!

Passo 5: Implementando o Servant

•  O Servant que implementa a interface definida na IDL StockServer pode ser uma classe que estende a classe abstrata StockServerPOA ou pode ser uma classe simples cuja instância é passada para a classe de delegação StockServerPOATie.

•  Para compilar o Servant, o compilador java deve ter no classpath as classes de skeleton, as classes de interface e as classes Helper e Holder geradas pelo compilador IDL.

Estratégias de implementação

•  CORBA suporta dois mecanismos para implementação da IDL por uma classe Servant –  por herança –  por delegação

•  A diferença principal entre os dois mecanismos é que, pelo mecanismo de delegação, a classe de implementação da IDL não precisa derivar de uma classe em particular

Usando herança

package StockMarket;

/* * StockServerImpl implementa a interface IDL StockServer */ public class StockServerImpl extends StockServerPOA { // As ações com seus respectivos valores private Map<String, Float> myStock;

public StockServerImpl() { myStock = new HashMap<String,Float>(); // Inicializa as ações com nomes e valores // atribuídos randomicamente ... }

public float getStockValue(String symbol) { if (myStock.containsKey(symbol)) { // Simbolo encontrado; retorna seu valor return myStock.get(symbol); } else { // Simbolo não foi encontrado return 0f; } }

public String[] getStockSymbols() { return myStock.keySet().toArray(new String[0]); } }

Usando delegação

package StockMarket; /** * StockServerImpl implementa a interface IDL StockServer usando * o mecanismo de delegação */ public class StockServerTieImpl implements StockServerOperations { // As ações com seus respectivos valores private Map<String, Float> myStock;

public StockServerImpl() { myStock = new HashMap<String,Float>(); // Inicializa as ações com nomes e valores // atribuídos randomicamente ... }

public float getStockValue(String symbol) { if (myStock.containsKey(symbol)) { // Simbolo encontrado; retorna seu valor return myStock.get(symbol); } else { // Simbolo não foi encontrado return 0f; } }

public String[] getStockSymbols() { return myStock.keySet().toArray(new String[0]); } }

Passo 6: Implementando o servidor

•  O programa servidor se encarrega de: –  inicializar o ORB –  criar o objeto Servant StockServerImpl –  exportar o Servant para o POA –  aguardar que o cliente envie requisições

•  Para compilar o servidor, o compilador java deve ter no classpath as classes de interface, a classe do skeleton, as classes Helper e Holder geradas pelo compilador IDL e, a classe do Servant.

Inicializa o ORB

Properties orbProps = new Properties();! orbProps.setProperty("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB");! orbProps.setProperty("org.omg.CORBA.ORBSingletonClass",! "org.jacorb.orb.ORBSingleton"); !

ORB orb = ORB.init(args, orbProps);!

init

public static ORB init(String[] args, Properties props) Creates a new ORB instance for a standalone application. This method may be called from applications only and returns a new fully functional ORB object each time it is called.

Parameters: args - command-line arguments for the application's main method; may be null props - application-specific properties; may be null Returns: the newly-created ORB instance

Cria o Servant que implementa a IDL

Servant stockServer = new StockServerImpl();!

•  Se o Servant tiver adotado a estratégia de implementação por herança:

•  Se o Servant tiver adotado a estratégia de implementação por delegação:

Servant stockServer = new StockServerPOATie(new StockServerImpl());!

Cria o Servant que implementa a IDL

•  Note que, até aqui, temos apenas um objeto Java instanciado.

•  Precisamos agora tornar esse objeto um objeto CORBA, capaz de receber as requisições dos clientes.

•  Usaremos, para isso, o POA.

Exporta o Servant para o POA

POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));! poa.the_POAManager().activate();! org.omg.CORBA.Object o = poa.servant_to_reference(stockServer);!

•  Obtém uma referência para uma instância do POA

•  Após fazer narrow da referência, é necessário ativar o POA (seu estado inicial é on-holding)

•  Registra o Servant no POA

Bloqueia a thread corrente para o ORB

orb.run();!

•  Bloqueia a thread corrente até o ORB terminar

Exemplo do servidor do StockServer

package StockMarket;!import java.io.*;!import org.omg.CORBA.ORB;!import org.omg.PortableServer.*;!public class StockServerMain {! public static void main(String args[]) {! try {! // Inicializa o ORB.! Properties orbProps = new Properties();! orbProps.setProperty("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB");! orbProps.setProperty("org.omg.CORBA.ORBSingletonClass",! "org.jacorb.orb.ORBSingleton");! ORB orb = ORB.init(args, orbProps);! // Cria o Servant StockServerImpl que implementa a IDL! Servant stockServer = new StockServerImpl();! // Obtém uma referência para o POA e registra o Servant nesse POA! POA poa = POAHelper.narrow(orb.resolve_initial_references("RootPOA"));! poa.the_POAManager().activate();! org.omg.CORBA.Object o = poa.servant_to_reference(stockServer);! // Escreve no arquivo a referência para o objeto CORBA! PrintWriter ps = new PrintWriter( new FileOutputStream(! new File( args[0] )));! ps.println(orb.object_to_string( o ));! ps.close();! // Bloqueia a thread corrente até o ORB finalizar! orb.run();! } catch (Exception ex) {! ex.printStackTrace();! }! }!}!

Passo 7: Implementando o cliente

•  O programa cliente se encarrega de: –  inicializar o ORB –  obter a referência para o objeto CORBA

StockServer –  fazer chamadas aos métodos definidos pela IDL

do StockServer •  O módulo cliente deve ter no classpath a classe de

stub _StockServerStub, a classe de assinatura StockServer e as classes Helper e Holder geradas pelo compilador IDL

Exemplo do cliente do StockServer package StockMarket;!import java.io.*!import org.omg.CORBA.ORB;!public class StockServerClient {! public static void main(String args[]) {! try {! // As propriedades que informam o uso do JacORB como ORB.! Properties orbProps = new Properties();! orbProps.setProperty("org.omg.CORBA.ORBClass", "org.jacorb.orb.ORB");! orbProps.setProperty("org.omg.CORBA.ORBSingletonClass",! "org.jacorb.orb.ORBSingleton");! // Inicializa o ORB.! ORB orb = ORB.init(args, orbProps);!

// Lê o IOR do arquivo cujo nome é passado como parâmetro! BufferedReader reader =! new BufferedReader(new InputStreamReader(new FileInputStream(args[0])));! String ior = reader.readLine();!

// Obtém a referência para objeto CORBA! org.omg.CORBA.Object obj = orb.string_to_object(ior);! StockServer myStock = StockServerHelper.narrow(obj);!

// Executa as chamadas ao objeto CORBA! StockServerClient stockClient = new StockServerClient(myStock);! stockClient.run();! }! catch (Exception e) {! e.printStackTrace();! }! }!}!

Exemplo do cliente do StockServer package StockMarket;!

import java.io.*!import org.omg.CORBA.ORB;!

public class StockServerClient {! private StockServer myStock;!

public StockServerClient(StockServer myStock) {! this.myStock = myStock;! }! public void run() {! try {! System.out.println(”Ações de mercado obtidas do StockServer:");! // Obtém os símbolos de todos as ações! String[] stockSymbols = myStock.getStockSymbols();!

// Mostra as ações com seus respectivos valores! for (int i = 0; i < stockSymbols.length; i++) {! System.out.println(stockSymbols[i] + " "! + myStock.getStockValue(stockSymbols[i]));! }! }! catch (org.omg.CORBA.SystemException e) {! e.printStackTrace();! }! }! public static void main(String args[]) {! ...! }!}!

Passo 8: Executando o servidor

java -cp ./build: lib/jacorb/antlr-2.7.2.jar: lib/jacorb/avalon-framework-4.1.5.jar: lib/jacorb/backport-util-concurrent.jar: lib/jacorb/idl.jar:lib/jacorb/jacorb-2.3.0.jar: lib/jacorb/logkit-1.2.jar: lib/jacorb/picocontainer-1.2.jar: lib/jacorb/wrapper-3.1.0.jar StockMarket.StockServerMain ior

Saída da execução do servidor

mjulia$ ./runserver Ações do mercado criadas: UION: 18.192759 LGBA: 46.23733 ZZSP: 48.71345 KLVV: 57.355362 ZDZR: 41.779728 UFTH: 74.87004 DNKS: 80.69647 AQVS: 99.87545 AZHM: 72.27951 PEMR: 35.293213

Passo 9: Executando o cliente

java -cp ./build: lib/jacorb/antlr-2.7.2.jar: lib/jacorb/avalon-framework-4.1.5.jar: lib/jacorb/backport-util-concurrent.jar: lib/jacorb/idl.jar:lib/jacorb/jacorb-2.3.0.jar: lib/jacorb/logkit-1.2.jar: lib/jacorb/picocontainer-1.2.jar: lib/jacorb/wrapper-3.1.0.jar StockMarket.StockServerClient ior

Saída da execução do cliente

mjulia$ ./runclient Ações de mercado obtidas do StockServer: UION 18.192759 LGBA 46.23733 ZZSP 48.71345 KLVV 57.355362 ZDZR 41.779728 UFTH 74.87004 DNKS 80.69647 AQVS 99.87545 AZHM 72.27951 PEMR 35.293213