Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot Protobuf No serializer found for class com.google.protobuf.UnknownFieldSet$Parser

I want to use spring boot with protobuf. Briefly I write demo code with belowing structure;

RestController->get entity->Postgres DB Repo->entity to protobuf object->return protobuf object

pom proto dependency;

<dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java</artifactId>
        <version>3.12.4</version>
    </dependency>
    <dependency>
        <groupId>com.googlecode.protobuf-java-format</groupId>
        <artifactId>protobuf-java-format</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>com.google.protobuf</groupId>
        <artifactId>protobuf-java-util</artifactId>
        <version>3.13.0</version>
    </dependency>

Proto file

syntax = "proto3";

package demo;

option java_package = "demo.model";
option java_outer_classname = "DemoProtos";

message DemoDto {
  int64 id = 1;
  string description = 2;    

}

gen.sh file

#!/usr/bin/env bash
    
SRC_DIR=`pwd`
DST_DIR=`pwd`/../src/main/

echo source:            $SRC_DIR
echo destination root:  $DST_DIR


function gen(){
    D=$1
    echo $D
    OUT=$DST_DIR/$D
    mkdir -p $OUT
    sudo protoc -I=$SRC_DIR --${D}_out=$OUT $SRC_DIR/demo.proto
}    

gen java

My RestController

@RestController
class DemoRestController {

    @Autowired
    private DemoRepository demoRepository;

    @RequestMapping("/demo/{id}")
    ResponseEntity<DemoProtos.DemoDto> date(@PathVariable Integer id) {
        Optional<Demo> demo = this.demoRepository.findById(id);

        if (demo.isPresent()) {
            Demo dt = demo.get();
            DemoProtos.DemoDto tempDemo = DemoProtos.DemoDto.newBuilder()
                    .setDescription(dt.getDescription())
                    .setId(id)
                    .build();
            return new ResponseEntity<>(tempDemo, HttpStatus.OK);
        }
        return null;
    }
}

Demo Entity Object

@Entity
@Table(name = "DEMO_TABLE", schema = "SDEMO")
@Data
public class Demo {

    @Id
    private Integer id;

    @Column(name = "description")
    private String description;

}

And application class

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    ProtobufHttpMessageConverter protobufHttpMessageConverter() {
        return new ProtobufHttpMessageConverter();
    }

}

When I request the http://localhost:8080/demo/2 occuring exception like this;

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet$Parser]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.google.protobuf.UnknownFieldSet$Parser and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: demo.model.DemoProtos.DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["parserForType"])
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.37.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ...
Caused by: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet$Parser]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.google.protobuf.UnknownFieldSet$Parser and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: demo.model.DemoProtos.DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["parserForType"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:341) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:287) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ...

2020-08-17 12:49:48.031 ERROR 1708168 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet$Parser]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.google.protobuf.UnknownFieldSet$Parser and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: demo.model.DemoProtos.DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["parserForType"])] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: No serializer found for class com.google.protobuf.UnknownFieldSet$Parser and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) (through reference chain: demo.model.DemoProtos.DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["parserForType"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400) ~[jackson-databind-2.11.1.jar:2.11.1]
...

Then I added this parameter to properties file.

spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

Exception changed to;

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: demo.model.DemoProtos$DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:626) ~[tomcat-embed-core-9.0.37.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.37.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.37.jar:9.0.37]
    ...
Caused by: org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: demo.model.DemoProtos$DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])
    at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:341) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.http.converter.AbstractGenericHttpMessageConverter.write(AbstractGenericHttpMessageConverter.java:104) ~[spring-web-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:287) ~[spring-webmvc-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    ...
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: demo.model.DemoProtos$DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:945) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:722) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.dataformat.xml.ser.XmlBeanSerializerBase.serializeFields(XmlBeanSerializerBase.java:212) ~[jackson-dataformat-xml-2.11.1.jar:2.11.1]
    ...

2020-08-17 11:56:07.430 ERROR 1691529 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[.[dispatcherServlet]      : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.google.protobuf.UnknownFieldSet]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: demo.model.DemoProtos$DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])] with root cause

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: demo.model.DemoProtos$DemoDto["unknownFields"]->com.google.protobuf.UnknownFieldSet["defaultInstanceForType"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1277) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:945) ~[jackson-databind-2.11.1.jar:2.11.1]
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:722) ~[jackson-databind-2.11.1.jar:2.11.1]
    ...

What is wrong for me, is there any comment my problem? Thanks

like image 870
compengr Avatar asked Aug 12 '26 14:08

compengr


2 Answers

I had this error and along as M.Deinum mentioned, headers mattered.

I was calling the route from a python script and added this, and the call started working:

headers={"Content-Type": mimetypes.PROTO, "Accept": mimetypes.PROTO},
like image 127
Sean Colombo Avatar answered Aug 14 '26 03:08

Sean Colombo


I also encountered the same problem and solved it through other means.

Reason: I found that the reason for my problem is that I encountered the serialization error mentioned above when converting the grpc Response field to Object.

Solution: Redefine the type and place the response value into the new type, which solves this problem.

The code is as follows:


    @GetMapping("/hello_grpc")
    public Object helloGrpc(@RequestParam(defaultValue = "hello") String content, @RequestParam(defaultValue = "0") Integer sleep) {
        LoadRequestParam param = LoadRequestParam.newBuilder().setContent(content).setSleep(sleep).build();
        HelloResponse response = ratingsGrpcClient.hello(HelloRequest.newBuilder().setParam(param).build());
        Map<String,String> result = new HashMap<>(4);
        result.put("content",response.getContent());
        result.put("ip",response.getIp());
        return result;
    }
like image 42
王玉帅 Avatar answered Aug 14 '26 05:08

王玉帅