当前位置: 首页 > 知识库问答 >
问题:

DefaultJmsHeaderMapper-未能将消息头“timestamp”映射到JMS属性

卫念
2023-03-14

我对来自JMSMessageProperties类的“timestamp”头有问题,或者在我看来是这样,它导致了以下错误

[WARN ] [2022-04-06 14:49:03,758] [voryouDuplicateCheck.container-1] DefaultJmsHeaderMapper - failed to map Message header 'timestamp' to JMS property
javax.jms.MessageNotWriteableException: Message properties are read-only
    at org.apache.activemq.command.ActiveMQMessage.checkReadOnlyProperties(ActiveMQMessage.java:740) ~[activemq-client-5.15.0.jar:5.15.0]
    at org.apache.activemq.command.ActiveMQMessage.setObjectProperty(ActiveMQMessage.java:494) ~[activemq-client-5.15.0.jar:5.15.0]
    at org.apache.activemq.command.ActiveMQMessage.setObjectProperty(ActiveMQMessage.java:488) ~[activemq-client-5.15.0.jar:5.15.0]
    at org.springframework.integration.jms.DefaultJmsHeaderMapper.fromHeaders(DefaultJmsHeaderMapper.java:152) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.jms.DefaultJmsHeaderMapper.fromHeaders(DefaultJmsHeaderMapper.java:57) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.jms.JmsSendingMessageHandler$HeaderMappingMessagePostProcessor.postProcessMessage(JmsSendingMessageHandler.java:167) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.jms.core.JmsTemplate$7.createMessage(JmsTemplate.java:686) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.core.JmsTemplate.doSend(JmsTemplate.java:593) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.core.JmsTemplate$3.doInJms(JmsTemplate.java:562) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.core.JmsTemplate.execute(JmsTemplate.java:484) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.core.JmsTemplate.send(JmsTemplate.java:559) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.core.JmsTemplate.convertAndSend(JmsTemplate.java:682) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.jms.JmsSendingMessageHandler.send(JmsSendingMessageHandler.java:143) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.jms.JmsSendingMessageHandler.handleMessageInternal(JmsSendingMessageHandler.java:116) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:89) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:423) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.channel.interceptor.WireTap.preSend(WireTap.java:168) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel$ChannelInterceptorList.preSend(AbstractMessageChannel.java:538) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:415) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSend(GenericMessagingTemplate.java:115) [spring-messaging-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:150) [spring-messaging-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.messaging.core.GenericMessagingTemplate.doSendAndReceive(GenericMessagingTemplate.java:45) [spring-messaging-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.messaging.core.AbstractMessagingTemplate.sendAndReceive(AbstractMessagingTemplate.java:42) [spring-messaging-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:97) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.doSendAndReceive(MessagingGatewaySupport.java:459) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.gateway.MessagingGatewaySupport.sendAndReceiveMessage(MessagingGatewaySupport.java:426) [spring-integration-core-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.jms.ChannelPublishingJmsMessageListener$GatewayDelegate.sendAndReceiveMessage(ChannelPublishingJmsMessageListener.java:512) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.integration.jms.ChannelPublishingJmsMessageListener.onMessage(ChannelPublishingJmsMessageListener.java:344) [spring-integration-jms-4.3.10.RELEASE.jar:4.3.10.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:721) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:681) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:651) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:317) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:255) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1166) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1158) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1055) [spring-jms-4.3.6.RELEASE.jar:4.3.6.RELEASE]
    at java.lang.Thread.run(Thread.java:748) [?:1.8.0_131]

