Thrift generation for Java

Summary: Java works, benchmark roundtrip at around 3ms, so right in between C++ and PHP


git-svn-id: https://svn.apache.org/repos/asf/incubator/thrift/trunk@664775 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/compiler/cpp/Makefile b/compiler/cpp/Makefile
index 6b12853..b857e8c 100644
--- a/compiler/cpp/Makefile
+++ b/compiler/cpp/Makefile
@@ -35,9 +35,9 @@
 # Source files
 SRC_FILES = main.cc \
             generate/t_generator.cc \
+            generate/t_java_generator.cc \
             generate/t_php_generator.cc \
-            generate/t_cpp_generator.cc \
-            generate/t_java_generator.cc
+            generate/t_cpp_generator.cc
 
 # Autogenerated files
 GEN_FILES = thrift.tab.hh \
diff --git a/compiler/cpp/src/generate/t_cpp_generator.cc b/compiler/cpp/src/generate/t_cpp_generator.cc
index 43f8021..72132e5 100644
--- a/compiler/cpp/src/generate/t_cpp_generator.cc
+++ b/compiler/cpp/src/generate/t_cpp_generator.cc
@@ -667,15 +667,10 @@
         f_service_ <<
           indent() << "throw facebook::thrift::Exception(\"Unexpected message type, name, or id\");" << endl;
       indent_down();
-      f_service_ <<
-        indent() << "}" << endl;
 
       f_service_ <<
-        endl <<
-        indent() << resultname << " __result;" << endl;
-
-      // Add a field to the return struct if non void
-      f_service_ <<
+        indent() << "}" << endl <<
+        indent() << resultname << " __result;" << endl <<
         indent() << "read_struct_" << resultname << "(_iprot, _itrans, __result);" << endl <<
         indent() << "_iprot->readMessageEnd(_itrans);" << endl <<
         endl;
@@ -727,21 +722,21 @@
 
   // Generate the header portion
   f_header_ <<
-    "class " << service_name_ << "ServerIf : " <<
+    "class " << service_name_ << "Server : " <<
     "public " << service_name_ << "If, " <<
     "public facebook::thrift::TProcessor {" << endl <<
     " public: " << endl;
   indent_up();
   f_header_ << 
     indent() <<
-    service_name_ << "ServerIf(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> protocol) : " <<
+    service_name_ << "Server(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> protocol) : " <<
                        "_iprot(protocol), _oprot(protocol) {}" << endl <<
     indent() <<
-    service_name_ << "ServerIf(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " <<
+    service_name_ << "Server(boost::shared_ptr<const facebook::thrift::protocol::TProtocol> iprot, boost::shared_ptr<const facebook::thrift::protocol::TProtocol> oprot) : " <<
                        "_iprot(iprot), _oprot(oprot) {}" << endl <<
     indent() << "bool process(boost::shared_ptr<facebook::thrift::transport::TTransport> _itrans, " <<
                              "boost::shared_ptr<facebook::thrift::transport::TTransport> _otrans);" << endl <<
-    indent() << "virtual ~" << service_name_ << "ServerIf() {}" << endl;
+    indent() << "virtual ~" << service_name_ << "Server() {}" << endl;
   indent_down();
 
   // Protected data members
@@ -768,7 +763,7 @@
 
   // Generate the server implementation
   f_service_ <<
-    "bool " << service_name_ << "ServerIf::" <<
+    "bool " << service_name_ << "Server::" <<
     "process(boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans) {" << endl;
   indent_up();
 
@@ -832,6 +827,10 @@
  * @param tfunction The function
  */
 void t_cpp_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_async()) {
+    return;
+  }
+
   t_struct result(tfunction->get_name() + "_result");
   t_field success(tfunction->get_returntype(), "success", 0);
   if (!tfunction->get_returntype()->is_void()) {
@@ -859,7 +858,7 @@
                                                 t_function* tfunction) {
   // Open function
   f_service_ <<
-    "void " << tservice->get_name() << "ServerIf::" <<
+    "void " << tservice->get_name() << "Server::" <<
     "process_" << tfunction->get_name() <<
     "(int32_t seqid, boost::shared_ptr<facebook::thrift::transport::TTransport> itrans, boost::shared_ptr<facebook::thrift::transport::TTransport> otrans)" << endl;
   scope_up(f_service_);
@@ -871,13 +870,19 @@
     indent() << argsname << " __args;" << endl <<
     indent() << "read_struct_" << argsname << "(_iprot, itrans, __args);" << endl <<
     indent() << "_iprot->readMessageEnd(itrans);" << endl <<
-    endl <<
-    indent() << resultname << " __result;" << endl;
- 
+    endl;
+
   t_struct* xs = tfunction->get_xceptions();
   const std::vector<t_field*>& xceptions = xs->get_members();
   vector<t_field*>::const_iterator x_iter;
 
+  // Declare result
+  if (!tfunction->is_async()) {
+    f_service_ <<
+      indent() << resultname << " __result;" << endl;
+  }
+
+  // Try block for functions with exceptions
   if (xceptions.size() > 0) {
     f_service_ <<
       indent() << "try {" << endl;
@@ -890,7 +895,7 @@
   vector<t_field*>::const_iterator f_iter;
 
   f_service_ << indent();
-  if (!tfunction->get_returntype()->is_void()) {
+  if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
     f_service_ << "__result.success = ";    
   }
   f_service_ <<
@@ -907,26 +912,39 @@
   f_service_ << ");" << endl;
 
   // Set isset on success field
-  if (!tfunction->get_returntype()->is_void()) {
+  if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
     f_service_ <<
       indent() << "__result.__isset.success = true;" << endl;
   }
 
-  if (xceptions.size() > 0) {
+  if (!tfunction->is_async() && xceptions.size() > 0) {
     indent_down();
     f_service_ << indent() << "}";
     for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
       f_service_ << " catch (" << (*x_iter)->get_type()->get_name() << " &" << (*x_iter)->get_name() << ") {" << endl;
-      indent_up();
-      f_service_ <<
-        indent() << "__result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
-        indent() << "__result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
-      indent_down();
-      f_service_ << indent() << "}";
+      if (!tfunction->is_async()) {
+        indent_up();
+        f_service_ <<
+          indent() << "__result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "__result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
+        indent_down();
+        f_service_ << indent() << "}";
+      } else {
+        f_service_ << "}";
+      }
     }
     f_service_ << endl;
   }
 
+  // Shortcut out here for async functions
+  if (tfunction->is_async()) {
+    f_service_ <<
+      indent() << "return;" << endl;
+    indent_down();
+    f_service_ << "}" << endl <<
+      endl;
+    return;
+  }
 
   // Serialize the result into a struct
   f_service_ <<
@@ -977,6 +995,9 @@
       case t_base_type::TYPE_STRING:
         f_service_ << "readString(itrans, " << name << ");";
         break;
+      case t_base_type::TYPE_BOOL:
+        f_service_ << "readBool(itrans, " << name << ");";
+        break;
       case t_base_type::TYPE_BYTE:
         f_service_ << "readByte(itrans, " << name << ");";
         break;
@@ -1172,6 +1193,9 @@
       case t_base_type::TYPE_STRING:
         f_service_ << "writeString(otrans, " << name << ");";
         break;
+      case t_base_type::TYPE_BOOL:
+        f_service_ << "writeBool(otrans, " << name << ");";
+        break;
       case t_base_type::TYPE_BYTE:
         f_service_ << "writeByte(otrans, " << name << ");";
         break;
@@ -1378,6 +1402,8 @@
     return "void";
   case t_base_type::TYPE_STRING:
     return "std::string";
+  case t_base_type::TYPE_BOOL:
+    return "bool";
   case t_base_type::TYPE_BYTE:
     return "int8_t";
   case t_base_type::TYPE_I16:
@@ -1413,6 +1439,9 @@
       case t_base_type::TYPE_STRING:
         result += " = \"\"";
         break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
       case t_base_type::TYPE_BYTE:
       case t_base_type::TYPE_I16:
       case t_base_type::TYPE_I32:
@@ -1478,6 +1507,8 @@
       throw "NO T_VOID CONSTRUCT";
     case t_base_type::TYPE_STRING:
       return "facebook::thrift::protocol::T_STRING";
+    case t_base_type::TYPE_BOOL:
+      return "facebook::thrift::protocol::T_BOOL";
     case t_base_type::TYPE_BYTE:
       return "facebook::thrift::protocol::T_BYTE";
     case t_base_type::TYPE_I16:
diff --git a/compiler/cpp/src/generate/t_java_generator.cc b/compiler/cpp/src/generate/t_java_generator.cc
index f112407..1b466f7 100644
--- a/compiler/cpp/src/generate/t_java_generator.cc
+++ b/compiler/cpp/src/generate/t_java_generator.cc
@@ -13,6 +13,7 @@
 void t_java_generator::init_generator(t_program* tprogram) {
   // Make output directory
   mkdir(T_JAVA_DIR, S_IREAD | S_IWRITE | S_IEXEC);
+  package_name_ = tprogram->get_namespace();
 }
 
 /**
@@ -20,7 +21,7 @@
  */
 string t_java_generator::java_package() {
   // TODO(mcslee): Allow destination package to be specified in .thrift file
-  return string("package ") + program_name_ + ";\n\n";
+  return string("package ") + package_name_ + ";\n\n";
 }
 
 /**
@@ -32,8 +33,7 @@
     "import java.util.ArrayList;\n" +
     "import java.util.HashMap;\n" +
     "import java.util.HashSet;\n" +
-    "import com.facebook.thrift.*;\n" +
-    "import com.facebook.thrift.protocol.TString;\n\n";
+    "import com.facebook.thrift.*;\n\n";
 }
 
 /**
@@ -104,6 +104,15 @@
  * @param tstruct The struct definition
  */
 void t_java_generator::generate_struct(t_struct* tstruct) {
+  generate_java_struct(tstruct, false);
+}
+
+void t_java_generator::generate_xception(t_struct* txception) {
+  generate_java_struct(txception, true);
+}
+
+void t_java_generator::generate_java_struct(t_struct* tstruct,
+                                            bool is_exception) {
   // Make output file
   string f_struct_name = string(T_JAVA_DIR)+"/"+(tstruct->get_name())+".java";
   ofstream f_struct;
@@ -112,23 +121,239 @@
   f_struct <<
     autogen_comment() <<
     java_package() <<
-    java_type_imports();
+    java_type_imports() <<
+    java_thrift_imports();
 
-  f_struct <<
-    "public class " << tstruct->get_name() << " ";
+  generate_java_struct_definition(f_struct,
+                                  tstruct,
+                                  is_exception);
+  f_struct.close();
+}
+
+void t_java_generator::generate_java_struct_definition(ofstream &out,
+                                                       t_struct* tstruct,
+                                                       bool is_exception,
+                                                       bool in_class,
+                                                       bool is_result) {
+  out <<
+    "public " << (in_class ? "static " : "") << "class " << tstruct->get_name() << " ";
   
-  scope_up(f_struct);
+  if (is_exception) {
+    out << "extends Exception ";
+  }
+  
+  scope_up(out);
 
   const vector<t_field*>& members = tstruct->get_members();
   vector<t_field*>::const_iterator m_iter; 
   for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
-    indent(f_struct) <<
+    indent(out) <<
       "public " << declare_field(*m_iter, true) << endl;
   }
+
+  if (members.size() > 0) {
+    out <<
+      endl <<
+      indent() << "Isset __isset = new Isset();" << endl <<
+      indent() << "public final class Isset {" << endl;
+    indent_up();
+      for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
+        indent(out) <<
+          "public boolean " << (*m_iter)->get_name() << " = false;" <<  endl;
+      }
+    indent_down();
+    out <<
+      indent() << "}" << endl <<
+      endl;
+  }
   
-  scope_down(f_struct);
+  generate_java_struct_reader(out, tstruct);
+  if (is_result) {
+    generate_java_struct_result_writer(out, tstruct);
+  } else {
+    generate_java_struct_writer(out, tstruct);
+  }
+  scope_down(out);
 }
 
