/** * Accept the given delivery by applying Accepted disposition state, and optionally settling. * * @param delivery * the delivery to update * @param settle * whether to settle * @return the delivery */ public static ProtonDelivery accepted(ProtonDelivery delivery, boolean settle) { delivery.disposition(Accepted.getInstance(), settle); return delivery; }
/** * Release the given delivery by applying Released disposition state, and optionally settling. * * @param delivery * the delivery to update * @param settle * whether to settle * @return the delivery */ public static ProtonDelivery released(ProtonDelivery delivery, boolean settle) { delivery.disposition(Released.getInstance(), settle); return delivery; }
@Override public Delivery disposition(final DeliveryState state, final boolean settle) { ackOnContext(v -> { delivery.disposition(state, settle); }); return this; }
/** * Settle the delivery for a received message * * @param messageId message identifier to settle */ public void settle(Object messageId) { if (this.deliveries.containsKey(messageId)) { ProtonDelivery delivery = this.deliveries.remove(messageId); delivery.disposition(Accepted.getInstance(), true); LOG.info("AMQP message [{}] settled", messageId); } }
/** * Settle the delivery for a received message * * @param messageId message identifier to settle */ public void settle(Object messageId) { if (this.deliveries.containsKey(messageId)) { ProtonDelivery delivery = this.deliveries.remove(messageId); delivery.disposition(Accepted.getInstance(), true); } } }
/** * Send an "accepted" delivery to the AMQP remote sender * * @param linkName AMQP link name * @param delivery AMQP delivery */ private void acceptedDelivery(String linkName, ProtonDelivery delivery) { delivery.disposition(Accepted.getInstance(), true); log.debug("Delivery sent [accepted] on link {}", linkName); }
@Override public Delivery accept() { ackOnContext(v -> { delivery.disposition(ACCEPTED, true); }); return this; }
/** * Reject the given delivery by applying Rejected disposition state, and optionally settling. * * @param delivery * the delivery to update * @param settle * whether to settle * @return the delivery */ public static ProtonDelivery rejected(ProtonDelivery delivery, boolean settle) { delivery.disposition(new Rejected(), settle); return delivery; }
/** * Rejects and settles an AMQP 1.0 message. * * @param delivery The message's delivery handle. * @param error The error condition to set as the reason for rejecting the message (may be {@code null}. * @throws NullPointerException if delivery is {@code null}. */ public static void rejected(final ProtonDelivery delivery, final ErrorCondition error) { Objects.requireNonNull(delivery); final Rejected rejected = new Rejected(); rejected.setError(error); // doesn't matter if null delivery.disposition(rejected, true); }
/** * Rejects and settles an AMQP 1.0 message. * * @param delivery The message's delivery handle. * @param error The error condition to set as the reason for rejecting the message (may be {@code null}. * @throws NullPointerException if delivery is {@code null}. */ public static void rejected(final ProtonDelivery delivery, final ErrorCondition error) { Objects.requireNonNull(delivery); final Rejected rejected = new Rejected(); rejected.setError(error); // doesn't matter if null delivery.disposition(rejected, true); }
private void handleMessage(ProtonSender protonSender, ProtonReceiver protonReceiver, ProtonDelivery protonDelivery, Message message) { if (log.isDebugEnabled()) { log.debug(this + ": forwarding message"); } if (!isMessageReplicated(message)) { forwardMessage(protonSender, protonReceiver, protonDelivery, message); } else { protonDelivery.disposition(Accepted.getInstance(), true); } }
/** * Updates this context's delivery state and settlement using the specified delivery. * * @param newDelivery The new delivery use to update this context's delivery. * * @return The new proton delivery. */ ProtonDelivery updateDelivery(final ProtonDelivery newDelivery) { return delivery.disposition(newDelivery.getRemoteState(), newDelivery.remotelySettled()); }
/** * Send a "rejected" delivery to the AMQP remote sender * * @param linkName AMQP link name * @param delivery AMQP delivery * @param cause exception related to the rejection cause */ private void rejectedDelivery(String linkName, ProtonDelivery delivery, Throwable cause) { Rejected rejected = new Rejected(); rejected.setError(new ErrorCondition(Symbol.valueOf(AmqpBridge.AMQP_ERROR_SEND_TO_KAFKA), cause.getMessage())); delivery.disposition(rejected, true); log.debug("Delivery sent [rejected] on link {}", linkName); }
protected void forwardMessage(final ProtonSender sender, final Message msg, final ProtonDelivery delivery) { sender.send(msg, updatedDelivery -> delivery.disposition(updatedDelivery.getRemoteState(), updatedDelivery.remotelySettled())); }
/** * Settles the command message with the <em>rejected</em> outcome * and flows credit to the peer. * <p> * This method also finishes the OpenTracing span returned by * {@link #getCurrentSpan()}. * * @param errorCondition The error condition to send in the disposition frame (may be {@code null}). * @param credit The number of credits to flow to the peer. * @throws IllegalArgumentException if credit is negative. */ public void reject(final ErrorCondition errorCondition, final int credit) { final Rejected rejected = new Rejected(); final Map<String, Object> items = new HashMap<>(2); items.put(Fields.EVENT, "rejected command for device"); if (errorCondition != null) { rejected.setError(errorCondition); Optional.ofNullable(errorCondition.getDescription()).ifPresent(s -> items.put(Fields.MESSAGE, s)); } TracingHelper.logError(currentSpan, items); delivery.disposition(rejected, true); if (credit > 0) { flow(credit); } currentSpan.finish(); }
/** * Modify the given delivery by applying Modified disposition state, with deliveryFailed and underliverableHere flags * as given, and optionally settling. * * @param delivery * the delivery to update * @param settle * whether to settle * @param deliveryFailed * whether the delivery should be treated as failed * @param undeliverableHere * whether the delivery is considered undeliverable by the related receiver * @return the delivery */ public static ProtonDelivery modified(ProtonDelivery delivery, boolean settle, boolean deliveryFailed, boolean undeliverableHere) { Modified modified = new Modified(); modified.setDeliveryFailed(deliveryFailed); modified.setUndeliverableHere(undeliverableHere); delivery.disposition(modified, settle); return delivery; }
private void messageHandler(ProtonReceiver receiver, ProtonDelivery delivery, Message message) { try { AmqpWillMessage amqpWillMessage = AmqpWillMessage.from(message); LOG.info("Received will on topic [{}] by client [{}]", amqpWillMessage.topic(), receiver.getName()); // TODO : having a callback to check if handling went well and send right disposition ? this.willHandler.handle(new WillData(receiver.getName(), amqpWillMessage)); delivery.disposition(Accepted.getInstance(), true); // NOTE : after receiving the AMQP_WILL, a new credit is issued because // with AMQP we want to change the "will" message during the client life receiver.flow(AMQP_WILL_CREDITS); } catch (IllegalArgumentException ex) { LOG.error("Error decoding will message", ex); ErrorCondition errorCondition = new ErrorCondition(AmqpError.DECODE_ERROR, "Received message is not a will message"); receiver.setCondition(errorCondition) .close(); } }
private void forwardMessage(ProtonSender protonSender, ProtonReceiver protonReceiver, ProtonDelivery sourceDelivery, Message message) { MessageAnnotations annotations = message.getMessageAnnotations(); if (annotations == null) { annotations = new MessageAnnotations(Collections.singletonMap(replicated, true)); } else { annotations.getValue().put(replicated, true); } message.setMessageAnnotations(annotations); protonSender.send(message, protonDelivery -> { sourceDelivery.disposition(protonDelivery.getRemoteState(), protonDelivery.remotelySettled()); protonReceiver.flow(protonSender.getCredit() - protonReceiver.getCredit()); }); }
/** * Verifies that the endpoint rejects malformed request messages. */ @Test public void testHandleMessageRejectsMalformedMessage() { final Message msg = ProtonHelper.message(); final ProtonConnection con = mock(ProtonConnection.class); final ProtonDelivery delivery = mock(ProtonDelivery.class); final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(false); // WHEN a malformed message is received endpoint.handleMessage(con, receiver, resource, delivery, msg); // THEN the link is closed and the message is rejected final ArgumentCaptor<DeliveryState> deliveryState = ArgumentCaptor.forClass(DeliveryState.class); verify(delivery).disposition(deliveryState.capture(), booleanThat(is(Boolean.TRUE))); assertThat(deliveryState.getValue(), instanceOf(Rejected.class)); verify(receiver, never()).close(); }
/** * Verifies that the endpoint rejects request messages for operations the client * is not authorized to invoke. */ @Test public void testHandleMessageRejectsUnauthorizedRequests() { final Message msg = ProtonHelper.message(); msg.setSubject("unauthorized"); msg.setReplyTo(REPLY_RESOURCE.toString()); final ProtonConnection con = mock(ProtonConnection.class); final ProtonDelivery delivery = mock(ProtonDelivery.class); final AuthorizationService authService = mock(AuthorizationService.class); when(authService.isAuthorized(any(HonoUser.class), any(ResourceIdentifier.class), anyString())).thenReturn(Future.succeededFuture(Boolean.FALSE)); final Future<Void> processingTracker = Future.future(); final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true, processingTracker); endpoint.setAuthorizationService(authService); endpoint.onLinkAttach(con, sender, REPLY_RESOURCE); // WHEN a request for an operation is received that the client is not authorized to invoke endpoint.handleMessage(con, receiver, resource, delivery, msg); // THEN the the message is rejected final ArgumentCaptor<DeliveryState> deliveryState = ArgumentCaptor.forClass(DeliveryState.class); verify(delivery).disposition(deliveryState.capture(), booleanThat(is(Boolean.TRUE))); assertThat(deliveryState.getValue(), instanceOf(Rejected.class)); verify(receiver, never()).close(); verify(authService).isAuthorized(Constants.PRINCIPAL_ANONYMOUS, resource, "unauthorized"); assertFalse(processingTracker.isComplete()); }