Skip to content

fix(rocketmq): log warning when FLAG or DELAY header is not numeric#4330

Open
daguimu wants to merge 1 commit into
alibaba:2025.1.xfrom
daguimu:fix/rocketmq-delay-flag-header-log
Open

fix(rocketmq): log warning when FLAG or DELAY header is not numeric#4330
daguimu wants to merge 1 commit into
alibaba:2025.1.xfrom
daguimu:fix/rocketmq-delay-flag-header-log

Conversation

@daguimu

@daguimu daguimu commented May 14, 2026

Copy link
Copy Markdown
Contributor

Describe what this PR does / why we need it

RocketMQMessageConverterSupport#getAndWrapMessage parses the MQ_FLAG and DELAY_TIME_LEVEL Spring Messaging headers into int via Integer.parseInt. The previous implementation wrapped both parses in try { ... } catch (Exception ignored) {}, so any malformed header (e.g. a String value injected via a SpEL expression, a typo, or a non-numeric class) was silently absorbed and the producer fell back to flag=0 and delayLevel=0 with no exception, no log line, and no signal to the caller.

The most user-visible consequence is on the delayed-delivery path: a misconfigured DELAY_TIME_LEVEL (e.g. "abc" from a SpEL that returned a String instead of an int) turns a delayed message into an immediate send and the application has no way of knowing.

Does this pull request fix one issue?

NONE

Describe how you did it

  • Added a class-level SLF4J logger to RocketMQMessageConverterSupport.
  • Replaced catch (Exception ignored) {} with catch (Exception e) { log.warn(...) }, including both header names (MQ_FLAG, DELAY_TIME_LEVEL) and their raw values in the warning so the misconfiguration is diagnosable.
  • Lifted the DELAY_TIME_LEVEL header lookup out of the try block so the catch clause can reference the raw value; both lookups are side-effect-free, so this is a no-op on the happy path. Parse order is unchanged (delayLevel first, then flag).
  • Kept the runtime fallback (flag=0, delayLevel=0) and the broad catch (Exception) to avoid any behaviour change for existing producers — only observability is added.

Describe how to verify it

mvn -pl spring-cloud-alibaba-starters/spring-cloud-starter-stream-rocketmq -am test (all 13 module tests pass locally, including 3 new ones).

New tests in RocketMQMessageConverterSupportTest:

  • nonNumericDelayTimeLevelHeaderFallsBackToZero — sets DELAY = "not-a-number", asserts rkmqMsg.getDelayTimeLevel() == 0.
  • nonNumericFlagHeaderFallsBackToZero — sets MQ_FLAG = "not-a-number", asserts rkmqMsg.getFlag() == 0.
  • invalidNumericHeaderDoesNotPropagateException — sets both headers to non-numeric values and asserts no exception escapes convertMessage2MQ.

These tests pass both before and after the fix; their role is regression lock-in for the silent-fallback semantics. The warning itself is verified manually by running with --logging.level.com.alibaba.cloud.stream.binder.rocketmq=WARN and sending a message with a malformed DELAY header.

Special notes for reviews

  • Behaviour-preserving change: identical outputs for every previously valid header value; identical fallback outputs for every previously-swallowed bad value; new log.warn is the only externally visible difference.
  • The new tests cannot mutation-verify the log.warn because the fix does not change the message-conversion output. I left them in as regression guards rather than introducing a new log-capture testing pattern (e.g. OutputCaptureExtension) that the module doesn't currently use elsewhere.
  • The try block's parse order is unchanged — delayLevel parses first, then flag. This matters in the unlikely case where one is numeric and the other isn't, and I wanted to keep that observable behaviour identical.

RocketMQMessageConverterSupport#getAndWrapMessage swallowed any
Integer.parseInt failure on the MQ_FLAG and DELAY_TIME_LEVEL message
headers with catch (Exception ignored) {}, silently falling back to
flag=0 and delayLevel=0. A producer that set DELAY to a misconfigured
non-numeric value (e.g. via a SpEL expression that produced a String
instead of an int) would have its delayed delivery silently turn into
an immediate send with no log line, no exception, and no way for the
caller to know the header was malformed.

Add an SLF4J logger to the support class and warn with both header
names and their actual values when parsing fails. Behaviour is
otherwise unchanged: flag and delayLevel still fall back to 0, the
broad catch (Exception) is kept, and the DELAY_TIME_LEVEL header lookup
remains inside the try block so any exception path that the original
code happened to absorb is still absorbed. Only the variable
declaration for delayLevelObj is hoisted out of the try block so the
catch clause can include its raw value in the warning.

Adds three regression tests that lock in the fallback behaviour:
non-numeric DELAY_TIME_LEVEL stays at 0, non-numeric FLAG stays at 0,
and conversion does not propagate a parse exception. These tests pass
both before and after the fix; their purpose is to prevent a future
refactor from regressing the silent-fallback semantics that downstream
producers may rely on.
@daguimu daguimu force-pushed the fix/rocketmq-delay-flag-header-log branch from 6f45a40 to ac70625 Compare May 14, 2026 16:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant