当 TAO orb 抛出时,Orber (Erlang ORB) 无法捕获用户定义的异常
Orber (Erlang ORB) not able to catch user defined exceptions when thrown by 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 应用程序时我需要做一些特殊的事情来启用正确的行为吗?
编辑 - 这就是我从 erlang 调用服务器的方式 -
在 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
在调用该方法之前,您需要将您的 IDL 定义注册到 orber 接口存储库 (IFR) 中。例如,如果您的 IDL 文件名为 messenger.idl
,编译它会创建 oe_messenger.erl
,它提供 oe_register/0
功能。调用它会将有关您的用户定义异常的信息注册到 IFR 中,orber 的 CDR 解码使用它能够正确解码包含该异常的任何响应:
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)
更新:在 orber 中需要这个额外的 IFR 注册步骤,而在 C++ ORB 中很少需要的原因是 CORBA 规范中的一些灵活性以及 C++ ORB 开发传统。 original CORBA specification 在某种程度上是静态和动态语言阵营之间的折衷。动态阵营坚持 IFR 在规范中,因为他们需要它来在运行时检索类型信息(显然他们如愿以偿,因为它一直是 CORBA 的一部分),但静态阵营认为 IFR 是不必要的,因为所有必要的类型信息可以编码在从 IDL 定义生成的 C/C++ 代码中。 C++ ORB 开发社区传统上遵循代码生成方法并将 IFR 视为可选的运行时组件,并且此问题中使用的 C++ ORB 从生成的存根和框架中检索有关用户定义的 cirrus_error
异常的信息。但是用其他语言编写的 ORB,例如 Smalltalk 和 Erlang,已经选择使用 IFR 作为 ORB 运行时的正常组件,因此它们需要将类型信息注册到 IFR 中,以便它对 ORB 运行时可用.不过,在 Erlang 中肯定可以将有关用户定义的异常的信息生成到 stubs/skeletons 中,并让运行时从那里检索它。
我有一个 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 应用程序时我需要做一些特殊的事情来启用正确的行为吗?
编辑 - 这就是我从 erlang 调用服务器的方式 -
在 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
在调用该方法之前,您需要将您的 IDL 定义注册到 orber 接口存储库 (IFR) 中。例如,如果您的 IDL 文件名为 messenger.idl
,编译它会创建 oe_messenger.erl
,它提供 oe_register/0
功能。调用它会将有关您的用户定义异常的信息注册到 IFR 中,orber 的 CDR 解码使用它能够正确解码包含该异常的任何响应:
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)
更新:在 orber 中需要这个额外的 IFR 注册步骤,而在 C++ ORB 中很少需要的原因是 CORBA 规范中的一些灵活性以及 C++ ORB 开发传统。 original CORBA specification 在某种程度上是静态和动态语言阵营之间的折衷。动态阵营坚持 IFR 在规范中,因为他们需要它来在运行时检索类型信息(显然他们如愿以偿,因为它一直是 CORBA 的一部分),但静态阵营认为 IFR 是不必要的,因为所有必要的类型信息可以编码在从 IDL 定义生成的 C/C++ 代码中。 C++ ORB 开发社区传统上遵循代码生成方法并将 IFR 视为可选的运行时组件,并且此问题中使用的 C++ ORB 从生成的存根和框架中检索有关用户定义的 cirrus_error
异常的信息。但是用其他语言编写的 ORB,例如 Smalltalk 和 Erlang,已经选择使用 IFR 作为 ORB 运行时的正常组件,因此它们需要将类型信息注册到 IFR 中,以便它对 ORB 运行时可用.不过,在 Erlang 中肯定可以将有关用户定义的异常的信息生成到 stubs/skeletons 中,并让运行时从那里检索它。