Thrift Java server OutOfMemoryError with Javascript client

霸气de小男生 提交于 2019-12-07 16:30:59

问题


I started learning thrift yesterday.

After a lot of effort, I successfully executed the Java tutorial. Java server and client are running perfectly.

But now, I want a javascript client to communicate with Java Thrift server.

For that, I moved all js files in js/ folder.

And paste index.html code as below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <title>Thrift Javascript Bindings - Tutorial Example</title>

  <script src="js/thrift.js"  type="text/javascript"></script>
  <script src="js/tutorial_types.js"    type="text/javascript"></script>
  <script src="js/shared_types.js"      type="text/javascript"></script>
  <script src="js/SharedService.js"     type="text/javascript"></script>
  <script src="js/Calculator.js"        type="text/javascript"></script>

  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>


  <script type="text/javascript" charset="utf-8">
  //<![CDATA[
  $(document).ready(function(){
    // remove pseudo child required for valid xhtml strict
    $("#op").children().remove();
    // add operations to it's dropdown menu
    $.each(Operation, function(key, value) {
      $('#op').append($("<option></option>").attr("value",value).text(key)); 
    });

     $('table.calculator').attr('width', 500);
  });

  function calc() {
    var transport = new Thrift.Transport("http://localhost:9090");
    var protocol  = new Thrift.Protocol(transport);
    var client    = new CalculatorClient(protocol);

    var work = new Work()
    work.num1 = $("#num1").val();
    work.num2 = $("#num2").val();
    work.op = $("#op").val();

    try {
      result = client.calculate(1, work);
      $('#result').val(result);
      $('#result').css('color', 'black');
    } catch(ouch){
      $('#result').val(ouch.why);
      $('#result').css('color', 'red');
    }
  }

  function auto_calc() {
    if ($('#autoupdate:checked').val() !== undefined) {
      calc();
    }
  }
  //]]>
  </script>

</head>
<body>
  <h2>Thrift Javascript Bindings</h2>
  <form action="">
  <table class="calculator">
    <tr>
      <td>num1</td>
      <td><input type="text" id="num1" value="20" onkeyup="javascript:auto_calc();"/></td>
    </tr>
    <tr>
      <td>Operation</td>
      <td><select id="op" size="1" onchange="javascript:auto_calc();"><option></option></select></td>
    </tr>
    <tr>
      <td>num2</td>
      <td><input type="text" id="num2" value="5" onkeyup="javascript:auto_calc();"/></td></tr>
    <tr>
      <td>result</td>
      <td><input type="text" id="result" value=""/></td></tr>
    <tr>
      <td><input type="checkbox" id="autoupdate" checked="checked"/>autoupdate</td>
      <td><input type="button" id="calculate" value="calculate" onclick="javascript:calc();"/></td>
    </tr>
  </table>
  </form>

  <p>This Java Script example uses <a href="https://git-wip-us.apache.org/repos/asf?p=thrift.git;a=blob;f=tutorial/tutorial.thrift;hb=HEAD">tutorial.thrift</a> and a Thrift server using JSON protocol and HTTP transport.
  </p>
    <p>
        <a href="http://validator.w3.org/check/referer"><img
            src="http://www.w3.org/Icons/valid-xhtml10"
            alt="Valid XHTML 1.0!" height="31" width="88" /></a>
    </p>
</body>
</html>

I replaced line

var transport = new Thrift.Transport("/thrift/service/tutorial/");

with

var transport = new Thrift.Transport("http://localhost:9090");

As, my server is on port 9090. And /thrift/service/tutorial was not making any sense to me neither it was working.

Then, when I open my page.

Java thrift server crashes with following error:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
    at org.apache.thrift.protocol.TBinaryProtocol.readStringBody(TBinaryProtocol.java:339)
    at org.apache.thrift.protocol.TBinaryProtocol.readMessageBegin(TBinaryProtocol.java:202)
    at org.apache.thrift.TBaseProcessor.process(TBaseProcessor.java:27)
    at org.apache.thrift.server.TSimpleServer.serve(TSimpleServer.java:83)
    at thrift.server.CalculatorServer.main(CalculatorServer.java:23)

