EmbeddedHeadersMessageConverter的StringIndexOutOfBoundsException

时间:2016-04-11 18:41:19

标签: spring spring-integration spring-cloud-stream

我正在将简单的Kafka消费者应用程序移出现有框架,感觉像spring-cloud-stream是一种简单的方法。我使用Initializr来引导应用程序,现在使用的是Spring-Boot v1.3.3和Spring-Cloud-Stream v1.0.0-RC1。该应用程序非常简单,它只需要从Kafka中选择一条消息,反序列化JSON编码对象并将其传递给我们现有的库。为了开始,我只使用了LogSink示例,因为最终我不会做其他事情(只是反序列化并将对象传递给不同的方法)。

一切都很好:它连接到Kafka,接收消息并将其传递给我的接收器(如byte [])。但是,EmbeddedHeadersMessageConverter会记录一个StringIndexOutOfBoundsException:

2016-04-11 10:06:50.287 ERROR 11464 --- [pool-1-thread-1] fkaMessageChannelBinder$ReceivingHandler : Could not convert message: 7B2267656E65726174696F6E223A3 [...]
java.lang.StringIndexOutOfBoundsException: String index out of range: 2009
    at java.lang.String.checkBounds(String.java:373) ~[na:1.8.0_25]
    at java.lang.String.<init>(String.java:413) ~[na:1.8.0_25]
    at org.springframework.cloud.stream.binder.EmbeddedHeadersMessageConverter.oldExtractHeaders(EmbeddedHeadersMessageConverter.java:131) ~[spring-cloud-stream-1.0.0.RC1.jar:1.0.0.RC1]
    at org.springframework.cloud.stream.binder.EmbeddedHeadersMessageConverter.extractHeaders(EmbeddedHeadersMessageConverter.java:104) ~[spring-cloud-stream-1.0.0.RC1.jar:1.0.0.RC1]
    at org.springframework.cloud.stream.binder.kafka.KafkaMessageChannelBinder$ReceivingHandler.handleRequestMessage(KafkaMessageChannelBinder.java:583) ~[spring-cloud-stream-binder-kafka-1.0.0.RC1.jar:1.0.0.RC1]
    at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:99) [spring-integration-core-4.2.5.RELEASE.jar:na]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) [spring-integration-core-4.2.5.RELEASE.jar:na]
    at org.springframework.integration.channel.FixedSubscriberChannel.send(FixedSubscriberChannel.java:69) [spring-integration-core-4.2.5.RELEASE.jar:na]
    at org.springframework.integration.channel.FixedSubscriberChannel.send(FixedSubscriberChannel.java:63) [spring-integration-core-4.2.5.RELEASE.jar:na]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) [spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:45) [spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:105) [spring-messaging-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:105) [spring-integration-core-4.2.5.RELEASE.jar:na]
    at org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter.access$300(KafkaMessageDrivenChannelAdapter.java:43) [spring-integration-kafka-1.3.0.RELEASE.jar:na]
    at org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter$AutoAcknowledgingChannelForwardingMessageListener.doOnMessage(KafkaMessageDrivenChannelAdapter.java:171) [spring-integration-kafka-1.3.0.RELEASE.jar:na]
    at org.springframework.integration.kafka.listener.AbstractDecodingMessageListener.onMessage(AbstractDecodingMessageListener.java:50) [spring-integration-kafka-1.3.0.RELEASE.jar:na]
    at org.springframework.integration.kafka.listener.QueueingMessageListenerInvoker$KafkaMessageDispatchingSubscriber.onNext(QueueingMessageListenerInvoker.java:221) [spring-integration-kafka-1.3.0.RELEASE.jar:na]
    at org.springframework.integration.kafka.listener.QueueingMessageListenerInvoker$KafkaMessageDispatchingSubscriber.onNext(QueueingMessageListenerInvoker.java:209) [spring-integration-kafka-1.3.0.RELEASE.jar:na]
    at reactor.core.processor.util.RingBufferSubscriberUtils.route(RingBufferSubscriberUtils.java:67) [reactor-core-2.0.7.RELEASE.jar:na]
    at reactor.core.processor.RingBufferProcessor$BatchSignalProcessor.run(RingBufferProcessor.java:789) [reactor-core-2.0.7.RELEASE.jar:na]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_25]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25]
    at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]

https://github.com/spring-cloud/spring-cloud-stream/issues/209似乎表明问题是缺少Kafka标题,这是真的,没有任何问题。但是提到的解决方案是添加

spring.cloud.stream.binder.kafka.mode=raw

到我的应用程序配置。不幸的是,这对我不起作用。此外,STS实际上已经为各个属性进行了自动完成,并建议

spring.cloud.stream.kafka.binder.mode=raw

两者(单独或组合)都没有任何区别,但仍然记录了例外情况。

我已经使用了Spring多年,但这将是我的第一个Spring-Boot / Spring-Cloud应用程序。

这是应用程序代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.stream.annotation.EnableBinding;
import org.springframework.cloud.stream.annotation.StreamListener;
import org.springframework.cloud.stream.messaging.Sink;
import org.springframework.integration.annotation.ServiceActivator;

@SpringBootApplication
public class UpdateApplication {
    private static Logger logger  = LoggerFactory.getLogger(UpdateApplication.class);

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

    @EnableBinding(Sink.class)
    public static class UpdateHandler {

        @StreamListener(Sink.INPUT)
        //@ServiceActivator(inputChannel=Sink.INPUT)
        public void loggerSink(Object payload) {
            logger.info("Received: " + payload);
        }        
    }
}

我尝试了@ServiceActivator和@StreamListener注释,在这种情况下似乎没有什么区别。

我的application.properties看起来像这样:

spring.cloud.stream.bindings.input.binder=kafka
spring.cloud.stream.bindings.input.destination=updates
spring.cloud.stream.bindings.input.group=update-client
spring.cloud.stream.kafka.binder.brokers=brokerName
spring.cloud.stream.kafka.binder.zkNodes=zookeeperName
spring.cloud.stream.kafka.binder.mode=raw

任何帮助摆脱这个错误都将不胜感激。

作为旁注:由于我刚开始尝试使用spring-cloud-stream,我添加了

spring.cloud.stream.bindings.updates.consumer.resetOffsets=true
spring.cloud.stream.bindings.updates.consumer.startOffset=earlist

配置,以避免每次重新启动时都必须发送新消息,但这不起作用。

2 个答案:

答案 0 :(得分:4)

由于RC该选项已移至.consumer.配置选项。

所以,现在你必须这样做:

spring.cloud.stream.bindings.input.consumer.mode=raw

查看Reference Manual中的更多信息。

答案 1 :(得分:0)

spring.cloud.stream.bindings.input.consumer.headerMode=raw

适用于版本1.1.0.RELEASE。