THRIFT-1805 Provide option for handling RTEs
Client: Java
Adds a Java option to the generator to generate code which lets Thrift
handle RuntimeExceptions from a service, and present them as
TApplicationException to the client.
This closes #1186
diff --git a/compiler/cpp/src/thrift/generate/t_java_generator.cc b/compiler/cpp/src/thrift/generate/t_java_generator.cc
index b732631..593eda6 100644
--- a/compiler/cpp/src/thrift/generate/t_java_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_java_generator.cc
@@ -70,6 +70,7 @@
use_option_type_ = false;
undated_generated_annotations_ = false;
suppress_generated_annotations_ = false;
+ handle_runtime_exceptions_ = false;
for( iter = parsed_options.begin(); iter != parsed_options.end(); ++iter) {
if( iter->first.compare("beans") == 0) {
bean_style_ = true;
@@ -91,6 +92,8 @@
reuse_objects_ = true;
} else if( iter->first.compare("option_type") == 0) {
use_option_type_ = true;
+ } else if( iter->first.compare("handle_runtime_exceptions") == 0) {
+ handle_runtime_exceptions_ = true;
} else if( iter->first.compare("generated_annotations") == 0) {
if( iter->second.compare("undated") == 0) {
undated_generated_annotations_ = true;
@@ -367,6 +370,7 @@
bool use_option_type_;
bool undated_generated_annotations_;
bool suppress_generated_annotations_;
+ bool handle_runtime_exceptions_;
};
@@ -3527,6 +3531,11 @@
indent(f_service_) << " return " << ((tfunction->is_oneway()) ? "true" : "false") << ";" << endl;
indent(f_service_) << "}" << endl << endl;
+ indent(f_service_) << "@Override" << endl;
+ indent(f_service_) << "protected boolean handleRuntimeExceptions() {" << endl;
+ indent(f_service_) << " return " << ((handle_runtime_exceptions_) ? "true" : "false") << ";" << endl;
+ indent(f_service_) << "}" << endl << endl;
+
indent(f_service_) << "public " << resultname << " getResult(I iface, " << argsname
<< " args) throws org.apache.thrift.TException {" << endl;
indent_up();
@@ -5265,6 +5274,9 @@
" android_legacy: Do not use java.io.IOException(throwable) (available for Android 2.3 and "
"above).\n"
" option_type: Wrap optional fields in an Option type.\n"
+ " handle_runtime_exceptions:\n"
+ " Send TApplicationException to the client when RuntimeException occurs on "
+ "the server. (Default behavior is to close the connection instead.)\n"
" java5: Generate Java 1.5 compliant code (includes android_legacy flag).\n"
" reuse-objects: Data objects will not be allocated, but existing instances will be used "
"(read and write).\n"
diff --git a/lib/java/src/org/apache/thrift/ProcessFunction.java b/lib/java/src/org/apache/thrift/ProcessFunction.java
index 992e859..5c039fe 100644
--- a/lib/java/src/org/apache/thrift/ProcessFunction.java
+++ b/lib/java/src/org/apache/thrift/ProcessFunction.java
@@ -1,6 +1,3 @@
-/**
- *
- */
package org.apache.thrift;
import org.apache.thrift.protocol.TMessage;
@@ -39,13 +36,12 @@
result = getResult(iface, args);
} catch(TException tex) {
LOGGER.error("Internal error processing " + getMethodName(), tex);
- if (!isOneway()) {
- TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR,
- "Internal error processing " + getMethodName());
- oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
- x.write(oprot);
- oprot.writeMessageEnd();
- oprot.getTransport().flush();
+ handleException(seqid, oprot);
+ return;
+ } catch(RuntimeException rex) {
+ LOGGER.error("Internal error processing " + getMethodName(), rex);
+ if (handleRuntimeExceptions()) {
+ handleException(seqid, oprot);
}
return;
}
@@ -58,6 +54,21 @@
}
}
+ private void handleException(int seqid, TProtocol oprot) throws TException {
+ if (!isOneway()) {
+ TApplicationException x = new TApplicationException(TApplicationException.INTERNAL_ERROR,
+ "Internal error processing " + getMethodName());
+ oprot.writeMessageBegin(new TMessage(getMethodName(), TMessageType.EXCEPTION, seqid));
+ x.write(oprot);
+ oprot.writeMessageEnd();
+ oprot.getTransport().flush();
+ }
+ }
+
+ protected boolean handleRuntimeExceptions() {
+ return false;
+ }
+
protected abstract boolean isOneway();
public abstract TBase getResult(I iface, T args) throws TException;