+void t_java_generator::generate_java_struct_reader(ofstream& out,
+                                                   t_struct* tstruct) {
+  out <<
+    indent() << "public static " << tstruct->get_name() << " read(TProtocol _iprot, TTransport _itrans) throws TException {" << endl;
+  indent_up();
+
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  // Declare stack tmp variables
+  out <<
+    indent() << tstruct->get_name() << " _value = new " << tstruct->get_name() << "();" << endl <<
+    indent() << "TField _field;" << endl <<
+    indent() << "TStruct _struct = _iprot.readStructBegin(_itrans);" << endl;
+  
+  // Loop over reading in fields
+  indent(out) <<
+    "while (true)" << endl;
+
+    scope_up(out);
+    
+    // Read beginning field marker
+    indent(out) <<
+      "_field = _iprot.readFieldBegin(_itrans);" << endl;
+    
+    // Check for field STOP marker and break
+    indent(out) <<
+      "if (_field.type == TType.STOP) { " << endl;
+    indent_up();
+    indent(out) <<
+      "break;" << endl;
+    indent_down();
+    indent(out) <<
+      "}" << endl;
+    
+    // Switch statement on the field we are reading
+    indent(out) <<
+      "switch (_field.id)" << endl;
+
+      scope_up(out);
+    
+      // Generate deserialization code for known cases
+      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+        indent(out) <<
+          "case " << (*f_iter)->get_key() << ":" << endl;
+        indent_up();
+        generate_deserialize_field(out, *f_iter, "_value.");
+        out <<
+          indent() << "_value.__isset." << (*f_iter)->get_name() << " = true;" << endl;
+        indent(out) <<
+          "break;" << endl;
+        indent_down();
+      }
+      
+      // In the default case we skip the field
+      out <<
+        indent() << "default:" << endl <<
+        indent() << "  TProtocolUtil.skip(_iprot, _itrans, _field.type);" << endl <<
+        indent() << "  break;" << endl;
+      
+      scope_down(out);
+
+    // Read field end marker
+    indent(out) <<
+      "_iprot.readFieldEnd(_itrans);" << endl;
+    
+    scope_down(out);
+      
+    out <<
+      indent() << "_iprot.readStructEnd(_itrans);" << endl <<
+      indent() << "return _value;" << endl; 
+
+  indent_down();
+  out <<
+    indent() << "}" << endl <<
+    endl;
+}
+
+void t_java_generator::generate_java_struct_writer(ofstream& out,
+                                                   t_struct* tstruct) {
+  out <<
+    indent() << "public void write(TProtocol _oprot, TTransport _otrans) throws TException {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out <<
+    indent() << "TStruct _struct = new TStruct(\"" << name << "\");" << endl <<
+    indent() << "TField _field = new TField();" << endl <<
+    indent() << "_oprot.writeStructBegin(_otrans, _struct);" << endl;
+
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    out <<
+      indent() << "_field.name = \"" << (*f_iter)->get_name() << "\";" << endl <<
+      indent() << "_field.type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
+      indent() << "_field.id = " << (*f_iter)->get_key() << ";" << endl <<
+      indent() << "_oprot.writeFieldBegin(_otrans, _field);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) <<
+      "_oprot.writeFieldEnd(_otrans);" << endl;
+  }
+  // Write the struct map
+  out <<
+    indent() << "_oprot.writeFieldStop(_otrans);" << endl <<
+    indent() << "_oprot.writeStructEnd(_otrans);" << endl;
+
+  indent_down();
+  out <<
+    indent() << "}" << endl <<
+    endl;
+}
+
+void t_java_generator::generate_java_struct_result_writer(ofstream& out,
+                                                          t_struct* tstruct) {
+  out <<
+    indent() << "public void write(TProtocol _oprot, TTransport _otrans) throws TException {" << endl;
+  indent_up();
+
+  string name = tstruct->get_name();
+  const vector<t_field*>& fields = tstruct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  out <<
+    indent() << "TStruct _struct = new TStruct(\"" << name << "\");" << endl <<
+    indent() << "TField _field = new TField();" << endl <<
+    indent() << "_oprot.writeStructBegin(_otrans, _struct);" << endl;
+
+  bool first = true;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    if (first) {
+      first = false;
+      out <<
+        endl <<
+        indent() << "if ";
+    } else {
+      out <<
+        " else if ";
+    }
+
+    out <<
+      "(this.__isset." << (*f_iter)->get_name() << ") {" << endl;
+    indent_up();
+
+    out <<
+      indent() << "_field.name = \"" << (*f_iter)->get_name() << "\";" << endl <<
+      indent() << "_field.type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
+      indent() << "_field.id = " << (*f_iter)->get_key() << ";" << endl <<
+      indent() << "_oprot.writeFieldBegin(_otrans, _field);" << endl;
+
+    // Write field contents
+    generate_serialize_field(out, *f_iter, "this.");
+
+    // Write field closer
+    indent(out) <<
+      "_oprot.writeFieldEnd(_otrans);" << endl;
+
+    indent_down();
+    indent(out) << "}";
+  }
+  // Write the struct map
+  out <<
+    endl <<
+    indent() << "_oprot.writeFieldStop(_otrans);" << endl <<
+    indent() << "_oprot.writeStructEnd(_otrans);" << endl;
+
+  indent_down();
+  out <<
+    indent() << "}" << endl <<
+    endl;
+}
+
+
 /**
  * Generates a thrift service. In C++, this comprises an entirely separate
  * header and source file. The header file defines the methods and includes
@@ -138,52 +363,9 @@
  * @param tservice The service definition
  */
 void t_java_generator::generate_service(t_service* tservice) {
-  // Generate the three main parts of the service
-  generate_service_interface(tservice);
-  generate_service_server(tservice);
-  generate_service_client(tservice);
-}
-
-/**
- * Generates a service interface definition.
- *
- * @param tservice The service to generate a header definition for
- */
-void t_java_generator::generate_service_interface(t_service* tservice) {
   // Make output file
-  string f_interface_name = string(T_JAVA_DIR)+"/"+service_name_+"If.java";
-  ofstream f_interface;
-  f_interface.open(f_interface_name.c_str());
-
-  f_interface <<
-    autogen_comment() <<
-    java_package() <<
-    java_type_imports();
-
-  f_interface <<
-    "public abstract class " << service_name_ << "If {" << endl;
-  indent_up();
-  vector<t_function*> functions = tservice->get_functions();
-  vector<t_function*>::iterator f_iter; 
-  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
-    indent(f_interface) <<
-      "public abstract " << function_signature(*f_iter) <<
-      " throws TException;" << endl;
-  }
-  indent_down();
-  f_interface <<
-    "}" << endl;
-  f_interface.close();
-}
-
-/**
- * Generates a service client definition.
- *
- * @param tservice The service to generate a server for.
- */
-void t_java_generator::generate_service_client(t_service* tservice) {
-  string f_client_name = string(T_JAVA_DIR)+"/"+service_name_+"Client.java";
-  f_service_.open(f_client_name.c_str());
+  string f_service_name = string(T_JAVA_DIR)+"/"+service_name_+".java";
+  f_service_.open(f_service_name.c_str());
 
   f_service_ <<
     autogen_comment() <<
@@ -192,13 +374,63 @@
     java_thrift_imports();
 
   f_service_ <<
-    "public class " << service_name_ << "Client " <<
-    "extends " << service_name_ << "If {" << endl;
+    "public class " << service_name_ << " {" << endl <<
+    endl;
+
+  // Generate the three main parts of the service
+  generate_service_interface(tservice);
+  generate_service_client(tservice);
+  generate_service_server(tservice);
+  generate_service_helpers(tservice);
+
+  f_service_ <<
+    "}" << endl;
+  f_service_.close();
+}
+
+/**
+ * Generates a service interface definition.
+ *
+ * @param tservice The service to generate a header definition for
+ */
+void t_java_generator::generate_service_interface(t_service* tservice) {
+  f_service_ <<
+    indent() << "public interface Iface {" << endl;
+  indent_up();
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter; 
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    indent(f_service_) <<
+      "public " << function_signature(*f_iter) << ";" << endl;
+  }
+  indent_down();
+  f_service_ <<
+    indent() << "}" << endl <<
+    endl;
+}
+
+void t_java_generator::generate_service_helpers(t_service* tservice) {
+  vector<t_function*> functions = tservice->get_functions();
+  vector<t_function*>::iterator f_iter; 
+  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
+    t_struct* ts = (*f_iter)->get_arglist();
+    generate_java_struct_definition(f_service_, ts, false, true);
+    generate_function_helpers(*f_iter);
+  }
+}
+
+/**
+ * Generates a service client definition.
+ *
+ * @param tservice The service to generate a server for.
+ */
+void t_java_generator::generate_service_client(t_service* tservice) {
+  f_service_ <<
+    "public static class Client implements Iface {" << endl;
   indent_up();
 
   indent(f_service_) <<
-    "public " << service_name_ << "Client" <<
-    "(TTransport trans, TProtocol prot)" << endl;
+    "public Client(TTransport trans, TProtocol prot)" << endl;
   scope_up(f_service_);
   indent(f_service_) << 
     "this(trans, trans, prot, prot);" << endl;
@@ -206,8 +438,7 @@
   f_service_ << endl;
 
   indent(f_service_) <<
-    "public " << service_name_ << "Client" <<
-    "(TTransport itrans, TTransport otrans," <<
+    "public Client(TTransport itrans, TTransport otrans," <<
     " TProtocol iprot, TProtocol oprot)" << endl;
   scope_up(f_service_);
   f_service_ <<
@@ -222,7 +453,10 @@
     indent() << "private TTransport _itrans;" << endl <<
     indent() << "private TTransport _otrans;" << endl <<
     indent() << "private TProtocol  _iprot;"  << endl <<
-    indent() << "private TProtocol  _oprot;"  << endl << endl;
+    indent() << "private TProtocol  _oprot;"  << endl <<
+    endl <<
+    indent() << "private int _seqid;" << endl <<
+    endl;
 
   // Generate client method implementations
   vector<t_function*> functions = tservice->get_functions();
@@ -232,7 +466,7 @@
 
     // Open function
     indent(f_service_) <<
-      "public " << function_signature(*f_iter) << " throws TException" << endl;
+      "public " << function_signature(*f_iter) << endl;
     scope_up(f_service_);
     indent(f_service_) <<
       "send_" << funname << "(";
@@ -269,74 +503,77 @@
                              string("send_") + (*f_iter)->get_name(),
                              (*f_iter)->get_arglist());
 
+    string argsname = (*f_iter)->get_name() + "_args";
+
     // Open function
     indent(f_service_) <<
-      "public " << function_signature(&send_function) << " throws TException" << endl;
+      "public " << function_signature(&send_function) << endl;
     scope_up(f_service_);
 
     // Serialize the request
     f_service_ <<
-      indent() <<
-      "_oprot.writeStructBegin(_otrans, " <<
-      "new TStruct(\"function\"));" << endl <<
-      indent() <<
-      "_oprot.writeFieldBegin(_otrans, " <<
-      "new TField(\"name\", TType.STRING, 0));" << endl <<
-      indent() <<
-      "_oprot.writeString(_otrans, " <<
-      "\"" << funname << "\");" << endl <<
-      indent() <<
-      "_oprot.writeFieldEnd(_otrans);" << endl <<
-      indent() <<
-      "_oprot.writeFieldBegin(_otrans, " <<
-      "new TField(\"args\", TType.STRUCT, 1));" << endl;
-    generate_serialize_struct((*f_iter)->get_arglist());
+      indent() << "_oprot.writeMessageBegin(_otrans, new TMessage(\"" << funname << "\", TMessageType.CALL, _seqid));" << endl <<
+      indent() << argsname << " __args = new " << argsname << "();" << endl;
+
+    for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
+      f_service_ <<
+        indent() << "__args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << ";" << endl;
+    }
+
     f_service_ <<
-      indent() <<
-      "_oprot.writeFieldEnd(_otrans);" << endl <<
-      indent() <<
-      "_oprot.writeFieldStop(_otrans);" << endl <<
-      indent() <<
-      "_oprot.writeStructEnd(_otrans);" << endl;
-    
-    // Flush the request
-    indent(f_service_) <<
-      "_otrans.flush();" << endl;
+      indent() << "__args.write(_oprot, _otrans);" << endl <<
+      indent() << "_oprot.writeMessageEnd(_otrans);" << endl <<
+      indent() << "_otrans.flush();" << endl;
 
     scope_down(f_service_);
     f_service_ << endl;
 
     if (!(*f_iter)->is_async()) {
+      string resultname = (*f_iter)->get_name() + "_result";
+
       t_struct noargs;
       t_function recv_function((*f_iter)->get_returntype(),
                                string("recv_") + (*f_iter)->get_name(),
-                               &noargs);
+                               &noargs,
+                               (*f_iter)->get_xceptions());
       // Open function
       indent(f_service_) <<
-        "public " << function_signature(&recv_function) << " throws TException" << endl;
+        "public " << function_signature(&recv_function) << endl;
       scope_up(f_service_);
-      
-      // Read the response
-      t_struct result_struct((*f_iter)->get_name() + "_result");
-      t_field result_field((*f_iter)->get_returntype(), "_result");
-      
-      // Add a field to the return struct if non void
-      if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) <<
-          declare_field(&result_field, true) << endl;
-        result_struct.append(&result_field);
-      }
-      
-      // Deserialize response struct
-      generate_deserialize_struct(&result_struct);
-      
+           
+      // TODO(mcslee): Message validation here
+
+      f_service_ <<
+        indent() << "TMessage _msg = _iprot.readMessageBegin(_itrans);" << endl <<
+        indent() << resultname << " __result = " << resultname << ".read(_iprot, _itrans);" << endl <<
+        indent() << "_iprot.readMessageEnd(_itrans);" << endl <<
+        endl;
+
       // Careful, only return _result if not a void function
       if (!(*f_iter)->get_returntype()->is_void()) {
-        indent(f_service_) <<
-          "return _result;" << endl;
-      } else {
+        f_service_ <<
+          indent() << "if (__result.__isset.success) {" << endl <<
+          indent() << "  return __result.success;" << endl <<
+          indent() << "}" << endl;
+      }
+
+      t_struct* xs = (*f_iter)->get_xceptions();
+      const std::vector<t_field*>& xceptions = xs->get_members();
+      vector<t_field*>::const_iterator x_iter;
+      for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+        f_service_ <<
+          indent() << "if (__result.__isset." << (*x_iter)->get_name() << ") {" << endl <<
+          indent() << "  throw __result." << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "}" << endl;
+      }
+
+      // Careful, only return _result if not a void function
+      if ((*f_iter)->get_returntype()->is_void()) {
         indent(f_service_) <<
           "return;" << endl;
+      } else {
+        f_service_ <<
+          indent() << "throw new TException(\"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
       }
       
       // Close function
@@ -348,7 +585,6 @@
   indent_down();
   f_service_ <<
     "}" << endl;
