I'm trying to create a wrapper DTO whereby the inner payload could be
anything. The main consumer will be a router that has to handle the
deserialization and fan the message out to receiving services. To do this I
need a key to effectively wrap and unwrap proto objects in a layer that
knows nothing of the inner payload type. I did look at using Any to get
this to work, however that requires you have a handle to the class of the
message you need to unpack. I worked around this creating a similar
construct of my own, AnyDto.
I created these protos to do the job:
syntax = "proto3";
option java_multiple_files = true;
package proto3spike.dtos;
message EnvelopeDto {
string operationName = 1;
AnyDto payload = 2;
}
message AnyDto {
string canonicalName = 1;
bytes value = 2;
}
The following utility to wrap and unwrap the AnyDto into a Message instance
package proto3spike;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.MessageLite;
import proto3spike.dtos.AnyDto;
public class AnyDtoMapper {
public static AnyDto mapToAnyDto(Message payload) throws
InvalidProtocolBufferException {
String canonicalName = payload.getClass().getCanonicalName();
return AnyDto.newBuilder()
.setCanonicalName(canonicalName)
.setValue(payload.toByteString())
.build();
}
public static Message mapFromAnyDto(AnyDto dto) throws Exception {
Class c = Class.forName(dto.getCanonicalName());
MessageLite defaultInstance = com.google.protobuf.Internal.
getDefaultInstance(c);
return (Message)defaultInstance
.getParserForType()
.parseFrom(dto.getValue());
}
}
When using mapFromAnyDto() higher order code needs to cast to a specific
Message instance. For now I'm happy to deal with that, effectively some
routing on the operationName field will get the message to the right place
where the case can be performed in a realisable way.
This works nicely with java to java communication.
However in Javascript, when I come to wrap and unwrap the message I'm left
with no reliable means to map AnyDto.canonicalName to the generated proto
objects.
It does look like the generated JS protos contain similar namespacing to
the corresponding class (and thus canonical name) in the java space. For
example, in the generated JS PB file:
/**
* @fileoverview
* @enhanceable
* @public
*/
// GENERATED CODE -- DO NOT EDIT!
var jspb = require('google-protobuf');
var goog = jspb;
var global = Function('return this')();
goog.exportSymbol('proto.proto3spike.dtos.AnyDto', null, global);
goog.exportSymbol('proto.proto3spike.dtos.EnvelopeDto', null, global);
/**
* Generated by JsPbCodeGenerator.
* @param {Array=} opt_data Optional initial data array, typically from a
* server response, or constructed directly in Javascript. The array is used
* in place and becomes part of the constructed object. It is not cloned.
* If no data is provided, the constructed object will be empty, but still
* valid.
* @extends {jspb.Message}
* @constructor
*/
proto.proto3spike.dtos.EnvelopeDto = function(opt_data) {
jspb.Message.initialize(this, opt_data, 0, -1, null, null);
};
goog.inherits(proto.proto3spike.dtos.EnvelopeDto, jspb.Message);
if (goog.DEBUG && !COMPILED) {
proto.proto3spike.dtos.EnvelopeDto.displayName =
'proto.proto3spike.dtos.EnvelopeDto';
}
// ... rest of the file ...
As you can see in debug mode there is a displayName on the message objects,
additionally the messages get exported to a global namespace that somewhat
matches the java package (and thus canonical name).
Using the canonical name of the java Message.class now seems like a hack.
Is there a reliable method to identify and lookup a message from both the
Java and Java script API so I can dynamically serialise/deserialise it?
If not, can I somehow extend the generated JS to add a custom key (i.e. the
canonical name) to the generated JavaScript code?
Thanks for any help
Keith
--
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/protobuf.
For more options, visit https://groups.google.com/d/optout.