[ 
https://issues.apache.org/jira/browse/ROCKETMQ-101?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15869353#comment-15869353
 ] 

ASF GitHub Bot commented on ROCKETMQ-101:
-----------------------------------------

Github user Jaskey commented on the issue:

    https://github.com/apache/incubator-rocketmq/pull/63
  
    @lizhanhui , # 4 is not the nessary conditions, since even it is not enble, 
the tpInfo's method is still used.
    
                try {
                    int index = tpInfo.getSendWhichQueue().getAndIncrement();
                    for (int i = 0; i < tpInfo.getMessageQueueList().size(); 
i++) {
                        int pos = Math.abs(index++) % 
tpInfo.getMessageQueueList().size();
                        if (pos < 0)
                            pos = 0;
                        MessageQueue mq = tpInfo.getMessageQueueList().get(pos);
                        if 
(latencyFaultTolerance.isAvailable(mq.getBrokerName())) {
                            if (null == lastBrokerName || 
mq.getBrokerName().equals(lastBrokerName))
                                return mq;
                        }
                    }
    
                    final String notBestBroker = 
latencyFaultTolerance.pickOneAtLeast();
                    int writeQueueNums = 
tpInfo.getQueueIdByBroker(notBestBroker);
                    if (writeQueueNums > 0) {
                        final MessageQueue mq = tpInfo.selectOneMessageQueue();
                        if (notBestBroker != null) {
                            mq.setBrokerName(notBestBroker);
                            
mq.setQueueId(tpInfo.getSendWhichQueue().getAndIncrement() % writeQueueNums);
                        }
                        return mq;
                    } else {
                        latencyFaultTolerance.remove(notBestBroker);//my npe is 
thrown here
                    }
                } 
    
    
    Besides, if topic route info is null which propably means user is send 
through my seletor method, resend should still respect user's seletor, so 
chosen broker is not enough, the chosen queue is needed, which may be another 
issue, I guess it is not a very minal effort, since the existing interface does 
not record any chosen queue info.


> Possible NullPointerException when retry in send Async way
> ----------------------------------------------------------
>
>                 Key: ROCKETMQ-101
>                 URL: https://issues.apache.org/jira/browse/ROCKETMQ-101
>             Project: Apache RocketMQ
>          Issue Type: Bug
>          Components: rocketmq-client
>            Reporter: Jaskey Lam
>            Assignee: Xiaorui Wang
>
> When retry async send, possible NPE will occure:
> java.lang.NullPointerException: null
>       at 
> com.alibaba.rocketmq.client.latency.MQFaultStrategy.selectOneMessageQueue(MQFaultStrategy.java:91)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.client.impl.producer.DefaultMQProducerImpl.selectOneMessageQueue(DefaultMQProducerImpl.java:404)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.client.impl.MQClientAPIImpl.onExceptionImpl(MQClientAPIImpl.java:385)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.client.impl.MQClientAPIImpl.access$100(MQClientAPIImpl.java:72)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.client.impl.MQClientAPIImpl$1.operationComplete(MQClientAPIImpl.java:356)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.remoting.netty.ResponseFuture.executeInvokeCallback(ResponseFuture.java:58)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.remoting.netty.NettyRemotingAbstract.scanResponseTable(NettyRemotingAbstract.java:255)
>  ~[classes/:na]
>       at 
> com.alibaba.rocketmq.remoting.netty.NettyRemotingClient$5.run(NettyRemotingClient.java:165)
>  [classes/:na]
>       at java.util.TimerThread.mainLoop(Timer.java:555) [na:1.7.0_80]
>       at java.util.TimerThread.run(Timer.java:505) [na:1.7.0_80]
> The problem is : when selectOneMessageQueue in MQFaultStrategy, the 
> topicPublishInfo which is just passed from sendKernelImpl, will be possiblly 
> null, which causes NPE.
> There are some places where sendKernelImpl wii have null TopicPublishInfo, 
> for example : 
>     private SendResult sendSelectImpl(//
>                                       Message msg, //
>                                       MessageQueueSelector selector, //
>                                       Object arg, //
>                                       final CommunicationMode 
> communicationMode, //
>                                       final SendCallback sendCallback, final 
> long timeout//
>     ) throws MQClientException, RemotingException, MQBrokerException, 
> InterruptedException {
>         this.makeSureStateOK();
>         Validators.checkMessage(msg, this.defaultMQProducer);
>         TopicPublishInfo topicPublishInfo = 
> this.tryToFindTopicPublishInfo(msg.getTopic());
>         if (topicPublishInfo != null && topicPublishInfo.ok()) {
>             MessageQueue mq = null;
>             try {
>                 mq = selector.select(topicPublishInfo.getMessageQueueList(), 
> msg, arg);
>             } catch (Throwable e) {
>                 throw new MQClientException("select message queue throws 
> exception.", e);
>             }
>             if (mq != null) {
>                 return this.sendKernelImpl(msg, mq, communicationMode, 
> sendCallback, null, timeout);//here, the topicroutinfo is null, which has the 
> risk of NPE
>             } else {
>                 throw new MQClientException("select message queue return 
> null.", null);
>             }
>         }
>         throw new MQClientException("No route info for this topic, " + 
> msg.getTopic(), null);
>     }
> This NPE will make retry fail, and even ,onException callback fail to be 
> called



--
This message was sent by Atlassian JIRA
(v6.3.15#6346)

Reply via email to