-  f_service_.close();
 }
 
 /**
@@ -357,28 +593,17 @@
  * @param tservice The service to generate a server for.
  */
 void t_java_generator::generate_service_server(t_service* tservice) {
-  string f_server_name = string(T_JAVA_DIR)+"/"+service_name_+"ServerIf.java";
-  f_service_.open(f_server_name.c_str());
-
-  f_service_ <<
-    autogen_comment() <<
-    java_package() <<
-    java_type_imports() <<
-    java_thrift_imports();
-
   // Generate the dispatch methods
   vector<t_function*> functions = tservice->get_functions();
   vector<t_function*>::iterator f_iter; 
 
   // Generate the header portion
   f_service_ <<
-    "public abstract class " << service_name_ << "ServerIf " <<
-    "extends " << service_name_ << "If implements TProcessor {" << endl;
+    "public abstract static class Server implements Iface, TProcessor {" << endl;
   indent_up();
 
   indent(f_service_) <<
-    "public " << service_name_ << "ServerIf" <<
-    "(TProtocol prot)" << endl;
+    "public Server(TProtocol prot)" << endl;
   scope_up(f_service_);
   indent(f_service_) << 
     "this(prot, prot);" << endl;
@@ -386,8 +611,7 @@
   f_service_ << endl;
 
   indent(f_service_) <<
-    "public " << service_name_ << "ServerIf" <<
-    "(TProtocol iprot, TProtocol oprot)" << endl;
+    "public Server(TProtocol iprot, TProtocol oprot)" << endl;
   scope_up(f_service_);
   f_service_ <<
     indent() << "_iprot = iprot;" << endl <<
@@ -406,22 +630,9 @@
   scope_up(f_service_);
 
   f_service_ <<
-    indent() <<
-    "String _fname;" << endl <<
-    indent() <<
-    "TStruct _struct;" << endl <<
-    indent() <<
-    "TField _field;" << endl <<
-    indent() <<
-    "_struct = _iprot.readStructBegin(_itrans);" << endl <<
-    indent() <<
-    "_field = _iprot.readFieldBegin(_itrans);" << endl <<
-    indent() <<
-    "_fname = _iprot.readString(_itrans);" << endl <<
-    indent() <<
-    "_iprot.readFieldEnd(_itrans);" << endl <<
-    indent() <<
-    "_field = _iprot.readFieldBegin(_itrans);" << endl;
+    indent() << "TMessage _msg = _iprot.readMessageBegin(_itrans);" << endl;
+
+  // TODO(mcslee): validate message
 
   bool first = true;
   for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
@@ -432,11 +643,11 @@
       first = false;
     }
     f_service_ <<
-      "if (_fname.equals(\"" << (*f_iter)->get_name() <<"\")) {" << endl;
+      "if (_msg.name.equals(\"" << (*f_iter)->get_name() <<"\")) {" << endl;
     indent_up();
     indent(f_service_) <<
       "process_" << (*f_iter)->get_name() <<
-      "(_itrans, _otrans);" << endl;
+      "(_msg.seqid, _itrans, _otrans);" << endl;
     indent_down();
     indent(f_service_) << "}";
   }
@@ -445,21 +656,14 @@
   indent_up();
   indent(f_service_) <<
     "System.err.println" <<
-    "(\"Unknown function: '\" + _field.name + \"'\");" << endl;
+    "(\"Unknown function: '\" + _msg.name + \"'\");" << endl;
   indent_down();
   indent(f_service_) <<
     "}" << endl;
-
+  
   // Read end of args field, the T_STOP, and the struct close
   f_service_ <<
-    indent() <<
-    "_iprot.readFieldEnd(_itrans);" << endl <<
-    indent() <<
-    "_field = _iprot.readFieldBegin(_itrans);" << endl <<   
-    indent() <<
-    "_iprot.readStructEnd(_itrans);" << endl <<
-    indent() <<
-    "return true;" << endl;
+    indent() << "return true;" << endl;
 
   scope_down(f_service_);
   f_service_ << endl;
@@ -473,8 +677,32 @@
   f_service_ <<
     "}" << endl <<
     endl;
+}
 
-  f_service_.close();
+/**
+ * Generates a struct and helpers for a function.
+ *
+ * @param tfunction The function
+ */
+void t_java_generator::generate_function_helpers(t_function* tfunction) {
+  if (tfunction->is_async()) {
+    return;
+  }
+
+  t_struct result(tfunction->get_name() + "_result");
+  t_field success(tfunction->get_returntype(), "success", 0);
+  if (!tfunction->get_returntype()->is_void()) {
+    result.append(&success);
+  }
+
+  t_struct* xs = tfunction->get_xceptions();
+  const vector<t_field*>& fields = xs->get_members();
+  vector<t_field*>::const_iterator f_iter;
+  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
+    result.append(*f_iter);
+  }
+
+  generate_java_struct_definition(f_service_, &result, false, true, true);
 }
 
 /**
@@ -487,28 +715,42 @@
   // Open function
   indent(f_service_) <<
     "private void process_" << tfunction->get_name() <<
-    "(TTransport _itrans, TTransport _otrans) throws TException" << endl;
+    "(int seqid, TTransport _itrans, TTransport _otrans) throws TException" << endl;
   scope_up(f_service_);
 
-  // Get the struct of function call params
-  t_struct* arg_struct = tfunction->get_arglist();
+  string argsname = tfunction->get_name() + "_args";
+  string resultname = tfunction->get_name() + "_result";
 
-  // Declare the function arguments
-  const vector<t_field*>& fields = arg_struct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    indent(f_service_) <<
-      declare_field(*f_iter, true) << endl;
+  f_service_ <<
+    indent() << argsname << " __args = " << argsname << ".read(_iprot, _itrans);" << endl <<
+    indent() << "_iprot.readMessageEnd(_itrans);" << endl;
+
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+
+  // Declare result for non async function
+  if (!tfunction->is_async()) {
+    f_service_ <<
+      indent() << resultname << " __result = new " << resultname << "();" << endl <<
+      endl;
   }
 
-  // Deserialize the function arguments as a struct
-  generate_deserialize_struct(arg_struct);
-  
-  // Generate the function call
-  f_service_ << indent();
-  if (!tfunction->get_returntype()->is_void()) {
+  // Try block for a function with exceptions
+  if (xceptions.size() > 0) {
     f_service_ <<
-      type_name(tfunction->get_returntype()) << " _result = ";
+      indent() << "try {" << endl;
+    indent_up();
+  }
+ 
+  // Generate the function call
+  t_struct* arg_struct = tfunction->get_arglist();
+  const std::vector<t_field*>& fields = arg_struct->get_members();
+  vector<t_field*>::const_iterator f_iter;
+
+  f_service_ << indent();
+  if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
+    f_service_ << "__result.success = ";
   }
   f_service_ <<
     tfunction->get_name() << "(";
@@ -519,21 +761,51 @@
     } else {
       f_service_ << ", ";
     }
-    f_service_ << (*f_iter)->get_name();
+    f_service_ << "__args." << (*f_iter)->get_name();
   }
   f_service_ << ");" << endl;
 
-  // Serialize the result into a struct
-  t_struct result_struct(tfunction->get_name() + "_result");
-  t_field result_field(tfunction->get_returntype(), "_result");
-
-  // Only append the field if non-void
-  if (!tfunction->get_returntype()->is_void()) {
-    result_struct.append(&result_field);
+  // Set isset on success field
+  if (!tfunction->is_async() && !tfunction->get_returntype()->is_void()) {
+    f_service_ <<
+      indent() << "__result.__isset.success = true;" << endl;
   }
-  generate_serialize_struct(&result_struct);
-  indent(f_service_) <<
-    "_otrans.flush();" << endl;
+
+  if (!tfunction->is_async() && xceptions.size() > 0) {
+    indent_down();
+    f_service_ << indent() << "}";
+    for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+      f_service_ << " catch (" << (*x_iter)->get_type()->get_name() << " " << (*x_iter)->get_name() << ") {" << endl;
+      if (!tfunction->is_async()) {
+        indent_up();
+        f_service_ <<
+          indent() << "__result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << ";" << endl <<
+          indent() << "__result.__isset." << (*x_iter)->get_name() << " = true;" << endl;
+        indent_down();
+        f_service_ << indent() << "}";
+      } else {
+        f_service_ << "}";
+      }
+    }
+    f_service_ << endl;
+  }
+
+  // Shortcut out here for async functions
+  if (tfunction->is_async()) {
+    f_service_ <<
+      indent() << "return;" << endl;
+    indent_down();
+    f_service_ << "}" << endl <<
+      endl;
+    return;
+  }
+
+  f_service_ <<
+    endl <<
+    indent() << "_oprot.writeMessageBegin(_otrans, new TMessage(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid));" << endl <<
+    indent() << "__result.write(_oprot, _otrans);" << endl <<
+    indent() << "_oprot.writeMessageEnd(_otrans);" << endl <<
+    indent() << "_otrans.flush();" << endl;
 
   // Close function
   scope_down(f_service_);
@@ -543,8 +815,9 @@
 /**
  * Deserializes a field of any type.
  */
