GH-3006: Read x-death count in a safer way

Fixes: #3006

We had an issue in our system trying to consume a message from RabbitMQ that contained an `x-death` header, with count value typed as `Integer`. 
This caused a `ClassCastException`.
The reason the count value was an int and not a long is that we were storing headers in an internal database as part of a recovery process, and the typing was slightly changed during serialisation / deserialisation.

* Use  `target.setRetryCount(numberValue.longValue());` in the `DefaultMessagePropertiesConverter` instead of cast to `long`

Signed-off-by: Raul Avila <raul.avila@pagonxt.com>

[artem.bilan@broadcom.com Improve commit message]

**Auto-cherry-pick to `3.2.x`**

Signed-off-by: Artem Bilan <artem.bilan@broadcom.com>
This commit is contained in:
Raul Avila
2025-03-12 14:43:20 +00:00
committed by GitHub
parent 3ecb055eda
commit 1741803975
2 changed files with 21 additions and 1 deletions

View File

@@ -44,6 +44,7 @@ import org.springframework.util.StringUtils;
* @author Artem Bilan
* @author Ngoc Nhan
* @author Johan Kaving
* @author Raul Avila
*
* @since 1.0
*/
@@ -147,7 +148,11 @@ public class DefaultMessagePropertiesConverter implements MessagePropertiesConve
if (target.getRetryCount() == 0) {
List<Map<String, ?>> xDeathHeader = target.getXDeathHeader();
if (!CollectionUtils.isEmpty(xDeathHeader)) {
target.setRetryCount((long) xDeathHeader.get(0).get("count"));
Object value = xDeathHeader.get(0).get("count");
if (value instanceof Number numberValue) {
target.setRetryCount(numberValue.longValue());
}
}
}

View File

@@ -104,6 +104,21 @@ public class DefaultMessagePropertiesConverterTests {
assertThat(((Map<String, Object>) messageProperties.getHeaders().get("map")).get("longString")).as("LongString nested in Map not converted to String").isEqualTo(longStringString);
}
@Test
public void testToMessagePropertiesXDeathCount() {
Map<String, Object> headers = new HashMap<String, Object>();
headers.put("x-death", List.of(Map.of("count", Integer.valueOf(2))));
BasicProperties source = new BasicProperties.Builder()
.headers(headers)
.build();
MessageProperties messageProperties = messagePropertiesConverter.toMessageProperties(source, envelope, "UTF-8");
assertThat(messageProperties.getRetryCount()).isEqualTo(2);
}
@Test
public void testLongLongString() {
Map<String, Object> headers = new HashMap<String, Object>();