How correctly add RetryAdvice to Jms.messageDriverChannelAdapter - spring

I'm very new to Spring Integration DSL and I need to add retrial with recovery to the existing IntegrationFlow. It takes data from Jms.messageDriverChannelAdapter and send it through different channels. I want to add RequestHandlerRetryAdvice for the whole flow.
My idea was to add it to the adapter, but it seems to support only ErrorChannel, without Advices & Retries and such. I've ended up wrapping the whole flow after Jms.messageDriverChannelAdapter in a .gateway with advice and .requireReply(false). It feels like a hack, but I couldn't find a better way to do it. Is there any better way to deal with such situation?

Unlike Spring AMQP's listener container a JMS one doesn't provide a hook to inject Advice chain into it, so, we really don't have choice and workaround it somehow. The RequestHandlerRetryAdvice and a .gateway() DSL is not so bad idea to go. The point is that a RequestHandlerRetryAdvice is applied only for the particular handleRequestMessage() method and is not propagated downstream. Having the flow wrapped into the gateway call from the mentioned handleRequestMessage() is the way to go.
I think we can come up with the solution on the JmsMessageDrivenEndpoint to wrap an internal listener with injected Advice chain, where one of them might be a RetryOperationsInterceptor.
Please, raise a GH issue and we'll think what we can do.

Related

Trying to create a "general" logging solution for requests in Spring Boot

I'm currently trying to create a info log for every request in the API I'm working on, but instead of creating a log for every request at the controller level, I wanted to try creating a "catch all" solution but I'm not being able to fullfill my goals.
I've decided to start the idea using Spring's #Aspect annotation, but using it isn't the best idea because I'd have to create one aspect for every controller that I have.
After some digging I found 2 possible solution paths that I could try to work on, #ControllerAdvice and creating an interceptor (which in theory is the one idea that I think has the most chances of succeeding and being a clean solution).
The problem is that I'm not being able to find much information regarding these ideas.
For the #ControllerAdvice idea I'm only finding it being used to handle exceptions, and for the interceptor idea I'm not finding anything similar to what I want to create.
Are these ideas feasible at all? Or should I just stick to logging everything at controller level?
Not sure if it's important but I'm currently working using LogBack library.
There is a ready solution for complete request and response logging for different client- and server-side technologies.
I'm using logbook tool for tracking request-response info for my rest endpoints.
https://github.com/zalando/logbook

Spring MVC to Spring Webflux migration - block vs subscribe

Let's imagine a scenario where there's an old app written using Servlet stack and you decide to migrate it to a Spring Webflux. Let's also say that first thing to migrate is RestTemplate to WebClient.
What would be preferred way of handling Mono or Flux that WebClient returns? Calling block seems okay solution since app uses RestTemplate which blocks anyway. subscribe should be a bit nicer since it has a callback, but maybe you have to wait to be able to continue. Also, with subscribe, do we need to handle a Disposable and, if yes, how, because I'm not sure where is the best place to call dispose on it?
And one more question regarding JDBC. How dangerous is to use Schedulers.boundedElastic()? From my understanding, having a separate thread pool should help especially if Netty is used. It's not ideal, but could it be a temporary solution until R2DBC drivers reach 1.0.0? What if app uses Tomcat? Is the situation better since Tomcat by default has more threads?
What would be preferred way of handling Mono or Flux that WebClient returns?
Given you're aiming to use Webflux, the ultimate preferred way is to deal with these publishers the entire way up your reactive chain. This means you won't end up calling subscribe on anything directly, because your controller will itself return a Mono (and everything, including the WebClient calls, will just be incorporated into that Mono via a series of reactive opreations in the chain.)
However, as you point out, you can't realistically migrate everything at once.
If it's only the WebClient that you're migrating for now, then just call block() to treat it the same way as your RestController. There's no advantage with calling subscribe() and then waiting for the subscription to complete - that's just a less obvious and more long-winded way of blocking.
Once you migrate more and more of your stack to reactive, you can do more and more in a reactive fashion, and then start to "move" your block() calls further up the chain as a result (until the block is at the controller level, and then you can just switch over to returning the Mono.)
Also, with subscribe, do we need to handle a Disposable
Only if you need to potentially cancel the subscriber (and it supports it.) This is quite a rare occurance in my experience.
And one more question regarding JDBC. How dangerous is to use Schedulers.boundedElastic()?
boundedElastic() is designed to be a wrapper for blocking IO, so there's nothing inherently wrong with using that on the reactor side. The only "danger" would be on the JDBC / app side as to if it fits your requirements:
It's capped at 10x the number of CPU cores
The number of "queued" tasks is capped at 100K
If you've got enough long running DB queries that this isn't enough, then you might consider using newBoundedElastic() instead and specifying the threadCap and queuedTaskCap manually.
What if app uses Tomcat? Is the situation better since Tomcat by default has more threads?
I wouldn't advise relying on it. Tomcat still uses one thread per request (even with Webflux), so the danger there is you end up blocking on a thread you shouldn't, and end up not realising and then relying on that behaviour (which would then all come tumbling down when you switched to Netty.)

