我有一个带有RabbitMQ活页夹的Spring Cloud Stream(Elmhurst版本)拆分器。我正在尝试对其进行更新,以便它将对负载使用Avro模式。我遇到了一个转换异常,这使得它似乎没有被调用Avro转换器,并且JSON转换器接收了消息并对其进行了触发。
由以下原因引起:org.springframework.messaging.converter.MessageConversionException:无法编写JSON:不是地图:{“ type”:“ record”,“ name”:“ SkinnyMessage”,“ namespace”:“ com.example .avro“,” doc“:”用于传递对消息对象的引用的轻消息“,”字段“:[{” name“:” id“,” type“:” string“},{” name“:” guid“ ,“” type“:” string“}]}(通过参考链:com.example.avro.SkinnyMessage [” schema“]-> org.apache.avro.Schema $ RecordSchema [” valueType“]);嵌套的异常是com.fasterxml.jackson.databind.JsonMappingException:不是映射:{“ type”:“ record”,“ name”:“ SkinnyMessage”,“ namespace”:“ com.example.avro”,“ doc”: “用于传递对消息对象的引用的轻消息”,“字段”:[{“名称”:“ id”,“类型”:“字符串”},{“名称”:“ guid”,“类型”:“字符串” }]}(通过参考链:com.example.avro.SkinnyMessage [“ schema”]-> org.apache.avro.Schema $ RecordSchema [“ valueType”])
我已经确认可以使用生成的Avro类(maven-avro插件)创建对象并将其序列化到磁盘,因此该部分似乎正确。我已经将项目从Groovy转换为Java,但仍然遇到相同的错误,因此我认为也可以排除。
以下是Avro模式:
{
"namespace": "com.example.avro",
"type": "record",
"name": "SkinnyMessage",
"doc": "Light message for passing references to Message objects",
"fields": [
{
"name": "id",
"type": "string"
},
{
"name": "guid",
"type": "string"
}
]
}
以及课程的相关部分:
@EnableBinding(Processor.class)
@EnableSchemaRegistryClient
class PagingQueryProcessorApplication {
@Timed(value = 'paging.query')
@Splitter(inputChannel = Processor.INPUT, outputChannel = Processor.OUTPUT)
List<SkinnyMessage> queryExecutor(def trigger){
log.debug 'Building query'
def query = queryConfiguration.buildQuery().toUriString()
log.info "Executing query: ${query}"
def response = service.getRecordings(query)
log.info "Returning response collection: ${response.body.content.size()}"
// We build a slim notification on each of the query responses
def skinnyMessages = response.body.content.collect{
new SkinnyMessage(it.getLink('self').getHref(), it.content.guid)
}
skinnyMessages
}
...
}
编辑:当我逐步调试时,可以看到AvroSchemaRegistryClientMessageConverter未能通过canConvertTo(payload, headers)
调用,因为标头中的mimeType
是application/json
而不是application/*+avro
,因此它将继续尝试其余的转换器链。
答案 0 :(得分:0)
如果我生成一条消息并在其上设置avro content-type标头,那似乎行得通,但这似乎是一种hack。
List<Message<SkinnyMessage>> skinnyMessages = response.body.content.collect{
MessageBuilder.withPayload(
new SkinnyMessage(it.getLink('self').getHref(), it.content.recordingGuid))
.setHeader('contentType', 'application/*+avro')
.build()
}
创建在RabbitMQ UI中看起来正确的消息:
contentType:application / vnd.skinnymessage.v1 + avro 相关ID:f8be74d6-f780-efcc-295d-338a8b7f2ea0 content_type:应用程序/八位字节流 有效载荷 96个字节 编码:字符串
thttps://example.com/message/2597061H9a688e40-3e30-4b17-80e9-cf4f897e8a91
但是,如果我正确理解了文档,则应该从application.yml:中透明地进行设置(如Schema Registry Samples):
spring:
cloud:
stream:
bindings:
output:
contentType: application/*+avro