You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@thrift.apache.org by "Jordan (JIRA)" <ji...@apache.org> on 2010/06/20 10:45:25 UTC

[jira] Issue Comment Edited: (THRIFT-550) JavaScript language target

    [ https://issues.apache.org/jira/browse/THRIFT-550?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12880600#action_12880600 ] 

Jordan edited comment on THRIFT-550 at 6/20/10 4:43 AM:
--------------------------------------------------------

Awesome project. You have no idea how helpful this is. I mean, could be quite helpful in the revolution of bring more complex client code to the front end. In addition, I can use the same service for my ajax webpage as I use for my iPhone app. A couple of issues:

1. Runtime exceptions. I would expect my operations to be able to accidentally throw an NPE/IllegalArgs (in Java) and have my js client catch them as follows:
catch(run) {

}
But it does not work. In some cases, the "run" is "undefined" and in other cases the auto-generated js bugs out. 

Unfortunately it may be more complicated than we think. For service operations in the .thrift file that declare a checked exception (that was also defined in the .thrift file) I notice something in the auto-generated Java code. 
For these operations that declare exceptions, there is a catch(Throwable) which transforms it into a TApplicationException. 
Unfortunately, for service operations that do NOT declare an exception, it does NOT catch throwable which seems very odd to me. Whether or not something declares a checked exception has nothing to do with whether or not it throws runtime exceptions. I believe this is a bug, go see for yourself. Search for "public class yourOperationName implements ProcessFunction".

2. Now, that aside, I still see some problems on the js side of things. 
For operations that do catch throwable on the client side, the js code tries to initalize a Thrift.ApplicationException.. Which doesn't exist. However there does appear to be something called Thrift.TApplicationException defined in thrift.js. Was this a bug? 

3. I would like a nicer async api (I can show you what I hacked up at the bottom of the post.)

3. Once this is working, how can we catch exceptions from asynchronous methods? The async api I like would be the following:
SYNC API:
client.callMethod(param1, param2);
ASYNC API:
asyncClient.callMethod(handler, param1, param2);
With this api it won't work at all. We would need to supply another error handler. Oh well.. 

4. It would be cool to have nicer async clients: Here is some code I came up with that takes in a client and generates an asyncClient with all of the same methods, except that the first parameter is the callback (yes, we'll eventually need an error callback too.) (yes, it requires jQuery, but I think that we could just require that the user have it for async clients.)



  function createAsyncThriftClient(syncThriftClient) {
      var retObj = {};
      for(var methodName in syncThriftClient) {
          if(typeof syncThriftClient[methodName] === 'function') {
              if(methodName.substring(0,5) == "send_" || methodName.substring(0,5) == "recv_") {
                  retObj[methodName] = syncThriftClient[methodName];
              } else {
                  retObj[methodName] = createThriftAsyncCall(syncThriftClient, methodName)  
              }
          }
      }
      return retObj;
  }

  var createThriftAsyncCall = function(syncThriftClient, methodName) {
      return function() {
          var calledMethodName = methodName;
          if(arguments.length < 1) {
              throw("Assync call must have a handler");
          }
          var successHandler = arguments[arguments.length-1];
          var apiArgs = new Array();
          for(var i = 0; i < arguments.length-1; i++) {
              apiArgs[i] = arguments[i];
          }
          jQuery.ajax({
              url: "/service",
              data: syncThriftClient["send_" + calledMethodName].apply(syncThriftClient, apiArgs),
              type: "POST",
              cache: false,
              success: function(res){
                  var _transport = new Thrift.Transport();
                  var _protocol  = new Thrift.Protocol(_transport);
                  var _client    = new TheService.TheServiceClient(_protocol);
                  _transport.setRecvBuffer(res);
                  var v =  _client["recv_" + calledMethodName].apply(_client);
                  successHandler(v);
              }
          });
      }
  };

EDIT: Actually, that code requires the callback as the last parameter to the assync.methodCall().


      was (Author: jordo):
    Awesome project. You have no idea how helpful this is. I mean, could be quite helpful in the revolution of bring more complex client code to the front end. In addition, I can use the same service for my ajax webpage as I use for my iPhone app. A couple of issues:

1. Runtime exceptions. I would expect my operations to be able to accidentally throw an NPE/IllegalArgs (in Java) and have my js client catch them as follows:
catch(run) {

}
But it does not work. In some cases, the "run" is "undefined" and in other cases the auto-generated js bugs out. 

Unfortunately it may be more complicated than we think. For service operations in the .thrift file that declare a checked exception (that was also defined in the .thrift file) I notice something in the auto-generated Java code. 
For these operations that declare exceptions, there is a catch(Throwable) which transforms it into a TApplicationException. 
Unfortunately, for service operations that do NOT declare an exception, it does NOT catch throwable which seems very odd to me. Whether or not something declares a checked exception has nothing to do with whether or not it throws runtime exceptions. I believe this is a bug, go see for yourself. Search for "public class yourOperationName implements ProcessFunction".

2. Now, that aside, I still see some problems on the js side of things. 
For operations that do catch throwable on the client side, the js code tries to initalize a Thrift.ApplicationException.. Which doesn't exist. However there does appear to be something called Thrift.TApplicationException defined in thrift.js. Was this a bug? 

3. I would like a nicer async api (I can show you what I hacked up at the bottom of the post.)

3. Once this is working, how can we catch exceptions from asynchronous methods? The async api I like would be the following:
SYNC API:
client.callMethod(param1, param2);
ASYNC API:
asyncClient.callMethod(handler, param1, param2);
With this api it won't work at all. We would need to supply another error handler. Oh well.. 

4. It would be cool to have nicer async clients: Here is some code I came up with that takes in a client and generates an asyncClient with all of the same methods, except that the first parameter is the callback (yes, we'll eventually need an error callback too.) (yes, it requires jQuery, but I think that we could just require that the user have it for async clients.)



  function createAsyncThriftClient(syncThriftClient) {
      var retObj = {};
      for(var methodName in syncThriftClient) {
          if(typeof syncThriftClient[methodName] === 'function') {
              if(methodName.substring(0,5) == "send_" || methodName.substring(0,5) == "recv_") {
                  retObj[methodName] = syncThriftClient[methodName];
              } else {
                  retObj[methodName] = createThriftAsyncCall(syncThriftClient, methodName)  
              }
          }
      }
      return retObj;
  }

  var createThriftAsyncCall = function(syncThriftClient, methodName) {
      return function() {
          var calledMethodName = methodName;
          if(arguments.length < 1) {
              throw("Assync call must have a handler");
          }
          var successHandler = arguments[arguments.length-1];
          var apiArgs = new Array();
          for(var i = 0; i < arguments.length-1; i++) {
              apiArgs[i] = arguments[i];
          }
          jQuery.ajax({
              url: "/service",
              data: syncThriftClient["send_" + calledMethodName].apply(syncThriftClient, apiArgs),
              type: "POST",
              cache: false,
              success: function(res){
                  var _transport = new Thrift.Transport();
                  var _protocol  = new Thrift.Protocol(_transport);
                  var _client    = new TheService.TheServiceClient(_protocol);
                  _transport.setRecvBuffer(res);
                  var v =  _client["recv_" + calledMethodName].apply(_client);
                  successHandler(v);
              }
          });
      }
  };



  
> JavaScript language target
> --------------------------
>
>                 Key: THRIFT-550
>                 URL: https://issues.apache.org/jira/browse/THRIFT-550
>             Project: Thrift
>          Issue Type: New Feature
>            Reporter: T Jake Luciani
>            Assignee: T Jake Luciani
>             Fix For: 0.3
>
>         Attachments: THRIFT-550_initialize_with_null.patch, thrift_js.patch, thrift_js_v2.patch, thrift_js_v3.patch
>
>
> This allows javascript clients to be built for browser based access to thrift services.
> The supported transport is XHTTPRequest and the supported Protocol is compatible with TJSONProtocol
> I've added a test in lib/js that is a java based HTTP server which implements ThriftTest service.
> I've put a version of this test service here http://3.rdrail.net:8080/test/test.html if you'd like to see it in action.
> It's been tested in ie 6,7,8, FF, and Safari.
> Let me know if you hit any issues.  The protocol and transport code aren't very error tolerant, but overall it seems to work quite well.

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.