THRIFT-142. java: Better handling of required fields

- On reading, behave the same way as the C++ code:
  throw an exception if a required field is missing.
- In addition, throw an exception if a required field is missing
  when writing.  For the JavaBeans code, this means that __isset
  is false (because it is maintained automatically).  For non-beans
  code, this means that the field is null.  Non-nullable fields are
  not checked in non-beans code.


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@719727 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index 3c71d9e..5606f81 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -885,6 +885,17 @@
     out <<
       indent() << "iprot.readStructEnd();" << endl;
 
+    // check to make sure all required fields are set
+    out << endl << indent() << "// check for required fields" << endl;
+    for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+      if ((*f_iter)->get_req() == t_field::T_REQUIRED) {
+        out <<
+          indent() << "if (!__isset." << (*f_iter)->get_name() << ") {" << endl <<
+          indent() << "  throw new TProtocolException(\"Required field '" << (*f_iter)->get_name() << "' was not found in serialized data!\");" << endl <<
+          indent() << "}" << endl;
+      }
+    }
+
   indent_down();
   out <<
     indent() << "}" << endl <<
@@ -906,6 +917,28 @@
   const vector<t_field*>& fields = tstruct->get_members();
   vector<t_field*>::const_iterator f_iter;
 
+  // check for required fields
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    t_field* field = (*f_iter);
+    if (field->get_req() == t_field::T_REQUIRED) {
+      if (bean_style_) {
+        indent(out) << "if (!__isset." << field->get_name() << ") {" << endl;
+        indent(out) << "  throw new TProtocolException(\"Required field '" << field->get_name() << "' was not present!\");" << endl;
+        indent(out) << "}" << endl;
+      } else {
+        if (type_can_be_null(field->get_type())) {
+          indent(out) << "if (" << field->get_name() << " == null) {" << endl;
+          indent(out) << "  throw new TProtocolException(\"Required field '" << field->get_name() << "' was not present!\");" << endl;
+          indent(out) << "}" << endl;
+        } else {
+          indent(out) << "// alas, we cannot check '" << field->get_name() << "' because it's a primitive and you chose the non-beans generator." << endl;
+        }
+      }
+    }
+  }
+
+  out << endl << endl;
+
   indent(out) << "TStruct struct = new TStruct(\"" << name << "\");" << endl;
   indent(out) << "oprot.writeStructBegin(struct);" << endl;