thrift-user mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Craig Artley <cart...@hotmail.com>
Subject RE: Using TApplicationException - need example
Date Fri, 18 May 2012 00:21:44 GMT

Rush, thanks for the reply and the example code. I got that working with Java server and clients
without too much drama.

Still, when I read the THRIFT-378 (https://issues.apache.org/jira/browse/THRIFT-378) I get
the feeling that it should not be this tedious. Quoting from the original description:

---
One workaround might be to add an InternalError exception and declare
 every method to throw that, but this would require wrapping each method
 implementation on the server with a try/catch/throw block, which is 
ugly and repetitive (especially if there are other try/catch blocks 
nested) – exactly the sort of code that Thrift is good at automating 
away.


I think the right fix would be for the server to catch runtime 
exceptions in the generated process methods and send back a 
TApplicationException.  This is what some other servers (e.g., Erlang) 
already do.---

So what we have done is essentially implement the "workaround": boilerplate code in every
method to explicitly catch internal problems and throw a custom exception.

The original reporter really nailed in the last sentence - server should automatically catch
run time exceptions and throw TApplicationExceptions to the client. The bug is marked as resolved
for nearly 3 years, so I must be completely misunderstanding the intent.  Isn't it supposed
to automatically toss back to the client a TApplicationException of type INTERNAL_ERROR? Do
I really have to do that by hand in every single method? Do people have to do that with C++
servers too, or is this only a problem with Java servers?

It was supposedly fixed, but maybe I just don't understand the goal. When my sever hits a
run time exception, the client just gets a cryptic TTransportException with no clue of what
went wrong.

Regards,
  -craig

----------------------------------------
> Subject: Re: Using TApplicationException - need example
> From: rush@manbert.com
> Date: Thu, 17 May 2012 09:44:30 -0700
> To: user@thrift.apache.org
>
>
> 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
 		 	   		  
Mime
View raw message