none
Abandon() in azure service bus , method takes message to dead letter queue RRS feed

  • General discussion

  • Hi All,

      I'm new to azure service bus, I'm developing a sample publish/subscribe application using java sdk. In this exercise what I want to achieve is I will publish 50 messages (json)to a queue, these are in below format.

    [{'lastname'='test0','firstName'='success0'}...{'lastname'='test49','firstName'='success49'}]

    In receiver application at 25th message , I want this message to abandon, so the 25th message will be

    available in queue. But when I run application, all 49 messages are completed and one message went to

    dead letter queue. I got below exception.

    Either receive link to 'asb.java.pub' closed with a transient error and reopened or the delivery was already settled by complete/abandon/defer/deadletter.
    2019-05-09 06:17:19 ERROR MessageAndSessionPump:241 - Completing message with sequence number '5002' failed
    java.lang.IllegalArgumentException: Delivery not found on the receive link.
    at com.geico.messaging.servicebus.primitives.CoreMessageReceiver.generateDeliveryNotFoundException(CoreMessageReceiver.java:1319)
    at com.geico.messaging.servicebus.primitives.CoreMessageReceiver.updateMessageStateAsync(CoreMessageReceiver.java:1161)
    at com.geico.messaging.servicebus.primitives.CoreMessageReceiver.completeMessageAsync(CoreMessageReceiver.java:1046)
    at com.geico.messaging.servicebus.MessageReceiver.lambda$3(MessageReceiver.java:267)
    at java.util.concurrent.CompletableFuture.uniComposeStage(Unknown Source)
    at java.util.concurrent.CompletableFuture.thenCompose(Unknown Source)
    at com.geico.messaging.servicebus.MessageReceiver.completeAsync(MessageReceiver.java:262)
    at com.geico.messaging.servicebus.MessageReceiver.completeAsync(MessageReceiver.java:255)
    at com.geico.messaging.servicebus.MessageAndSessionPump.lambda$6(MessageAndSessionPump.java:220)
    at java.util.concurrent.CompletableFuture.uniHandle(Unknown Source)
    at java.util.concurrent.CompletableFuture$UniHandle.tryFire(Unknown Source)
    at java.util.concurrent.CompletableFuture$Completion.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    .here is my publishing code

    ConnectionStringBuilder connectionResolver = new ConnectionStringBuilder(connectionString, "asb.java.pub"); 

    QueueClient sendClient = new QueueClient(connectionResolver,ReceiveMode.PEEKLOCK);

    for(int i =0;i<50;i++){Message message = new Message("{'lastname' = 'test"+i+"', 'firstName' ='success"+i+"'}");

    message.setLabel("name");sendClient.send(message);}sendClient.close();

    here is my subscriber code
    IMessageHandler ih=new IMessageHandler() {				
    public CompletableFuture<Void> onMessageAsync(IMessage message)   {
    byte[] body = message.getBody();					
    Map map = GSON.fromJson(new String(body, UTF_8), Map.class);	
    try{						if(map.get("lastname").equals("test25")){						return receiveClient.abandonAsync(message.getLockToken());
    ;
    }catch(Exception e){						e.printStackTrace();						
    }
    CompletableFuture.completedFuture(null);
    }
    public void notifyException(Throwable throwable, ExceptionPhase exceptionPhase) {
    					System.out.printf(exceptionPhase + "-" + throwable.getMessage());
    }
    };
    
    			receiveClient.registerMessageHandler(ih, executorService);

    my question is why message goes to deadletter , when I call abandon method. Can't I made a specific message to abandon or autocomplete false.So that that message will be available in the queue .

    Thank you.



    Thursday, May 9, 2019 10:46 AM

All replies

  • Every-time you abandon a message, delivery count will be increased by 1. And when it reaches to max delivery count (which is 10 default), it will be sent to dead-letter queue.

    Abandon affects just the one where it was abandoned, and dead letter queues are separate.

    One caveat is that if you want to resubmit messages from dead-letter queue, you can't send them directly to the corresponding subscription, it has to go through the topic again.

    Monday, May 13, 2019 6:45 AM
    Moderator
  • Thank you for the answere DixitArora, how can I send a specific message back to its queue, with out going to dead letter In my post I got below exception "Either receive link to 'asb.java.pub' closed with a transient error and reopened or the delivery was already settled by complete/abandon/defer/deadletter.
    2019-05-09 06:17:19 ERROR MessageAndSessionPump:241 - Completing message with sequence number '5002' failed
    java.lang.IllegalArgumentException: Delivery not found on the receive link."Either receive link to 'asb.java.pub' closed with a transient error and reopened or the delivery was already settled by complete/abandon/defer/deadletter.
    2019-05-09 06:17:19 ERROR MessageAndSessionPump:241 - Completing message with sequence number '5002' failed
    java.lang.IllegalArgumentException: Delivery not found on the receive link.

    If I commented return receiveClient.abandonAsync(message.getLockToken()) in onMessageAsync(IMessage message)  implementation,  in subscriber ccode, I didn't get any exception;


    Monday, May 13, 2019 8:27 AM
  • This is not possible, as far as I know. the only thing you could do is to add an extra filter on every subscription that has something like SubscriptionName='SubscriptionA'. If you then want to send you deadlettered message to the specific subscription, you can add a property SubscriptionName to it, to achieve your goal.

    Take into account that you also have to make sure that in your original filter, you add a condition to indicate that the property SubscriptionName should not exist.

    I agree however, that it would be a nice scenario to 'undeadletter' a message, so that it ends up again in his original subscription

    Monday, May 13, 2019 11:18 AM
    Moderator