I'm using protocol buffers 2.5 with Java. I have a proto file that defines a custom option. Another proto file uses that custom option. If I persist the corresponding FileDescriptorProto's and then read them and convert them to FileDescriptors, the reference to the custom option is manifested as unknown field. How do I cause that custom option to be resolved correctly?
Here's the code. I have two .proto files. protobuf-options.proto looks like this: package options; import "google/protobuf/descriptor.proto"; option java_package = "com.example.proto"; option java_outer_classname = "Options"; extend google.protobuf.FieldOptions { optional bool scrub = 50000;} The imported google/protobuf/descriptor.proto is exactly the descriptor.proto that ships with Protocol Buffers 2.5. example.proto looks like this: package example; option java_package = "com.example.protos"; option java_outer_classname = "ExampleProtos"; option optimize_for = SPEED; option java_generic_services = false; import "protobuf-options.proto"; message M { optional int32 field1 = 1; optional string field2 = 2 [(options.scrub) = true];} As you can see, field2 references the custom option defined by protobuf-options.proto. The following code writes a binary-encoded version of all three protos to /tmp: package com.example; import com.google.protobuf.ByteString;import com.google.protobuf.DescriptorProtos.FileDescriptorProto;import com.google.protobuf.Descriptors.FileDescriptor;import com.example.protos.ExampleProtos; import java.io.FileOutputStream;import java.io.OutputStream; /** * */public class PersistFDs { public void persist(final FileDescriptor fileDescriptor) throws Exception { System.out.println("persisting "+fileDescriptor.getName()); try (final OutputStream outputStream = new FileOutputStream("/tmp/"+fileDescriptor.getName())) { final FileDescriptorProto fileDescriptorProto = fileDescriptor.toProto(); final ByteString byteString = fileDescriptorProto.toByteString(); byteString.writeTo(outputStream); } for (final FileDescriptor dependency : fileDescriptor.getDependencies()) { persist(dependency); } } public static void main(String[] args) throws Exception { final PersistFDs self = new PersistFDs(); self.persist(ExampleProtos.getDescriptor()); }} Finally, the following code loads those those protos from /tmp, converts them back into FileDescriptors, and then checks for the custom option on field2: package com.example; import com.google.protobuf.ByteString;import com.google.protobuf.DescriptorProtos.FileDescriptorProto;import com.google.protobuf.Descriptors.FieldDescriptor;import com.google.protobuf.Descriptors.FileDescriptor;import com.google.protobuf.UnknownFieldSet.Field; import java.io.FileInputStream;import java.io.InputStream; /** * */public class LoadFDs { public FileDescriptorProto loadProto(final String filePath) throws Exception { try (final InputStream inputStream = new FileInputStream(filePath)) { final ByteString byteString = ByteString.readFrom(inputStream); final FileDescriptorProto result = FileDescriptorProto.parseFrom(byteString); return result; } } public static void main(final String[] args) throws Exception { final LoadFDs self = new LoadFDs(); final FileDescriptorProto descriptorFDProto = self.loadProto("/tmp/google/protobuf/descriptor.proto"); final FileDescriptorProto optionsFDProto = self.loadProto("/tmp/protobuf-options.proto"); final FileDescriptorProto fakeBoxcarFDProto = self.loadProto("/tmp/example.proto"); final FileDescriptor fD = FileDescriptor.buildFrom(descriptorFDProto, new FileDescriptor[0]); final FileDescriptor optionsFD = FileDescriptor.buildFrom(optionsFDProto, new FileDescriptor[] { fD }); final FileDescriptor fakeBoxcarFD = FileDescriptor.buildFrom(fakeBoxcarFDProto, new FileDescriptor[] { optionsFD }); final FieldDescriptor optionsFieldDescriptor = optionsFD.findExtensionByName("scrub"); if (optionsFieldDescriptor == null) { System.out.println("Did not find scrub's FieldDescriptor"); System.exit(1); } final FieldDescriptor sFieldDescriptor = fakeBoxcarFD.findMessageTypeByName("M").findFieldByName("field2"); System.out.println("unknown option fields "+sFieldDescriptor.getOptions().getUnknownFields()); final boolean hasScrubOption = sFieldDescriptor.getOptions().hasField(optionsFieldDescriptor); System.out.println("hasScrubOption: "+hasScrubOption); }} When I run LoadFDs, it fails with this exception: unknown option fields 50000: 1 Exception in thread "main" java.lang.IllegalArgumentException: FieldDescriptor does not match message type. at com.google.protobuf.GeneratedMessage$ExtendableMessage.verifyContainingType(GeneratedMessage.java:812) at com.google.protobuf.GeneratedMessage$ExtendableMessage.hasField(GeneratedMessage.java:761) at com.example.LoadFDs.main(LoadFDs.java:42) The options for FieldDescriptor for the s field ought to have a field for that custom option, but instead it has an unknown field. The field number and value on the unknown field are correct. It's just that the custom option is not getting resolved. How do I fix that? Bill Smith Austin, TX -- 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+unsubscr...@googlegroups.com. To post to this group, send email to protobuf@googlegroups.com. Visit this group at https://groups.google.com/group/protobuf. For more options, visit https://groups.google.com/d/optout.