As you may expect, the MANUAL ackMode delegates all the responsibility of performing the ACK on the Message to the application logic.
With this configuration, every Message received by either the listener or consume operations will have an ackId available in the MuleMessage attributes which identifies this Message uniquely for a given connection.
The ackId that identifies the Message will then be passed on to the jms:ack operation:
<flow name="consumerWithManualAck">
<jms:consume config-ref="JMS_config" destination="openTickets" ackMode="MANUAL"/>
<!--Do message processing-->
<logger message="#[payload]">
<jms:ack ackId="#[attributes.ackId]"/>
</flow>
Manual Session Recovery
When using the MANUAL ackMode, all Messages that are received but not acknowledged won`t be redelivered by the broker.
In case of an error that occurs during the Message processing that prevents it from being ACKed, the user is responsible for manually recovering all the Messages in the Session that have to be redelivered using the recover-session operation:
<flow name="consumerWithManualAck">
<jms:consume config-ref="JMS_config" destination="${destination}"
ackMode="MANUAL" target="consumedMessage" targetValue="#[message]"/>
<!--Do message processing-->
<logger message="#[payload]">
<jms:ack ackId="#[vars.consumedMessage.attributes.ackId]"/>
<error-handler>
<on-error-propagate>
<!--In case of error, recover the session-->
<jms:recover-session ackId="#[vars.consumedMessage.attributes.ackId]"/>
</on-error-continue>
</error-handler>
</flow>
Same as before, the Connection used for recovering the session has to be the same as the one used for receiving the Message.