OncePerRequestFilter and filter invocation - java

I am learning spring security and I came across the concept of filters. On reading a little bit what I understood is that dispatcher servlet receives the request first (also called the front controller for the same reason), after that it calls a certain mapper which helps to invoke the required controller method. Please let me know if my understanding is wrong somewhere.
Further I came across OncePerRequestFilter, I referred this link to understand it :
https://www.baeldung.com/spring-onceperrequestfilter
In an example mentioned here :
#Controller
public class HelloController {
#GetMapping(path = "/greeting")
public DeferredResult<String> hello(HttpServletResponse response) throws Exception {
DeferredResult<String> deferredResult = new DeferredResult<>();
executorService.submit(() -> perform(deferredResult));
return deferredResult;
}
private void perform(DeferredResult<String> dr) {
// some processing
dr.setResult("OK");
}
}
it says that if we use a normal Filter, it will be invoked twice,
1- because of the TOMCAT/http-worker thread and
2- because of the new thread branched out
My doubt is that how come branching out a new thread invokes the filter again. I mean my understanding was that filter just sits between dispatcher servlet and controller. After it has reached controller there is no filter coming in between, during the controller method processing.
Can anyone please help me understand the same.
In a nutshell, I have 2 doubts :
1- how spanning a new thread in controller may invoke the filter again, in case of async/defferedresult
2- does it means that for synchronous requests we dont need OncePerRequestFilter explicitly, It'll be anyway only once. If not, then in what case will the filter be invoked twice in case of Sync requests.

Related

Are multiple requests handled by single thread in Spring Boot until certain requests threshold is reached?

In my Spring Boot 2.1.6 project (based on Tomcat) I have a rest controller. I added a default constructor to it which prints something. I thought in Tomcat-based servers each request is handled in separate thread. So I expected each request to trigger a new controller object and as a result new print from the constructor. However, I made a test of sending 30 requests to the rest controller and I only see that the print was made once. So as far as I understand the rest controller handles all those requests in one thread.
My question is whether indeed multiple requests are handled in a single thread or maybe there's certain request threshold upon which another thread will be opened? I'm using default Spring Boot configuration perhaps this is controlled somewhere in the config?
This is the code for my controller:
#RestController
public class TrackingEventController {
public TrackingEventController() {
System.out.println("from TrackingEventController");
}
#RequestMapping(method=GET, path=trackingEventPath)
public ResponseEntity<Object> handleTrackingEvent(
#RequestParam(name = Routes.event) String event,
#RequestParam(name = Routes.pubId) String pubId,
#RequestParam(name = Routes.advId) String advId) {
return new ResponseEntity<>(null, new HttpHeaders(), HttpStatus.OK);
}
}
You're mixing two orthogonal concepts:
a thread
a controller instance
A single thread could create and/or use one, or several controller instances.
Multiple threads could also create and/or use one, or several controller instances.
The two are unrelated.
And how it actually works is
Spring beans are singletons by default, so Spring creates a single instance of your controller
A servlet container uses a pool of threads.
Every time a request comes in, a thread is chosen from the pool, and this thread handles the request. If the request is mapped to your controller, then the appropriate method of the unique controller instance is executed by this thread.
If you want to know which thread is handling the current request, add this to your controller method:
System.out.println(Thread.currentThread().getName());
Spring boot Tomcat thread pool default size is 200. You can make out that different threads server different requests. Put a debug point on some REST endpoint, and call it multiple times from Postman etc. From debugger, check the thread name. s.b.

Can API Request (GET Call) return a response to client and start a background task to finish request

I am using Spring Boot 1.4 and Java8. I want to know is it possible that if I receive a get request for an API in controller. I immediately return a response to the client and then create a background task for the request (that handle success and exception scenarios). I understand we can use completablefuture for async processing, but still from controller method for this API we generally send the response after using thenapply, exceptionally or get. That means though we have spawned a new thread. Main thread is still not free. I am looking for hit and forget kind of use case. Please suggest how it may be feasible.
as stated in comments you can use async functionality from Spring. For that you'll need a configuration like
#EnableAsync
#Configuration
public class AsyncConfig {
#Bean
public Executor threadPoolTaskExecutor() {
return new ConcurrentTaskExecutor(Executors.newCachedThreadPool());
}
}
then put the annotation on the method which is running the background task
#Async
void runBgTask() { /* ... */ }
and call it in your controller method
#GetMapping("/foo")
public Foo hello() {
runBgTask();
return new Foo();
}

Rest Web Service Interface - Multithreaded

Below is a snippet of an existing Rest Interface implementation.
#RestController
#RequestMapping("/login")
public class LoginController {
#Autowired
private LoginProcessor loginProcessor;
#RequestMapping(
consumes = MediaType.TEXT_XML_VALUE,
produces = { MediaType.TEXT_XML_VALUE,
MediaType.APPLICATION_JSON_VALUE },
value = "/v1/login",
method = RequestMethod.POST)
public LoginResponse loginRequest(
#RequestBody String credentials) throws JAXBException {
return loginProcessor.request(credentials);
}
}
If the REST call to loginRequest() is initiated from different clients, and possibly, at the same time :-
1) Will a new thread be created to handle each request. Therefore, all requests are being processed concurrently ?
or
2) Is there one thread to handle all requests, which would mean only loginRequest() is being executed at any one time, and other request are queued up ?
I would ideally like to the interface to be able to handle multiple requests at any one time.
Thank you for your help in both clarifying and furthering my understanding on the subject.
Pete
You can search stack overflow for this type of question as it has been answered before. You can read these answers:
https://stackoverflow.com/a/7457252/10632970
https://stackoverflow.com/a/17236345/10632970
Good luck with your studies.
Every application should run in server either web server (tomcat) or application server (web logic), by default tomcat web container will have 200 threads ( you can adjust as your wish), so 200 threads can process concurrently at a time in tomcat
For every input request will be taken by web container thread and next to dispatcher servlet to corresponding controller class
I suppose you are using spring framework ( as you have used Autowired and other annotations). Thus to ans your ques: Yes spring will create new thread for each new request. Kindly refer to this answer, this should solve your queries
https://stackoverflow.com/a/17236345/7622687

