On May 16, 2012, at 10:07 PM, Steve Angelovich wrote:
> What is TApplicationException intended to be used for?
>
> Is there a mechanism in thrift to propagate a runtime exception from the
> server back to the client?
>
> How do others deal with a case where the caller has made an RPC call with an
> invalid argument. In Java I'd normally throw a IllegalArgumentException, is
> something like this possible in thrift or do I have to add another user
> defined exception type which will result in the caller having to deal with
> another checked exception.
>
>
> Thanks for any help
> Steve
>
>
> On 05/10/2012 05:06 PM, Craig Artley wrote:
>
>
> Hello, I want to take exceptions on the server and return them back to the
> client. For example, say the client's request leads to a run time exception
> like IllegalArgumentException. I think that TApplicationException with
> INTERNAL_ERROR is the way to do this, but I couldn't get it to work and I
> can't find any examples.
>
> In my service handler, I check the args. If they are invalid, I threw a
> TApplicationException like this
> throw new
> TApplicationException(TApplicationException.INTERNAL_ERROR,"Illegal argument
> blah blah");
>
> It still showed up in my client as a TTransportException:
> org.apache.thrift.transport.TTransportException
> at
> org.apache.thrift.transport.TIOStreamTransport.read(TIOStreamTransport.java:132)
>
> I'm sure I am just misunderstanding something. What am I missing? Can anyone
> provide an example of robust exception handling in the server to the client?
>
> I read about it in THRIFT-378
> https://issues.apache.org/jira/browse/THRIFT-378
>
> Regards,
> -craig
You can define your own exception types. Here's a real world example:
-----------------------------------------------------
File OurThriftException.thrift:
struct ExceptionInfoAll
{
1: string name, /** The class name of the exception */
2: string message, /** If not a OurCustomException, this
is the result of what().
If OurCustomException, this is the
result of ex.toString(). */
}
struct ExceptionInfoOurCustomException
{
1: string errorCodeName, /** The name of the error, such as
DeviceNotFound
This is
specific to the exception class */
2: i32 errorCodeValue, /** The numeric value of the error code
*/
3: string description, /** The description string defined in
the exception's EXCEPTION_TABLE */
4: string debugMsg, /** The debug message attached to the
exception at the throw point */
5: string location, /** The location information that may
have been attached at the throw point. */
}
struct ExceptionInfo
{
1: ExceptionInfoAll defaultInfo,
/** Available for any exception */
2: optional ExceptionInfoOurCustomException ourInfo,
/** Available only for OurCustomException */
}
exception OurThriftExceptionWire
{
1: ExceptionInfo excInfo, /** The
information extracted from the exception that was caught by the server. */
}
-----------------------------------------------------
Once you do this, you can define a service like this:
service MyService
{
returnType myCall ( args here) throws (1: OurThriftException.
OurThriftExceptionWire ex),
}
On your server side, you do this (I have neglected to set the __isset values to
make the code clearer.):
returnType myCall_handler (args)
{
try
{
do something
}
catch (OurCustomException &ex)
{
OurThriftExceptionWire wireEx;
wireEx.excInfo.defaultInfo = "OurCustomException";
wireEx.excInfo.defaultInfo.message = ex.what();
// Extract info from OurCustomException here and pack into
wireEx.excInfo.ourInfo
throw wireEx;
}
catch (std::exception &ex)
{
OurThriftExceptionWire wireEx;
wireEx.excInfo.defaultInfo = "OurCustomException";
wireEx.excInfo.defaultInfo.message = ex.what();
throw wireEx;
}
}
And on your client side you do this:
try
{
myCall (args)
}
catch (OurThriftExceptionWire &ex)
{
// Now you have exception details from the server side. We would throw
an exception type
// specific to the library where this code is, but it would contain all
the info from
// ex.excInfo.
}
I hope that helps.
Best regards,
Rush