Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handling Exceptions that may occur after receiving message and before processMessage() getting called. #370

Open
harshitshah4 opened this issue Aug 27, 2021 · 5 comments

Comments

@harshitshah4
Copy link

Hey,

First of all thanks for this awesome library.

Is there a way to handle or catch any exceptions that may occur in the library after the message is received from the queue and is not yet sent to the processMessage() method.

Scenario:

In Spring Boot, we can use @Payload for de-serializing the message into Custom POJO class. Now assume that some exception occurs while de-serializing the message, in this case message will never be received to processMessage() and will keep on retrying and will never get deleted from the Queue.

This was just an example to explain the issue.

I am assuming that there are many such errors/exceptions that may occur after the message is successfully received by the library but is not yet sent to the processMessage(), is there a way to handle such exceptions and provide a custom logic of what needs to be done with such messages.

Thanks.

@JaidenAshmore
Copy link
Owner

Is there a way to handle or catch any exceptions that may occur in the library after the message is received from the queue and is not yet sent to the processMessage() method.

Interesting, yeah this is not something that I considered as a use case and considered that failing and sending it back to the queue for reprocessing/DLQ would be enough.

Some ways we could solve this is:

Use a fallback annotation, like @QueueListerFallback

We could have something like:

@QueueListener(id="myListener", ...)
public void myMethod(@Payload MyObject payload) { ... }

@QueueListerFallback(id="myListener")
public void fallbackMyMethod(Message message, Exception e) {
   //  You can do your manual processing here, maybe allowing you to mark as successfully processed
}

This is pretty clean but would involve a lot more infrastructure changes and splits up your processing between two methods. I would also want it to support other implementations like ktor so it would involve a lot more design investment so I don't believe I would get around to doing this.

Provide a new payload annotation for this specific case

@QueueListener(...)
public void myMethod(@SafePayload Either<MyObject, Exception> payloadOrError) {
// listener has the responsibility to figure this out
}

This is technically a lot easier and is something that you could even implement yourself! You could use the original PayloadArgumentResolver as a reference and integrate it into your spring app using this guide: Spring - How to add a custom argument resolver.

If this approach works for you and you feel like committing back to this repo, I am happy to take PRs.

Just let the message listener handle it

The easiest approach is to just let you handle the parsing of the POJO inside your listener, e.g. I believe you can do something like this:

@QueueListener(id="myListener", ...)
public void myMethod(@Payload String rawPayload) { 
    try {
    new ObjectMapper().readValue(rawPayload, MyPojo.class)
   } catch (Exception e) {
       // handle your error
   }
   // use your object or fallback parsing here
 }

obviously the negative being you have to implement your own parsing but it is the lowest effort from you side.

Let me know what you think!

@harshitshah4
Copy link
Author

Hey, Thanks for the detailed response.

This is technically a lot easier and is something that you could even implement yourself! You could use the original PayloadArgumentResolver as a reference and integrate it into your spring app using this guide: Spring - How to add a custom argument resolver.

While this solution seems decent. Apart from the Argument Resolver Service we may also need to consider other components where exceptions could occur after the messages are received but not yet sent to processMessage(). I took a look at the code base, I couldn't find anywhere else where Exception might occur apart from Thread's RuntimeException, etc.

Can you think of any other situations/places where an Exception might occur and the caller would benefit by allowing it to take decision-based on it ?

Let me know if I am missing something.

Thanks.

@JaidenAshmore
Copy link
Owner

I have tried to cover all those cases so think if the message is chosen to be processed I think it would send it to the function if all the arguments can be successfully resolved.

@harshitshah4
Copy link
Author

Thanks,

So Can I pick this up ?
I was thinking @SafePayload approach works fine.

@JaidenAshmore
Copy link
Owner

Yeah that's fine if you wanted to commit it back to the repo. You can also just build it in your repo specific for your use case as well

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

No branches or pull requests

2 participants