I am fairly new to protobufs, so please bear with me. I am receiving
protobuf messages that were compiled for C++ and I need to read them
in Java. They are created WITHOUT descriptors by the provider and I
cannot change that but I do have access to the base .proto files that
the messages were based on.
My questions are:
1) What is the best/fastest way to generate the file descriptor(s)
into Java? This should be equal to calling importer.import in C++
based on what I have read.
2) I assume that question 1 will involve a call out to protoc from
Java. If so, how should that look in general and what command/options
should be used? My goal is to get the file descriptor, after which I
can get everything else from within Java
3) Is there any way to do this without the protoc callout? I am pretty
sure there is not, but since I am here, I'll ask.
I should mention that I can already get the routing key from within
Java without the descriptor, so I can parse that to determine what
base proto file that I need the descriptor for.
If you can't get a FileDescriptorSet ahead of time you'll need to
create one by calling out to protoc at run time...
The optimal thing would be to pre-compile the proto files into
FileDescriptorSet protobuf files and then have those available to you
at runtime so you dont have to make System.exec calls - and as such
become somewhat platform dependent.
The call you want to make is in the form
protoc --descriptor_set_out=[filename] --include_imports <proto file>
You probably want the include imports directive.
You can do this with System.exec() from java at runtime.
You can then load the resultant file (which will be a
FileDescriptorSet).
Here's a freebie:
final FileDescriptorSet fds = FileDescriptorSet.parseFrom(new
FileInputStream(myFile)); // load the file however you feel
appropriate - but close your streams : )
// special note - if you have custom options, you will
need to create an ExtensionRegistry with them and use it while parsing
the FileDescriptorSet
try {
Map<String, FileDescriptor> fdl = new HashMap<String,
FileDescriptor>();
FileDescriptor current = null;
for (FileDescriptorProto fdp : fds.getFileList()) {
final List<String> dependencyList =
fdp.getDependencyList();
final FileDescriptor[] fda = new
FileDescriptor[dependencyList
.size()];
for (int i = 0; i < fda.length; i++) {
FileDescriptor fddd =
fdl.get(dependencyList.get(i));
if (fddd == null) {
// missing imports! - this should not happen
unless you left off the --include_imports directive
} else {
fda[i] = fddd;
}
}
current = FileDescriptor.buildFrom(fdp, fda);
fdl.put(current.getName(), current);
}
// the "fdl" object now has all the descriptors - grab the
one you need.
By the way... for being pretty new to protobufs you're playing with
some pretty advanced features using the Descriptors at run-time.
Handy warning... depending on how you move objects around in java -
you may want to be aware the DynamicMessage, unlike GeneratedMessage,
is not Serializable. (this may not matter - but it can trip you up if
you're using JMS or some other java mechanism to send data and didn't
build the protos first). There are good reasons for this, so no it
can't be avoided.
On Oct 5, 1:12 pm, Dale Durham <geny...@gmail.com> wrote:
> I am fairly new to protobufs, so please bear with me. I am receiving
> protobuf messages that were compiled for C++ and I need to read them
> in Java. They are created WITHOUT descriptors by the provider and I
> cannot change that but I do have access to the base .proto files that
> the messages were based on.
> My questions are:
> 1) What is the best/fastest way to generate the file descriptor(s)
> into Java? This should be equal to calling importer.import in C++
> based on what I have read.
> 2) I assume that question 1 will involve a call out to protoc from
> Java. If so, how should that look in general and what command/options
> should be used? My goal is to get the file descriptor, after which I
> can get everything else from within Java
> 3) Is there any way to do this without the protoc callout? I am pretty
> sure there is not, but since I am here, I'll ask.
> I should mention that I can already get the routing key from within
> Java without the descriptor, so I can parse that to determine what
> base proto file that I need the descriptor for.
> I am fairly new to protobufs, so please bear with me. I am receiving
> protobuf messages that were compiled for C++ and I need to read them
> in Java. They are created WITHOUT descriptors by the provider and I
> cannot change that but I do have access to the base .proto files that
> the messages were based on.
> My questions are:
> 1) What is the best/fastest way to generate the file descriptor(s)
> into Java? This should be equal to calling importer.import in C++
> based on what I have read.
> 2) I assume that question 1 will involve a call out to protoc from
> Java. If so, how should that look in general and what command/options
> should be used? My goal is to get the file descriptor, after which I
> can get everything else from within Java
> 3) Is there any way to do this without the protoc callout? I am pretty
> sure there is not, but since I am here, I'll ask.
> I should mention that I can already get the routing key from within
> Java without the descriptor, so I can parse that to determine what
> base proto file that I need the descriptor for.
Thanks for the detailed and very helpful responses! First and
foremost, believe me when I say that the decision to tinker with the
more advanced protobuf features was somewhat forced on me, not a
choice that I made. I have to decode messages sent over the wire as
AMQP messages that are wrapping C++ compiled protobufs from a legacy
system.
I need to make the protobuf message details visible off-platform via a
browser, thus the choice for Java in favor of just using C++. Once I
receive the AMQP messages off-platform, I have no need or concern for
serialization from that point on, only display. I am pretty sure that
one I have the file descriptors, the rest will be fairly easy. I could
just generate the java source as you indicate below, but I thought
that may be a bit more expensive than just creating the file
descriptors, especially given that we have a huge amount of messages.
Thanks again for the rapid and detailed response! Hopefully, I'll get
some time today to muddle through this and see how it goes.
Regards,
Dale
On Oct 5, 2:19 pm, Benjamin Wright <compuware...@gmail.com> wrote:
> Also... if you have the base protos... why can't you simple compile
> the Java code for working with them?
> protoc --java_out=./gen-src myproto.proto
> On Oct 5, 1:12 pm, Dale Durham <geny...@gmail.com> wrote:
> > Hi All,
> > I am fairly new to protobufs, so please bear with me. I am receiving
> > protobuf messages that were compiled for C++ and I need to read them
> > in Java. They are created WITHOUT descriptors by the provider and I
> > cannot change that but I do have access to the base .proto files that
> > the messages were based on.
> > My questions are:
> > 1) What is the best/fastest way to generate the file descriptor(s)
> > into Java? This should be equal to calling importer.import in C++
> > based on what I have read.
> > 2) I assume that question 1 will involve a call out to protoc from
> > Java. If so, how should that look in general and what command/options
> > should be used? My goal is to get the file descriptor, after which I
> > can get everything else from within Java
> > 3) Is there any way to do this without the protoc callout? I am pretty
> > sure there is not, but since I am here, I'll ask.
> > I should mention that I can already get the routing key from within
> > Java without the descriptor, so I can parse that to determine what
> > base proto file that I need the descriptor for.
By "wrapping C++ compiled protobufs" I'm assuming that the protocol
buffers in transit are serialized as protobufs... so the C++ is a non-
issue (unless you mean some bizarre struct-based comms are going on...
in which case good luck ;-)
If you're in a web server environment you're probably better off
generating the java code as it will perform better and be easier to
interact with than dynamic protobufs code. If you have program size
constraints then dynamic is certainly the best way to keep code size
down as long as you're willing to deal with the increased complexity
(for you).
I use dynamic protobufs as I'm often working in an environment where I
don't always know what protocol buffers I will be using until run time
- at which point the FileDescriptorSet can be used to work with any
protobufs. For instance, this is useful when developing tooling for
Domain Specific Languages in the Eclipse IDE that are based on
protocol buffers. As it is somewhat difficult and clumsy to do class
loading for project class files, the FileDescriptorSets are an
excellent way to get generic access to any proto file being used.
If you do get stuck working with protobufs the purely dynamic way -
feel free to post here anytime. The dynamic usage is poorly
documented and there are various 'land mines' I've run into through my
usage - I would be happy to save you the same trouble.
On Oct 6, 9:51 am, Dale Durham <geny...@gmail.com> wrote:
> Thanks for the detailed and very helpful responses! First and
> foremost, believe me when I say that the decision to tinker with the
> more advanced protobuf features was somewhat forced on me, not a
> choice that I made. I have to decode messages sent over the wire as
> AMQP messages that are wrapping C++ compiled protobufs from a legacy
> system.
> I need to make the protobuf message details visible off-platform via a
> browser, thus the choice for Java in favor of just using C++. Once I
> receive the AMQP messages off-platform, I have no need or concern for
> serialization from that point on, only display. I am pretty sure that
> one I have the file descriptors, the rest will be fairly easy. I could
> just generate the java source as you indicate below, but I thought
> that may be a bit more expensive than just creating the file
> descriptors, especially given that we have a huge amount of messages.
> Thanks again for the rapid and detailed response! Hopefully, I'll get
> some time today to muddle through this and see how it goes.
> Regards,
> Dale
> On Oct 5, 2:19 pm, Benjamin Wright <compuware...@gmail.com> wrote:
> > Also... if you have the base protos... why can't you simple compile
> > the Java code for working with them?
> > protoc --java_out=./gen-src myproto.proto
> > On Oct 5, 1:12 pm, Dale Durham <geny...@gmail.com> wrote:
> > > Hi All,
> > > I am fairly new to protobufs, so please bear with me. I am receiving
> > > protobuf messages that were compiled for C++ and I need to read them
> > > in Java. They are created WITHOUT descriptors by the provider and I
> > > cannot change that but I do have access to the base .proto files that
> > > the messages were based on.
> > > My questions are:
> > > 1) What is the best/fastest way to generate the file descriptor(s)
> > > into Java? This should be equal to calling importer.import in C++
> > > based on what I have read.
> > > 2) I assume that question 1 will involve a call out to protoc from
> > > Java. If so, how should that look in general and what command/options
> > > should be used? My goal is to get the file descriptor, after which I
> > > can get everything else from within Java
> > > 3) Is there any way to do this without the protoc callout? I am pretty
> > > sure there is not, but since I am here, I'll ask.
> > > I should mention that I can already get the routing key from within
> > > Java without the descriptor, so I can parse that to determine what
> > > base proto file that I need the descriptor for.