Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/spring-boot/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Axon 4从AMQP接收事件_Java_Spring Boot_Rabbitmq_Amqp_Axon - Fatal编程技术网

Java 使用Axon 4从AMQP接收事件

Java 使用Axon 4从AMQP接收事件,java,spring-boot,rabbitmq,amqp,axon,Java,Spring Boot,Rabbitmq,Amqp,Axon,我试图通过rabbitmq将消息发送到基于axon4 spring引导的系统。已收到消息,但未触发任何事件。我很确定我遗漏了一个重要的部分,但到目前为止我还没有弄清楚 这里是我申请的相关部分。yml axon: amqp: exchange: axon.fanout transaction-mode: publisher_ack # adding the following lines changed nothing eventhandli

我试图通过rabbitmq将消息发送到基于axon4 spring引导的系统。已收到消息,但未触发任何事件。我很确定我遗漏了一个重要的部分,但到目前为止我还没有弄清楚

这里是我申请的相关部分。yml

axon:
    amqp:
        exchange: axon.fanout
        transaction-mode: publisher_ack
    # adding the following lines changed nothing
    eventhandling:
        processors:
            amqpEvents:
                source: in.queue
                mode: subscribing
spring:
    rabbitmq:
        username: rabbit
        password: rabbit
从文档中,我发现我应该创建一个SpringAMQpMessageSourcebean:

导入com.rabbitmq.client.Channel;
导入lombok.extern.slf4j.slf4j;
导入org.axonframework.extensions.amqp.eventhandling.AMQPMessageConverter;
导入org.axonframework.extensions.amqp.eventhandling.spring.SpringAMQPMessageSource;
导入org.springframework.amqp.core.Message;
导入org.springframework.amqp.rabbit.annotation.RabbitListener;
导入org.springframework.context.annotation.Bean;
导入org.springframework.context.annotation.Configuration;
@Slf4j
@配置
公共类Axonfig{
@豆子
SpringAMQPMessageSource输入消息源(最终AMQPMessageConverter消息转换器){
返回新的SpringAMQPMessageSource(messageConverter){
@RabbitListener(queues=“in.queue”)
@凌驾
公共消息无效(最终消息消息、最终通道){
调试(“收到的外部消息:{},通道:{}”,消息,通道);
super.onMessage(消息、频道);
}
};
}
}
如果我从rabbitmq管理面板向队列发送消息,我会看到以下日志:

axonfig:收到的外部消息:(正文:'[B@13f7aeef(字节[167])'MessageProperties[headers={},contentLength=0,receivedDeliveryMode=NON_PERSISTENT,Redelived=false,receivedExchange=,ReceiveDrootingKey=in.queue,deliveryTag=2,consumerTag=amq.ctag-xi34jwHHA_uXJensteX5DW,consumerQueue=in.queue]),通道:缓存的兔子通道:AMQChannel(amqp://rabbit@127.0.0.1:5672/,1),康涅狄格州:Proxy@11703cc8共享兔子连接:SimpleConnection@581cb879[代表=amqp://rabbit@127.0.0.1:5672/,localPort=58614]

此处是应接收事件的聚合:

导入lombok.extern.slf4j.slf4j;
导入org.axonframework.commandhandling.CommandHandler;
导入org.axonframework.config.ProcessingGroup;
导入org.axonframework.eventsourcing.EventSourcingHandler;
导入org.axonframework.modeling.command.AggregateIdentifier;
导入org.axonframework.spring.stereotype.Aggregate;
导入pm.mbo.easyway.api.app.order.commands.ConfirmOrderCommand;
导入pm.mbo.easyway.api.app.order.commands.PlaceOrderCommand;
导入pm.mbo.easyway.api.app.order.commands.ShipOrderCommand;
导入pm.mbo.easyway.api.app.order.events.OrderConfirmedEvent;
导入pm.mbo.easyway.api.app.order.events.OrderPlacedEvent;
导入pm.mbo.easyway.api.app.order.events.OrderShippedEvent;
导入静态org.axonframework.modeling.command.AggregateLifecycle.apply;
@ProcessingGroup(“amqpEvents”)
@Slf4j
@聚合
公共类OrderAggregate{
@聚合标识符
私有字符串orderId;
私有布尔序;
@命令处理程序
public OrderAggregate(最终PlaceOrderCommand命令){
debug(“命令:{}”,command);
应用(新的OrderPlacedEvent(command.getOrderId(),command.getProduct());
}
@命令处理程序
公共无效句柄(最终确认命令命令){
debug(“命令:{}”,command);
应用(新订单确认文件(订单ID));
}
@命令处理程序
公共无效句柄(最终ShipOrderCommand){
debug(“命令:{}”,command);
如果(!订单已确认){
抛出新的IllegalStateException(“无法发送尚未确认的订单”);
}
应用(新订单ShippedEvent(订单ID));
}
@EventSourcingHandler
在(最终OrderPlacedEvent事件)上公开作废{
调试(“事件:{}”,事件);
this.orderId=event.getOrderId();
orderconfirm=false;
}
@EventSourcingHandler
在(最终订单确认事件)上公开作废{
调试(“事件:{}”,事件);
orderconfirm=true;
}
@EventSourcingHandler
公共无效(最终订单ShippedEvent事件){
调试(“事件:{}”,事件);
orderconfirm=true;
}
受保护的OrderAggregate(){
}
}
因此,问题是系统接收到消息,但没有触发任何事件。消息的内容似乎不相关。无论我向队列发送什么,我都只从onMessage方法获得一条日志消息

SpringAMQPMessageSource的JavaDoc说:

/**
 * MessageListener implementation that deserializes incoming messages and forwards them to one or more event processors.
 * <p>
 * The SpringAMQPMessageSource must be registered with a Spring MessageListenerContainer and forwards each message
 * to all subscribed processors.
 * <p>
 * Note that the Processors must be subscribed before the MessageListenerContainer is started. Otherwise, messages will
 * be consumed from the AMQP Queue without any processor processing them.
 *
 * @author Allard Buijze
 * @since 3.0
 */
所以问题是,如何正确注册事件处理器。有没有一种方法可以用spring正确注册? 更新2:

这方面也不走运:

@Slf4j
@Component("rabbitMQSpringAMQPMessageSource")
public class RabbitMQSpringAMQPMessageSource extends SpringAMQPMessageSource {

    @Autowired
    public RabbitMQSpringAMQPMessageSource(final AMQPMessageConverter messageConverter) {
        super(messageConverter);
    }

    @RabbitListener(queues = "${application.queues.in}")
    @Override
    public void onMessage(final Message message, final Channel channel) {

        try {
            final var eventProcessorsField = this.getClass().getSuperclass().getDeclaredField("eventProcessors");
            eventProcessorsField.setAccessible(true);
            final var eventProcessors = (List<Consumer<List<? extends EventMessage<?>>>>) eventProcessorsField.get(this);
            log.debug("eventProcessors: {}", eventProcessors);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            e.printStackTrace();
        }

        log.debug("received message: message={}, channel={}", message, channel);
        super.onMessage(message, channel);
    }

}
除上述内容外,以编程方式注册也没有帮助:

    @Autowired
    void configure(EventProcessingModule epm,
                   RabbitMQSpringAMQPMessageSource rabbitMessageSource) {
        epm.registerSubscribingEventProcessor("rabbitMQSpringAMQPMessageSource", c -> rabbitMessageSource);
        epm.assignProcessingGroup("amqpEvents", "rabbitMQSpringAMQPMessageSource");// this line also made no difference
    }
当然@ProcessingGroup(“amqpEvents”)在我的类中已经就位,该类包含@EventSourcingHandler注释的方法


更新25.4.19:

请参阅Allard接受的答案。非常感谢您指出我犯的错误:我错过了EventSourcingHandler不接收来自外部的消息。这是用于预测的。不是用于分发聚合!ups 下面是现在从rabbitmq接收事件的配置/类:


在Axon中,聚合不接收来自“外部”的事件。聚合内部的事件处理程序(更具体地说,它们是EventSourcingHandler)只处理由同一聚合实例发布的事件,以便它可以重建其先前的状态

只有外部事件处理程序(例如更新投影的处理程序)才会从外部源接收事件

为了实现这一点,application.yml应该将bean名称作为处理器的源而不是队列名称

    eventhandling:
        processors:
            amqpEvents:
                source: in.queue
                mode: subscribing
应成为:

    eventhandling:
        processors:
            amqpEvents:
                source: inputMessageSource
                mode: subscribing
但同样,这只适用于在组件上定义的事件处理程序,而不适用于聚合。

Thx Allard!这很有帮助
    @Autowired
    void configure(EventProcessingModule epm,
                   RabbitMQSpringAMQPMessageSource rabbitMessageSource) {
        epm.registerSubscribingEventProcessor("rabbitMQSpringAMQPMessageSource", c -> rabbitMessageSource);
        epm.assignProcessingGroup("amqpEvents", "rabbitMQSpringAMQPMessageSource");// this line also made no difference
    }
axon:
    eventhandling:
        processors:
            amqpEvents:
                source: rabbitMQSpringAMQPMessageSource
                mode: SUBSCRIBING
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.axonframework.extensions.amqp.eventhandling.AMQPMessageConverter;
import org.axonframework.extensions.amqp.eventhandling.spring.SpringAMQPMessageSource;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Slf4j
@Component("rabbitMQSpringAMQPMessageSource")
public class RabbitMQSpringAMQPMessageSource extends SpringAMQPMessageSource {

    @Autowired
    public RabbitMQSpringAMQPMessageSource(final AMQPMessageConverter messageConverter) {
        super(messageConverter);
    }

    @RabbitListener(queues = "${application.queues.in}")
    @Override
    public void onMessage(final Message message, final Channel channel) {
        log.debug("received message: message={}, channel={}", message, channel);
        super.onMessage(message, channel);
    }

}
import lombok.extern.slf4j.Slf4j;
import org.axonframework.config.ProcessingGroup;
import org.axonframework.eventhandling.EventHandler;
import org.axonframework.queryhandling.QueryHandler;
import org.springframework.stereotype.Service;
import pm.mbo.easyway.api.app.order.events.OrderConfirmedEvent;
import pm.mbo.easyway.api.app.order.events.OrderPlacedEvent;
import pm.mbo.easyway.api.app.order.events.OrderShippedEvent;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@ProcessingGroup("amqpEvents")
@Service
public class OrderedProductsEventHandler {

    private final Map<String, OrderedProduct> orderedProducts = new HashMap<>();

    @EventHandler
    public void on(OrderPlacedEvent event) {
        log.debug("event: {}", event);
        String orderId = event.getOrderId();
        orderedProducts.put(orderId, new OrderedProduct(orderId, event.getProduct()));
    }

    @EventHandler
    public void on(OrderConfirmedEvent event) {
        log.debug("event: {}", event);
        orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> {
            orderedProduct.setOrderConfirmed();
            return orderedProduct;
        });
    }

    @EventHandler
    public void on(OrderShippedEvent event) {
        log.debug("event: {}", event);
        orderedProducts.computeIfPresent(event.getOrderId(), (orderId, orderedProduct) -> {
            orderedProduct.setOrderShipped();
            return orderedProduct;
        });
    }

    @QueryHandler
    public List<OrderedProduct> handle(FindAllOrderedProductsQuery query) {
        log.debug("query: {}", query);
        return new ArrayList<>(orderedProducts.values());
    }

}
RabbitMQSpringAMQPMessageSource : received message: ... 
OrderedProductsEventHandler : event: OrderShippedEvent...
    eventhandling:
        processors:
            amqpEvents:
                source: in.queue
                mode: subscribing
    eventhandling:
        processors:
            amqpEvents:
                source: inputMessageSource
                mode: subscribing