Орбер (Erlang ORB) не может перехватить определенные пользователем исключения при выдаче с помощью TAO orb
У меня есть C++ CORBA-сервер, который реализует интерфейс, выбрасывающий пользовательское исключение.
Я легко могу поймать конкретное исключение, когда клиент и сервер реализованы на C++ (протестировано с использованием TAO orb и omniORB).
Но когда я вызываю тот же метод из Erlang (используя orber), исключение появляется как общее исключение, а не как определенное пользователем исключение.
Чтобы проверить это, я просто использовал простой IDL -
interface Messenger {
exception cirrus_error{
short error_code;
string error_desc;
};
boolean send_message(in string user_name,
in string subject,
inout string message) raises (cirrus_error);
};
Если и сервер, и клиент находятся в C++, я получаю исключение (для тестирования я его кодировал, чтобы всегда выдавать пользовательское исключение)
CORBA exception: cirrus_error (IDL:Messenger/cirrus_error:1.0)
Но когда вызывается через Erlang - я получаю -
** exception throw: {'EXCEPTION',{'UNKNOWN',[],1330446337,'COMPLETED_MAYBE'}}
in function corba:raise/1
Нужно ли делать что-то особенное при заявлении приложения Orber, чтобы включить правильное поведение?
Edit - это то, как я называю сервер из Erlang -
По подсказке Эрланга, это то, что я делаю -
1> orber:jump_start().
2> O = corba:string_to_object(IORStr).
3> 'Messenger':send_message(O, "s", "t", "f").
** exception throw: {'EXCEPTION',{'UNKNOWN',[],1330446337,'COMPLETED_MAYBE'}}
in function corba:raise/1
1 ответ
Вам нужно зарегистрировать ваши определения IDL в репозитории интерфейса orber (IFR) перед вызовом метода. Если ваш файл IDL назван messenger.idl
например, его компиляция создает oe_messenger.erl
, который обеспечивает oe_register/0
функция. Вызов этого регистрирует информацию о вашем определяемом пользователем исключении в IFR, который использует декодирование CDR orber, чтобы иметь возможность правильно декодировать любые ответы, содержащие это исключение:
1> orber:jump_start().
...
2> ic:gen(messenger).
Erlang IDL compiler version 4.4
ok
3> make:all().
Recompile: Messenger
Recompile: Messenger_cirrus_error
Recompile: oe_messenger
oe_messenger.erl:65: Warning: function oe_get_top_module/4 is unused
oe_messenger.erl:91: Warning: function oe_destroy_if_empty/2 is unused
up_to_date
4> oe_messenger:oe_register().
ok
5> M = corba:string_to_object(IORStr).
...
6> 'Messenger':send_message(M, "a", "b", "c").
** exception throw: {'EXCEPTION',{'Messenger_cirrus_error',"IDL:Messenger/cirrus_error:1.0",
1234,"yep, an error"}}
in function corba:raise/1 (corba.erl, line 646)
Обновление: Причина, по которой этот дополнительный шаг регистрации IFR необходим в orber, хотя редко, если вообще требуется в ORB C++, обусловлена некоторой гибкостью спецификации CORBA, а также традициями разработки ORB C++. Первоначальная спецификация CORBA была частично компромиссом между статическими и динамическими языковыми лагерями. Динамический лагерь настаивал на том, чтобы IFR была в спецификации, так как они нуждались в ней для получения информации о типе во время выполнения (и, очевидно, они получили свое желание, поскольку она всегда была частью CORBA), но статический лагерь предполагал, что IFR не требуется, поскольку все необходимая информация о типе может быть закодирована в коде C/C++, сгенерированном из определений IDL. Сообщество разработчиков C++ ORB традиционно следовало подходу генерации кода и рассматривало IFR как необязательный компонент времени выполнения, а ORB C++, используемые в этом вопросе, извлекали информацию о пользовательских cirrus_error
исключение из сгенерированных заглушек и скелетов. Но ORB, написанные на других языках, таких как Smalltalk и Erlang, решили использовать IFR в качестве обычного компонента среды выполнения ORB, и поэтому им требуется регистрация информации о типе в IFR, чтобы она была доступна для среды выполнения ORB., Тем не менее, в Erlang было бы возможно сгенерировать информацию о пользовательских исключениях в заглушки / скелеты и заставить среду выполнения извлечь ее оттуда.