CAMEL-24403: camel-mail: handle MessageRemovedException in processCommit to avoid null cause in error log - #25553
Conversation
…null cause in error log When an IMAP message is expunged between being fetched and the commit callback running, IMAPMessage.setFlag() throws MessageRemovedException whose getMessage() returns null. This surfaced as: Caused by: [javax.mail.MessageRemovedException - null] Fix: catch MessageRemovedException before the generic MessagingException handler and wrap it with an explicit description so the error log always shows a non-null cause message: Caused by: [javax.mail.MessagingException - Message already removed/expunged on server (no flag update possible)] Add MailConsumerCommitExpungedMessageTest with two cases: - expunged message produces a wrapped MessagingException with non-null message - other MessagingExceptions are passed through unchanged Co-authored-by: Claude <claude@anthropic.com>
JIRA Issue: CAMEL-24403Link: https://issues.apache.org/jira/browse/CAMEL-24403 ProblemWhen an IMAP message is expunged (deleted by another client or server-side policy) between the time it is fetched by and when the on-completion commit callback fires, throws . This exception is constructed without a message string so returns , producing: Stack TraceRoot Causeextends but is constructed without a message string, so returns . The existing block in passed it directly to the exception handler, which included the null in the formatted output. Expected Log After Fix |
atiaomar1978-hub
left a comment
There was a problem hiding this comment.
Review summary
AI-generated review on behalf of atiaomar1978-hub
Focused, correct bug fix for CAMEL-24403. When an IMAP message is already expunged on the server, Message.setFlag() throws MessageRemovedException with a null message, which produced useless Caused by: [... - null] lines in the commit error log.
What looks good
- Dedicated
catch (MessageRemovedException)before the genericMessagingExceptionhandler — correct, sinceMessageRemovedExceptionextendsMessagingException. - Wrapping preserves the original exception as cause while supplying a clear operator-facing message.
- The catch covers the whole
processCommittry block, so expunged messages during copy/move (copyOrMoveMessageIfRequired) get the same treatment — not justsetFlag. - Two targeted unit tests: expunged-message wrapping + regression that other
MessagingExceptions pass through unchanged. - Minimal production diff (6 lines) with meaningful test coverage.
Suggestions (non-blocking)
- New test class uses
publicvisibility and JUnit assertions — project convention prefers package-private tests and AssertJ (assertThat). Minor polish only; existingcamel-mailtests are mixed.
Verdict
Approve — ready to merge once CI is green.
Review performed with code inspection and Bugbot. Does not replace specialized tools (CodeRabbit, Sourcery, SonarCloud).
Review complete ✅AI-generated on behalf of atiaomar1978-hub Verdict: Approve — clean fix for the null-cause logging issue. Bugbot found no functional bugs. One minor convention note on the new test class (package-private + AssertJ) — non-blocking. Note: CI checks were not yet reported on the branch at review time — please confirm green before merge. Thanks @mayurbm for the focused fix and the regression test guarding the pass-through behaviour for other |
…s, AssertJ assertions Per project convention (review comment on PR apache#25553): - Drop public modifier from test class and test methods - Replace JUnit assertEquals/assertInstanceOf/assertNotNull with AssertJ assertThat(...).isInstanceOf().hasMessage().hasCauseInstanceOf() No functional change; tests still pass (Tests run: 2, Failures: 0). Co-authored-by: Claude <claude@anthropic.com>
|
Addressed review feedback from @atiaomar1978-hub: Comment 1 (MailConsumer.java line 530 — catch placement): Comment 2 (MailConsumerCommitExpungedMessageTest.java line 52 — test conventions):
Local validation after changes:
|
Summary
Fixes CAMEL-24403.
When an IMAP message is expunged between fetch time and the on-completion commit callback,
IMAPMessage.setFlag()throwsMessageRemovedExceptionwhosegetMessage()returnsnull, producing a confusing log entry:Root Cause
MessageRemovedExceptionextendsMessagingExceptionbut is constructed without a message string sogetMessage()returnsnull. The existingcatch (MessagingException e)block inprocessCommit()passed it directly to the exception handler, which included the null in the formatted output.Fix
Catch
MessageRemovedExceptionbefore the genericMessagingExceptionhandler inprocessCommit()and wrap it with an explicit description:Expected log output after fix:
Stack Trace (from CAMEL-24403)
Changes
components/camel-mail/src/main/java/org/apache/camel/component/mail/MailConsumer.java— addjakarta.mail.MessageRemovedExceptionimport; split catch blockcomponents/camel-mail/src/test/java/org/apache/camel/component/mail/MailConsumerCommitExpungedMessageTest.java(new) — 2 unit tests:testCommitWithExpungedMessageProducesNonNullCause— verifiesMessageRemovedExceptionis wrapped with a non-null message and root cause preservedtestCommitWithOtherMessagingExceptionPassedThroughAsIs— verifies otherMessagingExceptiontypes pass through unchangedTest Results
AI Attribution
This contribution was developed with AI assistance using Claude Code.