-void t_java_generator::generate_deserialize_field(t_field* tfield,
-                                                 string prefix) {
+void t_java_generator::generate_deserialize_field(ofstream& out,
+                                                  t_field* tfield,
+                                                  string prefix) {
   t_type* type = tfield->get_type();
   while (type->is_typedef()) {
     type = ((t_typedef*)type)->get_type();
@@ -557,14 +830,15 @@
 
   string name = prefix + tfield->get_name();
 
-  if (type->is_struct()) {
-    generate_deserialize_struct((t_struct*)(tfield->get_type()),
-                                 name + ".");
+  if (type->is_struct() || type->is_xception()) {
+    generate_deserialize_struct(out,
+                                (t_struct*)(tfield->get_type()),
+                                name);
   } else if (type->is_container()) {
-    generate_deserialize_container(tfield->get_type(), name);
+    generate_deserialize_container(out, tfield->get_type(), name);
   } else if (type->is_base_type() || type->is_enum()) {
 
-    indent(f_service_) <<
+    indent(out) <<
       name << " = _iprot.";
     
     if (type->is_base_type()) {
@@ -575,24 +849,30 @@
           name;
         break;
       case t_base_type::TYPE_STRING:        
-        f_service_ << "readString(_itrans);";
+        out << "readString(_itrans);";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "readBool(_itrans);";
         break;
       case t_base_type::TYPE_BYTE:
-        f_service_ << "readByte(_itrans);";
+        out << "readByte(_itrans);";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "readI16(_itrans);";
         break;
       case t_base_type::TYPE_I32:
-        f_service_ << "readI32(_itrans);";
+        out << "readI32(_itrans);";
         break;
       case t_base_type::TYPE_I64:
-        f_service_ << "readI64(_itrans);";
+        out << "readI64(_itrans);";
         break;
       default:
-        throw "compiler error: no C++ name for base type " + tbase;
+        throw "compiler error: no Java name for base type " + tbase;
       }
     } else if (type->is_enum()) {
-      f_service_ << "readI32(_itrans);";
+      out << "readI32(_itrans);";
     }
-    f_service_ <<
+    out <<
       endl;
   } else {
     printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
@@ -606,86 +886,17 @@
  * buffer for deserialization, and that there is a variable protocol which
  * is a reference to a TProtocol serialization object.
  */
-void t_java_generator::generate_deserialize_struct(t_struct* tstruct,
-                                                  string prefix) {
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  scope_up(f_service_);
-
-  // Read the struct fields from the protocol
-  string _struct = tmp("_struct");
-  string _field = tmp("_field");
-  
-  // Declare stack tmp variables
-  f_service_ <<
-    indent() << "TField " << _field << ";" << endl <<
-    indent() << "TStruct " << _struct << " = _iprot.readStructBegin(_itrans);" << endl;
-  
-  // Loop over reading in fields
-  indent(f_service_) <<
-    "while (true)" << endl;
-
-    scope_up(f_service_);
-    
-    // Read beginning field marker
-    indent(f_service_) <<
-      _field << " = _iprot.readFieldBegin(_itrans);" << endl;
-    
-    // Check for field STOP marker and break
-    indent(f_service_) <<
-      "if (" << _field << ".type == TType.STOP) { " << endl;
-    indent_up();
-    indent(f_service_) <<
-      "break;" << endl;
-    indent_down();
-    indent(f_service_) <<
-      "}" << endl;
-    
-    // Switch statement on the field we are reading
-    indent(f_service_) <<
-      "switch ((int)" << _field << ".id)" << endl;
-
-      scope_up(f_service_);
-    
-      // Generate deserialization code for known cases
-      for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-        indent(f_service_) <<
-          "case " << (*f_iter)->get_key() << ":" << endl;
-        indent_up();
-        generate_deserialize_field(*f_iter, prefix);
-        indent(f_service_) <<
-          "break;" << endl;
-        indent_down();
-      }
-      
-      // In the default case we skip the field
-      f_service_ <<
-        indent() <<
-        "default:" << endl <<
-        indent() <<
-        "  TProtocolUtil.skip(_iprot, _itrans, " << 
-        _field << ".type);" << endl <<
-        indent() <<
-        "  break;" << endl;
-      
-      scope_down(f_service_);
-
-    // Read field end marker
-    indent(f_service_) <<
-      "_iprot.readFieldEnd(_itrans);" << endl;
-    
-    scope_down(f_service_);
-      
-  indent(f_service_) <<
-    "_iprot.readStructEnd(_itrans);" << endl;
-
-  scope_down(f_service_);
+void t_java_generator::generate_deserialize_struct(ofstream& out,
+                                                   t_struct* tstruct,
+                                                   string prefix) {
+  out <<
+    indent() << prefix << " = " << tstruct->get_name() << ".read(_iprot, _itrans);" << endl;
 }
 
-void t_java_generator::generate_deserialize_container(t_type* ttype,
-                                                     string prefix) {
-  scope_up(f_service_);
+void t_java_generator::generate_deserialize_container(ofstream& out,
+                                                      t_type* ttype,
+                                                      string prefix) {
+  scope_up(out);
   
   string obj;
 
@@ -699,96 +910,99 @@
 
   // Declare variables, read header
   if (ttype->is_map()) {
-    f_service_ <<
+    out <<
       indent() << "TMap " << obj << " = _iprot.readMapBegin(_itrans);" << endl;
   } else if (ttype->is_set()) {
-    f_service_ <<
+    out <<
       indent() << "TSet " << obj << " = _iprot.readSetBegin(_itrans);" << endl;
   } else if (ttype->is_list()) {
-    f_service_ <<
+    out <<
       indent() << "TList " << obj << " = _iprot.readListBegin(_itrans);" << endl;
   }
 
 
   // For loop iterates over elements
   string i = tmp("_i");
-  indent(f_service_) <<
+  indent(out) <<
     "for (int " << i << " = 0; " <<
     i << " < " << obj << ".size" << "; " <<
     "++" << i << ")" << endl;
   
-    scope_up(f_service_);
+    scope_up(out);
     
     if (ttype->is_map()) {
-      generate_deserialize_map_element((t_map*)ttype, prefix);
+      generate_deserialize_map_element(out, (t_map*)ttype, prefix);
     } else if (ttype->is_set()) {
-      generate_deserialize_set_element((t_set*)ttype, prefix);
+      generate_deserialize_set_element(out, (t_set*)ttype, prefix);
     } else if (ttype->is_list()) {
-      generate_deserialize_list_element((t_list*)ttype, prefix);
+      generate_deserialize_list_element(out, (t_list*)ttype, prefix);
     }
     
-    scope_down(f_service_);
+    scope_down(out);
 
   // Read container end
   if (ttype->is_map()) {
-    indent(f_service_) << "_iprot.readMapEnd(_itrans);" << endl;
+    indent(out) << "_iprot.readMapEnd(_itrans);" << endl;
   } else if (ttype->is_set()) {
-    indent(f_service_) << "_iprot.readSetEnd(_itrans);" << endl;
+    indent(out) << "_iprot.readSetEnd(_itrans);" << endl;
   } else if (ttype->is_list()) {
-    indent(f_service_) << "_iprot.readListEnd(_itrans);" << endl;
+    indent(out) << "_iprot.readListEnd(_itrans);" << endl;
   }
 
-  scope_down(f_service_);
+  scope_down(out);
 }
 
 
 /**
  * Generates code to deserialize a map
  */
-void t_java_generator::generate_deserialize_map_element(t_map* tmap,
+void t_java_generator::generate_deserialize_map_element(ofstream& out,
+                                                        t_map* tmap,
                                                         string prefix) {
   string key = tmp("_key");
   string val = tmp("_val");
   t_field fkey(tmap->get_key_type(), key);
   t_field fval(tmap->get_val_type(), val);
 
-  indent(f_service_) <<
+  indent(out) <<
     declare_field(&fkey, true) << endl;
-  indent(f_service_) <<
+  indent(out) <<
     declare_field(&fval, true) << endl;
 
-  generate_deserialize_field(&fkey);
-  generate_deserialize_field(&fval);
+  generate_deserialize_field(out, &fkey);
+  generate_deserialize_field(out, &fval);
 
-  indent(f_service_) <<
+  indent(out) <<
     prefix << ".put(" << key << ", " << val << ");" << endl;
 }
 
-void t_java_generator::generate_deserialize_set_element(t_set* tset,
+void t_java_generator::generate_deserialize_set_element(ofstream& out,
+                                                        t_set* tset,
                                                         string prefix) {
   string elem = tmp("_elem");
   t_field felem(tset->get_elem_type(), elem);
 
-  indent(f_service_) <<
+  indent(out) <<
     declare_field(&felem, true) << endl;
 
-  generate_deserialize_field(&felem);
+  generate_deserialize_field(out, &felem);
 
-  indent(f_service_) <<
+  indent(out) <<
     prefix << ".add(" << elem << ");" << endl;
 }
 
-void t_java_generator::generate_deserialize_list_element(t_list* tlist,
+void t_java_generator::generate_deserialize_list_element(ofstream& out,
+                                                         t_list* tlist,
                                                          string prefix) {
   string elem = tmp("_elem");
   t_field felem(tlist->get_elem_type(), elem);
 
-  indent(f_service_) <<
+  indent(out) <<
     declare_field(&felem, true) << endl;
 
-  generate_deserialize_field(&felem);
+  generate_deserialize_field(out, &felem);
 
-  indent(f_service_) <<
+  indent(out) <<
     prefix << ".add(" << elem << ");" << endl;
 }
 
@@ -799,8 +1013,9 @@
  * @param tfield The field to serialize
  * @param prefix Name to prepend to field name
  */
-void t_java_generator::generate_serialize_field(t_field* tfield,
-                                               string prefix) {
+void t_java_generator::generate_serialize_field(ofstream& out,
+                                                t_field* tfield,
+                                                string prefix) {
   t_type* type = tfield->get_type();
   while (type->is_typedef()) {
     type = ((t_typedef*)type)->get_type();
@@ -812,16 +1027,18 @@
       prefix + tfield->get_name();
   }
   
-  if (type->is_struct()) {
-    generate_serialize_struct((t_struct*)(tfield->get_type()),
-                              prefix + tfield->get_name() + ".");
+  if (type->is_struct() || type->is_xception()) {
+    generate_serialize_struct(out,
+                              (t_struct*)(tfield->get_type()),
+                              prefix + tfield->get_name());
   } else if (type->is_container()) {
-    generate_serialize_container(tfield->get_type(),
+    generate_serialize_container(out,
+                                 tfield->get_type(),
                                  prefix + tfield->get_name());
   } else if (type->is_base_type() || type->is_enum()) {
 
     string name = prefix + tfield->get_name();
-    indent(f_service_) <<
+    indent(out) <<
       "_oprot.";
     
     if (type->is_base_type()) {
@@ -832,24 +1049,30 @@
           "compiler error: cannot serialize void field in a struct: " + name;
         break;
       case t_base_type::TYPE_STRING:
-        f_service_ << "writeString(_otrans, " << name << ");";
+        out << "writeString(_otrans, " << name << ");";
+        break;
+      case t_base_type::TYPE_BOOL:
+        out << "writeBool(_otrans, " << name << ");";
         break;
       case t_base_type::TYPE_BYTE:
-        f_service_ << "writeByte(_otrans, " << name << ");";
+        out << "writeByte(_otrans, " << name << ");";
+        break;
+      case t_base_type::TYPE_I16:
+        out << "writeI16(_otrans, " << name << ");";
         break;
       case t_base_type::TYPE_I32:
-        f_service_ << "writeI32(_otrans, " << name << ");";
+        out << "writeI32(_otrans, " << name << ");";
         break;
       case t_base_type::TYPE_I64:
-        f_service_ << "writeI64(_otrans, " << name << ");";
+        out << "writeI64(_otrans, " << name << ");";
         break;
       default:
-        throw "compiler error: no C++ name for base type " + tbase;
+        throw "compiler error: no Java name for base type " + tbase;
       }
     } else if (type->is_enum()) {
-      f_service_ << "writeI32(_otrans, " << name << ");";
+      out << "writeI32(_otrans, " << name << ");";
     }
-    f_service_ << endl;
+    out << endl;
   } else {
     printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
            prefix.c_str(),
@@ -864,64 +1087,31 @@
  * @param tstruct The struct to serialize
  * @param prefix  String prefix to attach to all fields
  */
-void t_java_generator::generate_serialize_struct(t_struct* tstruct,
+void t_java_generator::generate_serialize_struct(ofstream& out,
+                                                 t_struct* tstruct,
                                                  string prefix) {
-  string name = tstruct->get_name();
-  const vector<t_field*>& fields = tstruct->get_members();
-  vector<t_field*>::const_iterator f_iter;
-
-  scope_up(f_service_);
-  string _struct = tmp("_struct");
-  string _field = tmp("_field");
-
-  f_service_ <<
-    indent() <<
-    "TStruct " << _struct << " = new TStruct(\"" << name << "\");" << endl <<
-    indent() <<
-    "TField " << _field << " = new TField();" << endl <<
-    indent() <<
-    "_oprot.writeStructBegin(_otrans, " << _struct << ");" << endl;
-  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
-    f_service_ <<
-      indent() <<
-      _field << ".name = \"" << (*f_iter)->get_name() << "\";" << endl <<
-      indent() <<
-      _field << ".type = " << type_to_enum((*f_iter)->get_type()) << ";" << endl <<
-      indent() <<
-      _field << ".id = " << (*f_iter)->get_key() << ";" << endl <<
-      indent() <<
-      "_oprot.writeFieldBegin(_otrans, " << _field << ");" << endl;
-    // Write field contents
-    generate_serialize_field(*f_iter, prefix);
-    // Write field closer
-    indent(f_service_) <<
-      "_oprot.writeFieldEnd(_otrans);" << endl;
-  }
-  // Write the struct map
-  f_service_ <<
-    indent() << "_oprot.writeFieldStop(_otrans);" << endl <<
-    indent() << "_oprot.writeStructEnd(_otrans);" << endl;
-
-  scope_down(f_service_);
+  out <<
+    indent() << prefix << ".write(_oprot, _otrans);" << endl;
 }
 
-void t_java_generator::generate_serialize_container(t_type* ttype,
+void t_java_generator::generate_serialize_container(ofstream& out,
+                                                    t_type* ttype,
                                                     string prefix) {
-  scope_up(f_service_);
+  scope_up(out);
   
   if (ttype->is_map()) {
-    indent(f_service_) <<
+    indent(out) <<
       "_oprot.writeMapBegin(_otrans, new TMap(" <<
       type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
       type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
       prefix << ".size()));" << endl;
   } else if (ttype->is_set()) {
-    indent(f_service_) <<
+    indent(out) <<
       "_oprot.writeSetBegin(_otrans, new TSet(" <<
       type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
       prefix << ".size()));" << endl;
   } else if (ttype->is_list()) {
-    indent(f_service_) <<
+    indent(out) <<
       "_oprot.writeListBegin(_otrans, new TList(" <<
       type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
       prefix << ".size()));" << endl;
@@ -929,81 +1119,84 @@
 
   string iter = tmp("_iter");
   if (ttype->is_map()) {
-    indent(f_service_) <<
+    indent(out) <<
       "for (" <<
       type_name(((t_map*)ttype)->get_key_type()) << " " << iter <<
       " : " <<
       prefix << ".keySet())";
   } else if (ttype->is_set()) {
-    indent(f_service_) <<
+    indent(out) <<
       "for (" <<
       type_name(((t_set*)ttype)->get_elem_type()) << " " << iter <<
       " : " <<
       prefix << ")";
   } else if (ttype->is_list()) {
-    indent(f_service_) <<
+    indent(out) <<
       "for (" <<
       type_name(((t_list*)ttype)->get_elem_type()) << " " << iter <<
       " : " <<
       prefix << ")";
   }
 
-    scope_up(f_service_);
+    scope_up(out);
 
     if (ttype->is_map()) {
-      generate_serialize_map_element((t_map*)ttype, iter, prefix);
+      generate_serialize_map_element(out, (t_map*)ttype, iter, prefix);
     } else if (ttype->is_set()) {
-      generate_serialize_set_element((t_set*)ttype, iter);
+      generate_serialize_set_element(out, (t_set*)ttype, iter);
     } else if (ttype->is_list()) {
-      generate_serialize_list_element((t_list*)ttype, iter);
+      generate_serialize_list_element(out, (t_list*)ttype, iter);
     }
     
     if (ttype->is_map()) {
-      indent(f_service_) <<
+      indent(out) <<
         "_oprot.writeMapEnd(_otrans);" << endl;
     } else if (ttype->is_set()) {
-      indent(f_service_) <<
+      indent(out) <<
         "_oprot.writeSetEnd(_otrans);" << endl;
     } else if (ttype->is_list()) {
-      indent(f_service_) <<
+      indent(out) <<
         "_oprot.writeListEnd(_otrans);" << endl;
     }
     
-    scope_down(f_service_);
+    scope_down(out);
  
-  scope_down(f_service_);  
+  scope_down(out);  
 }
 
 /**
  * Serializes the members of a map.
  *
- */
-void t_java_generator::generate_serialize_map_element(t_map* tmap,
+ */ 
+void t_java_generator::generate_serialize_map_element(ofstream& out,
+                                                      t_map* tmap,
                                                       string iter,
                                                       string map) {
   t_field kfield(tmap->get_key_type(), iter);
-  generate_serialize_field(&kfield, "");
+  generate_serialize_field(out, &kfield, "");
 
   t_field vfield(tmap->get_val_type(), map + ".get(" + iter + ")");
-  generate_serialize_field(&vfield, "");
+  generate_serialize_field(out, &vfield, "");
 }
 
 /**
  * Serializes the members of a set.
  */
-void t_java_generator::generate_serialize_set_element(t_set* tset,
+void t_java_generator::generate_serialize_set_element(ofstream& out,
+                                                      t_set* tset,
                                                       string iter) {
   t_field efield(tset->get_elem_type(), iter);
-  generate_serialize_field(&efield, "");
+  generate_serialize_field(out, &efield, "");
 }
 
 /**
  * Serializes the members of a list.
  */
-void t_java_generator::generate_serialize_list_element(t_list* tlist,
-                                                      string iter) {
+void t_java_generator::generate_serialize_list_element(ofstream& out,
+                                                       t_list* tlist,
+                                                       string iter) {
   t_field efield(tlist->get_elem_type(), iter);
-  generate_serialize_field(&efield, "");
+  generate_serialize_field(out, &efield, "");
 }
 
 /**
@@ -1051,8 +1244,12 @@
     return "void";
   case t_base_type::TYPE_STRING:
     return "String";
+  case t_base_type::TYPE_BOOL:
+    return "boolean";
   case t_base_type::TYPE_BYTE:
     return "byte";
+  case t_base_type::TYPE_I16:
+    return (in_container ? "Short" : "short");
   case t_base_type::TYPE_I32:
     return (in_container ? "Integer" : "int");
   case t_base_type::TYPE_I64:
@@ -1081,9 +1278,14 @@
       case t_base_type::TYPE_VOID:
         throw "NO T_VOID CONSTRUCT";
       case t_base_type::TYPE_STRING:
-        result += " = \"\"";
+        // result += " = \"\"";
+        result += " = null";
+        break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
         break;
       case t_base_type::TYPE_BYTE:
+      case t_base_type::TYPE_I16:
       case t_base_type::TYPE_I32:
       case t_base_type::TYPE_I64:
         result += " = 0";
@@ -1106,11 +1308,19 @@
  * @return String of rendered function definition
  */
 string t_java_generator::function_signature(t_function* tfunction,
-                                           string prefix) {
+                                            string prefix) {
   t_type* ttype = tfunction->get_returntype();
-  return
+  std::string result =
     type_name(ttype) + " " + prefix + tfunction->get_name() +
-    "(" + argument_list(tfunction->get_arglist()) + ")";
+    "(" + argument_list(tfunction->get_arglist()) + ") throws ";
+  t_struct* xs = tfunction->get_xceptions();
+  const std::vector<t_field*>& xceptions = xs->get_members();
+  vector<t_field*>::const_iterator x_iter;
+  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
+    result += (*x_iter)->get_type()->get_name() + ", ";
+  }
+  result += "TException";
+  return result;
 }
 
 /**
@@ -1148,8 +1358,12 @@
       throw "NO T_VOID CONSTRUCT";
     case t_base_type::TYPE_STRING:
       return "TType.STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType.BOOL";
     case t_base_type::TYPE_BYTE:
       return "TType.BYTE";
+    case t_base_type::TYPE_I16:
+      return "TType.I16";
     case t_base_type::TYPE_I32:
       return "TType.I32";
     case t_base_type::TYPE_I64:
@@ -1157,7 +1371,7 @@
     }
   } else if (type->is_enum()) {
     return "TType.I32";
-  } else if (type->is_struct()) {
+  } else if (type->is_struct() || type->is_xception()) {
     return "TType.STRUCT";
   } else if (type->is_map()) {
     return "TType.MAP";
diff --git a/compiler/cpp/src/generate/t_java_generator.h b/compiler/cpp/src/generate/t_java_generator.h
index 0fa9074..2c8e247 100644
--- a/compiler/cpp/src/generate/t_java_generator.h
+++ b/compiler/cpp/src/generate/t_java_generator.h
@@ -31,52 +31,75 @@
   void generate_typedef (t_typedef*  ttypedef);
   void generate_enum    (t_enum*     tenum);
   void generate_struct  (t_struct*   tstruct);
+  void generate_xception(t_struct*   txception);
   void generate_service (t_service*  tservice);
 
   /** Service-level generation functions */
 
+  void generate_java_struct(t_struct* tstruct, bool is_exception);
+
+  void generate_java_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false, bool in_class=false, bool is_result=false);
+  void generate_java_struct_reader(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_result_writer(std::ofstream& out, t_struct* tstruct);
+  void generate_java_struct_writer(std::ofstream& out, t_struct* tstruct);
+
+  void generate_function_helpers(t_function* tfunction);
+
   void generate_service_interface (t_service* tservice);
+  void generate_service_helpers   (t_service* tservice);
   void generate_service_client    (t_service* tservice);
   void generate_service_server    (t_service* tservice);
   void generate_process_function  (t_service* tservice, t_function* tfunction);
 
   /** Serialization constructs */
 
-  void generate_deserialize_field        (t_field*    tfield, 
+  void generate_deserialize_field        (std::ofstream& out,
+                                          t_field*    tfield, 
                                           std::string prefix="");
   
-  void generate_deserialize_struct       (t_struct*   tstruct,
+  void generate_deserialize_struct       (std::ofstream& out,
+                                          t_struct*   tstruct,
                                           std::string prefix="");
   
-  void generate_deserialize_container    (t_type*     ttype,
+  void generate_deserialize_container    (std::ofstream& out,
+                                          t_type*     ttype,
                                           std::string prefix="");
   
-  void generate_deserialize_set_element  (t_set*      tset,
+  void generate_deserialize_set_element  (std::ofstream& out,
+                                          t_set*      tset,
                                           std::string prefix="");
 
-  void generate_deserialize_map_element  (t_map*      tmap,
+  void generate_deserialize_map_element  (std::ofstream& out,
+                                          t_map*      tmap,
                                           std::string prefix="");
 
-  void generate_deserialize_list_element (t_list*     tlist,
+  void generate_deserialize_list_element (std::ofstream& out,
+                                          t_list*     tlist,
                                           std::string prefix="");
 
-  void generate_serialize_field          (t_field*    tfield,
+  void generate_serialize_field          (std::ofstream& out,
+                                          t_field*    tfield,
                                           std::string prefix="");
 
-  void generate_serialize_struct         (t_struct*   tstruct,
+  void generate_serialize_struct         (std::ofstream& out,
+                                          t_struct*   tstruct,
                                           std::string prefix="");
 
-  void generate_serialize_container      (t_type*     ttype,
+  void generate_serialize_container      (std::ofstream& out,
+                                          t_type*     ttype,
                                           std::string prefix="");
 
-  void generate_serialize_map_element    (t_map*      tmap,
+  void generate_serialize_map_element    (std::ofstream& out,
+                                          t_map*      tmap,
                                           std::string iter,
                                           std::string map);
 
-  void generate_serialize_set_element    (t_set*      tmap,
+  void generate_serialize_set_element    (std::ofstream& out,
+                                          t_set*      tmap,
                                           std::string iter);
 
-  void generate_serialize_list_element   (t_list*     tlist,
+  void generate_serialize_list_element   (std::ofstream& out,
+                                          t_list*     tlist,
                                           std::string iter);
 
   /** Helper rendering functions */
@@ -94,14 +117,9 @@
  private:
 
   /** File streams */
+  std::string package_name_;
 
-  std::ofstream f_types_;
-  std::ofstream f_header_;
   std::ofstream f_service_;
-
-  std::ofstream f_client_;
-  std::ofstream f_server_;
-
 };
 
 #endif
diff --git a/compiler/cpp/src/generate/t_php_generator.cc b/compiler/cpp/src/generate/t_php_generator.cc
index efd24c5..6f4b76a 100644
--- a/compiler/cpp/src/generate/t_php_generator.cc
+++ b/compiler/cpp/src/generate/t_php_generator.cc
@@ -687,6 +687,11 @@
             indent() << "}" << endl <<
             indent() << "$" << name << " = " << itrans << "->readAll($_len);" << endl;
           break;
+        case t_base_type::TYPE_BOOL:
+          out <<
+            indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));" << endl <<
+            indent() << "$" << name << " = (bool)$" << name << "[1];" << endl;
+          break;
         case t_base_type::TYPE_BYTE:
           out <<
             indent() << "$" << name << " = unpack('c', " << itrans << "->readAll(1));" << endl <<
@@ -748,6 +753,9 @@
         case t_base_type::TYPE_STRING:        
           out << "readString($itrans, $" << name << ");";
           break;
+        case t_base_type::TYPE_BOOL:
+          out << "readBool($itrans, $" << name << ");";
+          break;
         case t_base_type::TYPE_BYTE:
           out << "readByte($itrans, $" << name << ");";
           break;
@@ -975,6 +983,10 @@
             indent() << "$_output .= pack('N', strlen($" << name << "));" << endl <<
             indent() << "$_output .= $" << name << ";" << endl;
           break;
+        case t_base_type::TYPE_BOOL:
+          out <<
+            indent() << "$_output .= pack('c', $" << name << " ? 1 : 0);" << endl;
+          break;
         case t_base_type::TYPE_BYTE:
           out <<
             indent() << "$_output .= pack('c', $" << name << ");" << endl;
@@ -1013,6 +1025,9 @@
         case t_base_type::TYPE_STRING:
           out << "writeString($otrans, $" << name << ");";
           break;
+        case t_base_type::TYPE_BOOL:
+          out << "writeBool($otrans, $" << name << ");";
+          break;
         case t_base_type::TYPE_BYTE:
           out << "writeByte($otrans, $" << name << ");";
           break;
@@ -1225,6 +1240,8 @@
     return "void";
   case t_base_type::TYPE_STRING:
     return "TString";
+  case t_base_type::TYPE_BOOL:
+    return "bool";
   case t_base_type::TYPE_BYTE:
     return "UInt8";
   case t_base_type::TYPE_I16:
@@ -1258,6 +1275,9 @@
       case t_base_type::TYPE_STRING:
         result += " = ''";
         break;
+      case t_base_type::TYPE_BOOL:
+        result += " = false";
+        break;
       case t_base_type::TYPE_BYTE:
       case t_base_type::TYPE_I16:
       case t_base_type::TYPE_I32:
@@ -1330,6 +1350,8 @@
       throw "NO T_VOID CONSTRUCT";
     case t_base_type::TYPE_STRING:
       return "TType::STRING";
+    case t_base_type::TYPE_BOOL:
+      return "TType::BOOL";
     case t_base_type::TYPE_BYTE:
       return "TType::BYTE";
     case t_base_type::TYPE_I16:
diff --git a/compiler/cpp/src/generate/t_php_generator.h b/compiler/cpp/src/generate/t_php_generator.h
index d5bc8e0..0cc837f 100644
--- a/compiler/cpp/src/generate/t_php_generator.h
+++ b/compiler/cpp/src/generate/t_php_generator.h
@@ -41,7 +41,7 @@
 
 
   void generate_php_struct(t_struct* tstruct, bool is_exception);
-  void generate_php_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception);
+  void generate_php_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false);
   void generate_php_struct_reader(std::ofstream& out, t_struct* tstruct);
   void generate_php_struct_writer(std::ofstream& out, t_struct* tstruct);
 
diff --git a/compiler/cpp/src/parse/t_base_type.h b/compiler/cpp/src/parse/t_base_type.h
index 5aebba7..1429d1c 100644
--- a/compiler/cpp/src/parse/t_base_type.h
+++ b/compiler/cpp/src/parse/t_base_type.h
@@ -14,6 +14,7 @@
   enum t_base {
     TYPE_VOID,
     TYPE_STRING,
+    TYPE_BOOL,
     TYPE_BYTE,
     TYPE_I16,
     TYPE_I32,
diff --git a/compiler/cpp/src/parse/t_program.h b/compiler/cpp/src/parse/t_program.h
index 98968ff..abb368b 100644
--- a/compiler/cpp/src/parse/t_program.h
+++ b/compiler/cpp/src/parse/t_program.h
@@ -32,6 +32,7 @@
     name_(name), namespace_() {
     type_void   = new t_base_type("void",   t_base_type::TYPE_VOID);
     type_string = new t_base_type("string", t_base_type::TYPE_STRING);
+    type_bool   = new t_base_type("bool",   t_base_type::TYPE_BOOL);
     type_byte   = new t_base_type("byte",   t_base_type::TYPE_BYTE);
     type_i16    = new t_base_type("i16",    t_base_type::TYPE_I16);
     type_i32    = new t_base_type("i32",    t_base_type::TYPE_I32);
@@ -40,6 +41,7 @@
 
   ~t_program() {
     delete type_string;
+    delete type_bool;
     delete type_byte;
     delete type_i16;
     delete type_i32;
@@ -62,6 +64,7 @@
   // Accessors for global types
   t_type* get_void_type()   const { return type_void;   }
   t_type* get_string_type() const { return type_string; }
+  t_type* get_bool_type()   const { return type_byte;   }
   t_type* get_byte_type()   const { return type_byte;   }
   t_type* get_i16_type()    const { return type_i16;    }
   t_type* get_i32_type()    const { return type_i32;    }
@@ -122,6 +125,7 @@
   // Global base types
   t_type* type_void;
   t_type* type_string;
+  t_type* type_bool;
   t_type* type_byte;
   t_type* type_i16;
   t_type* type_i32;
diff --git a/compiler/cpp/src/thrift.l b/compiler/cpp/src/thrift.l
index 1f4d7fe..1ff7708 100644
--- a/compiler/cpp/src/thrift.l
+++ b/compiler/cpp/src/thrift.l
@@ -36,6 +36,7 @@
 "namespace"   { return tok_namespace; }
 
 "void"        { return tok_void;     }
+"bool"        { return tok_bool;     }
 "byte"        { return tok_byte;     }
 "i16"         { return tok_i16;      }
 "i32"         { return tok_i32;      }
diff --git a/compiler/cpp/src/thrift.y b/compiler/cpp/src/thrift.y
index 069d6c8..e738180 100644
--- a/compiler/cpp/src/thrift.y
+++ b/compiler/cpp/src/thrift.y
@@ -39,6 +39,7 @@
 %token tok_namespace
 
 /** Base datatypes */
+%token tok_bool
 %token tok_byte
 %token tok_string
 %token tok_i16
@@ -368,6 +369,11 @@
       pdebug("BaseType -> tok_string");
       $$ = g_program->get_string_type();
     }
+| tok_bool
+    {
+      pdebug("BaseType -> tok_bool");
+      $$ = g_program->get_bool_type();
+    }
 | tok_byte
     {
       pdebug("BaseType -> tok_byte");
diff --git a/lib/cpp/src/protocol/TProtocol.h b/lib/cpp/src/protocol/TProtocol.h
index 2b3666f..e9d560c 100644
--- a/lib/cpp/src/protocol/TProtocol.h
+++ b/lib/cpp/src/protocol/TProtocol.h
@@ -200,10 +200,15 @@
    */
   uint32_t skip(shared_ptr<TTransport> in, TType type) const {
     switch (type) {
+    case T_BOOL:
+      {
+        bool boolv;
+        return readBool(in, boolv);
+      }
     case T_BYTE:
       {
-        int8_t byte;
-        return readByte(in, byte);
+        int8_t bytev;
+        return readByte(in, bytev);
       }
     case T_I16:
       {
diff --git a/lib/java/src/protocol/TBinaryProtocol.java b/lib/java/src/protocol/TBinaryProtocol.java
index a759005..d90dece 100644
--- a/lib/java/src/protocol/TBinaryProtocol.java
+++ b/lib/java/src/protocol/TBinaryProtocol.java
@@ -9,13 +9,23 @@
  * @author Mark Slee <mcslee@facebook.com>
  */
 public class TBinaryProtocol implements TProtocol {
+
+  public void writeMessageBegin(TTransport out, TMessage message) throws TException {
+    writeString(out, message.name);
+    writeByte(out, message.type);
+    writeI32(out, message.seqid);
+  }
+
+  public void writeMessageEnd(TTransport out) throws TException {}
+
+
   public void writeStructBegin(TTransport out, TStruct struct) throws TException {}
 
   public void writeStructEnd(TTransport out) throws TException {}
 
   public void writeFieldBegin(TTransport out, TField field) throws TException {
     writeByte(out, field.type);
-    writeI32(out, field.id);
+    writeI16(out, field.id);
   }
 
   public void writeFieldEnd(TTransport out) throws TException {}
@@ -46,14 +56,21 @@
 
   public void writeSetEnd(TTransport out) throws TException {}
 
+  public void writeBool(TTransport out, boolean b) throws TException {
+    writeByte(out, b ? (byte)1 : (byte)0);
+  }
+
   byte[] bout = new byte[1];
   public void writeByte(TTransport out, byte b) throws TException {
     bout[0] = b;
     out.write(bout, 0, 1);
   }
 
-  public void writeU32(TTransport out, int u32) throws TException {
-    writeI32(out, u32);
+  byte[] i16out = new byte[2];
+  public void writeI16(TTransport out, short i16) throws TException {
+    i16out[0] = (byte)(0xff & (i16 >> 8));
+    i16out[1] = (byte)(0xff & (i16));
+    out.write(i16out, 0, 2);
   }
 
   byte[] i32out = new byte[4];
@@ -65,10 +82,6 @@
     out.write(i32out, 0, 4);
   }
 
-  public void writeU64(TTransport out, long u64) throws TException {
-    writeI64(out, u64);
-  }
-
   byte[] i64out = new byte[8];
   public void writeI64(TTransport out, long i64) throws TException {
     i64out[0] = (byte)(0xff & (i64 >> 56));
@@ -92,6 +105,16 @@
    * Reading methods.
    */
 
+  public TMessage readMessageBegin(TTransport in) throws TException {
+    TMessage message = new TMessage();
+    message.name = readString(in);
+    message.type = readByte(in);
+    message.seqid = readI32(in);
+    return message;
+  }
+
+  public void readMessageEnd(TTransport in) throws TException {}
+
   public TStruct readStructBegin(TTransport in) throws TException {
     return new TStruct();
   }
@@ -102,7 +125,7 @@
     TField field = new TField();
     field.type = readByte(in);
     if (field.type != TType.STOP) {
-      field.id = readI32(in);
+      field.id = readI16(in);
     }
     return field;
   }
@@ -137,14 +160,23 @@
 
   public void readSetEnd(TTransport in) throws TException {}
 
+  public boolean readBool(TTransport in) throws TException {
+    return (readByte(in) == 1);
+  }
+
   byte[] bin = new byte[1];
   public byte readByte(TTransport in) throws TException {
     in.readAll(bin, 0, 1);
     return bin[0];
   }
 
-  public int readU32(TTransport in) throws TException {
-    return readI32(in);
+  byte[] i16rd = new byte[2];
+  public short readI16(TTransport in) throws TException {
+    in.readAll(i16rd, 0, 2);
+    return
+      (short)
+      (((i16rd[0] & 0xff) << 8) |
+       ((i16rd[1] & 0xff)));
   }
 
   byte[] i32rd = new byte[4];
@@ -156,11 +188,7 @@
       ((i32rd[2] & 0xff) <<  8) |
       ((i32rd[3] & 0xff));
   }
-
-  public long readU64(TTransport in) throws TException {
-    return readI64(in);
-  }
-  
+ 
   byte[] i64rd = new byte[8];
   public long readI64(TTransport in) throws TException {
     in.readAll(i64rd, 0, 8);
diff --git a/lib/java/src/protocol/TField.java b/lib/java/src/protocol/TField.java
index 50570fb..d32d708 100644
--- a/lib/java/src/protocol/TField.java
+++ b/lib/java/src/protocol/TField.java
@@ -8,7 +8,7 @@
 public class TField {
   public TField() {}
 
-  public TField(String n, byte t, int i) {
+  public TField(String n, byte t, short i) {
     name = n;
     type = t;
     id = i;
@@ -16,5 +16,5 @@
 
   public String name = "";
   public byte   type = TType.STOP;
-  public int    id   = 0;
+  public short  id   = 0;
 }
diff --git a/lib/java/src/protocol/TMessage.java b/lib/java/src/protocol/TMessage.java
new file mode 100644
index 0000000..92f4f8b
--- /dev/null
+++ b/lib/java/src/protocol/TMessage.java
@@ -0,0 +1,20 @@
+package com.facebook.thrift.protocol;
+
+/**
+ * Helper class that encapsulates struct metadata.
+ *
+ * @author Mark Slee <mcslee@facebook.com>
+ */
+public class TMessage {
+  public TMessage() {}
+
+  public TMessage(String n, byte t, int s) {
+    name = n;
+    type = t;
+    seqid = s;
+  }
+
+  public String name = "";
+  public byte type;
+  public int seqid;
+}
diff --git a/lib/java/src/protocol/TMessageType.java b/lib/java/src/protocol/TMessageType.java
new file mode 100644
index 0000000..905f99a
--- /dev/null
+++ b/lib/java/src/protocol/TMessageType.java
@@ -0,0 +1,11 @@
+package com.facebook.thrift.protocol;
+
+/**
+ * Message type constants in the Thrift protocol.
+ *
+ * @author Mark Slee <mcslee@facebook.com>
+ */
+public final class TMessageType {
+  public static final byte CALL  = 1;
+  public static final byte REPLY = 2;
+}
diff --git a/lib/java/src/protocol/TProtocol.java b/lib/java/src/protocol/TProtocol.java
index a60becb..69fe885 100644
--- a/lib/java/src/protocol/TProtocol.java
+++ b/lib/java/src/protocol/TProtocol.java
@@ -14,6 +14,11 @@
    * Writing methods.
    */
 
+  public void writeMessageBegin(TTransport out,
+                                TMessage   message) throws TException;
+
+  public void writeMessageEnd  (TTransport out)     throws TException;
+  
   public void writeStructBegin (TTransport out,
                                 TStruct    struct)  throws TException;
 
@@ -41,18 +46,18 @@
 
   public void writeSetEnd      (TTransport out)     throws TException;
 
+  public void writeBool        (TTransport out,
+                                boolean    b)       throws TException;
+
   public void writeByte        (TTransport out,
                                 byte       b)       throws TException;
 
-  public void writeU32         (TTransport out,
-                                int        u32)     throws TException;
+  public void writeI16         (TTransport out,
+                                short      i16)     throws TException;
 
   public void writeI32         (TTransport out,
                                 int        i32)     throws TException;
 
-  public void writeU64         (TTransport out,
-                                long       u64)     throws TException;
-
   public void writeI64         (TTransport out,
                                 long       i64)     throws TException;
 
@@ -63,36 +68,40 @@
    * Reading methods.
    */
 
-  public TStruct readStructBegin  (TTransport in)  throws TException;
+  public TMessage readMessageBegin (TTransport in)  throws TException;
 
-  public void    readStructEnd    (TTransport in)  throws TException;
+  public void     readMessageEnd   (TTransport in)  throws TException;
 
-  public TField  readFieldBegin   (TTransport in)  throws TException;
+  public TStruct  readStructBegin  (TTransport in)  throws TException;
+
+  public void     readStructEnd    (TTransport in)  throws TException;
+
+  public TField   readFieldBegin   (TTransport in)  throws TException;
   
-  public void    readFieldEnd     (TTransport in)  throws TException;
+  public void     readFieldEnd     (TTransport in)  throws TException;
  
-  public TMap    readMapBegin     (TTransport in)  throws TException;
+  public TMap     readMapBegin     (TTransport in)  throws TException;
 
-  public void    readMapEnd       (TTransport in)  throws TException;
+  public void     readMapEnd       (TTransport in)  throws TException;
 
-  public TList   readListBegin    (TTransport in)  throws TException;
+  public TList    readListBegin    (TTransport in)  throws TException;
 
-  public void    readListEnd      (TTransport in)  throws TException;
+  public void     readListEnd      (TTransport in)  throws TException;
 
-  public TSet    readSetBegin     (TTransport in)  throws TException;
+  public TSet     readSetBegin     (TTransport in)  throws TException;
 
-  public void    readSetEnd       (TTransport in)  throws TException;
+  public void     readSetEnd       (TTransport in)  throws TException;
 
-  public byte    readByte         (TTransport in)  throws TException;
+  public boolean  readBool         (TTransport in)  throws TException;
 
-  public int     readU32          (TTransport in)  throws TException;
+  public byte     readByte         (TTransport in)  throws TException;
 
-  public int     readI32          (TTransport in)  throws TException;
+  public short    readI16          (TTransport in)  throws TException;
 
-  public long    readU64          (TTransport in)  throws TException;
-  
-  public long    readI64          (TTransport in)  throws TException;
+  public int      readI32          (TTransport in)  throws TException;
+ 
+  public long     readI64          (TTransport in)  throws TException;
 
-  public String  readString       (TTransport in)  throws TException;
+  public String   readString       (TTransport in)  throws TException;
 
 }
diff --git a/lib/java/src/protocol/TProtocolUtil.java b/lib/java/src/protocol/TProtocolUtil.java
index b8e5afe..5223639 100644
--- a/lib/java/src/protocol/TProtocolUtil.java
+++ b/lib/java/src/protocol/TProtocolUtil.java
@@ -14,16 +14,22 @@
     throws TException {
 
     switch (type) {
+    case TType.BOOL:
+      {
+        prot.readBool(in);
+      }
     case TType.BYTE:
       {
         prot.readByte(in);
       }
-    case TType.U32:
+    case TType.I16:
+      {
+        prot.readI16(in);
+      }
     case TType.I32:
       {
         prot.readI32(in);
       }
-    case TType.U64:
     case TType.I64:
       {
         prot.readI64(in);
diff --git a/lib/java/src/protocol/TString.java b/lib/java/src/protocol/TString.java
deleted file mode 100644
index 04fcc1d..0000000
--- a/lib/java/src/protocol/TString.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package com.facebook.thrift.protocol;
-
-/**
- * Wrapper around String so that you can pass this object to a function and
- * have it set the internal string value.
- *
- * @author Mark Slee <mcslee@facebook.com>
- */
-public class TString {
-  public TString() {}
-
-  public TString(String v) {
-    value = v;
-  }
-
-  public String value = "";
-}
diff --git a/lib/java/src/protocol/TType.java b/lib/java/src/protocol/TType.java
index 96f06d3..37b53bd 100644
--- a/lib/java/src/protocol/TType.java
+++ b/lib/java/src/protocol/TType.java
@@ -6,17 +6,16 @@
  * @author Mark Slee <mcslee@facebook.com>
  */
 public final class TType {
-  public static final byte STOP   = 1;
-  public static final byte BYTE   = 2;
-  public static final byte U16    = 3;
-  public static final byte I16    = 4;
-  public static final byte U32    = 5;
-  public static final byte I32    = 6;
-  public static final byte U64    = 7;
-  public static final byte I64    = 8;
-  public static final byte STRING = 9;
-  public static final byte STRUCT = 10;
-  public static final byte MAP    = 11;
-  public static final byte SET    = 12;
-  public static final byte LIST   = 13;
+  public static final byte STOP   = 0;
+  public static final byte VOID   = 1;
+  public static final byte BOOL   = 2;
+  public static final byte BYTE   = 3;
+  public static final byte I16    = 6;
+  public static final byte I32    = 8;
+  public static final byte I64    = 10;
+  public static final byte STRING = 11;
+  public static final byte STRUCT = 12;
+  public static final byte MAP    = 13;
+  public static final byte SET    = 14;
+  public static final byte LIST   = 15;
 }
diff --git a/lib/php/src/protocol/TProtocol.php b/lib/php/src/protocol/TProtocol.php
index 15938df..d703bd7 100644
--- a/lib/php/src/protocol/TProtocol.php
+++ b/lib/php/src/protocol/TProtocol.php
@@ -79,6 +79,8 @@
 
   public abstract function writeSetEnd($out);
   
+  public abstract function writeBool($out, $bool);
+
   public abstract function writeByte($out, $byte);
   
   public abstract function writeI16($out, $i16);
@@ -127,6 +129,8 @@
   
   public abstract function readSetEnd($in);
 
+  public abstract function readBool($in, &$bool);
+  
   public abstract function readByte($in, &$byte);
   
   public abstract function readI16($in, &$i16);
@@ -146,6 +150,8 @@
    */
   public function skip($in, $type) {
     switch ($type) {
+    case TType::BOOL:
+      return $this->readBool($in, $bool);
     case TType::BYTE:
       return $this->readByte($in, $byte);
     case TType::I16;
diff --git a/lib/php/src/protocol/TType.php b/lib/php/src/protocol/TType.php
index 22c1c3d..6ef0935 100644
--- a/lib/php/src/protocol/TType.php
+++ b/lib/php/src/protocol/TType.php
@@ -11,22 +11,22 @@
  * Data types that can be sent via Thrift
  */
 class TType {
-  const STOP = 0;
-  const VOID = 1;
-  const BOOL = 2;
-  const BYTE = 3;
-  const I08 = 4;
-  const I16 = 6;
-  const I32 = 8;
-  const I64 = 10;
+  const STOP   = 0;
+  const VOID   = 1;
+  const BOOL   = 2;
+  const BYTE   = 3;
+  const I08    = 4;
+  const I16    = 6;
+  const I32    = 8;
+  const I64    = 10;
   const STRING = 11;
-  const UTF7 = 11;
+  const UTF7   = 11;
   const STRUCT = 12;
-  const MAP = 13;
-  const SET = 14;
-  const LST = 15;    // N.B. cannot use LIST keyword in PHP!
-  const UTF8 = 16;
-  const UTF16 = 17;
+  const MAP    = 13;
+  const SET    = 14;
+  const LST    = 15;    // N.B. cannot use LIST keyword in PHP!
+  const UTF8   = 16;
+  const UTF16  = 17;
 }
 
 /**
@@ -34,7 +34,7 @@
  */
 class TMessageType {
   const CALL  = 1;
-  const REPLY  = 2;
+  const REPLY = 2;
 }
 
 ?>
diff --git a/test/cpp/src/TestServer.cc b/test/cpp/src/TestServer.cc
index baf2ae5..2f2d97d 100644
--- a/test/cpp/src/TestServer.cc
+++ b/test/cpp/src/TestServer.cc
@@ -19,10 +19,10 @@
 
 using namespace thrift::test;
 
-class TestServer : public ThriftTestServerIf {
+class TestServer : public ThriftTestServer {
  public:
   TestServer(shared_ptr<TProtocol> protocol) :
-    ThriftTestServerIf(protocol) {}
+    ThriftTestServer(protocol) {}
 
   void testVoid() {
     printf("testVoid()\n");
diff --git a/test/java/build.xml b/test/java/build.xml
index 80a73d7..d7d712a 100644
--- a/test/java/build.xml
+++ b/test/java/build.xml
@@ -14,7 +14,7 @@
 
   <target name="generate">
     <exec executable="thrift">
-      <arg line="-java ../ThriftTest.thrift" />
+      <arg line="--java ../ThriftTest.thrift" />
     </exec>
   </target>
 
@@ -23,6 +23,11 @@
     <javac srcdir="${src}" destdir="${build}" classpath="${cpath}:${gen}" />
   </target>
 
+  <target name="compileonly">
+    <javac srcdir="${gen}" destdir="${build}" classpath="${cpath}" />
+    <javac srcdir="${src}" destdir="${build}" classpath="${cpath}:${gen}" />
+  </target>
+
   <target name="test" depends="compile">
     <jar jarfile="thrifttest.jar" basedir="${build}"/>
   </target>
diff --git a/test/java/src/TestClient.java b/test/java/src/TestClient.java
index cbcd802..686920c 100644
--- a/test/java/src/TestClient.java
+++ b/test/java/src/TestClient.java
@@ -1,11 +1,11 @@
 package com.facebook.thrift.test;
 
-import ThriftTest.*;
-import com.facebook.thrift.types.*;
+// Generated code
+import thrift.test.*;
+
 import com.facebook.thrift.transport.TSocket;
 import com.facebook.thrift.transport.TTransportException;
 import com.facebook.thrift.protocol.TBinaryProtocol;
-import com.facebook.thrift.protocol.TString;
 
 import java.util.HashMap;
 import java.util.HashSet;
@@ -39,8 +39,8 @@
         new TSocket(host, port);
       TBinaryProtocol binaryProtocol =
         new TBinaryProtocol();
-      ThriftTestClient testClient =
-        new ThriftTestClient(tSocket, binaryProtocol);
+      ThriftTest.Client testClient =
+        new ThriftTest.Client(tSocket, binaryProtocol);
 
       for (int test = 0; test < numTests; ++test) {
 
@@ -69,154 +69,154 @@
          * STRING TEST
          */
         System.out.print("testString(\"Test\")");
-        TString s = testClient.testString(new TString("Test"));
-        System.out.print(" = \"" + s.value + "\"\n");
-   
+        String s = testClient.testString("Test");
+        System.out.print(" = \"" + s + "\"\n");
+
         /**
          * BYTE TEST
          */
         System.out.print("testByte(1)");
-        UInt8 u8 = testClient.testByte(new UInt8((short)1));
-        System.out.print(" = " + u8.get() + "\n");
+        byte i8 = testClient.testByte((byte)1);
+        System.out.print(" = " + i8 + "\n");
   
         /**
          * I32 TEST
          */
         System.out.print("testI32(-1)");
-        Int32 i32 = testClient.testI32(new Int32(-1));
-        System.out.print(" = " + i32.get() + "\n");
+        int i32 = testClient.testI32(-1);
+        System.out.print(" = " + i32 + "\n");
 
         /**
          * I64 TEST
          */
         System.out.print("testI64(-34359738368)");
-        Int64 i64 = testClient.testI64(new Int64(-34359738368L));
-        System.out.print(" = " + i64.get() + "\n");
+        long i64 = testClient.testI64(-34359738368L);
+        System.out.print(" = " + i64 + "\n");
 
         /**
          * STRUCT TEST
          */
         System.out.print("testStruct({\"Zero\", 1, -3, -5})");
         Xtruct out = new Xtruct();
-        out.string_thing.value = "Zero";
-        out.byte_thing.set((short)1);
-        out.i32_thing.set(-3);
-        out.i64_thing.set(-5);
+        out.string_thing = "Zero";
+        out.byte_thing = (byte) 1;
+        out.i32_thing = -3;
+        out.i64_thing = -5;
         Xtruct in = testClient.testStruct(out);
         System.out.print(" = {" +
-                         "\"" + in.string_thing.value + "\", " +
-                         in.byte_thing.get() + ", " +
-                         in.i32_thing.get() + ", " +
-                         in.i64_thing.get() + "}\n");
+                         "\"" + in.string_thing + "\", " +
+                         in.byte_thing + ", " +
+                         in.i32_thing + ", " +
+                         in.i64_thing + "}\n");
 
         /**
          * NESTED STRUCT TEST
          */
         System.out.print("testNest({1, {\"Zero\", 1, -3, -5}), 5}");
         Xtruct2 out2 = new Xtruct2();
-        out2.byte_thing.set((short)1);
+        out2.byte_thing = (short)1;
         out2.struct_thing = out;
-        out2.i32_thing.set(5);
+        out2.i32_thing = 5;
         Xtruct2 in2 = testClient.testNest(out2);
         in = in2.struct_thing;
         System.out.print(" = {" +
-                         in2.byte_thing.get() + ", {" +
-                         "\"" + in.string_thing.value + "\", " +
-                         in.byte_thing.get() + ", " +
-                         in.i32_thing.get() + ", " +
-                         in.i64_thing.get() + "}, " +
-                         in2.i32_thing.get() + "}\n");
+                         in2.byte_thing + ", {" +
+                         "\"" + in.string_thing + "\", " +
+                         in.byte_thing + ", " +
+                         in.i32_thing + ", " +
+                         in.i64_thing + "}, " +
+                         in2.i32_thing + "}\n");
 
         /**
          * MAP TEST
          */
-        HashMap<Int32,Int32> mapout = new HashMap<Int32,Int32>();
+        HashMap<Integer,Integer> mapout = new HashMap<Integer,Integer>();
         for (int i = 0; i < 5; ++i) {
-          mapout.put(new Int32(i), new Int32(i-10));
+          mapout.put(i, i-10);
         }
         System.out.print("testMap({");
         boolean first = true;
-        for (Int32 key : mapout.keySet()) {
+        for (int key : mapout.keySet()) {
           if (first) {
             first = false;
           } else {
             System.out.print(", ");
           }
-          System.out.print(key.get() + " => " + mapout.get(key).get());
+          System.out.print(key + " => " + mapout.get(key));
         }
         System.out.print("})");
-        HashMap<Int32,Int32> mapin = testClient.testMap(mapout);
+        HashMap<Integer,Integer> mapin = testClient.testMap(mapout);
         System.out.print(" = {");
         first = true;
-        for (Int32 key : mapin.keySet()) {
+        for (int key : mapin.keySet()) {
           if (first) {
             first = false;
           } else {
             System.out.print(", ");
           }
-          System.out.print(key.get() + " => " + mapout.get(key).get());
+          System.out.print(key + " => " + mapout.get(key));
         }
         System.out.print("}\n");
 
         /**
          * SET TEST
          */
-        HashSet<Int32> setout = new HashSet<Int32>();
+        HashSet<Integer> setout = new HashSet<Integer>();
         for (int i = -2; i < 3; ++i) {
-          setout.add(new Int32(i));
+          setout.add(i);
         }
         System.out.print("testSet({");
         first = true;
-        for (Int32 elem : setout) {
+        for (int elem : setout) {
           if (first) {
             first = false;
           } else {
             System.out.print(", ");
           }
-          System.out.print(elem.get());
+          System.out.print(elem);
         }
         System.out.print("})");
-        HashSet<Int32> setin = testClient.testSet(setout);
+        HashSet<Integer> setin = testClient.testSet(setout);
         System.out.print(" = {");
         first = true;
-        for (Int32 elem : setin) {
+        for (int elem : setin) {
           if (first) {
             first = false;
           } else {
             System.out.print(", ");
           }
-          System.out.print(elem.get());
+          System.out.print(elem);
         }
         System.out.print("}\n");
 
         /**
          * LIST TEST
          */
-        ArrayList<Int32> listout = new ArrayList<Int32>();
+        ArrayList<Integer> listout = new ArrayList<Integer>();
         for (int i = -2; i < 3; ++i) {
-          listout.add(new Int32(i));
+          listout.add(i);
         }
         System.out.print("testList({");
         first = true;
-        for (Int32 elem : listout) {
+        for (int elem : listout) {
           if (first) {
             first = false;
           } else {
             System.out.print(", ");
           }
-          System.out.print(elem.get());
+          System.out.print(elem);
         }
         System.out.print("})");
-        ArrayList<Int32> listin = testClient.testList(listout);
+        ArrayList<Integer> listin = testClient.testList(listout);
         System.out.print(" = {");
         first = true;
-        for (Int32 elem : listin) {
+        for (int elem : listin) {
           if (first) {
             first = false;
           } else {
             System.out.print(", ");
           }
-          System.out.print(elem.get());
+          System.out.print(elem);
         }
         System.out.print("}\n");
 
@@ -224,44 +224,44 @@
          * ENUM TEST
          */
         System.out.print("testEnum(ONE)");
-        Int32 ret = testClient.testEnum(Numberz.ONE);
-        System.out.print(" = " + ret.get() + "\n");
+        int ret = testClient.testEnum(Numberz.ONE);
+        System.out.print(" = " + ret + "\n");
 
         System.out.print("testEnum(TWO)");
         ret = testClient.testEnum(Numberz.TWO);
-        System.out.print(" = " + ret.get() + "\n");
+        System.out.print(" = " + ret + "\n");
 
         System.out.print("testEnum(THREE)");
         ret = testClient.testEnum(Numberz.THREE);
-        System.out.print(" = " + ret.get() + "\n");
+        System.out.print(" = " + ret + "\n");
 
         System.out.print("testEnum(FIVE)");
         ret = testClient.testEnum(Numberz.FIVE);
-        System.out.print(" = " + ret.get() + "\n");
+        System.out.print(" = " + ret + "\n");
 
         System.out.print("testEnum(EIGHT)");
         ret = testClient.testEnum(Numberz.EIGHT);
-        System.out.print(" = " + ret.get() + "\n");
+        System.out.print(" = " + ret + "\n");
 
         /**
          * TYPEDEF TEST
          */
         System.out.print("testTypedef(309858235082523)");
-        Int64 uid = testClient.testTypedef(new Int64(309858235082523L));
-        System.out.print(" = " + uid.get() + "\n");
+        long uid = testClient.testTypedef(309858235082523L);
+        System.out.print(" = " + uid + "\n");
 
         /**
          * NESTED MAP TEST
          */
         System.out.print("testMapMap(1)");
-        HashMap<Int32,HashMap<Int32,Int32>> mm =
-          testClient.testMapMap(new Int32(1));
+        HashMap<Integer,HashMap<Integer,Integer>> mm =
+          testClient.testMapMap(1);
         System.out.print(" = {");
-        for (Int32 key : mm.keySet()) {
-          System.out.print(key.get() + " => {");
-          HashMap<Int32,Int32> m2 = mm.get(key);
-          for (Int32 k2 : m2.keySet()) {
-            System.out.print(k2.get() + " => " + m2.get(k2).get() + ", ");
+        for (int key : mm.keySet()) {
+          System.out.print(key + " => {");
+          HashMap<Integer,Integer> m2 = mm.get(key);
+          for (int k2 : m2.keySet()) {
+            System.out.print(k2 + " => " + m2.get(k2) + ", ");
           }
           System.out.print("}, ");
         }
@@ -271,29 +271,29 @@
          * INSANITY TEST
          */
         Insanity insane = new Insanity();
-        insane.userMap.put(Numberz.FIVE, new Int64(5000));
+        insane.userMap.put(Numberz.FIVE, (long)5000);
         Xtruct truck = new Xtruct();
-        truck.string_thing.value = "Truck";
-        truck.byte_thing.set((short)8);
-        truck.i32_thing.set(8);
-        truck.i64_thing.set(8);
+        truck.string_thing = "Truck";
+        truck.byte_thing = (byte)8;
+        truck.i32_thing = 8;
+        truck.i64_thing = 8;
         insane.xtructs.add(truck);
         System.out.print("testInsanity()");
-        HashMap<Int64,HashMap<Int32,Insanity>> whoa =
+        HashMap<Long,HashMap<Integer,Insanity>> whoa =
           testClient.testInsanity(insane);
         System.out.print(" = {");
-        for (Int64 key : whoa.keySet()) {
-          HashMap<Int32,Insanity> val = whoa.get(key);
-          System.out.print(key.get() + " => {");
+        for (long key : whoa.keySet()) {
+          HashMap<Integer,Insanity> val = whoa.get(key);
+          System.out.print(key + " => {");
 
-          for (Int32 k2 : val.keySet()) {
+          for (int k2 : val.keySet()) {
             Insanity v2 = val.get(k2);
-            System.out.print(k2.get() + " => {");
-            HashMap<Int32, Int64> userMap = v2.userMap;
+            System.out.print(k2 + " => {");
+            HashMap<Integer, Long> userMap = v2.userMap;
             System.out.print("{");
-            for (Int32 k3 : userMap.keySet()) {
-              System.out.print(k3.get() + " => " +
-                               userMap.get(k3).get() + ", ");
+            for (int k3 : userMap.keySet()) {
+              System.out.print(k3 + " => " +
+                               userMap.get(k3) + ", ");
             }
             System.out.print("}, ");
 
@@ -301,10 +301,10 @@
             System.out.print("{");
             for (Xtruct x : xtructs) {
               System.out.print("{" +
-                               "\"" + x.string_thing.value + "\", " +
-                               x.byte_thing.get() + ", " +
-                               x.i32_thing.get() + ", "+
-                               x.i64_thing.get() + "}, ");
+                               "\"" + x.string_thing + "\", " +
+                               x.byte_thing + ", " +
+                               x.i32_thing + ", "+
+                               x.i64_thing + "}, ");
             }
             System.out.print("}");
 
diff --git a/test/java/src/TestServer.java b/test/java/src/TestServer.java
index 0acc8a2..4e415ae 100644
--- a/test/java/src/TestServer.java
+++ b/test/java/src/TestServer.java
@@ -1,22 +1,22 @@
 package com.facebook.thrift.test;
 
-import com.facebook.thrift.types.*;
+import com.facebook.thrift.TException;
 import com.facebook.thrift.protocol.TBinaryProtocol;
 import com.facebook.thrift.protocol.TProtocol;
-import com.facebook.thrift.protocol.TString;
 import com.facebook.thrift.server.TServer;
 import com.facebook.thrift.server.TSimpleServer;
 import com.facebook.thrift.transport.TServerSocket;
 import com.facebook.thrift.transport.TServerTransport;
 
-import ThriftTest.*;
+// Generated code
+import thrift.test.*;
 
 import java.net.ServerSocket;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 
-public class TestServer extends ThriftTestServerIf {
+public class TestServer extends ThriftTest.Server {
   public TestServer(TProtocol prot) {
     super(prot);
   }
@@ -25,159 +25,199 @@
     System.out.print("testVoid()\n");
   }
 
-  public TString testString(TString thing) {
-    System.out.print("testString(\"" + thing.value + "\")\n");
+  public String testString(String thing) {
+    System.out.print("testString(\"" + thing + "\")\n");
     return thing;
   }
 
-  public UInt8 testByte(UInt8 thing) {
-    System.out.print("testByte(" + thing.get() + ")\n");
+  public byte testByte(byte thing) {
+    System.out.print("testByte(" + thing + ")\n");
     return thing;
   }
 
-  public Int32 testI32(Int32 thing) {
-    System.out.print("testI32(" + thing.get() + ")\n");
+  public int testI32(int thing) {
+    System.out.print("testI32(" + thing + ")\n");
     return thing;
   }
 
-  public Int64 testI64(Int64 thing) {
-    System.out.print("testI64(" + thing.get() + ")\n");
+  public long testI64(long thing) {
+    System.out.print("testI64(" + thing + ")\n");
     return thing;
   }
   
   public Xtruct testStruct(Xtruct thing) {
     System.out.print("testStruct({" +
-                     "\"" + thing.string_thing.value + "\", " +
-                     thing.byte_thing.get() + ", " +
-                     thing.i32_thing.get() + ", " +
-                     thing.i64_thing.get() + "})\n");
+                     "\"" + thing.string_thing + "\", " +
+                     thing.byte_thing + ", " +
+                     thing.i32_thing + ", " +
+                     thing.i64_thing + "})\n");
     return thing;
   }
   
   public Xtruct2 testNest(Xtruct2 nest) {
     Xtruct thing = nest.struct_thing;
     System.out.print("testNest({" +
-                     nest.byte_thing.get() + ", {" +
-                     "\"" + thing.string_thing.value + "\", " +
-                     thing.byte_thing.get() + ", " +
-                     thing.i32_thing.get() + ", " +
-                     thing.i64_thing.get() + "}, " +
-                     nest.i32_thing.get() + "})\n");
+                     nest.byte_thing + ", {" +
+                     "\"" + thing.string_thing + "\", " +
+                     thing.byte_thing + ", " +
+                     thing.i32_thing + ", " +
+                     thing.i64_thing + "}, " +
+                     nest.i32_thing + "})\n");
     return nest;
   }
   
-  public HashMap<Int32,Int32> testMap(HashMap<Int32,Int32> thing) {
+  public HashMap<Integer,Integer> testMap(HashMap<Integer,Integer> thing) {
     System.out.print("testMap({");
     boolean first = true;
-    for (Int32 key : thing.keySet()) {
+    for (int key : thing.keySet()) {
       if (first) {
         first = false;
       } else {
         System.out.print(", ");
       }
-      System.out.print(key.get() + " => " + thing.get(key).get());
+      System.out.print(key + " => " + thing.get(key));
     }
     System.out.print("})\n");
     return thing;
   }
 
-  public HashSet<Int32> testSet(HashSet<Int32> thing) {
+  public HashSet<Integer> testSet(HashSet<Integer> thing) {
     System.out.print("testSet({");
     boolean first = true;
-    for (Int32 elem : thing) {
+    for (int elem : thing) {
       if (first) {
         first = false;
       } else {
         System.out.print(", ");
       }
-      System.out.print(elem.get());
+      System.out.print(elem);
     }
     System.out.print("})\n");
     return thing;
   }
 
-  public ArrayList<Int32> testList(ArrayList<Int32> thing) {
+  public ArrayList<Integer> testList(ArrayList<Integer> thing) {
     System.out.print("testList({");
     boolean first = true;
-    for (Int32 elem : thing) {
+    for (int elem : thing) {
       if (first) {
         first = false;
       } else {
         System.out.print(", ");
       }
-      System.out.print(elem.get());
+      System.out.print(elem);
     }
     System.out.print("})\n");
     return thing;
   }
 
-  public Int32 testEnum(Int32 thing) {
-    System.out.print("testEnum(" + thing.get() + ")\n");
+  public int testEnum(int thing) {
+    System.out.print("testEnum(" + thing + ")\n");
     return thing;
   }
 
-  public Int64 testTypedef(Int64 thing) {
-    System.out.print("testTypedef(" + thing.get() + ")\n");
+  public long testTypedef(long thing) {
+    System.out.print("testTypedef(" + thing + ")\n");
     return thing;
   }
 
-  public HashMap<Int32,HashMap<Int32,Int32>> testMapMap(Int32 hello) {
-    System.out.print("testMapMap(" + hello.get() + ")\n");
-    HashMap<Int32,HashMap<Int32,Int32>> mapmap =
-      new HashMap<Int32,HashMap<Int32,Int32>>();
+  public HashMap<Integer,HashMap<Integer,Integer>> testMapMap(int hello) {
+    System.out.print("testMapMap(" + hello + ")\n");
+    HashMap<Integer,HashMap<Integer,Integer>> mapmap =
+      new HashMap<Integer,HashMap<Integer,Integer>>();
 
-    HashMap<Int32,Int32> pos = new HashMap<Int32,Int32>();
-    HashMap<Int32,Int32> neg = new HashMap<Int32,Int32>();
+    HashMap<Integer,Integer> pos = new HashMap<Integer,Integer>();
+    HashMap<Integer,Integer> neg = new HashMap<Integer,Integer>();
     for (int i = 1; i < 5; i++) {
-      pos.put(new Int32(i), new Int32(i));
-      neg.put(new Int32(-i), new Int32(-i));
+      pos.put(i, i);
+      neg.put(-i, -i);
     }
 
-    mapmap.put(new Int32(4), pos);
-    mapmap.put(new Int32(-4), neg);
+    mapmap.put(4, pos);
+    mapmap.put(-4, neg);
 
     return mapmap;
   }
 
-  public HashMap<Int64, HashMap<Int32,Insanity>> testInsanity(Insanity argument) {
+  public HashMap<Long, HashMap<Integer,Insanity>> testInsanity(Insanity argument) {
     System.out.print("testInsanity()\n");
     
     Xtruct hello = new Xtruct();
-    hello.string_thing.value = "Hello2";
-    hello.byte_thing.set((short)2);
-    hello.i32_thing.set(2);
-    hello.i64_thing.set(2);
+    hello.string_thing = "Hello2";
+    hello.byte_thing = 2;
+    hello.i32_thing = 2;
+    hello.i64_thing = 2;
 
     Xtruct goodbye = new Xtruct();
-    goodbye.string_thing.value = "Goodbye4";
-    goodbye.byte_thing.set((short)4);
-    goodbye.i32_thing.set(4);
-    goodbye.i64_thing.set(4);
+    goodbye.string_thing = "Goodbye4";
+    goodbye.byte_thing = (byte)4;
+    goodbye.i32_thing = 4;
+    goodbye.i64_thing = (long)4;
 
     Insanity crazy = new Insanity();
-    crazy.userMap.put(Numberz.EIGHT, new Int64(8));
+    crazy.userMap.put(Numberz.EIGHT, (long)8);
     crazy.xtructs.add(goodbye);
 
     Insanity looney = new Insanity();
-    crazy.userMap.put(Numberz.FIVE, new Int64(5));
+    crazy.userMap.put(Numberz.FIVE, (long)5);
     crazy.xtructs.add(hello);
 
-    HashMap<Int32,Insanity> first_map = new HashMap<Int32, Insanity>();
-    HashMap<Int32,Insanity> second_map = new HashMap<Int32, Insanity>();;
+    HashMap<Integer,Insanity> first_map = new HashMap<Integer, Insanity>();
+    HashMap<Integer,Insanity> second_map = new HashMap<Integer, Insanity>();;
 
     first_map.put(Numberz.TWO, crazy);
     first_map.put(Numberz.THREE, crazy);
 
     second_map.put(Numberz.SIX, looney);
 
-    HashMap<Int64,HashMap<Int32,Insanity>> insane =
-      new HashMap<Int64, HashMap<Int32,Insanity>>();
-    insane.put(new Int64(1), first_map);
-    insane.put(new Int64(2), second_map);
+    HashMap<Long,HashMap<Integer,Insanity>> insane =
+      new HashMap<Long, HashMap<Integer,Insanity>>();
+    insane.put((long)1, first_map);
+    insane.put((long)2, second_map);
 
     return insane;
   }
 
+  public Xtruct testMulti(byte arg0, int arg1, long arg2, HashMap<Short,String> arg3, int arg4, long arg5) {
+    System.out.print("testMulti()\n");
+    
+    Xtruct hello = new Xtruct();;
+    hello.string_thing = "Hello2";
+    hello.byte_thing = arg0;
+    hello.i32_thing = arg1;
+    hello.i64_thing = arg2;
+    return hello;
+  }
+
+  public void testException(String arg) throws Xception {
+    System.out.print("testException("+arg+")\n");
+    if (arg.equals("Xception")) {
+      Xception x = new Xception();
+      x.errorCode = 1001;
+      x.message = "This is an Xception";
+      throw x;
+    }
+    return;
+  }
+
+  public Xtruct testMultiException(String arg0, String arg1) throws Xception, Xception2 {
+    System.out.print("testMultiException(" + arg0 + ", " + arg1 + ")\n");
+    if (arg0.equals("Xception")) {
+      Xception x = new Xception();
+      x.errorCode = 1001;
+      x.message = "This is an Xception";
+    } else if (arg0.equals("Xception2")) {
+      Xception2 x = new Xception2();
+      x.errorCode = 2002;
+      x.struct_thing.string_thing = "This is an Xception2";
+    }
+     
+    Xtruct result = new Xtruct();
+    result.string_thing = arg1;
+    return result;
+  }
+
+
   public static void main(String [] args) {
     try {
       int port = 9090;