Why filter chain is called twice for an asynchronous endpoint - spring

I'm developing a Spring boot based app. I noticed that for asynchronous endpoints authentication filter is called twice, for regular endpoints it's called once. I couldn't find the reason, but I found an issue in the net https://jira.spring.io/browse/SPR-12608 , where it's said that filters for async endpoints are called twice, before and after async endpoint execution. It would explain double authentication call. I'd like to know is this expected behavior, why it's done like that and how to avoid double authentication.
UPD:
I found a way how to avoid filter being firing second time after async endpoint finished. The thing I need to do is to analyse what kind of dispatcher is assigned to the request, if it's async - proceed further on filter chain. I added the following method to the filter:
#Override
public final void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
if (request.getDispatcherType() == DispatcherType.ASYNC) {
filterChain.doFilter(request, response);
} else {
super.doFilter(request, response, filterChain);
}
}

I am seeing exactly the same behavior and I think it is related to the fact that asynchronous call is being split into 2 phases.
At first, regular container thread is kicked and an interim response is generated, but that response is not being returned to the client it is being held back until async dispatcher competes. Once async thread is done processing interim response is replaced with the real one from async thread and returned to the client.
Both threads go through the same filter chain. Therefore you see duplicate invocation.
If you want your filter to be invoked once you should extend from OncePerRequestFilter. It will check if your filter was already invoked during the course of the request (even though the request handling consists of 2 stages each of them handled by their own threads).

I had the same problem with a concrete implementation of the class AbstractAuthenticationProcessingFilter, I belive to solve it It's better create a custom implementation of whaterver class that implements OncePerRequestFilter, in my particular case I created an implementation of AuthenticationFilter.

Related

New session for each call to the Spring Boot server with JWT problem

I'm working to limit the number of sessions per user in Spring Boot, so as to limit the number of devices it can connect.
this is my WebSecurityConfigurerAdapter:
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED).maximumSessions(10).maxSessionsPreventsLogin(true);
I tried to change SessionCreationPolicy in various states, or not declare it:
http.sessionManagement().maximumSessions(10).maxSessionsPreventsLogin(true);
every time I call the server, a new session is generated, up to exceeding the declared limit, so I am no longer authorized to make a call.
I noticed that the creation of the new session takes place in GenericFilterBean, exactly after running filterChain.doFilter (req, response)
I carry the file GenericFilterBean:
#Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain)
{
...
**filterChain.doFilter(req, response);**
...
}
do you know the way to avoid that every call to the server generates a new session? My goal is one session for each device.
Thanks a lot for availability !!!

How to not lose Request attributes when making async (asynchronous) from one Rest Service to another

Currently I'm facing the following issue:
Rest service (Implemented using Spring Boot)
Inside my rest service I need to make an asynchronous call to another rest service.
I'm using #Async into the public method that will perform the async call.
I'm using Feign Client to make that rest call.
I'm intercepting the request using a feign.RequestInterceptor
Now the problem:
In the current implementation of the RequestInterceptor we have
#Override
public void apply(RequestTemplate requestTemplate) {
/// Getting a NullPointer here as obviously we have changed the from one thread to another
/// when the async call was made
final HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
.getRequest();
//some other irrelevant logic for this example....
}
As we move from one thread to the spawned thread, the information is lost.
I'm assuming it has to do with the threadlocal and somehow I should pass the information to an inheritablethreadlocal.
What should be the approach to be able to pass the ServletRequestAttributes to the spawned thread, without losing the information? (basically I'm interested in be able to preserve headers that came in the original thread).

Count AsyncResponse calls in spring boot metrics

I have a JAX-RS service backend written in Spring boot 2 and using micrometer for metrics.
By default the metrics contain very nice http metrics as http_server_requests_seconds_count.
These work great for normal GET and PUT requests. One method in my service uses JAX-RS AsyncRequest though.
#GET
#Produces(APPLICATION_JSON)
#Path("next/{position}")
public void getNext(
#PathParam("position") Long position,
#Suspended final AsyncResponse response) throws InterruptedException {
...
// Somewhere in the code in another thread I invoke
response.resume(entity);
...
}
These calls do not seem to be counted at all. Is there a way to enable counting them?
If not should I simply feed the same counters manually from my code?

Spring SecurityContext in Async Controller Response

According to WebAsyncManager documentation,
An async scenario starts with request processing as usual in a thread (T1). Concurrent request handling can be initiated by calling startCallableProcessing or startDeferredResultProcessing, both of which produce a result in a separate thread (T2). The result is saved and the request dispatched to the container, to resume processing with the saved result in a third thread (T3). Within the dispatched thread (T3), the saved result can be accessed via getConcurrentResult() or its presence detected via hasConcurrentResult().
The Spring SecurityContext is available in T1 and T2, but not in T3. I need the SecurityContext in T3, while serializing the response (it's a peculiar requirement). I can fix this by setting
spring.security.filter.dispatcher-types=REQUEST,ERROR,ASYNC, but this causes my entire FilterChain to run twice, which I'm trying to avoid.
Is there a way to get the SecurityContext in T3 without running the FilterChain again?

MassTransit fault consumer not invoked for request/response

What is the best practice for handling exceptions in MassTransit 3+ with regard to Request/Response pattern? The docs here mention that if a ResponseAddress exists on a message, the Fault message will be sent to that address, but how does one consumer/receive the messages at that address? The ResponseAddress for Bus.Request seems to be an auto-generated MassTransit address that I don't have control over, so I don't know how to access the exception thrown in the main consumer. What am I missing? Here's my code to register the consumer and its fault consumer using Unity container:
cfg.ReceiveEndpoint(host, "request_response_queue", e =>
{
e.Consumer<IConsumer<IRequestResponse>>(container);
e.Consumer(() => container.Resolve<IMessageFaultConsumer<IRequestResponse>>() as IConsumer<Fault<IRequestResponse>>);
});
And here's my attempt at a global message fault consumer:
public interface IMessageFaultConsumer<TMessage>
{
}
public class MessageFaultConsumer<TMessage> : IConsumer<Fault<TMessage>>, IMessageFaultConsumer<TMessage>
{
public Task Consume(ConsumeContext<Fault<TMessage>> context)
{
Console.WriteLine("MessageFaultConsumer");
return Task.FromResult(0);
}
}
This approach DOES work when I use Bus.Publish as opposed to Bus.Request. I also looked into creating an IConsumeObserver and putting my global exception logging code into the ConsumeFault method, but that has the downside of being invoked every exception prior to the re-tries giving up. What is the proper way to handle exceptions for request/response?
First of all, the request/response support in MassTransit is meant to be used with the .Request() method, or the request client (MessageRequestClient or PublishRequestClient). With these methods, if the consumer of the request message throws an exception, that exception is packaged into the Fault<T>, which is sent to the ResponseAddress. Since the .Request() method, and the request client are both asynchronous, using await will throw an exception with the exception data from the fault included. That's how it is designed, await the request and it will either complete, timeout, or fault (throw an exception upon await).
If you are trying to put in some global "exception handler" code for logging purposes, you really should log those at the service boundary, and an observer is the best way to handle it. This way, you can just implement the ConsumeFault method, and log to your event sink. However, this is synchronous within the consumer pipeline, so recognize the delay that could be introduced.
The other option is to of course just consume Fault<T>, but as you mentioned, it does not get published when the request client is used with the response address in the header. In this case, perhaps your requester should publish an event indicating that operation X faulted, and you can log that -- at the business context level versus the service level.
There are many options here, it's just choosing the one that fits your use case best.

Resources