Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling parseFrom() method for generic protobuffer class in java

I'm calling an api to get the an input stream and then call static method parseFrom(inputstream) to convert it to the protobuffclass.

If I do it with a specific class it works:

public CustomerDTOOuterClass.CustomerDTO GetCustomer()
{
    CustomerDTOOuterClass.CustomerDTO customer = null;
    try
    {
        URL url = new URL("https://localhost:44302/Api/customer/1?");

        HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-Type", "application/x-protobuf");
        conn.connect();

        InputStream is = conn.getInputStream();

        CustomerDTOOuterClass.CustomerDTO customer =
                CustomerDTOOuterClass.CustomerDTO.parseFrom(is);

        conn.disconnect();
    }
    catch(Exception ex)
    {
        System.out.println("[ "+ex.getMessage()+" ]");
    }

    return customer;
}

but if I change it to generic type it fails because T doesn't have the method parseFrom, is there any interface I could implement in T so I can call the parseFrom method?

public T GetObject()
{
    T object = null;
    try
    {
        URL url = new URL("https://localhost:44302/Api/customer/1?");

        HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-Type", "application/x-protobuf");
        conn.connect();

        InputStream is = conn.getInputStream();

        T object = T.parseFrom(is);

        conn.disconnect();
    }
    catch(Exception ex)
    {
        System.out.println("[ "+ex.getMessage()+" ]");
    }

    return object;
}

this is the error I get: Error:(68, 27) error: cannot find symbol method parseFrom(InputStream)

like image 881
Francisco Gutiérrez Avatar asked Dec 24 '14 20:12

Francisco Gutiérrez


2 Answers

Every generated protobuf type contains a static member called PARSER which is an implementation of the com.google.protobuf.Parser<T> interface. Your getObject method simply needs to take a Parser<T> as a parameter. So then you'd call it like:

Foo foo = getObject(Foo.PARSER);
like image 105
Kenton Varda Avatar answered Jan 03 '23 19:01

Kenton Varda


If you want to do this for T, it's easier and more natural to pass the Class<T> (i.e. the class of the Proto type) into the constructor of your class, and then obtain the Parser from that like this:

public class Thing<T extends Message> {
    final Parser<T> parser;

    Thing(Class<T> cls) {
        parser = (Parser<T>) cls.getMethod("parser").invoke(null);
    }

    T deserialize(byte[] bytes) {
        parser.parseFrom(bytes);  // try/catch etc
    }
}
like image 22
gub Avatar answered Jan 03 '23 18:01

gub