我知道这是由于ActiveMQMessage类中的check ReadOnly变量造成的,下面的方法对此负责

  @Override
    public void setObjectProperty(String name, Object value) throws JMSException {
        setObjectProperty(name, value, true);
    }

    public void setObjectProperty(String name, Object value, boolean checkReadOnly) throws JMSException {

        if (checkReadOnly) {
            checkReadOnlyProperties();
        }
        if (name == null || name.equals("")) {
            throw new IllegalArgumentException("Property name cannot be empty or null");
        }

        if (value instanceof UTF8Buffer) {
            value = value.toString();
        }

        checkValidObject(value);
        value = convertScheduled(name, value);
        PropertySetter setter = JMS_PROPERTY_SETERS.get(name);

        if (setter != null && value != null) {
            setter.set(this, value);
        } else {
            try {
                this.setProperty(name, value);
            } catch (IOException e) {
                throw JMSExceptionSupport.create(e);
            }
        }
    }

  private void checkReadOnlyProperties() throws MessageNotWriteableException {
        if (readOnlyProperties) {
            throw new MessageNotWriteableException("Message properties are read-only");
        }
    }

DefaultJmsHeaderMapper类ich捕获异常并将其记录为WARN

@Override
public void fromHeaders(MessageHeaders headers, javax.jms.Message jmsMessage) {
    try {
        Object jmsCorrelationId = headers.get(JmsHeaders.CORRELATION_ID);
        if (jmsCorrelationId instanceof Number) {
            jmsCorrelationId = jmsCorrelationId.toString();
        }
        if (jmsCorrelationId instanceof String) {
            try {
                jmsMessage.setJMSCorrelationID((String) jmsCorrelationId);
            }
            catch (Exception e) {
                this.logger.info("failed to set JMSCorrelationID, skipping", e);
            }
        }
        Object jmsReplyTo = headers.get(JmsHeaders.REPLY_TO);
        if (jmsReplyTo instanceof Destination) {
            try {
                jmsMessage.setJMSReplyTo((Destination) jmsReplyTo);
            }
            catch (Exception e) {
                this.logger.info("failed to set JMSReplyTo, skipping", e);
            }
        }
        Object jmsType = headers.get(JmsHeaders.TYPE);
        if (jmsType instanceof String) {
            try {
                jmsMessage.setJMSType((String) jmsType);
            }
            catch (Exception e) {
                this.logger.info("failed to set JMSType, skipping", e);
            }
        }
        for (Entry<String, Object> entry : headers.entrySet()) {
            String headerName = entry.getKey();
            if (StringUtils.hasText(headerName) && !headerName.startsWith(JmsHeaders.PREFIX)
                    && jmsMessage.getObjectProperty(headerName) == null) {
                Object value = entry.getValue();
                if (value != null) {
                    if (SUPPORTED_PROPERTY_TYPES.contains(value.getClass())) {
                        try {
                            String propertyName = this.fromHeaderName(headerName);
                            jmsMessage.setObjectProperty(propertyName, value);
                        }
                        catch (Exception e) {
                            if (headerName.startsWith("JMSX")
                                    || headerName.equals(IntegrationMessageHeaderAccessor.PRIORITY)) {
                                if (this.logger.isTraceEnabled()) {
                                    this.logger.trace("skipping reserved header, it cannot be set by client: "
                                            + headerName);
                                }
                            }
                            else if (this.logger.isWarnEnabled()) {
                                this.logger.warn("failed to map Message header '" + headerName + "' to JMS property", e); // **<-- this part**
                            }
                        }
                    }
                    else if (IntegrationMessageHeaderAccessor.CORRELATION_ID.equals(headerName)) {
                        String propertyName = fromHeaderName(headerName);
                        jmsMessage.setObjectProperty(propertyName, value.toString());
                    }
                }
            }
        }
    }
    catch (Exception e) {
        if (this.logger.isWarnEnabled()) {
            this.logger.warn("error occurred while mapping from MessageHeaders to JMS properties", e);
        }
    }
}

我知道这只是一个警告,但是我们希望保持日志干净,所以我们的想法是不要记录这个特定的WARN或尝试不传递。我已经基于DefaultJmsHeaderMapper创建了一个自定义映射器并使用它,但是正如你在starckTrace中看到的,默认映射器仍在使用。

这里是XML文件中的配置

