Compilando a IDL - Tecgraf JIRA / Confluence - PUC-Rio

Propaganda
Desenvolvendo uma
aplicação CORBA utilizando
Java
Tecgraf PUC-Rio
setembro de 2013
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 JDK
• A versão 3.1 do Jacorb pode ser obtida:
• Do pacote do exercício, no site do curso
• http://www.jacorb.org
• Precisaremos também do JDK 1.6
• Para fazer build do exemplo, usaremos o Ant:
– http://ant.apache.org/
Libs do Pacote do Exercício
•
•
•
•
idl-3.1.jar
jacorb-3.1.jar
slf4j-api-1.6.4.jar
slf4j-jdk14-1.6.4.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}"/>
<taskdef name="jacidl" classname="org.jacorb.idl.JacIDL">
<classpath>
<pathelement location="${lib}/${jacorb}/idl-3.1.jar"/>
</classpath>
</taskdef>
<jacidl destdir="${generated}" srcdir="${idl}"/>
</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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 à 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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
e 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
• 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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 3.1, 19-Aug-2012
* @version generated at Jun 24, 2013 3:43:01 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
<!-- Cria o diretorio para compilacao -->
<mkdir dir="${build}" />
-->
-->
-->
codigo java">
<!-- Compila os fontes do src e do gerenerated -->
<javac destdir="${build}“ encoding="iso-8859-1">
<compilerarg value="-Xbootclasspath/p:${lib}/${jacorb}/jacorb-3.1.jar"/>
<src path="${generated}"/>
<src path="${src}"/>
<classpath>
<pathelement location="${lib}/${jacorb}/jacorb-3.1.jar"/>
</classpath>
</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
// fixos ou atribuídos randomicamente
...
}
public synchronized 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 synchronized 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 StockServerTieImpl () {
myStock = new HashMap<String,Float>();
// Inicializa as ações com nomes e valores
// fixos ou atribuídos randomicamente
...
}
public synchronized 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 synchronized 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
registrar o Servant em um 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
• Se o Servant tiver adotado a estratégia de
implementação por herança:
StockServer stockServer = new StockServerImpl();
• Se o Servant tiver adotado a estratégia de
implementação por delegação:
StockServer stockServer = new StockServerPOATie(new StockServerTieImpl());
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 padrão
• 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
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 o objeto CORBA
org.omg.CORBA.Object obj = orb.string_to_object(ior);
StockServer server = StockServerHelper.narrow(obj);
// Executa as chamadas ao objeto CORBA StockServer
…
}
}
}
catch (…) {
…
}
Exemplo do cliente do StockServer
package StockMarket;
import java.io.*;
import java.util.Properties;
import org.omg.CORBA.COMM_FAILURE;
import org.omg.CORBA.ORB;
import org.omg.CORBA.TRANSIENT;
public class StockServerClient {
public static void main(String args[]) {
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);
String ior;
(…) // lê o IOR do arquivo
try {
org.omg.CORBA.Object obj = orb.string_to_object(ior);
StockServer server = StockServerHelper.narrow(obj);
System.out.println("Ações de mercado obtidas do StockServer:");
String[] stockSymbols = server.getStockSymbols();
for (int i = 0; i < stockSymbols.length; i++) {
System.out.println(stockSymbols[i] + " "
+ myStock.getStockValue(stockSymbols[i]));
}
}
catch (TRANSIENT e) {
System.err.println("O serviço encontra-se indisponível.");
}
catch (COMM_FAILURE e) {
System.err.println("Falha de comunicação com o serviço.");
}
}
}
Passo 8: Executando o servidor
java -Djava.endorsed.dirs=lib\jacorb
-cp “build;lib\jacorb\jacorb-3.1.jar;
lib\jacorb\slf4j-api-1.6.4.jar;
lib\jacorb\slf4j-jdk14-1.6.4.jar”
StockMarket.StockServerMain ior
Saída da execução do servidor
./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 -Djava.endorsed.dirs=lib\jacorb
-cp “build;lib\jacorb\jacorb-3.1.jar”
StockMarket.StockServerClient ior
Saída da execução do cliente
./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
Download