SDK Openbus – C# Tecgraf PUC-Rio Novembro de 2013 versão 1 - julho/2013 Passo 1: Obtendo o SDK Openbus • A última versão do SDK C# do Openbus pode ser obtida em: • http://www.tecgraf.puc-rio.br/openbus • Precisaremos também do .NET 4.0 (Visual Studio 2010) versão 1 - julho/2013 Libs do SDK Openbus 2.0.0.0 • Openbus: • OpenBus.Idl.dll • OpenBus.dll • OpenBus.Legacy.dll • IIOP.NET: • IIOPChannel.dll • log4net.dll • Nunit.framework.dll • SCS: • Scs.Core.dll • Scs.dll • BouncyCastle: • BouncyCastle.Crypto.dll versão 1 - julho/2013 Executáveis do SDK Openbus 2.0.0.0 • IIOP.NET: • IDLToCLSCompiler.exe • IIOPChannel.dll • IDLPreprocessor.dll versão 1 - julho/2013 Passo 2: Preparando os stubs e skeletons • Usaremos como base a mesma IDL do exemplo StockMarket mostrado no exercício do SCS • Compilar a IDL • Compilar o código C# das classes geradas pelo compilador IDL e das classes que implementam as facetas descritas na IDL versão 1 - julho/2013 Passo 3: Implementando as facetas do componente • O componente StockSeller possui duas facetas: • StockServer • StockExchange • As classes StockServerImpl e StockExchangeImpl implementam, respectivamente, cada uma dessas facetas • Opcionalmente, para compartilhar o estado entre as duas facetas, teremos implementada a classe StockSellerContext de contexto do componente versão 1 - julho/2013 Passo 4: Implementando um Servidor • Um programa servidor se encarrega de: – realizar a conexão por certificado – criar o componente que implementa as facetas necessárias – registrar uma oferta de serviço – instalar um ProcessExit para desconectar do barramento antes de finalizar a aplicação – manter ativa a execução do ORB versão 1 - julho/2013 Fluxo principal do servidor namespace StockSeller { internal static class StockSeller { private static Assistant _assistant; private static void Main(String[] args) { // Registra handler para o caso do processo ser finalizado AppDomain.CurrentDomain.ProcessExit += CurrentDomainProcessExit; // Inicializa o assistente do OpenBus _assistant = ConnectWithOpenBus(args); // Cria o componente IComponent ic = CreateComponent(); // Registra o serviço no barramento ServiceProperty[] serviceProperties = new[] { new ServiceProperty("offer.domain", "StockMarket") }; _assistant.RegisterService(ic, serviceProperties); Console.WriteLine("StockSeller rodando."); // Bloqueia a thread corrente até o ORB finalizar Thread.Sleep(Timeout.Infinite); } } } versão 1 - julho/2013 Fazer a conexão por certificado private static void MyLoginFailureCallback(Assistant assistant, Exception e) { Console.WriteLine(e); } private static void MyRegisterFailureCallback(Assistant assistant, IComponent ic, ServiceProperty[] props, Exception e) { Console.WriteLine(e); } private static Assistant ConnectWithOpenBus(String[] args) { string host = args[0]; ushort port = UInt16.Parse(args[1]); string entity = args[2]; string privateKeyPath = args[3]; PrivateKey privateKey = Crypto.ReadKeyFile(privateKeyPath); PrivateKeyProperties assistantProps = new PrivateKeyProperties(entity, privateKey) { LoginFailureCallback = MyLoginFailureCallback, RegisterFailureCallback = MyRegisterFailureCallback }; return new AssistantImpl(host, port, assistantProps); } versão 1 - julho/2013 Registrar a oferta de serviço ServiceProperty[] serviceProperties = new[] { new ServiceProperty("offer.domain", "StockMarket") }; _assistant.RegisterService(ic, serviceProperties); versão 1 - julho/2013 Implementação do ProcessExit private static void CurrentDomainProcessExit(object sender, EventArgs e) { if (_assistant != null) { _assistant.Shutdown(); } } versão 1 - julho/2013 Passo 5: Implementando o Cliente • O programa cliente se encarrega de: – Conectar com o Openbus através de usuário e senha – Buscar pelo(s) serviço(s) que procura – Utilizar o(s) serviço(s) versão 1 - julho/2013 Conectando com usuário e senha private static void MyLoginFailureCallback(Assistant assistant, Exception e) { Console.WriteLine(e); } private static void MyFindFailureCallback(Assistant assistant, Exception e) { Console.WriteLine(e); } private static void Main(String[] args) { … PasswordProperties passProperties = new PasswordProperties(entity, password) { LoginFailureCallback = MyLoginFailureCallback, FindFailureCallback = MyFindFailureCallback }; Assistant assistant = new AssistantImpl(host, port, passProperties); … } versão 1 - julho/2013 Procurando pelas facetas // Faz busca utilizando propriedades geradas automaticamente e // propriedades definidas pelo serviço específico string stockServerIDLType = Repository.GetRepositoryID(typeof(StockServer)); string stockExchangeIDLType = Repository.GetRepositoryID(typeof(StockExchange)); // propriedades geradas automaticamente ServiceProperty autoProp = new ServiceProperty("openbus.component.interface", stockServerIDLType); ServiceProperty autoProp2 = new ServiceProperty("openbus.component.interface", stockExchangeIDLType); // propriedade definida pelo serviço StockSeller ServiceProperty prop = new ServiceProperty("offer.domain", "StockMarket"); // busca por QUAISQUER serviços com as facetas esperadas de um // StockSeller e pertencentes ao domínio StockMarket ServiceOfferDesc[] offers = Utils.FilterWorkingOffers( assistant.FindServices(new[] { prop, autoProp, autoProp2 }, -1)); versão 1 - julho/2013 Passo 6: Executando no VisualStudio 2010 • Antes de executar, precisamos modificar uma configuração do Visual Studio: Debug -> Options and Settings… -> desmarcar opção “Enable Just My Code” • Essa opção, além da sua funcionalidade intencionada que é útil (pular código que não é do usuário durante o debugging), faz com que o debugger crie um breakpoint se qualquer exceção de código que não seja do usuário for lançada • A biblioteca do OpenBus é distribuída em modo release com otimizações, e portanto será considerada non-user code • O protocolo OpenBus lança exceções CORBA para sinalizar diversas situações, e não desejamos que o debugger pare a execução a cada uma delas • A solução mais simples é simplesmente desabilitar a opção acima, mas perde-se sua funcionalidade intencionada versão 1 - julho/2013 Passo 6: Executando no VisualStudio 2010 • Outra solução possível, mantendo o JMC, é abrir a janela: Debug -> Exceptions… • E desmarcar toda a seção “User-unhandled” para “Common Language Runtime Exceptions” – No entanto, o debugger não parará por exceções CLR que gostaríamos que parasse • Portanto, a opção menos radical é deixar a seção marcada e adicionar novas entradas desmarcadas dentro dela para cada exceção que não se deseja capturar em debugging. As exceções lançadas pela biblioteca OpenBus C# são: – omg.org.CORBA.NO_PERMISSION – omg.org.PortableInterceptor.ForwardRequest • O IIOP.NET pode lançar uma série de exceções adicionais, como BAD_PARAM. No entanto, talvez seja interessante deixar que essas estourem. Caso deseje que elas passem diretamente para o cliente, adicione novas entradas de exceções ou desative o JMC versão 1 - julho/2013