How to construct a Builder from a FieldDescriptor with JavaType.MESSAGE

1,265 views
Skip to first unread message

Jon Emerson

unread,
Jan 26, 2015, 7:31:44 PM1/26/15
to prot...@googlegroups.com
Hi There,

I'm writing a utility to convert data stored in MongoDB back to protocol buffer format.  My strategy is to look for each field in the protocol buffer definition, and if there's a matching field from my MongoDB object, then pull that data and set it on my protocol buffer builder.  This works great, except for embedded messages.  I can't figure out how to create a Builder for an embedded message.

Here's my first try:

          switch (fieldDescriptor.getJavaType()) {
            ...
            case MESSAGE:
              Class<T> type = (Class<T>) fieldDescriptor.getDefaultValue().getClass(); // getDefaultValue throws.
              messageBuilder.addRepeatedField(fieldDescriptor,
                  fromDBObject((BasicBSONObject) object.get(fieldName), type));
              break;

But the noted line throws with the error, "java.lang.UnsupportedOperationException: FieldDescriptor.getDefaultValue() called on an embedded message field."

Here's my second try:
          switch (fieldDescriptor.getJavaType()) {
            ...
            case MESSAGE:
              Message.Builder embeddedMessageBuilder = messageBuilder.getFieldBuilder(fieldDescriptor); // getFieldBuilder throws.
              Class<T> type = (Class<T>) embeddedMessageBuilder.getDefaultInstanceForType().getClass();
              messageBuilder.addRepeatedField(fieldDescriptor,
                  fromDBObject((BasicBSONObject) object.get(fieldName), type));
              break;

Here, the noted line throws with the error, "java.lang.UnsupportedOperationException: getFieldBuilder() called on a non-Message type."

I'm not sure what else to try.  My question boils down to a very simple one: Given a FieldDescriptor that describes an embedded repeated MESSAGE field, how can you create a Builder for it?

Thanks!
jon

Feng Xiao

unread,
Jan 26, 2015, 8:55:34 PM1/26/15
to Jon Emerson, prot...@googlegroups.com
As it's a repeated field, you should use "getRepeatedFieldBuilder".

--
You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To unsubscribe from this group and stop receiving emails from it, send an email to protobuf+u...@googlegroups.com.
To post to this group, send email to prot...@googlegroups.com.
Visit this group at http://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.

Jon Emerson

unread,
Jan 26, 2015, 11:19:36 PM1/26/15
to Feng Xiao, prot...@googlegroups.com
Ah, thanks for the response!  That wasn't it though - Calling .getRepeatedFieldBuilder(FieldDescriptor, int) against a Builder I'm just starting to populate will inevitably give only IndexOutOfBounds exceptions... Since nothing's set in the repeated field yet!

But your response did give give me a huge hint: LOTS of new functionality for working with repeated field builders was added in the November 2014 release to Github.  I was still using the release from July.  So I didn't see .newBuilderForField(FieldDescriptor)... that was what I needed!  After upgrading to the latest branch I was up and going in no time.

Here's my final (working!) code:

            case MESSAGE:
              Message.Builder embeddedMessageBuilder =
                  messageBuilder.newBuilderForField(fieldDescriptor);
              Class<T> type = (Class<T>) embeddedMessageBuilder.getDefaultInstanceForType().getClass();
              for (T t : fromDBList((BasicBSONList) object.get(fieldName), type)) {
                messageBuilder.addRepeatedField(fieldDescriptor, t);
              }
              break;

It's still a bit janky that I construct a Builder to get its DefaultInstance to then get its Class (I do this because I call my methods recursively, and the top-most method needs a hint as to the top-most Object's class)... But, hey, it works for now.  If there's more elegant ways to get a Class from a repeated FieldDescriptor, I'd love to hear it.

Thanks!!
Reply all
Reply to author
Forward
0 new messages