Indeed, the payload format that both IS and UM understand is google protocol buffers, so as a prerequisite, your document type should be using protobuf encoding in IS (and not IData). Generally speaking, there are two ways to work with a protobuf message. One is to generate a type/stub from a protobuf definition, much similar to how you can generate a stub from an xml schema for a web service call for example. The second option is to approach it as a generic structured document, similar to what a document type in IS looks like. I am assuming you are after the second approach.
In UM native API, the way to handle protobuf events is by using the nProtobufEvent class, which is a subclass of the standard nConsumeEvent. If you’ve published a protobuf encoded event from IS, you should be able to typecast it to nProtobufEvent when you handle it through the UM native API (regardless of whether you are using Java, C# or C++). From this point on, you will need to unmarshall the protobuf payload into a structured document. UM will not do that automatically and in fact most of the time this is not needed.
In order to unmarshall the payload you will need the protobuf definition which can be obtained from the channel attributes (com.pcbsys.nirvana.client.nChannelAttributes#getProtobufDescriptorSets).
The protobuf descriptor is actually a compiled binary itself, and technically one channel can hold several descriptors. Ultimately the goal is to get a com.google.protobuf.Descriptors.Descriptor and build a protobuf DynamicMessage out of it using the protobuf API - DynamicMessage.parseFrom(descriptor, payload), where the payload is com.pcbsys.nirvana.client.nProtobufEvent#getEventData() and the descriptor is the one that corresponds to the event root type (com.pcbsys.nirvana.client.nProtobufEvent#getAttributes().getType()). Once you have a protobuf DynamicMessage you can traverse its attributes as a generic structured document.
Building the descriptors can get quite complex due to a potentially nested structure with multiple complex types and various references between them. The safest approach is to load all definitions in your descriptor. I believe that you can also obtain the definitions from IS - I believe it can store them in files on disk when certain debug option is switched on. You can store them in files after extracting them from the UM channel too, and then load them up using com.google.protobuf.DescriptorProtos.FileDescriptorSet#newBuilder()
In runtime I wouldn’t expect that the protobuf definitions would change frequently (if at all), so it wouldn’t make sense to build these descriptor for every event, but rather maintain a cache. This is how the Enterprise Manager works for example. Unfortunately it’s not a public API that can be exposed.
I searched around but unfortunately I couldn’t find ready-to-use samples. I’ll see if I can get something written up, but it might take some time.