1

I have a fairly straightforward Thrift IDL (split into two files as shown):

core.thrift

namespace cpp MyProduct.Core
namespace java com.mycompany.myproduct.core
namespace py myproduct.core

/**
 * Struct used to indicate a location referenced by geodetic coordinates.
 */ 
struct GeoPoint{
    /**
     * Latitude for this point
     */
    1: required double latitude;

    /**
     * Longitude for this point
     */
    2: required double longitude;

    /**
     * Elevation for this point
     */
    3: required double elevation;
}

processing.thrift

include "core.thrift"

namespace cpp MyProduct.Processing
namespace java com.mycompany.myproduct.processing
namespace py myproduct.processing

/**
 * MyProduct processing services
 */
service PointsQuery{
   /**
    * Returns elevation of a list of input (geodetic) points
    * The elevation attribute in input GeoPoints are ignored
    */
    list<double> getElevations(1: required list<core.GeoPoint> inputPoints = [], 2: required string layername = "undefined");
}

I am using a Python Tornado Server and a Java client, for which the code looks like:

Python server:

class PointQueryHandler(object):
    def __init__(self):
        self.log = {}

    def getElevations(self, inputPoints, layerName, callback=None):        
        elevation_list = []
        // ...implementation here to fill elevation list with doubles...
        if callback:
            callback(elevation_list)
        else:
            return elevation_list

def main():
    handler = PointQueryHandler()
    processor = PointsQuery.Processor(handler)
    factory = TBinaryProtocol.TBinaryProtocolFactory()
    server = TTornado.TTornadoServer(processor, factory)

    print "Starting the server..."
    server.bind(9090)
    server.start(1)
    ioloop.IOLoop.instance().start()

if __name__ == "__main__":
    main()

Java Client:

public class QueryPointsTest {
    public static void main(String [] args) {
        try {
            TTransport transport;

            transport = new TSocket("localhost", 9090);
            transport.open();

            TProtocol protocol = new TBinaryProtocol(transport);
            PointsQuery.Client client = new PointsQuery.Client(protocol);

            perform(client);

            transport.close();
        } catch (TTransportException x) {
            System.out.println("Unable to connect to service provider: " + "localhost" + 9090);
        } catch (TException err){
            System.out.println("Error when accessing remote service: ");
            err.printStackTrace();
        }
    }

    private static void perform(PointsQuery.Client client) throws TException
    {
        List<GeoPoint> pointList = new ArrayList<GeoPoint>();

        GeoPoint pt1 = new GeoPoint(74.53951, 34.36709, 0.0);
        GeoPoint pt2 = new GeoPoint(74.52242,34.35413, 0.0);
        GeoPoint pt3 = new GeoPoint(74.51398,34.41069, 0.0);
        GeoPoint pt4 = new GeoPoint(83, 39.36709, 0.0);

        pointList.add(pt1);
        pointList.add(pt2);
        pointList.add(pt3);
        pointList.add(pt4);

        List<Double> result = client.getElevations(pointList, "dummylayername");
        System.out.println("Done");
    }
}

The client successfully connects to the server and the Python PointQueryHandler.getElevations function gets called. However, the problem is that the arguments to PointQueryHandler.getElevations are always the default arguments of an empty list and "undefined" string. Whatever data I pass from the Java client is not, for some reason, arriving at the server.

What could be going wrong?

(Thrift version: 0.9.2, Python 2.7.5, JDK 1.7.0_45, Platform: Windows 7 64-bit)

balajeerc
  • 3,998
  • 7
  • 35
  • 51
  • Hi. I see it's been a while since you asked this but.. I have the same issue and was wondering if you got any luck with this. If you can remember of course... – melis Dec 13 '16 at 17:15

1 Answers1

0

There are some known issues around default arguments, a lot of languages still do not implement this at all. Hence, what puzzles me the most is the fact that you always get the defaults ...?

The recommendation is to convert the args into a single struct which you pass as the only argument. That struct may have defaults or use optional fields instead as you like it and as it matches your use case best.

JensG
  • 13,148
  • 4
  • 45
  • 55