最近做ActiveMQ相关工作,有需求发送JMS里使用自定义的Timestamp和MessageID.
修改Timestamp
很顺利.Producer对象设置 setDisableMessageTimestame(true) .在发送Message前给Message设置 setJMSTimestamp(当前时间的毫秒数) 再发送,从总线看到的Timestamp就是自定义的时间了
修改MessageID
很坑爹,花了两天时间.本以为同timestamp一样给 Producer 设置 setDisableMesssageID(true) 然后在发送Message前给Message设置 setJMSMessageID(...) 就能得到预期的效果,但结果令我失望.后来以各种方式对ConnectionFactory、Producer、Message进行设置都无效.于是我找了它的源码研究下发现,它的发送代码有这样一个片段
-
- ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection);
-
-
- if (msg == message) {
- msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
- } else {
- msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
- message.setJMSMessageID(msg.getMessageId().toString());
- }
我不知道这是神马黑科技,为么if else里都给message设置同样的值.且不说这个,我把代码
- ActiveMQMessage msg = ActiveMQMessageTransformation.transformMessage(message, connection);
拿出来测试发现msg总和我自己的message相等,哥们费解了.else同学,你是来打酱油的吗
哥们被坑了,time is money frend一天时间就这样没了.算了哥们我自立更生,过程很曲折.
根据发送源码知道
- msg.setMessageId(new MessageId(producer.getProducerInfo().getProducerId(), sequenceNumber));
messageid是从Producer中获得的.更具体地说是从ProducerId的getConnectionId()中得到的,所以只要把ProcuderId中的 getConnectionId() 改了就行吧,根据我的分析它们的关系如下
ConnectionFactory--生成-->Connection--生成-->Session--生成-->Producer
就是说要得到自己的Producer得从ConnectionFactory做起,经过漫长的继承和重载终于有了自己的ProducerId,当我根据业务返回自定义messageid后发现总线没有收到或者说程序没有成功发送消息.由此知道如果生成和发送时的connectionid不一样就不会发送数据,如果要改就得从connection生成时改.哥们绕远路了,还是个错路.
最终我分析出的逻辑大体是这样:
ConnectionFactory生成Connection
Connection生成Session并传入ConnectionInfo
Session生成Producer并传入ConnectionInfo和SessionInfo.
所以ConnectionInfo是关键,这样只要重写ActiveMQConnectionFactory和ActiveMQConnection两个类就行了.我在重写Factory中加了一个createConnection(String messageid)方法返回自己重写的Connection类,在重写的Connection中声明一个新的ConnectionInfo 属性,并在构造方法中重新构造ConnectionInfo ,再覆盖原来的getConnectionInfo()方法,返回本类中声明的ConnectionInfo对象就搞定了.
代码片段
CustomActiveMQConnectionFactory.Java
- Transport transport = super.createTransport();
- connection = new CustomActiveMQConnection(transport,super.getClientIdGenerator(),factoryStats,messageid);
- connection.setUserName(userName);
- connection.setPassword(password);
- super.configureConnection(connection);
- transport.start();
- if (clientID != null) {
- connection.setDefaultClientID(clientID);
- }
- return connection;
CustomActiveMQConnection.java
- public CustomActiveMQConnection(final Transport transport,
- IdGenerator clientIdGenerator, JMSStatsImpl factoryStats,String messageid)
- throws Exception {
- super(transport, clientIdGenerator, factoryStats);
-
- String uniqueId = super.getConnectionInfo().getConnectionId().getValue();
- if(messageid!=null){
- Matcher matcher = pattern.matcher(uniqueId);
- if(matcher.find()){
- String localName = matcher.group(1);
- uniqueId = uniqueId.replace(localName, messageid);
- }
- }
-
- this.info = new ConnectionInfo(new ConnectionId(uniqueId));
- this.info.setManageable(true);
- this.info.setFaultTolerant(transport.isFaultTolerant());
- }
代码下载
原文代码:http://blog.youkuaiyun.com/fxz1982/article/details/7480073