Kafka listeners with different retry attempts - spring-kafka

I have three spring #KafkaListeners, all consuming from the same topic, but I need to have different retry attempts for each listener which results in having different RetryPolicy I guess.
I am on version 2.7.11 right now; Should I define three different listener container Factories as well or there is a way to handle them on the same listener container factory?

RetryTemplate in the container factory is deprecated now that error handlers support backoffs and exception classification.
https://github.com/spring-projects/spring-kafka/issues/1886
You can add a container customizer to the factory and set a different error handler (with different back offs) for each container.

Related

Spring Boot Kafka error messages not being logged by Datadog agent

I'm using an event handler method with #KafkaListener based on default spring-kafka library, together with the embedded Datadog agent on the container running the application.
When Rest endpoints calls fails, it automatically inject the error messages on spans and I can see them on Datadog.
Although for Kafka errors, I can only see spans with "error: true".
I'm not using anything special other than that. Is there something needed in order to track event errors on Datadog?

Since ILogger<T> is a singleton, how different threads can use BeginScope() without affecting others?

This is related to this question. Context: .Net Core 3.1, using Microsoft.Extensions.Logging
Loggers are singletons in the application's IHost. If I inject (DI) an ILogger<T> into my class or method, the injected object is the same instance other classes or methods receive if they ask for ILogger<T>. This poses the question of what happens when I use logger.BeginScope($"Processing {transactionId}") in one thread. What happens with the other threads? Do they change the logging scope as well? Do logging scopes get mixed up? If they don't: how does that work, being their loggers the same object? If they do mix scopes, how can I make two threads use different logging scopes for a given ILogger<T> type?
This depends on the logger implementation, but typically they're implemented using a type of stack held within an AsyncLocal.
A call to BeginScope will put a new item onto that stack, and the adjoining Dispose will pop it off of that stack.
When the logger is invoked via LogInformation or otherwise, the data of the current stack object will be copied to write it to the console or whatever output that logger instance is configured to do.
The AsyncLocal is what gives the framework the ability to store information across threads and tasks.
For reference, check out the Microsoft.Extensions.Logging.Console source code:
ConsoleLogger.cs#L67
LoggerExternalScopeProvider.cs#L14

Tracking Event Processor - Retry Execption originating from Event Handlers

I am trying to configure an ErrorHandler for a TrackingEventProcessor so that any exception in my #EventHandler annotated method will be retried.
Currently using Axon Framework 4 and looking how to achieve this.
I'd recommend to set the PropagatingErrorHandler as the ListenerInvocationErrorHandler in this case.
Know that there are two error handling levels within a given Event Processor, namely:
The ListenerInvocationErrorHandler, catching the exceptions thrown from within your #EventHandler annotated methods. This defaults to a LoggingErrorHandler instance, which logs the exception.
The ErrorHandler, catching the transaction exceptions of the given EventProcessor. This defaults to a PropagatingErrorHandler, which rethrows the exceptions.
The TrackingEventProcessor (TEP) EventProcessor implementation is the one which will retry events with a certain (unconfigurable) back-off, if the configured ErrorHandler throws an exception.
If you want to retry on every exception (which might be a debatable approach anyhow), you'd thus want to enter the retry scheme of the TEP. To achieve this, you simply should configure the ListenerInvocationErrorHandler to also be a PropagatingErrorHandler. I'd recommending reading the Reference Guide on the matter too, to get a better idea of how to configure this.

How to get all EJB timers?

