[omniORB] Narrowing DII exception - take 2

Kevin Bailey ke-omniorb@retriever.dyndns.org
Mon, 30 Jul 2001 11:09:04 -0700


I'm still trying to find the right way to propagate a user exception
through a DII request. I suspect the included example is closer to
the correct way than before but it still translates all user exceptions
to CORBA::MARSHAL.

It can't even narrow the exception to an UnknownUserException.
This implies that the exception is a genuine CORBA::MARSHAL and
that either the unmarshalling of user exceptions has a bug or
that I'm supposed to configure the DII request to accept an
exception of that type prior to the evocation. I can't find
any way to do the latter, however.

Can someone at least tell me if this is the correct way ?
If it is, is this a known bug ? I haven't found anything
mentioning it in the archives.

// pingtest.cc

#include "pingable.hh"
#include <iostream>

class Pingable_i:
  public POA_Fruit::Pingable
{
  public:
  
  virtual void Ping();
};

bool ping_should_throw;

void Pingable_i::Ping()
{
  std::cout << "Pingable_i::Ping" << std::endl;
  
  if (ping_should_throw)
    throw Fruit::MyUserException();
}

void DII_Evoke(Fruit::Pingable_ptr r_pingable)
{
  CORBA::Request_var r_request = r_pingable->_request("Ping");
  r_request->invoke();
  try
  {
    CORBA::Exception* p_ex;
    p_ex = r_request->env()->exception();
    if (p_ex)
    {
      std::cout << "Caught exception" << std::endl;
      
      CORBA::UnknownUserException* p_un_ex;
      p_un_ex = CORBA::UnknownUserException::_downcast(p_ex);
      if (p_un_ex)
      {
        std::cout << "Narrowed to UnknownUserException" << std::endl;
        
        const Fruit::MyUserException* p_my_ex;
        if (p_un_ex->exception() >>= p_my_ex)
        {
          std::cout << "Extracted Fruit::MyUserException" << std::endl;
          
          const_cast<Fruit::MyUserException*>(p_my_ex)->_raise();
        }
      }
      p_ex->_raise();
    }
  }
  catch (CORBA::MARSHAL&)
  {
    std::cout << "Caught CORBA::MARSHAL" << std::endl;
  }
  catch (Fruit::MyUserException&)
  {
    std::cout << "Caught Fruit::MyUserException" << std::endl;
  }
}

int main(int argc, char* argv[])
{
  CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, "omniORB3");

  CORBA::Object_var obj = orb->resolve_initial_references("RootPOA");
  PortableServer::POA_var poa = PortableServer::POA::_narrow(obj);

  PortableServer::POAManager_var pman = poa->the_POAManager();
  pman->activate();
  
  Pingable_i* p_ping = new Pingable_i();
  
  Fruit::Pingable_var r_pingable = p_ping->_this();
  
  // Try once to make sure that the call is ok
  ping_should_throw = false;
  DII_Evoke(r_pingable);
  
  // Have it throw a user exception
  ping_should_throw = true;
  DII_Evoke(r_pingable);
  
  orb->destroy();
  
  return 0;
}

// pingable.idl

module Fruit
{

exception MyUserException
{
};

interface Pingable
{
  void Ping()
    raises(MyUserException);
};

};