Code review comment: [SpotBugs-P2] Possible null pointer dereference of encodedPair in com.microsoft.azure.servicebus.primitives.RequestResponseLink$InternalSender.runSendLoop() on exception path  A reference value which is null on some exception control path is dereferenced here.  This may lead to a NullPointerException when the code is executed.  Note that because SpotBugs currently does not prune infeasible exception paths, this may be a false warning. Also note that SpotBugs considers the default case of a switch statement to be an exception path, since the default case is often infeasible.

Code before review:
private void runSendLoop() {
synchronized (this.pendingSendsSyncLock) {
if (this.isSendLoopRunning) {
return;
} else {
this.isSendLoopRunning = true;
}
}
TRACE_LOGGER.debug("Starting requestResponseLink {} internal sender send loop", this.parent.linkPath);
try {
while (this.sendLink != null && this.sendLink.getLocalState() == EndpointState.ACTIVE && this.sendLink.getRemoteState() == EndpointState.ACTIVE && this.availableCredit.get() > 0) {
String requestIdToBeSent;
synchronized (pendingSendsSyncLock) {
requestIdToBeSent = this.pendingRetrySends.poll();
if (requestIdToBeSent == null) {
requestIdToBeSent = this.pendingFreshSends.poll();
if (requestIdToBeSent == null) {
this.isSendLoopRunning = false;
TRACE_LOGGER.debug("RequestResponseLink {} internal sender send loop ending as there are no more requests enqueued.", this.parent.linkPath);
break;
}
}
}
RequestResponseWorkItem requestToBeSent = this.parent.pendingRequests.get(requestIdToBeSent);
if (requestToBeSent != null) {
Delivery delivery = this.sendLink.delivery(UUID.randomUUID().toString().getBytes(UTF_8));
delivery.setMessageFormat(DeliveryImpl.DEFAULT_MESSAGE_FORMAT);
TransactionContext transaction = requestToBeSent.getTransaction();
if (transaction != TransactionContext.NULL_TXN) {
TransactionalState transactionalState = new TransactionalState();
transactionalState.setTxnId(new Binary(transaction.getTransactionId().array()));
delivery.disposition(transactionalState);
}
Pair<byte[], Integer> encodedPair = null;
try {
encodedPair = Util.encodeMessageToOptimalSizeArray(requestToBeSent.getRequest(), this.maxMessageSize);
} catch (PayloadSizeExceededException exception) {
this.parent.exceptionallyCompleteRequest((String)requestToBeSent.getRequest().getMessageId(), new PayloadSizeExceededException(String.format("Size of the payload exceeded Maximum message size: %s kb", this.maxMessageSize / 1024), exception), false);
}
if (encodedPair != null) {
try {
int sentMsgSize = this.sendLink.send(encodedPair.getFirstItem(), 0, encodedPair.getSecondItem());
assert sentMsgSize == encodedPair.getSecondItem() : "Contract of the ProtonJ library for Sender.Send API changed";
delivery.settle();
this.availableCredit.decrementAndGet();
if (TRACE_LOGGER.isDebugEnabled()) {
TRACE_LOGGER.debug("RequestResponseLink {} internal sender sent a request. available credit :{}", this.parent.linkPath, this.availableCredit.get());
}
} catch (Exception e) {
if (TRACE_LOGGER.isErrorEnabled()) {
TRACE_LOGGER.error("RequestResponseLink {} failed to send request with request id:{}.", this.parent.linkPath, requestIdToBeSent, e);
}
this.parent.exceptionallyCompleteRequest(requestIdToBeSent, e, false);
}
} else {
if (TRACE_LOGGER.isErrorEnabled()) {
TRACE_LOGGER.error("NULL_POINTER exception: encodedPair in RequestResponseLink");
}
}
} else {
if (TRACE_LOGGER.isWarnEnabled()) {
TRACE_LOGGER.warn("Request with id:{} not found in the requestresponse link.", requestIdToBeSent);
}
}
}
} finally {
synchronized (this.pendingSendsSyncLock) {
if (this.isSendLoopRunning) {
this.isSendLoopRunning = false;
}
}
TRACE_LOGGER.debug("RequestResponseLink {} internal sender send loop stopped.", this.parent.linkPath);
}
}

Line under review: if (encodedPair != null) {

Code after addressing the review:
private void runSendLoop() {
synchronized (this.pendingSendsSyncLock) {
if (this.isSendLoopRunning) {
return;
} else {
this.isSendLoopRunning = true;
}
}
TRACE_LOGGER.debug("Starting requestResponseLink {} internal sender send loop", this.parent.linkPath);
try {
while (this.sendLink != null && this.sendLink.getLocalState() == EndpointState.ACTIVE && this.sendLink.getRemoteState() == EndpointState.ACTIVE && this.availableCredit.get() > 0) {
String requestIdToBeSent;
synchronized (pendingSendsSyncLock) {
requestIdToBeSent = this.pendingRetrySends.poll();
if (requestIdToBeSent == null) {
requestIdToBeSent = this.pendingFreshSends.poll();
if (requestIdToBeSent == null) {
this.isSendLoopRunning = false;
TRACE_LOGGER.debug("RequestResponseLink {} internal sender send loop ending as there are no more requests enqueued.", this.parent.linkPath);
break;
}
}
}
RequestResponseWorkItem requestToBeSent = this.parent.pendingRequests.get(requestIdToBeSent);
if (requestToBeSent != null) {
Delivery delivery = this.sendLink.delivery(UUID.randomUUID().toString().getBytes(UTF_8));
delivery.setMessageFormat(DeliveryImpl.DEFAULT_MESSAGE_FORMAT);
TransactionContext transaction = requestToBeSent.getTransaction();
if (transaction != TransactionContext.NULL_TXN) {
TransactionalState transactionalState = new TransactionalState();
transactionalState.setTxnId(new Binary(transaction.getTransactionId().array()));
delivery.disposition(transactionalState);
}
Pair<byte[], Integer> encodedPair = null;
try {
encodedPair = Util.encodeMessageToOptimalSizeArray(requestToBeSent.getRequest(), this.maxMessageSize);
} catch (PayloadSizeExceededException exception) {
this.parent.exceptionallyCompleteRequest((String)requestToBeSent.getRequest().getMessageId(), new PayloadSizeExceededException(String.format("Size of the payload exceeded Maximum message size: %s kb", this.maxMessageSize / 1024), exception), false);
}
try {
int sentMsgSize = this.sendLink.send(encodedPair.getFirstItem(), 0, encodedPair.getSecondItem());
assert sentMsgSize == encodedPair.getSecondItem() : "Contract of the ProtonJ library for Sender.Send API changed";
delivery.settle();
this.availableCredit.decrementAndGet();
TRACE_LOGGER.debug("RequestResponseLink {} internal sender sent a request. available credit :{}", this.parent.linkPath, this.availableCredit.get());
} catch (Exception e) {
TRACE_LOGGER.error("RequestResponseLink {} failed to send request with request id:{}.", this.parent.linkPath, requestIdToBeSent, e);
this.parent.exceptionallyCompleteRequest(requestIdToBeSent, e, false);
}
} else {
TRACE_LOGGER.warn("Request with id:{} not found in the requestresponse link.", requestIdToBeSent);
}
}
} finally {
synchronized (this.pendingSendsSyncLock) {
if (this.isSendLoopRunning) {
this.isSendLoopRunning = false;
}
}
TRACE_LOGGER.debug("RequestResponseLink {} internal sender send loop stopped.", this.parent.linkPath);
}
}