Here is the CalculatorServer java class.

package thrift.server;

import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TServer.Args;
import org.apache.thrift.server.TSimpleServer;
import org.apache.thrift.transport.TServerSocket;
import org.apache.thrift.transport.TServerTransport;
import org.apache.thrift.transport.TTransportException;

import tutorial.Calculator;

public class CalculatorServer {

    public static void main(String[] args) {
        CalculatorHandler handler = new CalculatorHandler();
        Calculator.Processor<CalculatorHandler> processor = new Calculator.Processor<>(handler);        

        try {
            TServerTransport serverTransport = new TServerSocket(9090);
            TServer server = new TSimpleServer(new Args(serverTransport).processor(processor));

            System.out.println("Starting the simple server...");
            server.serve();
        } catch (TTransportException e) {
            e.printStackTrace();
        }
    }

}

Rest of the code is used from Thrift Tutorials. In fact, Java Thrift server is working perfectly with Java Thrift client. I don't think there is any problem at Java Server side.

Can anyone tell what is going wrong?

Is there any alternative for Javascript client?

I am using thrift to communicate between my Java SE application and a website on local computer. So that, I can develop my GUI using HTML+CSS+JS, rather using Java Swing.


回答1:


I have been looking for an easy way to use thrift inside polymer javascript. Finally here is the solution after It took me three days analyzing other solutions. They where working but they all needed to read the view.html local location file from my http://localhost:8088/view.html request. I found this so expensive since i am using google app engine and compute engine at the same time. i cant locate the local directory on app engine so here is what is did.

  1. Write your java server pretty much like this.
  2. write your polymer element like this

    <dom-module id="thrift-client">
    <template>
    </template>
    <script>
        Polymer({
            is:'thrift-client',
            ready:function(){
                var transport = new Thrift.TXHRTransport("http://localhost:8088/service");
    
                var protocol  = new Thrift.TJSONProtocol(transport);
    
                var client = new NtvApiClient(protocol);
    
                var result = client.ping(); // ping the java server. custom
    
                console.log(result);
            }
    
            });
    </script>
    

  3. Note that the http://localhost can be changed to http://Your_server_ip_address.

  4. please make sure the java server has a check point exactly named as service

  5. bravo, we have all it takes to access the java server now from a javascript web client without providing any file path.

  6. Note that with this u can easily use in plain js. like this

                    var transport = new Thrift.TXHRTransport("http://localhost:8088/service");
                    var protocol  = new Thrift.TJSONProtocol(transport);
                    var client = new NtvApiClient(protocol);
                    var result = client.ping(); 
    

    Cheers.




回答2:


Default 'TTransport' is not a http protocol based server. If you want to use http as the communication protocol which seems the only way for js at the client side, you should use a http based 'TTransport'. Take a look at 'org.apache.thrift.server.TServlet', it's a simple way to build a http based thrift server in a servlet.

You should also use 'TJSONProtocol' instead of 'TBinaryProtocol' at server side because thrift js can NOT handle binary data well. This is the code snippet I used before.

public class CalculatorServlet extends TServlet 
{
   public CalculatorServlet() 
   {
      //'Calculator' is the generated class from thrift, 
      //'CalculatorHandler' is the implement class for thrift rpc
      super(new Calculator.Processor(
            new CalculatorHandler()),
            new TJSONProtocol.Factory());
  }
}



回答3:


IIRC, JavaScript supports only the JSON protocol. This is (of course) incompatible with binary.

Therefore the solution is: use the JSON protocol instead of the binary protocol in your server.

A good rule of thumb with Thrift is, to always use the same transport/protocol stack on both ends. In this particilar case this means:

  • HTTP Server
  • JSON protocol
  • no extras like framed protocol (buffered would work, btw)

(There are some exceptions, because some server types intrinsically require framed, but that's a whole other story and has nothing to do with your problem)



来源:https://stackoverflow.com/questions/21821787/thrift-java-server-outofmemoryerror-with-javascript-client

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!