未找到默认构造函数

未找到默认构造函数

本文介绍了Spring Integration Aggregator 与 MongoDbMessageStore:无法实例化 GenericMessage:未找到默认构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将 Spring Integration 4.3.11 与 Spring Data MongoDB 1.10.6 一起使用.我有一个使用 MongoDbMessageStore 的消息聚合器.当来自消息序列的消息传入时,它会保留在 MongoDB 中,但紧接着(在 osistore.AbstractMessageGroupStore#addMessageToGroup 中)当从 MongoDB 读取相同消息时抛出异常>

I'm using Spring Integration 4.3.11 with Spring Data MongoDB 1.10.6. I have a message aggregator that uses MongoDbMessageStore. When a message from a message sequence comes in, it's persisted in MongoDB, but immediately after that (in o.s.i.store.AbstractMessageGroupStore#addMessageToGroup) an exception is thrown when the same message is read from MongoDB that

Failed to instantiate [org.springframework.messaging.support.GenericMessage]: No default constructor found

完整的堆栈跟踪:

org.springframework.messaging.MessageHandlingException: error occurred in message handler [org.springframework.integration.dsl.AggregatorSpec$InternalAggregatingMessageHandler#0]; nested exception is org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate org.springframework.messaging.support.GenericMessage using constructor NO_CONSTRUCTOR with arguments
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:139)
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148)
    at org.springframework.integration.dispatcher.UnicastingDispatcher.access$000(UnicastingDispatcher.java:53)
    at org.springframework.integration.dispatcher.UnicastingDispatcher$3.run(UnicastingDispatcher.java:129)
    at org.springframework.integration.util.ErrorHandlingTaskExecutor$1.run(ErrorHandlingTaskExecutor.java:55)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Caused by: org.springframework.data.mapping.model.MappingInstantiationException: Failed to instantiate org.springframework.messaging.support.GenericMessage using constructor NO_CONSTRUCTOR with arguments
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:64)
    at org.springframework.data.convert.ClassGeneratingEntityInstantiator.createInstance(ClassGeneratingEntityInstantiator.java:83)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:259)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:239)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:199)
    at org.springframework.data.mongodb.core.convert.MappingMongoConverter.read(MappingMongoConverter.java:195)
    at org.springframework.integration.mongodb.store.MongoDbMessageStore$MessageReadingMongoConverter.read(MongoDbMessageStore.java:520)
    at org.springframework.integration.mongodb.store.MongoDbMessageStore$MessageReadingMongoConverter.read(MongoDbMessageStore.java:529)
    at org.springframework.integration.mongodb.store.MongoDbMessageStore$MessageReadingMongoConverter.read(MongoDbMessageStore.java:485)
    at org.springframework.data.mongodb.core.MongoTemplate$ReadDbObjectCallback.doWith(MongoTemplate.java:2324)
    at org.springframework.data.mongodb.core.MongoTemplate.executeFindMultiInternal(MongoTemplate.java:1969)
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1787)
    at org.springframework.data.mongodb.core.MongoTemplate.doFind(MongoTemplate.java:1770)
    at org.springframework.data.mongodb.core.MongoTemplate.find(MongoTemplate.java:644)
    at org.springframework.data.mongodb.core.MongoTemplate.findOne(MongoTemplate.java:609)
    at org.springframework.integration.mongodb.store.MongoDbMessageStore.getMessageGroup(MongoDbMessageStore.java:245)
    at org.springframework.integration.store.AbstractMessageGroupStore.addMessageToGroup(AbstractMessageGroupStore.java:210)
    at org.springframework.integration.aggregator.AbstractCorrelatingMessageHandler.store(AbstractCorrelatingMessageHandler.java:621)
    at org.springframework.integration.aggregator.AbstractCorrelatingMessageHandler.handleMessageInternal(AbstractCorrelatingMessageHandler.java:413)
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127)
    ... 9 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.messaging.support.GenericMessage]: No default constructor found; nested exception is java.lang.NoSuchMethodException: org.springframework.messaging.support.GenericMessage.<init>()
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:105)
    at org.springframework.data.convert.ReflectionEntityInstantiator.createInstance(ReflectionEntityInstantiator.java:61)
    ... 28 common frames omitted
Caused by: java.lang.NoSuchMethodException: org.springframework.messaging.support.GenericMessage.<init>()
    at java.lang.Class.getConstructor0(Class.java:3082)
    at java.lang.Class.getDeclaredConstructor(Class.java:2178)
    at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:102)
    ... 29 common frames omitted

我已经使用 Spring Integration DSL 设置了聚合器,如下所示:

I've set up the aggregator with Spring Integration DSL as follows:

IntegrationFlows
.from(
        Amqp.inboundAdapter(connectionFactory, properties.getQueue())
                .errorChannel(errorChannel)
                .mappedRequestHeaders(MAPPED_AMQP_HEADERS)
                .taskExecutor(amqpConsumerExecutor)
                .concurrentConsumers(properties.getConcurrentConsumers())
                .messageConverter(new Jackson2JsonMessageConverter())
                .defaultRequeueRejected(false)
)
.channel(resultChannel)
.aggregate(aggregator -> aggregator
        .expireGroupsUponCompletion(true)
        .groupTimeout(properties.getGroupTimeout())
        .expireGroupsUponTimeout(true)
        .messageStore(new MongoDbMessageStore(mongoDbFactory))
        .outputProcessor(new ResponseAggregator())
)
// ...

mongoDbFactory 由 Spring Boot 自动配置.

The mongoDbFactory is autoconfigured by Spring Boot.

消息在 MongoDB 中持久化:

The message persisted in MongoDB:

{
    "_id" : ObjectId("59ca5c1349ac540d17911afc"),
    "_createdDate" : NumberLong(1506434067236),
    "_class" : "org.springframework.integration.mongodb.store.MongoDbMessageStore$MessageWrapper",
    "_groupId" : "39f292df-4b75-6531-e570-1950ef6bb8e2",
    "_messageType" : "org.springframework.messaging.support.GenericMessage",
    "payload" : {
        "_class" : "com.example.Response",
        "status" : 0
    },
    "headers" : {
        "amqp_receivedDeliveryMode" : "PERSISTENT",
        "sequenceNumber" : 1,
        "amqp_deliveryTag" : NumberLong(3),
        "sequenceSize" : 15,
        "amqp_consumerQueue" : "response",
        "amqp_redelivered" : false,
        "amqp_receivedRoutingKey" : "response",
        "amqp_contentEncoding" : "UTF-8",
        "json__TypeId__" : "com.example.Response",
        "correlationId" : "39f292df-4b75-6531-e570-1950ef6bb8e2",
        "id" : LUUID("fcf5ba73-30a0-1674-2767-d9980c09fb49"),
        "amqp_consumerTag" : "amq.ctag-A0tTqrEhhbEDxN5OEGs3hA",
        "contentType" : "application/json",
        "timestamp" : NumberLong(1506434067171)
    },
    "_group_timestamp" : NumberLong(1506434067179),
    "_group_update_timestamp" : NumberLong(1506434067179),
    "_last_released_sequence" : 0,
    "_group_complete" : false,
    "sequence" : 2
}

我做错了什么?

推荐答案

您必须将 MongoDbMessageStore 声明为 bean:

You have to declare MongoDbMessageStore as a bean:

@Bean
MongoDbMessageStore messageStore() {
    return new MongoDbMessageStore(mongoDbFactory);
}

...

.messageStore(messageStore())

它具有特定的 BeanFactoryAware 逻辑,包括:

It has particular BeanFactoryAware logic including:

public void afterPropertiesSet() throws Exception {
    if (this.applicationContext != null) {
        this.converter.setApplicationContext(this.applicationContext);
    }
    this.converter.afterPropertiesSet();

MessageReadingMongoConverter 执行的逻辑如下:

 public void afterPropertiesSet() {
        List<Object> customConverters = new ArrayList<Object>();
        customConverters.add(new UuidToDBObjectConverter());
        customConverters.add(new DBObjectToUUIDConverter());
        customConverters.add(new MessageHistoryToDBObjectConverter());
        customConverters.add(new DBObjectToGenericMessageConverter());
        customConverters.add(new DBObjectToMutableMessageConverter());
        DBObjectToErrorMessageConverter docToErrorMessageConverter = new DBObjectToErrorMessageConverter();
        if (MongoDbMessageStore.this.whiteListPatterns != null) {
            docToErrorMessageConverter.deserializingConverter
                    .addWhiteListPatterns(MongoDbMessageStore.this.whiteListPatterns);
        }
        customConverters.add(docToErrorMessageConverter);
        customConverters.add(new DBObjectToAdviceMessageConverter());
        customConverters.add(new ThrowableToBytesConverter());
        this.setCustomConversions(new CustomConversions(customConverters));
        super.afterPropertiesSet();
    }

注意DBObjectToGenericMessageConverter.这就是 GenericMessage 将如何实例化而不是基于默认构造函数的策略.

Pay attention to the DBObjectToGenericMessageConverter. That is how GenericMessage will be instantiate instead of default constructor-based strategy.

这篇关于Spring Integration Aggregator 与 MongoDbMessageStore:无法实例化 GenericMessage:未找到默认构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 18:17