/** {@inheritDoc} */ @Override public boolean sendMessageToSubscriber(ProtocolMessage protocolMessage, AndesContent content) throws AndesException { boolean sendSuccess; DeliverableAndesMetadata messageMetadata = protocolMessage.getMessage(); if (messageMetadata.isRetain()) { recordRetainedMessage(messageMetadata.getMessageID()); } // Should get the message from the list ByteBuffer message = MQTTUtils.getContentFromMetaInformation(content); // Will publish the message to the respective queue if (null != mqqtServerChannel) { try { // TODO:review - instead of getSubscribedDestination() used message destination mqqtServerChannel.distributeMessageToSubscriber( wildcardDestination, message, messageMetadata.getMessageID(), messageMetadata.getQosLevel(), messageMetadata.isPersistent(), getMqttSubscriptionID(), getSubscriberQOS(), messageMetadata); // We will indicate the ack to the kernel at this stage // For MQTT QOS 0 we do not get ack from subscriber, hence will be implicitly creating an // ack if (QOSLevel.AT_MOST_ONCE.getValue() == getSubscriberQOS() || QOSLevel.AT_MOST_ONCE.getValue() == messageMetadata.getQosLevel()) { mqqtServerChannel.implicitAck(messageMetadata.getMessageID(), getChannelID()); } sendSuccess = true; } catch (MQTTException e) { final String error = "Error occurred while delivering message to the subscriber for message :" + messageMetadata.getMessageID(); log.error(error, e); throw new AndesException(error, e); } } else { sendSuccess = false; } return sendSuccess; }
/** * write message to channel * * @param queueEntry message to send * @throws AndesException */ private void sendMessage(QueueEntry queueEntry) throws AndesException { String msgHeaderStringID = (String) queueEntry.getMessageHeader().getHeader("msgID"); Long messageID = queueEntry.getMessage().getMessageNumber(); try { if (amqpSubscription instanceof SubscriptionImpl.AckSubscription) { MessageTracer.trace( messageID, "", "Sending message " + msgHeaderStringID + " messageID-" + messageID + "-to channel " + getChannelID()); amqpSubscription.send(queueEntry); } else if (amqpSubscription instanceof SubscriptionImpl.NoAckSubscription) { MessageTracer.trace( messageID, "", "Sending message " + msgHeaderStringID + " messageID-" + messageID + "-to channel " + getChannelID()); amqpSubscription.send(queueEntry); // After sending message we simulate acknowledgment for NoAckSubscription UUID channelID = ((SubscriptionImpl.NoAckSubscription) amqpSubscription).getChannel().getId(); AndesAckData andesAckData = AndesUtils.generateAndesAckMessage(channelID, messageID); Andes.getInstance().ackReceived(andesAckData); } else { throw new AndesException( "Error occurred while delivering message. Unexpected Subscription type for " + "message with ID : " + msgHeaderStringID); } } catch (AMQException e) { // The error is not logged here since this will be caught safely higher up in the execution // plan : // MessageFlusher.deliverAsynchronously. If we have more context, its better to log here too, // but since this is a general explanation of many possible errors, no point in logging at // this state. ProtocolMessage protocolMessage = ((AMQMessage) queueEntry.getMessage()).getAndesMetadataReference(); log.error( "AMQP Protocol Error while delivering message to the subscriber subID= " + amqpSubscription.getSubscriptionID() + " message id= " + messageID + " slot= " + protocolMessage.getMessage().getSlot().getId(), e); throw new ProtocolDeliveryFailureException( "Error occurred while delivering message with ID : " + msgHeaderStringID, e); } }