<bean id="voryouDuplicateCheckQueue" class="org.apache.activemq.command.ActiveMQQueue">
      <constructor-arg index="0" value="voryouDuplicateCheck${jms.queue.postfix}" />
      </bean>
   
   <bean id="voryouDuplicateCheckCustomJmsHeaderMapper" class="com.example.ws.impl.voryou.CustomJmsHeaderMapper" >
   </bean>
    <int-jms:inbound-gateway id="voryouDuplicateCheck"
                      request-destination="voryouDuplicateCheckQueue"
                      request-channel="voryouDuplicateCheckChannel"
                      extract-request-payload="false" 
                      header-mapper="voryouDuplicateCheckCustomJmsHeaderMapper"
                      auto-startup="true"
                     
                       />
                      
   <int:channel id="voryouDuplicateCheckChannel">
      <int:interceptors>      
         <int:wire-tap channel="loggingServiceChannel" />
      </int:interceptors>
   </int:channel>
                      
   <int:service-activator id="activatorSasoVoryouDuplicateCheck" input-channel="voryouDuplicateCheckChannel" ref="voryouDuplicateCheckBES"
      method="getRequest" output-channel="loggingChannel" />
      

你们有没有遇到过类似的问题并找到了解决方案?主要目的不是记录这种类型的错误。

共有1个答案

印飞捷
2023-03-14

首先,4.3。x不再受支持。最后的4.3。x、 2020年底的版本为4.3.24。

其次,在消息创建期间,属性被标记为只读是很奇怪的。

避免日志的一种方法是将头映射器的日志级别设置为ERROR。

 类似资料:
  • 在Spring集成中使用出站网关时,我试图在JMS标头中发送回复Q详细信息。我了解到JIRA#INT-97中的增强功能在将Spring消息标头发送到JMS目标之前将其复制到JMS标头。 在将消息发送到出站网关之前,将消息头设置如下。message.getHeader(). setAtcm(JmsTargetAdapter.JMS_REPLY_TO, myReplyDestation); 但是我无法

  • 我从一个xml模式生成java类,对于一个复杂类型,我希望jaxb使用一个现有的类,我有一个外部绑定定制文件。自定义类被解组为正确的,除了该类型的单个属性,该属性从未在java类中填充。 下面是类型/类问题的演示。 模式中定义的内容是: 读取匹配xml文件的代码段是: 在这个xml中阅读: 使用JAXB生成的Thing类(不使用自定义xjb),输出符合预期: 使用只有getters的自定义Thin

  • 问题内容: 我阅读了今年的UberConf的幻灯片,其中一位发言者认为Spring JMS给您的消息队列系统增加了性能开销,但是在幻灯片中我看不到任何证据支持这一点。演讲者还提出了点对点比传统“发布- 订阅”方法更快的情况,因为每个消息仅发送一次,而不是广播给每个消费者。 我想知道是否有经验的Java消息传递专家可以在这里介绍一些技术问题: 使用Spring JMS而不是单纯的JMS实际上会产生性

  • 版本: SpringBoot: 2.3.12。发布 SpringCloud:Hoxton。SR12 SpringCloud Starter Sleuth: 3.0.3 骆驼: 3.4.6 我想将Sleuth添加到一个预先存在的项目中,该项目现在使用ActiveMQ,以前它使用JMS。当我这样做时,ActiceMQ消息中的值会被阻止/删除(其中一个是“filename”,它是S2请求的键值)。其他J

  • 我需要将源类中的字段值映射到字段属性。我可以使用Mapstruct使用@mapper注释的'expression'参数来完成 有没有其他方法可以不使用“表达式”来进行映射?

  • 我有一个web应用程序,它通过WebLogic中的JMS与其他Java web应用程序通信。 我读到这样的答案:如何从PHP连接Jms? 我安装了ActiveMQ并尝试使用它。但是在Weblogic中,我们需要“jms_factory”和“queue_name”。我想它使用t3协议。