1

I am implementing the Spring Batch-Integration Remote Chunking. After deserialization of the received ChunkRequest, I got the following error:

    2022-05-08 18:19:12.910 ERROR 2184 --- [container-0-C-1] o.s.integration.handler.LoggingHandler   : org.springframework.messaging.MessageHandlingException: error occurred during processing message in 'MethodInvokingMessageProcessor' [org.springframework.integration.handler.MethodInvokingMessageProcessor@58a8ea6f]; nested exception is java.lang.NullPointerException: Cannot invoke "java.lang.Class.getGenericInterfaces()" because "targetType" is null, failedMessage=GenericMessage [payload=byte[2069], headers={kafka_offset=38, scst_nativeHeadersPresent=true, kafka_consumer=org.apache.kafka.clients.consumer.KafkaConsumer@65b9c0ef, deliveryAttempt=3, kafka_timestampType=CREATE_TIME, kafka_receivedPartitionId=0, contentType=application/json, kafka_receivedTopic=clientRequests, kafka_receivedTimestamp=1652027934877, kafka_groupId=workerConsumerGroup}]
        at org.springframework.integration.support.utils.IntegrationUtils.wrapInHandlingExceptionIfNecessary(IntegrationUtils.java:191)
        at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:113)
        at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:105)
        at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:136)
        at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:56)
        at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115)
        at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133)
        at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
        at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
        at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:317)
        at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:272)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
        at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
        at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutput(AbstractMessageProducingHandler.java:457)
        at org.springframework.integration.handler.AbstractMessageProducingHandler.doProduceOutput(AbstractMessageProducingHandler.java:325)
        at org.springframework.integration.handler.AbstractMessageProducingHandler.produceOutput(AbstractMessageProducingHandler.java:268)
        at org.springframework.integration.handler.AbstractMessageProducingHandler.sendOutputs(AbstractMessageProducingHandler.java:232)
        at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:142)
        at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:56)
        at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:115)
        at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:133)
        at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:106)
        at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72)
        at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:317)
        at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:272)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166)
        at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47)
        at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:109)
        at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:216)
        at org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter.sendMessageIfAny(KafkaMessageDrivenChannelAdapter.java:397)
        at org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter.access$300(KafkaMessageDrivenChannelAdapter.java:83)
        at org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter$IntegrationRecordMessageListener.onMessage(KafkaMessageDrivenChannelAdapter.java:454)
        at org.springframework.integration.kafka.inbound.KafkaMessageDrivenChannelAdapter$IntegrationRecordMessageListener.onMessage(KafkaMessageDrivenChannelAdapter.java:428)
        at org.springframework.kafka.listener.adapter.RetryingMessageListenerAdapter.lambda$onMessage$0(RetryingMessageListenerAdapter.java:125)
        at org.springframework.retry.support.RetryTemplate.doExecute(RetryTemplate.java:329)
        at org.springframework.retry.support.RetryTemplate.execute(RetryTemplate.java:255)
        at org.springframework.kafka.listener.adapter.RetryingMessageListenerAdapter.onMessage(RetryingMessageListenerAdapter.java:119)
        at org.springframework.kafka.listener.adapter.RetryingMessageListenerAdapter.onMessage(RetryingMessageListenerAdapter.java:42)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeOnMessage(KafkaMessageListenerContainer.java:2637)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeOnMessage(KafkaMessageListenerContainer.java:2617)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeRecordListener(KafkaMessageListenerContainer.java:2544)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeWithRecords(KafkaMessageListenerContainer.java:2429)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeRecordListener(KafkaMessageListenerContainer.java:2307)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:1981)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeIfHaveRecords(KafkaMessageListenerContainer.java:1365)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1356)
        at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:1251)
        at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
        at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
        at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Class.getGenericInterfaces()" because "targetType" is null
        at net.jodah.typetools.TypeResolver.getTypeVariableMap(TypeResolver.java:494)
        at net.jodah.typetools.TypeResolver.resolveRawClass(TypeResolver.java:387)
        at net.jodah.typetools.TypeResolver.resolveRawClass(TypeResolver.java:373)
        at org.springframework.cloud.function.context.catalog.FunctionTypeUtils.isMessage(FunctionTypeUtils.java:351)
        at org.springframework.cloud.stream.converter.ApplicationJsonMessageMarshallingConverter.convertParameterizedType(ApplicationJsonMessageMarshallingConverter.java:126)
        at org.springframework.cloud.stream.converter.ApplicationJsonMessageMarshallingConverter.convertFromInternal(ApplicationJsonMessageMarshallingConverter.java:97)
        at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:185)
        at org.springframework.messaging.converter.CompositeMessageConverter.fromMessage(CompositeMessageConverter.java:70)
        at org.springframework.cloud.stream.config.SmartPayloadArgumentResolver.resolveArgument(SmartPayloadArgumentResolver.java:115)
        at org.springframework.messaging.handler.invocation.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:118)
        at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:147)
        at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:115)
        at org.springframework.integration.handler.support.MessagingMethodInvokerHelper$HandlerMethod.invoke(MessagingMethodInvokerHelper.java:1102)
        at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.invokeHandlerMethod(MessagingMethodInvokerHelper.java:584)
        at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:479)
        at org.springframework.integration.handler.support.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:357)
        at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:110)
        ... 51 more

