由于解析错误,未调用Spring-Kafka消费者的侦听器方法

时间:2020-09-10 11:07:19

标签: spring-boot spring-kafka

我正在尝试使用Kafka-Spring(spring-boot)实现Kafka使用者。我使用生产者发送消息,但Spring引发异常,并且由于该异常而未调用我的侦听器方法。
这是我的侦听器方法:

@Service
public class KafkaExchangeApi {

    @KafkaListener(topics = ORDER_TOPIC, groupId = "group_id")
    public void handleOrderResponse(@Payload GatewayOrder response) {
       System.println("order caught");
    }

}


@AllArgsConstructor
@NoArgsConstructor(force = true)
@Builder
@Getter
@ToString
public class GatewayOrder {

    private final long uid;
    
    private final long orderId;

    private final int userCookie;

    private final long size;
    private final OrderAction action;
    private final OrderType orderType;

    private final String symbol;

    // mutable fields

    private List<GatewayDeal> deals = new ArrayList<>();

    @Setter
    private BigDecimal price;

    @Setter
    private long filled;

    @Setter
    private GatewayOrderState state;

}

这是我的配置:

server:
  port: 9000
spring:
  kafka:
    consumer:
      bootstrap-servers: 192.168.1.3:9092
      group-id: group-id
      auto-offset-reset: earliest
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
    producer:
      bootstrap-servers: 192.168.1.3:9092
      key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
      value-deserializer: org.apache.kafka.common.serialization.StringDeserializer

我认为生产者发送的JSON消息格式错误,我测试了是否可以使用JSON解析器对其进行解析,并确认可以对其进行解析...
那么,为什么我会收到此异常?

020-09-10 17:04:41.878  INFO 5946 --- [ntainer#1-0-C-1] o.a.k.c.c.internals.SubscriptionState    : [Consumer clientId=consumer-group_id-2, groupId=group_id] Resetting offset for partition order-0 to offset 0.
2020-09-10 17:04:41.879  INFO 5946 --- [ntainer#1-0-C-1] o.s.k.l.KafkaMessageListenerContainer    : group_id: partitions assigned: [order-0]
2020-09-10 17:04:55.250 ERROR 5946 --- [ntainer#1-0-C-1] o.s.k.l.SeekToCurrentErrorHandler        : Backoff none exhausted for ConsumerRecord(topic = order, partition = 0, leaderEpoch = 0, offset = 0, CreateTime = 1599746694173, serialized key size = -1, serialized value size = 160, headers = RecordHeaders(headers = [], isReadOnly = false), key = null, value = {"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"})

org.springframework.kafka.listener.ListenerExecutionFailedException: Listener method could not be invoked with the incoming message
Endpoint handler details:
Method [public void  tradeapi.service.KafkaExchangeApi.handleOrderResponse( tradeapi.model.internal.GatewayOrder)]
Bean [ tradeapi.service.KafkaExchangeApi@2143ea5e]; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot handle message; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot convert from [java.lang.String] to [ tradeapi.model.internal.GatewayOrder] for GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}], failedMessage=GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}]; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot handle message; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot convert from [java.lang.String] to [ tradeapi.model.internal.GatewayOrder] for GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}], failedMessage=GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.decorateException(KafkaMessageListenerContainer.java:1925) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeErrorHandler(KafkaMessageListenerContainer.java:1913) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:1812) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:1739) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:1636) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:1366) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1082) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:990) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) ~[na:na]
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:834) ~[na:na]
Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot handle message; nested exception is org.springframework.messaging.converter.MessageConversionException: Cannot convert from [java.lang.String] to [ tradeapi.model.internal.GatewayOrder] for GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}], failedMessage=GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}]
    at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:340) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:86) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.adapter.RecordMessagingMessageListenerAdapter.onMessage(RecordMessagingMessageListenerAdapter.java:51) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:1880) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeOnMessage(KafkaMessageListenerContainer.java:1862) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:1799) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    ... 8 common frames omitted
Caused by: org.springframework.messaging.converter.MessageConversionException: Cannot convert from [java.lang.String] to [ tradeapi.model.internal.GatewayOrder] for GenericMessage [payload={"uid":1, "orderId":1, "userCookie": 0, "size": 1, "action": "ASK", "orderType": "IOC", "symbol": "ABC", "deals":null, "price":1, "filled": 0, "state":"ACTIVE"}, headers={kafka_offset=0, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@fb7548f, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, kafka_receivedTopic=order, kafka_receivedTimestamp=1599746694173, kafka_groupId=group_id}]
    at org.springframework.messaging.handler.annotation.support.PayloadMethodArgumentResolver.resolveArgument(PayloadMethodArgumentResolver.java:145) ~[spring-messaging-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.kafka.annotation.KafkaListenerAnnotationBeanPostProcessor$KafkaNullAwarePayloadArgumentResolver.resolveArgument(KafkaListenerAnnotationBeanPostProcessor.java:901) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:117) ~[spring-messaging-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:148) ~[spring-messaging-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:116) ~[spring-messaging-5.2.8.RELEASE.jar:5.2.8.RELEASE]
    at org.springframework.kafka.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:48) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:329) ~[spring-kafka-2.5.5.RELEASE.jar:2.5.5.RELEASE]
    ... 13 common frames omitted

1 个答案:

答案 0 :(得分:0)

使用StringDeserializer,您需要向应用程序中添加JsonMessageConverter @Bean。请参见https://docs.spring.io/spring-kafka/docs/2.6.0/reference/html/#messaging-message-conversion-引导程序会将其自动配置到侦听器容器工厂中。

使用ByteArrayDeserializer避免不必要的从byte[]String的转换,效率更高。

或者您可以对kafka使用者配置使用经过适当配置的JsonDeserializer

无论哪种方式,您都需要将Jackson添加到类路径中。