jackson-dataformats-binary icon indicating copy to clipboard operation
jackson-dataformats-binary copied to clipboard

[protobuf] 'Map' type not supported as type by protobuf module

Open amanvishnani opened this issue 6 years ago • 9 comments

java.lang.UnsupportedOperationException: 'Map' type not supported as type by protobuf module
	at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtoBufSchemaVisitor._throwUnsupported(ProtoBufSchemaVisitor.java:208) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.fasterxml.jackson.dataformat.protobuf.schemagen.ProtoBufSchemaVisitor.expectMapFormat(ProtoBufSchemaVisitor.java:96) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.fasterxml.jackson.databind.ser.std.MapSerializer.acceptJsonFormatVisitor(MapSerializer.java:907) ~[jackson-databind-2.8.10.jar:2.8.10]
	at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.acceptTypeElement(MessageElementVisitor.java:137) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.getDataType(MessageElementVisitor.java:121) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.buildFieldElement(MessageElementVisitor.java:86) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.fasterxml.jackson.dataformat.protobuf.schemagen.MessageElementVisitor.optionalProperty(MessageElementVisitor.java:59) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.depositSchemaProperty(BeanPropertyWriter.java:816) ~[jackson-databind-2.8.10.jar:2.8.10]
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.acceptJsonFormatVisitor(BeanSerializerBase.java:832) ~[jackson-databind-2.8.10.jar:2.8.10]
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.acceptJsonFormatVisitor(DefaultSerializerProvider.java:580) ~[jackson-databind-2.8.10.jar:2.8.10]
	at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:3666) ~[jackson-databind-2.8.10.jar:2.8.10]
	at com.fasterxml.jackson.databind.ObjectMapper.acceptJsonFormatVisitor(ObjectMapper.java:3645) ~[jackson-databind-2.8.10.jar:2.8.10]
	at com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper.generateSchemaFor(ProtobufMapper.java:110) ~[jackson-dataformat-protobuf-2.9.2.jar:2.9.2]
	at com.amanvishnani.crudapp.SampleController.test(SampleController.java:73) ~[classes/:na]
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.7.0_80]
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) ~[na:1.7.0_80]
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_80]
	at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_80]
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:967) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:635) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) ~[spring-webmvc-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:742) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) ~[tomcat-embed-websocket-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [na:1.7.0_80]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [na:1.7.0_80]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.20.jar:8.5.20]
	at java.lang.Thread.run(Thread.java:745) [na:1.7.0_80]

I am trying to get protobuf schema of the following POJO object.

class Test {
    Map<String,String> props;

/* Getters & Setters */
}

The exception is thrown on executing the following LOC.

ProtobufMapper mapper = new ProtobufMapper();
ProtobufSchema schemaWrapper = mapper.generateSchemaFor(Test.class); // On this line
NativeProtobufSchema nativeProtobufSchema = schemaWrapper.getSource();

String asProtofile = nativeProtobufSchema.toString();
System.out.println(asProtofile);

I was hoping that since Maps are supported in Protocol Buffers then it should have been implemented in this library. I am using the following version.

<dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-protobuf</artifactId>
            <version>2.9.2</version>
</dependency>

amanvishnani avatar Nov 07 '17 15:11 amanvishnani

Thank you for reporting this.

Protobuf v2 does not really have a Map type natively as far as I recall, and has to be emulated by something like an array of objects with 2 properties (key and value). So the challenge is that of choosing a standard representation for such structure; I am not sure if spec suggests anything.

Similar problem probably affects the reverse case too, of a map-like structure to bind to Java Map values.

cowtowncoder avatar Nov 07 '17 16:11 cowtowncoder

I can find Map definition on the official doc webpage. https://developers.google.com/protocol-buffers/docs/proto#maps

amanvishnani avatar Nov 07 '17 16:11 amanvishnani

Ah. Ok. Well then that should be quite doable. Thank you for pointing that out -- I think (although can not point out) that this was added after module was originally written, so I just recall that there is no native structure. Either way, yes, handling should be added.

cowtowncoder avatar Nov 07 '17 16:11 cowtowncoder

I'd also love to have this feature. Is there any ETA?

felixbarny avatar Feb 16 '18 14:02 felixbarny

I don't think anyone is working on this. Typically any work would be accompanied by updates here.

cowtowncoder avatar Feb 16 '18 18:02 cowtowncoder

This seems like a fairly important feature in order for this to be useable. Any updates on this being implemented?

Edit: Also, are there any workarounds? I was thinking about providing a StdSerializer/Deserializer, but I'm fairly certain that that wouldn't help with the generation of the schema. Is there a way for me to tell it to consider a Map<String, String> to be a List<Pair<String, String>> for the purpose of generating the schema (and then I can go ahead and implement the serialization/deserialization myself).

MrThreepwood avatar Oct 22 '18 17:10 MrThreepwood

Any updates on this?

amanvishnani avatar Jan 29 '20 18:01 amanvishnani

looks pretty hard to add arbitrary map support, consider well known json type in protobuf is not well supported.

holyshipt avatar Feb 11 '20 23:02 holyshipt

Later spec version (for Protobuf 2.x) does seem to indicate guidance on how to handle Map types, so this should be doable. I just wish I had time to work on this.

cowtowncoder avatar Feb 12 '20 02:02 cowtowncoder