Any idea about the exception? As I can see it is related to the message handler. I have tested by creating a custom deserializer and without deserializer.

Example of my Serializer

public class ChunkRequestSerializer implements Serializer<ChunkRequest>{

private static final Logger logger = LoggerFactory.getLogger(ChunkRequestSerializer.class);

@Override
public byte[] serialize(String topic, ChunkRequest data) {

    if (data == null) {
        return null;
    }

    String dataType = data.getClass().getName();
    logger.debug("--> serializing: {}",dataType);

    byte[] dataBytes = null;
    try {

        dataBytes = SerializationUtils.serialize(data);

    } catch (Exception e) {
        logger.error("Error serializing data", e);
    }
    
    return dataBytes;
}

}

The example of Deserializer:

    @Slf4j
public class ChunkRequestDeserializer implements Deserializer<ChunkRequest> {


    @Override
    public ChunkRequest deserialize(String topic, byte[] data) {

        log.debug("------------------->deserialize");
        
            if (data == null) {
            return null;
        }

        return (ChunkRequest) SerializationUtils.deserialize(data);
    }

}
  • 1
    Why do you use Spring Cloud Stream for your solution? How do you serialize that request? – Artem Bilan May 08 '22 at 21:01
  • Hi Artem, I have chosen Spring cloud stream because it is very easy to setup the Kafka and binders. And also because it was more easier to use the functional programming style because the “@input” from spring integration has been deprecated. I serialized the ChunkRequest using my custom serialization which uses SerializationUtils from spring. – Eddy Bayonne May 08 '22 at 22:17
  • Please share your custom serializer. The issue seems to happen in `org.springframework.cloud.function...` so I'm not sure this is related to Spring Batch per se. If you can isolate the problem in a failing unit test, I can try to take a deeper look. – Mahmoud Ben Hassine May 09 '22 at 08:05
  • @MahmoudBenHassine I have updated my question by adding my serializer and deserializer. Thanks – Pascoal Eddy Bayonne May 09 '22 at 08:26
  • Well, the `@Input` was also a part of Spring Cloud Stream, not Spring Integration. We need to know how you consume that input from Kafka. How do you replace that `@Input` and `@StreamListener` ? – Artem Bilan May 09 '22 at 13:34
  • Any updates, please? May you can share with us a simple project to reproduce? – Artem Bilan May 10 '22 at 16:16
  • @ArtemBilan yes sure, in few hours i'll be in my city and then i will share the code here. Thanks for your help – Pascoal Eddy Bayonne May 10 '22 at 17:14
  • @ArtemBilan here is the example. It occurs when i try to consume the ChunkRequest on the worker side https://github.com/PascoalBayonne/example-issue-batch – Pascoal Eddy Bayonne May 10 '22 at 21:24
  • Thanks for that, but you didn't explain how to run it and what to expect to be failed. It is hard to guess all the pieces in such a complex project. Thanks – Artem Bilan May 11 '22 at 15:25
  • @ArtemBilan you are right, you just must have a Kafka broker running on your machine. 1- run the app for the manager profile which will produce chunkRequest. 2- run the worker which will consume the event, deserialize it and then it will throw the exception described in the section. – Pascoal Eddy Bayonne May 11 '22 at 18:10
  • 1
    Here is what we have caught: https://github.com/spring-cloud/spring-cloud-function/pull/871. No promises yet, but consider to have that `RemoteChunkingWorkerBuilder` without generics. – Artem Bilan May 12 '22 at 19:04

1 Answers1

0

This is a very simple case, I am a bit disappointed that no one could even tell or specify that we need to use the native encoding while using a custom serialization:

spring.cloud.stream.bindings.<mybinding>.producer.use-native-encoding=true

example here: Spring Batch ChunkRequest throws stackOverflow