【问题标题】:Can Avro-generated classes be used directly with Spring HATEOAS EntityModel?Avro 生成的类可以直接与 Spring HATEOAS EntityModel 一起使用吗?
【发布时间】:2019-10-08 14:04:44
【问题描述】:

我正在尝试使用 avro-maven-plugin 1.8.2 和 spring-hateoas 1.0.0.RELEASE(通过 Spring Boot 2.2.0.RC1)从模式生成的域模型类。 Spring MVC 5.2.0.RELEASE 框架在@RestController 创建的EntityModel 序列化期间抛出org.springframework.http.converter.HttpMessageNotWritableExceptionEntityModel 是使用 SimpleIdentifiableRepresentationModelAssembler 子类组装的。

在将 Avro 对象传递给表示模型组装器之前将它们映射到 POJO 可以在序列化期间按预期工作,但从长远来看,复制域模型不会针对此应用程序进行扩展。我读过custom media types,我可能会为application/hal+avro+json 做这样的事情,但对于表示模型之外的一组对象来说,这是一个很深的兔子洞,很容易序列化为简单的 JSON。特别是因为 REST 客户端实际上并不需要嵌入在这些对象中的 Avro 模式......但是。 Avro 的内部消费者确实需要它。

FundController.java:

@Autowired
private final FundRepresentationModelAssembler assembler;

...

@GetMapping(value = "/funds/{id}")
public ResponseEntity<EntityModel<Fund>> findOne(@PathVariable final String id) {
  return this.repo.findById(id)
    .map(this.assembler::toModel)
    .map(ResponseEntity::ok)
    .orElse(ResponseEntity.notFound().build());
}

FundRepresentationModelAssembler.java:

@Component
public class FundRepresentationModelAssembler extends SimpleIdentifiableRepresentationModelAssembler<Fund> {
    public FundRepresentationModelAssembler() {
        super(FundController.class);
    }
}

模型 pom.xml:

<plugins>
  <plugin>
    <groupId>org.apache.avro</groupId>
    <artifactId>avro-maven-plugin</artifactId>
    <version>1.8.2</version>
    <executions>
      <execution>
        <phase>generate-sources</phase>
        <goals>
          <goal>schema</goal>
        </goals>
      </execution>
    </executions>
  </plugin>
  ...
</plugins>

模型架构:

{"namespace": "org.example.model",
 "type": "record",
 "name": "Fund",
 "fields": [
     {"name": "id", "type": "string"},
     {"name": "description",  "type": "string"}
 ]
}

格式正确的错误是:

org.springframework.http.converter.HttpMessageNotWritableException:
  Could not write JSON:
    Not an array: {"type":"record","name":"Fund","namespace":"org.example.model","fields":[{"name":"id","type":"string"},{"name":"description","type":"string"}]}

nested exception is com.fasterxml.jackson.databind.JsonMappingException: 
  Not an array: {"type":"record","name":"Fund","namespace":"org.example.model","fields":[{"name":"id","type":"string"},{"name":"description","type":"string"}]} 

through reference chain: org.springframework.hateoas.EntityModel["content"]
  ->org.example.model.Fund["schema"]
    ->org.apache.avro.Schema$RecordSchema["elementType"]

我希望存在一种将“序列化提示”通过 HATEOAS 框架传递给 Jackson 的方法。

【问题讨论】:

    标签: spring-boot spring-mvc avro spring-hateoas


    【解决方案1】:

    一旦我了解了 Spring HATEOAS EntityModel 的工作原理,这被证明是最简单的事情。它没有特别的魔力,它只是使用@JsonUnwrapped,所以Jackson 将其内容字段序列化到与其链接相同的级别。 Spring 提供的 Jackson ObjectMapper 假定内容是 POJO,除非我注册了更合适的内容。杰克逊提供jackson-dataformat-avro。所需要的只是向 Spring 注册:

    @SpringBootApplication
    public class ChartOfAccounts {
        public static void main(String[] args) {
            SpringApplication.run(ChartOfAccounts.class, args);
        }
    
        @Bean
        public AvroModule avroDataFormat() {
            return new AvroModule();
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-01-04
      • 1970-01-01
      • 1970-01-01
      • 2013-08-30
      • 1970-01-01
      • 2018-01-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多