Spring boot 2.1.5, WebFlux, Reactor: How to deal properly with MDC

Spring boot 2.1.5
Project Reactor 3.2.9
I am setting up a bunch of rest reactive APIs using the above-mentioned frameworks and I am running into an annoying problem with MDC (mapped diagnostic context). My applications are in JAVA.
MDC relies on thread locals to store the current query's mapped context to put in the logs. That system, obviously, is not perfect and contradicts the reactive pattern since the different steps of your execution will be executed through different threads.
I have run into the same problem with the Play Reactive framework but found a workaround there by copying the mapped context transparently from one actor to another.
For spring and reactor, I could not find a satisfying solution yet.
Some random examples found on the internet:
First - It works but forces you to use a bunch of utility methods
Same thing
Second - It tries to copy the context during the onNext publisher event but seems to lose some features on the way of doing that. The signal context, for example, is lost.
I am in need of a proper solution to deal with this:
A library which would make the link between MDC and reactor?
A way to tweak reactor/spring to achieve it transparently?
Any advice?
"I could not find a satisfying solution yet."
Working with contexts is the only solution for the moment. Since as you said threadlocals goes against everything that has to do with reactive programming. Using thread local as a storage point during a request is a resource heavy way of solving things and in my opinion poor design. Unless logging frameworks themselves come up with a better solution to the problem we developers must pass the data through the context to accommodate for the logging frameworks blocking nature.
Reactive programming is a paradigm shift in the programming world. Other things like database drivers, that use threadlocal to rollback transactions are also in big trouble. the JDBC database driver spec is defined as blocking in nature, and atm. there has been attempts by spring and the R2DBC project to define a new JDBC driver spec that is inherently non/blocking. This means that all vendors must rewrite ther database driver implementations from scratch.
Reactive program is so new that lots of libraries need to rewrite entire codebases. The logging frameworks as we know it needs to be rewritten from the ground up which is a huge task. And the context in reactive is actually something that should not even be in reactive programming, it was implemented just to accommodate for MDC problems.
It's actually a lot of overhead needing to pass data from thread to thread.
So what can we do?
push on logging frameworks, and/or help logging frameworks to rewrite their codebase
Accept that there is no "tweak" that will magically fix this
use the context and the way suggested in the blogposts
Project reactor context

Spring Context Event

I am currently studying Spring.
While reading a Spring book, I met a part regarding Event.
By using context.publishEvent(..), I could trigger the event.
But I don't know what It's exactly for.
I can use other Method instead of using complicated publishEvent.
Please, tell me. thank you.
Spring Events are used to implement publish-subscribe model (or observer pattern) where two not-related parts of code must be somehow connected.
Think of the analogy of web applications where servlet container creates http sessions and your code is informed about this using javax.servlet.http.HttpSessionListener.
Spring uses this mechanism internally. It's much more visible in Spring Security where several parts of the code are informed about e.g., successfull authentication.

PUT method in jersey

I am new to Restful webservice. When I was going through the tutorials, I saw that PUT method can be used to create the resource. the creation means adding into the database or somewhere by implementing our own effort? or will Jersey take care of creating the resource its own?
Sorry for asking silly questions.. I did not get the way what PUT is doing..
Thanks
Bhanu
Jersey won't do anything except you tell it to. A PUT request semantically should create or update a ressource, so if you plan to create some entity, thats the HTTP method to use. Use #PUT to annotate your method and implement your functionality (as your tutorials tell you).

Resources