A real-world controller example with Spring 5: Web Reactive

I want to be involved in a reactive programming world with Spring. As I realised, it gives me a choice between two different paradigms: the annotation-based (with well-known to us #Controller, #RequestMapping) and the reactive one (which is intended to resolve an "Annotation Hell").
My problem is a lack of understanding how a typical reactive controller will look like. There are three conceptual interfaces, which I can use in my controller class:
HandlerFunction<T> (1) - I define a method for each specific ServerRequest
which returns a concrete HandlerFunction<T> instance, then register these methods with a router. Right?
RouterFunction (2) and FilterFunction (3) - Is there a specific place where all RequestPredicates with corresponding HandlerFunctions should be placed? Or can I do it separately in each controller (as I used to do with the annotation approach)? If so, how then to notify a global handler (router, if any?) to apply this router part from this controller?
It's how I see a reactive controller "template" by now:
public class Controller {
// handlers
private HandlerFunction<ServerResponse> handleA() {
return request -> ok().body(fromObject("a"));
}
// router
public RouterFunction<?> getRouter() {
return route(GET("/a"), handleA()).and(
route(GET("/b"), handleB()));
}
// filter
public RouterFunction<?> getFilter() {
return route(GET("/c"), handleC()).filter((request, next) -> next.handle(request));
}
}
And, finally, how to say that it is a controller, without marking it with the annotation?
I've read the Spring reference and all posts related to this issue on the official blog. There is a plenty of samples, but all of them are pulled out of context (IMHO) and I can't assemble them into a full picture.
I would appreciate if you could provide a real-world example and good practices of how to organise interactions between these functions.
This is not a real world example, but so far Is how I view some kind of organization on this:
https://github.com/LearningByExample/reactive-ms-example
As far as I concerned:
RouterFunction is the closest analogue to #Controller (#RequestMapping precisely) in terms of new Spring approach:
Incoming requests are routed to handler functions with a
RouterFunction (i.e. Function>). A router function evaluates to a
handler function if it matches; otherwise it returns an empty result.
The RouterFunction has a similar purpose as a #RequestMapping
annotation. However, there is an important distinction: with the
annotation your route is limited to what can be expressed through the
annotation values, and the processing of those is not trivial to
override; with router functions the processing code is right in front
of you: you can override or replace it quite easily.
Then instead of Spring Boot SpringApplication.run in main method your run server manually by :
// route is your route function
HttpHandler httpHandler = RouterFunctions.toHttpHandler(route);
HttpServlet servlet = new ServletHttpHandlerAdapter(httpHandler);
Tomcat server = new Tomcat();
Context rootContext = server.addContext("",
System.getProperty("java.io.tmpdir"));
Tomcat.addServlet(rootContext, "servlet", servlet);
rootContext.addServletMapping("/", "servlet");
tomcatServer.start();
There are both reactive and non-reactive approach. It's illustrated on Spring github

Button onClick Call Java Method Until Certain Result

I'm completely new to the Spring framework (and most web development in general), but I'm trying to hook up some heavy Java backend code to a new Spring and JSP project. My Controller's handleRequest() is kicking off a long running worker thread before it returns my request.jsp ModelAndView object. After that I'd like to be able to still interface with this Controller from my JSP form to be able to call isThreadDone() in the Controller whenever a button in the form is clicked. Based on three different results, I then redirect accordingly. Is this possible with my current approach? This seems to violate some of the Spring MVC approach, but I can't think of a good way to do this that I can wrap my head around. If anything is way off here, please excuse my ignorance. Thanks in advance.
Take a look at the Spring #Async annotation. If you annotate a Service-layer bean with that annotation, it then runs in its own thread, allowing your Controller thread to run without interruption after calling the Service method. Have that thread is set a value held at the Class level for the Service via synchronous methods, and your Controller code can just check those toggles at will to see if the process is done or not. Something like:
#Service
public myServiceClass {
private boolean isDone = false;
public synchronized void setIsDone(boolean isDone) {
isDone = isDone;
}
public synchronized boolean getIsDone() {
return isDone;
}
#Async
public void myServiceMethod() {
...long-running stuff...
setIsDone(true);
}
In the Controller:
#Controller
class MyController {
#RequestMapping
public kickOffHandlerMethod() {
myServiceClass.myServiceMethod();
}
}
#RequestMapping
public dependentHandlerMethod() {
if(myServiceClass.getIsDone()) {
...do something...
}
}
}
If more than one request might kick off the process, then I would save each isDone toggle in a HashMap with some kind of identifier. Then the threads would update individual toggles, one for each request.
Well, anything is possible, right? Based on what you've provided, you can just keep a reference to the thread--maybe in the HttpSession--so that when a new request comes in from clicking the button, you can query it and return an appropriate response.

Categories

Resources