Custom Event Cannot be Deserialized
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 45/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- java, rabbitmq, spring-boot
調査の方向性
BusJacksonAutoConfiguration.java、特に180行目のBusJacksonMessageConverter.convertFromInternalから始め、ここに示されているTestEvent、@RemoteApplicationEventScan、およびRabbitMQのpublisher/listener設定を使って失敗を再現してください。Spring Boot 3.5.7/Spring Cloud 2025.0.0と新しいバージョンの間でデシリアライゼーションを比較し、カスタムRemoteApplicationEventがnull-sourceエラーなしで受信されることを確認してください。
索引モデルが issue の本文から書いたものです。
説明
Describe the bug
After upgrading Spring Boot to 4 and Spring Cloud to 2025.1.0, I am getting similar error in logs as spring-cloud/spring-cloud-bus#284 but in my case for custom events. I can confirm, with Spring Boot 3.5.7 and Spring Cloud 2025.0.0 it works as expected and no error thrown. I am adding samples as below, in my current setup event publisher and listener are different spring boot applications connected to the same RabbitMQ.
P.S: First I bumped versions for the event publisher, and listener was able to receive custom events without any problem. After bumped versions for event listener, it started failing to deserialize.
Sample
Event class definition:
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.springframework.cloud.bus.event.RemoteApplicationEvent;
@EqualsAndHashCode(callSuper = true)
public class TestEvent extends RemoteApplicationEvent {
@Getter
private String key;
public TestEvent() {
}
public TestEvent(Object source, String originService, String destination, String key) {
super(source, originService, () -> destination);
this.key = key;
}
}
Spring boot application entrypoint:
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.bus.jackson.RemoteApplicationEventScan;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.mongodb.config.EnableMongoAuditing;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
@SpringBootApplication
@EnableMongoRepositories
@ComponentScan(basePackages = {"org.test"})
@EnableMongoAuditing(auditorAwareRef = "auditorProvider")
@RemoteApplicationEventScan(basePackages = {"org.test"})
@EnableFeignClients
public class TestServiceApplication {
public static void main(String[] args) {
SpringApplication.run(TestServiceApplication.class, args);
}
}
Event listener:
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class TestEventListener {
@EventListener
public void onTestEvent(TestEvent event) {
log.info("Received TestEvent {}", event);
}
Event publisher:
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.bus.BusProperties;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
public class PublisherService {
private final ApplicationEventPublisher applicationEventPublisher;
private final BusProperties busProperties;
protected void publishEvent(String destination, String key) {
log.debug("Publishing test event with destination {} and key {}", destination, key);
TestEvent testEvent = new TestEvent(this, busProperties.getId(), String.format("%s:**", destination), key);
applicationEventPublisher.publishEvent(testEvent);
}
}
Error logs
2025-12-02T08:34:15.636+03:00 ERROR 64774 --- [test-service] [uCnbIRZGKBk_Q-1] o.s.c.b.j.BusJacksonMessageConverter : Cannot construct instance of `org.test.model.event.TestEvent`, problem: null source
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); byte offset: spring-cloud/spring-cloud-bus#234]
tools.jackson.databind.exc.ValueInstantiationException: Cannot construct instance of `org.test.model.event.TestEvent`, problem: null source
at [Source: REDACTED (`StreamReadFeature.INCLUDE_SOURCE_IN_LOCATION` disabled); byte offset: spring-cloud/spring-cloud-bus#234]
at tools.jackson.databind.exc.ValueInstantiationException.from(ValueInstantiationException.java:44) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.DeserializationContext.instantiationException(DeserializationContext.java:2080) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.std.StdValueInstantiator.wrapAsDatabindException(StdValueInstantiator.java:581) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.std.StdValueInstantiator.rewrapCtorProblem(StdValueInstantiator.java:602) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:289) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.ValueInstantiator.createFromObjectWith(ValueInstantiator.java:270) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.bean.PropertyBasedCreator.build(PropertyBasedCreator.java:252) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.bean.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:697) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.bean.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1417) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.bean.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:480) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.bean.BeanDeserializer._deserializeOther(BeanDeserializer.java:235) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.bean.BeanDeserializer.deserialize(BeanDeserializer.java:202) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:138) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:103) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.AbstractDeserializer.deserializeWithType(AbstractDeserializer.java:243) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:72) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.DeserializationContextExt.readRootValue(DeserializationContextExt.java:265) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2610) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:1627) ~[jackson-databind-3.0.2.jar:3.0.2]
at org.springframework.cloud.bus.jackson.BusJacksonMessageConverter.convertFromInternal(BusJacksonAutoConfiguration.java:180) ~[spring-cloud-bus-5.0.0.jar:5.0.0]
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:179) ~[spring-messaging-7.0.1.jar:7.0.1]
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:171) ~[spring-messaging-7.0.1.jar:7.0.1]
at org.springframework.cloud.function.context.config.SmartCompositeMessageConverter.fromMessage(SmartCompositeMessageConverter.java:75) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.convertInputMessageIfNecessary(SimpleFunctionRegistry.java:1428) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.convertInputIfNecessary(SimpleFunctionRegistry.java:1180) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.doApply(SimpleFunctionRegistry.java:787) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:627) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.observability.ObservationFunctionAroundWrapper.lambda$nonReactorStream$0(ObservationFunctionAroundWrapper.java:50) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at io.micrometer.observation.Observation.observe(Observation.java:564) ~[micrometer-observation-1.16.0.jar:1.16.0]
at org.springframework.cloud.function.observability.ObservationFunctionAroundWrapper.nonReactorStream(ObservationFunctionAroundWrapper.java:50) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.observability.ObservationFunctionAroundWrapper.doApply(ObservationFunctionAroundWrapper.java:45) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.context.catalog.FunctionAroundWrapper.apply(FunctionAroundWrapper.java:44) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry$FunctionInvocationWrapper.apply(SimpleFunctionRegistry.java:624) ~[spring-cloud-function-context-5.0.0.jar:5.0.0]
at org.springframework.cloud.stream.function.PartitionAwareFunctionWrapper.apply(PartitionAwareFunctionWrapper.java:92) ~[spring-cloud-stream-5.0.0.jar:5.0.0]
at org.springframework.cloud.stream.function.FunctionConfiguration$FunctionWrapper.apply(FunctionConfiguration.java:830) ~[spring-cloud-stream-5.0.0.jar:5.0.0]
at org.springframework.cloud.stream.function.FunctionConfiguration$FunctionToDestinationBinder$1.handleMessageInternal(FunctionConfiguration.java:668) ~[spring-cloud-stream-5.0.0.jar:5.0.0]
at org.springframework.integration.handler.AbstractMessageHandler.doHandleMessage(AbstractMessageHandler.java:102) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:70) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:133) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:150) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:123) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:72) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.channel.AbstractMessageChannel.sendInternal(AbstractMessageChannel.java:438) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.channel.AbstractMessageChannel.sendWithMetrics(AbstractMessageChannel.java:409) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:338) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:310) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:187) ~[spring-messaging-7.0.1.jar:7.0.1]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:166) ~[spring-messaging-7.0.1.jar:7.0.1]
at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:47) ~[spring-messaging-7.0.1.jar:7.0.1]
at org.springframework.messaging.core.AbstractMessageSendingTemplate.send(AbstractMessageSendingTemplate.java:108) ~[spring-messaging-7.0.1.jar:7.0.1]
at org.springframework.integration.endpoint.MessageProducerSupport.sendMessageWithTracking(MessageProducerSupport.java:278) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.endpoint.MessageProducerSupport.sendMessage(MessageProducerSupport.java:267) ~[spring-integration-core-7.0.0.jar:7.0.0]
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter.access$000(AmqpInboundChannelAdapter.java:71) ~[spring-integration-amqp-7.0.0.jar:7.0.0]
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$Listener.lambda$onMessage$0(AmqpInboundChannelAdapter.java:392) ~[spring-integration-amqp-7.0.0.jar:7.0.0]
at org.springframework.core.retry.RetryTemplate.execute(RetryTemplate.java:142) ~[spring-core-7.0.1.jar:7.0.1]
at org.springframework.integration.amqp.inbound.AmqpInboundChannelAdapter$Listener.onMessage(AmqpInboundChannelAdapter.java:385) ~[spring-integration-amqp-7.0.0.jar:7.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1683) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1612) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1599) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:1590) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListenerAndHandleException(AbstractMessageListenerContainer.java:1539) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.lambda$executeListener$1(AbstractMessageListenerContainer.java:1517) ~[spring-rabbit-4.0.0.jar:4.0.0]
at io.micrometer.observation.Observation.observe(Observation.java:499) ~[micrometer-observation-1.16.0.jar:1.16.0]
at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1517) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1116) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1061) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.mainLoop(SimpleMessageListenerContainer.java:1465) ~[spring-rabbit-4.0.0.jar:4.0.0]
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1359) ~[spring-rabbit-4.0.0.jar:4.0.0]
at java.base/java.lang.Thread.run(Thread.java:1583) ~[na:na]
Caused by: java.lang.IllegalArgumentException: null source
at java.base/java.util.EventObject.<init>(EventObject.java:57) ~[na:na]
at org.springframework.context.ApplicationEvent.<init>(ApplicationEvent.java:48) ~[spring-context-7.0.1.jar:7.0.1]
at org.springframework.cloud.bus.event.RemoteApplicationEvent.<init>(RemoteApplicationEvent.java:61) ~[spring-cloud-bus-5.0.0.jar:5.0.0]
at org.test.model.event.TestEvent.<init>(TestEvent.java:16) ~[classes/:na]
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:733) ~[na:na]
at tools.jackson.databind.introspect.AnnotatedConstructor.call(AnnotatedConstructor.java:113) ~[jackson-databind-3.0.2.jar:3.0.2]
at tools.jackson.databind.deser.std.StdValueInstantiator.createFromObjectWith(StdValueInstantiator.java:287) ~[jackson-databind-3.0.2.jar:3.0.2]
... 64 common frames omitted
- 主要言語
- Java
- スター
- 1.1k
- フォーク
- 653
- 平均マージ
- 12時間 59分
- マージ済み PR(30日)
- 7
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
spring-cloud/spring-cloud-stream のほかの issue
-
Deadlock between `KafkaBinderMetrics.close()` and the offset-lag task on context shutdown対応中かも @caiocv18 が 3 日前に担当しました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 55/100
spring-cloud/spring-cloud-stream#3332 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
DefaultPollableMessageSource: invoke afterSendCompletion for already-applied interceptors when a message is discarded対応中かも @ferblaca が 4 日前に担当しました。 オープン
難易度 3/5 1〜2日 初心者へのやさしさ 74/100
spring-cloud/spring-cloud-stream#3316 ·
メンテナーはふだん 1 日以内に返信
-
StreamBridge removing BindingProperties leads to wrong destination in ProvisioningProvider再び着手できるかも @olegz が 63 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンbug
spring-cloud/spring-cloud-stream#3257 · コメント 6 件 · リアクション 2 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
StreamBridge's hashProducerProperties produces hash collisions across different binding names, causing Partition key cannot be null再び着手できるかも このイシューのプルリクエストはマージされずにクローズされました。 オープン
難易度 4/5 3〜5日 初心者へのやさしさ 48/100
spring-cloud/spring-cloud-stream#3242 · コメント 2 件 ·
メンテナーはふだん 1 日以内に返信
-
v4.3.3 no longer adds a header "TIMESTAMP" on kafka messages consumed再び着手できるかも @olegz が 95 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンBackport 4.3.x bug
spring-cloud/spring-cloud-stream#3211 · コメント 3 件 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
spring-cloud/spring-cloud-stream の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1〜3時間 初心者へのやさしさ 85/100
hibernate/hibernate-reactive#4485 ·
メンテナーはふだん 1 日以内に返信
-
type: dependency-upgrade
難易度 2/5 1〜3時間 初心者へのやさしさ 61/100
spring-projects/spring-graphql#1556 ·
-
hermes-queue
難易度 1/5 1時間未満 初心者へのやさしさ 91/100
chrisalunlloyd2-sudo/mindpalace#373 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信