1
votes

I write a server(Go)-client(Java) programe, and use protobuf for communication. Define a proto file and share between server and client. In server side:

  • compile shared proto file into go by protoc
  • serialize the object by proto.Marshal
  • send it to client that make a request to its service

In client side:

  • compile shared proto file into java by protoc
  • get bytes is transferred via http
  • deserialize the bytes into object.

Here i get following error:

"com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field. This could mean either that the input has been truncated or that an embedded message misreported its own length."

I confirmed http work fine and value of bytes received in client side are same to bytes send by server. Do you have same problem on this?

Here is proto file

syntax = "proto3";
package tutorial;

message Person {
    string name = 1;
    int32 id = 2; 
    string email = 3;

    enum PhoneType {
        MOBILE = 0;
        HOME = 1;
        WORK = 2;
    }

    message PhoneNumber {
        string number = 1;
        PhoneType type = 2;
    }

    repeated PhoneNumber phones = 4;
}

message AddressBook {
    repeated Person people = 1;
}

In Go server side :

func TodoIndex(w http.ResponseWriter, r *http.Request) {

    w.Header().Set("Content-Type", "application/x-protobuf")
    w.WriteHeader(http.StatusOK)
    p := &Person{
        Id:    1234,
        Name:  "John Doe",
        Email: "jdoe@example.com",
        Phones: []*Person_PhoneNumber{
            {Number: "555-4321", Type: Person_HOME},
        },
    }
    out, err := proto.Marshal(p)
    if err != nil {
        panic(err)
    }
    w.Write(out)
}

In Java client side:

public class MainJavaAndGo {
public static void main(String[] args){
    try {
        long start = (new Date()).getTime();
        System.out.println("begin get");
        connect();

        System.out.println("end get");
        long time = (new Date()).getTime() - start;
    }catch(Exception e){
        e.printStackTrace();
    }
}

public static void connect(){
    DefaultBHttpClientConnection connection = new DefaultBHttpClientConnection(8 * 1024);
    HttpHost server = hostForString("localhost:8080");
    try {

        Socket socket = new Socket(server.getHostName(), server.getPort());
        connection.bind(socket);

        HttpCoreContext writeContext = HttpCoreContext.create();
        writeContext.setTargetHost(server);

        BasicHttpEntityEnclosingRequest httpRequest = new BasicHttpEntityEnclosingRequest("GET",
                "/todos");

        HttpProcessor httpproc = makeHttpProcessor();
        HttpRequestExecutor httpexecutor = new HttpRequestExecutor();
        httpexecutor.preProcess(httpRequest, httpproc, writeContext);
        HttpResponse response = httpexecutor.execute(httpRequest, connection, writeContext);
        httpexecutor.postProcess(response, httpproc, writeContext);
        InputStream inputStream = response.getEntity().getContent();
        byte[] data = IOUtils.toByteArray(inputStream);
        Addressbook.AddressBook addressBook = Addressbook.AddressBook.parseFrom(data);
        int foo = 0;
        foo++;


    }catch(Exception e){
        e.printStackTrace();
        try {
            connection.shutdown();
        }catch (Exception ioe){
            ioe.printStackTrace();
        }
    }
}
public static  HttpHost hostForString(String hostStr) {
    String[] host = hostStr.split(":", 2);
    HttpHost httphost = new HttpHost(host[0], Integer.parseInt(host[1]));

    return httphost;
}

public static HttpProcessor makeHttpProcessor() {
    return HttpProcessorBuilder.create().add(new RequestContent()).add(new RequestTargetHost())
            .add(new RequestConnControl()).add(new RequestUserAgent("Test Protobuf/1.1"))
            .add(new RequestExpectContinue(true)).build();
}
}

I got InvalidProtocolBufferException

com.google.protobuf.InvalidProtocolBufferException: While parsing a protocol message, the input ended unexpectedly in the middle of a field.  This could mean either that the input has been truncated or that an embedded message misreported its own length.
    at com.google.protobuf.InvalidProtocolBufferException.truncatedMessage(InvalidProtocolBufferException.java:82)
    at com.google.protobuf.CodedInputStream$ArrayDecoder.skipRawBytes(CodedInputStream.java:1200)
    at com.google.protobuf.CodedInputStream$ArrayDecoder.skipField(CodedInputStream.java:578)
    at com.auth0.protobuf.Addressbook$Person.<init>(Addressbook.java:112)
    at com.auth0.protobuf.Addressbook$Person.<init>(Addressbook.java:77)
    at com.auth0.protobuf.Addressbook$Person$1.parsePartialFrom(Addressbook.java:1817)
    at com.auth0.protobuf.Addressbook$Person$1.parsePartialFrom(Addressbook.java:1812)
    at com.google.protobuf.CodedInputStream$ArrayDecoder.readMessage(CodedInputStream.java:816)
    at com.auth0.protobuf.Addressbook$AddressBook.<init>(Addressbook.java:1914)
    at com.auth0.protobuf.Addressbook$AddressBook.<init>(Addressbook.java:1871)
    at com.auth0.protobuf.Addressbook$AddressBook$1.parsePartialFrom(Addressbook.java:2571)
    at com.auth0.protobuf.Addressbook$AddressBook$1.parsePartialFrom(Addressbook.java:2566)
    at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:163)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:197)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:209)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:214)
    at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49)
    at com.auth0.protobuf.Addressbook$AddressBook.parseFrom(Addressbook.java:2065)
    at com.auth0.MainJavaAndGo.connect(MainJavaAndGo.java:78)
    at com.auth0.MainJavaAndGo.main(MainJavaAndGo.java:35)
1
What does your socket on the Java side look like? It sounds like you are only getting a partial message back.tier1
on the Java side, i request service by HttpRequestExecutor HttpHost server = new HttpHost("localhost", 8080); Socket socket = new Socket(server.getHostName(), server.getPort()); connection.bind(socket);Tam Le
At what point are you reading from the socket? Can you edit your original post with that so it's formatted properly?tier1
thank you for your comment. i've just post full version of java client side i get bytes from server via HttpResponse by httpexecutor.execute. It's like response from a request to restful service.Tam Le

1 Answers

0
votes

Thank you all I found answer from all your comment. My serialize and deserialize structure is different. I edited to Addressbook.Person person = Addressbook.Person.parseFrom(data); and then it work.