In EJB 3.1 I can get all timers for a specific bean using TimerService#getTimers() on the TimerService instance obtained for that bean.
What I actually need however is a system-wide version of this. I.e. I would like to have a list of all Timers in the EJB container.
Is something like that possible?
There simply is no official API for this in EJB 3.1.
If you're only using annotations and/or interfaces to mark your timeout method, you could do a run-time walk over all classes on the class path and check if this annotation or interface is present. This will at least give you the beans which theoretically can have timers associated with them.
Unfortunately, this still won't give you the actual timers for those beans. In EJB 3.1, the time information can only be requested from the session context, which as you already seem to know is private for each bean. This means that only the bean itself can see what timers it has.
As an alternative to what Nayan is suggesting, you could let your beans implement a method that gives you this info. You can then mark this method with either an interface or a custom annotation.
In your system-wide sweep over all timer classes you first try to discover all beans that can have timers associated with them, and of those you then try to find whether they have the required annotation or interface. If they don't have this latter thing, you can log a warning. The advantage of this method is that it's less likely that timers slip through the cracks.
Yet another method, but a very brittle one, is to hack into whatever private structure the container holds to store the timer information. For persistent timers there is at least the persist store which you can check, and somewhere in the container there must be the structure you're after. It must be there as the container itself has to be aware of this. Often a container has some private API to get to this and you can hack into that via reflective tricks.
It can also be that containers offer a proprietary API for this. E.g. in Java EE 5 it's impossible to do a programmatic login in the Servlet container, but JBoss AS has a proprietary API that allows you to do exactly that.
EJB 3.2 has a method called "getAllTimers()".
https://docs.oracle.com/javaee/7/api/javax/ejb/TimerService.html#getAllTimers--
Description:
Returns all active timers associated with the beans in the same module in which the caller bean is packaged. These include both the programmatically-created timers and the automatically-created timers.
Below is the sample code fragment for fetching information of all the existing timers of the system.
//---
private void viewSystemTimers(){
Collection<Timer> allTimers = sessionContext.getTimerService().getTimers();
Iterator<Timer> iterator = allTimers.iterator();
while (iterator.hasNext()) {
Timer timer = (Timer) iterator.next();
System.out.println("SYSTEM TIMER : "+timer.getInfo());
}
}
//---
You can only see timers of your own class. With the EJB Scheduler you can't list all timers of your application.
#Resource
private TimerService timerService;
for (Timer timer : timerService.getTimers()) {
// do anything
}
With Quartz you can via Scheduler.getJobNames/triggerNames for all jobs/triggers of you application.

Singleton vs Single Thread

Normally Servlets are initiated just once and web container simple spawns a new thread for every user request. Let's say if I create my own web container from scratch and instead of Threads, I simply create Servlets as Singleton. Will I be missing anything here? I guess, in this case, the singleton can only service one user request at a time and not multiple.
Normally Servlets are initiated just once and web container simple spawns a new thread for every user request.
The first statement is true, but the second actually not. Normally, threads are been created once during applications startup and kept in a thread pool. When a thread has finished its request-response processing job, it will be returned to the pool. That's also why using ThreadLocal in a servletcontainer must be taken with high care.
Let's say if I create my own web container from scratch and instead of Threads, I simply create Servlets as Singleton. Will I be missing anything here?
They does not necessarily need to follow the singleton pattern. Just create only one instance of them during application's startup and keep them in memory throughout application's lifetime and just let all threads access the same instance.
I guess, in this case, the singleton can only service one user request at a time and not multiple.
This is not true. This will only happen when you synchronize the access to the singleton's methods on an application-wide lock. For example by adding the synchronized modifier to the method of your servlet or a synchronized(this) in the manager's method who is delegating the requests to the servlets.
JavaEE used to have a mechanism for this - a marker interface called SingleThreadModel that your servlet could implement:
Ensures that servlets handle only one request at a time. This interface has no methods.
If a servlet implements this interface, you are guaranteed that no two threads will execute concurrently in the servlet's service method. The servlet container can make this guarantee by synchronizing access to a single instance of the servlet, or by maintaining a pool of servlet instances and dispatching each new request to a free servlet.
Note that SingleThreadModel does not solve all thread safety issues. For example, session attributes and static variables can still be accessed by multiple requests on multiple threads at the same time, even when SingleThreadModel servlets are used. It is recommended that a developer take other means to resolve those issues instead of implementing this interface, such as avoiding the usage of an instance variable or synchronizing the block of the code accessing those resources. This interface is deprecated in Servlet API version 2.4.
Containers could use this to instantiate a new servlet for each request, or maintain a pool of them, if they chose to.
This was deprecated in Servlet 2.4, for the reasons documented above. Those same reasons still apply to your question.
That's basically it.
I would question the motivations for creating your own container, with so many available for a wide range of purposes.

Resources