Spring boot Spring jms侦听器在转换为消息时覆盖id头<;对象>;

Spring boot Spring jms侦听器在转换为消息时覆盖id头<;对象>;,spring-boot,listener,spring-jms,Spring Boot,Listener,Spring Jms,我有一条jms消息,消息头中有一个名为id的属性 当此jms消息转换为消息时,在我的侦听器中 @JmsListener(id = "cis-listener", destination = "${amiga.service.jms.cis-listener.destination-fqdn}", containerFactory = "containerFactoryListener") public void receiv

我有一条jms消息,消息头中有一个名为id的属性

当此jms消息转换为消息时,在我的侦听器中

  @JmsListener(id = "cis-listener", destination = "${amiga.service.jms.cis-listener.destination-fqdn}",
  containerFactory = "containerFactoryListener")
  public void receiveMessage(Message<Object> event) throws UnknownMessageException {
  ...
@JmsListener(id=“cis listener”,destination=“${amiga.service.jms.cis listener.destination fqdn}”,
containerFactory=“containerFactoryListener”)
public void receiveMessage(消息事件)引发未知消息异常{
...
实例化MessageHeader时,此属性将被生成的UUID覆盖:

    protected MessageHeaders(@Nullable Map<String, Object> headers, @Nullable UUID id, @Nullable Long timestamp) {
    this.headers = (headers != null ? new HashMap<>(headers) : new HashMap<>());

    if (id == null) {
        this.headers.put(ID, getIdGenerator().generateId());
    }
    ...
protectedmessageheaders(@Nullable-Map-headers、@Nullable-UUID-id、@Nullable-Long-timestamp){
this.headers=(headers!=null?新建HashMap(headers):新建HashMap());
if(id==null){
this.headers.put(ID,getIdGenerator().generateId());
}
...
是否有一些选项可以重命名我在消息中收到的id头属性以保留该值


我可以通过使用javax.jms.Message更改侦听器接收的对象来访问此属性,但我更喜欢使用spring jms消息实现。

您可以向侦听器适配器添加自定义的
JmsHeaderMapper

  • 将容器工厂
    autoStartup
    设置为
    false
  • JmdListenerContainerEndpointRegistry
    (按id)获取容器
  • 从容器中获取消息侦听器并将其强制转换为
    AbstractAdapteableMessageListener
  • 设置自定义标题映射器
  • 启动容器

你的映射器应该将你的外部
id
头映射到其他东西。
id
是spring messaging中保留的。它可以是
SimpleJMHeaderMapper

的子类你好Gary Russell首先感谢你的回复和帮助,很高兴能得到该部分开发人员的回答对春天我有怀疑

在您的解决方案中,我不喜欢被迫禁用AutoStart。在我们的项目中,我们不强制AutoStart,但如果需要,此属性将被忽略,因为我们在设置自定义标头映射器后强制启动。我们应该在容器启动之前定义其他属性并检查其值。更改此属性有点奇怪容器AutoStart属性的含义

我也对MessageHeader定义有疑虑。我把消息和MessageHeader类看作JMS消息类的包装器/装饰器。我理解这两个类被定义为使消息和标头属性的实例化和访问变得更容易。 这就是为什么我不明白为什么时间戳和id值会被覆盖。我认为包装器不应该添加这种逻辑,尤其是在消息头中接收id属性的情况并不罕见。如果spring需要id来处理消息,可能在创建之前,应该检查属性id是否存在,并使用其他名称而是id,与时间戳相同。 这两个属性名由spring保留,但jms定义并不禁止使用它

我不喜欢这个解决方案,但我认为我们将被迫更改侦听器以接收jms消息,尽管实例化消息以测试它更困难,但我认为这是一个更好的选择


再次感谢您的时间和帮助。

Hello@gary russell感谢您的回复。当我尝试从JmsListenerContainerEndpointRegistry获取容器时,我总是得到一个空值。此对象中的属性listenerContainers为空:-(您可能在上下文生命周期中尝试得太早;您需要等待上下文刷新。因为您使用的是引导,所以可以在ApplicationRunner中执行此操作。