如何解决WebSphere JMS中带连字符Header的CWSIA0112E警告?
解决WebSphere JMS下带连字符Header的映射警告问题
这个问题我之前在类似的Spring Integration + WebSphere环境里碰到过,根源很明确:WebSphere的默认JMS提供者对属性名称有严格要求,必须符合合法Java标识符规则(只能包含字母、数字、下划线,不能以数字开头,也不能有连字符这类特殊符号)。而Spring Integration自带的DefaultJmsHeaderMapper默认会直接把原Header名称作为JMS属性名,这就导致带连字符的Header无法正常映射,抛出CWSIA0112E警告/错误。
自定义Header Mapper是完美的解决方案
当然可以通过自定义JmsHeaderMapper来解决,核心思路是:在将Header映射为JMS属性时,把带连字符的名称转换成合法格式(比如替换成下划线,或者转成驼峰命名);在反向映射(从JMS属性转回Header)时,再把名称转换回去,保证消息的完整性。
下面给你具体的实现示例:
1. 自定义HeaderMapper类
继承DefaultJmsHeaderMapper,重写映射逻辑:
import org.springframework.integration.jms.DefaultJmsHeaderMapper; import org.springframework.messaging.MessageHeaders; import org.springframework.messaging.MessagingException; import javax.jms.JMSException; import javax.jms.Message; import java.util.Enumeration; import java.util.Map; public class WebSphereJmsHeaderMapper extends DefaultJmsHeaderMapper { // 处理从MessageHeaders到JMS属性的正向映射:把连字符替换为下划线 @Override protected void fromHeaders(MessageHeaders headers, Message jmsMessage) { Map<String, Object> filteredHeaders = filterHeaders(headers); for (Map.Entry<String, Object> entry : filteredHeaders.entrySet()) { String originalHeaderName = entry.getKey(); // 替换连字符为下划线,生成合法的JMS属性名 String validPropertyName = originalHeaderName.replace("-", "_"); if (isJmsProperty(validPropertyName)) { setJmsProperty(jmsMessage, validPropertyName, entry.getValue()); } } } // 处理从JMS属性到MessageHeaders的反向映射:把下划线转回连字符 @Override protected void populateStandardHeaders(Map<String, Object> headers, Message jmsMessage) { super.populateStandardHeaders(headers, jmsMessage); try { Enumeration<?> propertyNames = jmsMessage.getPropertyNames(); while (propertyNames.hasMoreElements()) { String propertyName = (String) propertyNames.nextElement(); // 跳过JMS保留属性,避免重复处理 if (!isJmsReservedProperty(propertyName)) { // 将下划线转回连字符,还原原始Header名称 String originalHeaderName = propertyName.replace("_", "-"); headers.put(originalHeaderName, jmsMessage.getObjectProperty(propertyName)); } } } catch (JMSException e) { throw new MessagingException("读取JMS属性失败", e); } } }
2. 在Spring配置中启用自定义Mapper
如果用JavaConfig,配置如下:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.integration.jms.JmsMessageDrivenChannelAdapter; import org.springframework.integration.jms.JmsSendingMessageHandler; import javax.jms.ConnectionFactory; @Configuration public class JmsIntegrationConfig { // 注册自定义HeaderMapper @Bean public WebSphereJmsHeaderMapper webSphereJmsHeaderMapper() { WebSphereJmsHeaderMapper mapper = new WebSphereJmsHeaderMapper(); // 允许所有Header参与映射(你也可以指定具体的Header列表) mapper.setOutboundHeaderNames("*"); return mapper; } // 配置JMS消息发送处理器 @Bean public JmsSendingMessageHandler jmsSendingHandler(ConnectionFactory connectionFactory) { JmsSendingMessageHandler handler = new JmsSendingMessageHandler(connectionFactory); handler.setHeaderMapper(webSphereJmsHeaderMapper()); return handler; } // 配置JMS消息驱动适配器(消费端) @Bean public JmsMessageDrivenChannelAdapter jmsMessageDrivenAdapter(ConnectionFactory connectionFactory) { JmsMessageDrivenChannelAdapter adapter = new JmsMessageDrivenChannelAdapter(connectionFactory, "your-target-queue"); adapter.setHeaderMapper(webSphereJmsHeaderMapper()); return adapter; } }
备选方案:直接排除不需要的Header
如果你不需要保留这些带连字符的Header,也可以通过配置默认的DefaultJmsHeaderMapper来排除它们,避免警告:
@Bean public DefaultJmsHeaderMapper defaultJmsHeaderMapper() { DefaultJmsHeaderMapper mapper = new DefaultJmsHeaderMapper(); // 指定要排除的Header名称 mapper.setExcludedHeaders("Keep-Alive", "Transfer-Encoding"); return mapper; }
不过这种方式会丢失这些Header的信息,所以更推荐前面的自定义映射方案,既能符合WebSphere的要求,又能保留Header内容。
内容的提问来源于stack exchange,提问作者Kris Swat
相关产品推荐
相关产品推荐

