How to implement a clean up method after request finish process in a spring boot application for clean data such as thread locals
I try with ServletRequestListener.requestDestroyed api, but it does not get hit after the request finish
One possible answer is that you have neglected to register the listener. The Servlet javadocs say:
In order to receive these notification events, the implementation class must be either declared in the deployment descriptor of the web application, annotated with WebListener, or registered via one of the addListener methods defined on ServletContext.
There may be other ways to implement this using Spring; e.g. using a handler intercepter; see Remove ThreadLocal object within a Spring MVC website?
If you were using plain servlets (without the Spring MVC infrastructure), another approach would be to do the cleanup in your servlet's service method or the doXxx methods. Or in a Filter in front of the servlet.
Related
In a spring boot app (2.3), is it possible to have a method be executed after context is initialized, but before the app starts to take requests? I don't know if becoming ready to accept requests is part of the spring context initialization or if that is a separate step.
Note that ideally if this method throws an exception, the service fails to start, but that is not a requirement.
I tried ContextRefreshedEvent. However, the app is accepting requests at that point. (While my ContextRefreshedEvent event listener method is executing, requests can come in and execute at the same time.)
(I can't use #PostContruct, because my method depends on many different beans being initialized.)
The specific use case is that I have a spring cloud config server. I want it to pre-load authentication data into cache prior to accepting requests. The loading of this data depends on bootstrap/app config files being loaded, ApplicationEnvironmentPreparedEvent listener being called, beans being constructed, etc.
As Andy Wilkinson pointed out (thank you!), to do this, implement a bean's method with the desired behavior and add the #PostConstruct annotation. The method will be called after all beans are initialized (and environment prepared) but before the service starts taking requests.
I want to create a REST API in spring boot which can handle around 100TPS. Lets say I create a basic REST api using a sample application in spring boot. Does this automatically handles multi threading. Lets consider the code bellow.
#RequestMapping(method = RequestMethod.POST, value="findByPackageActivationId")
#ResponseBody
public JSONObject findByPackageActivationId(#RequestBody IncomingRestObject incomingRestObject) {
//My work here
}
By default Spring Boot web applications are multi-threaded and will handle multiple requests concurrently.REST controller is multithreaded as the DisptcherServlet handles multiple requests from the clients concurrently and serves using the respective controller methods.You can change any of the default thread settings as well (e.g. server.tomcat.max-threads). For more information refer here :-
https://docs.spring.io/spring/docs/current/spring-framework-reference/web.html#mvc
REST controller is multithreaded as the DisptcherServlet handles multiple requests from the clients concurrently and serves using the respective controller method
You can scale your app as per your requirements to achive desired TPS
https://dzone.com/articles/how-to-test-if-your-multi-threaded-java-rest-servi
For every request from the client, the server will create a new thread and assign that request to newly created thread. You don't have to handle this explicitly.
Also for your requirement(100 Threads), you can configure this on the server. You can refer this link for tomcat configuration as its default server for spri.
Spring Framework provide these feature internally, these are benefits that spring provide over core servlet coding that we used to do in older days. It also provide the way to control it.
For Ex you can change limit of number of thread to create using server.tomcat.max-threads (For tomcat).
For Basic understading on multi threading with spring boot please refer https://www.e4developer.com/2018/03/30/introduction-to-concurrency-in-spring-boot/
I'm planing to migrate my old app to Spring-Boot.
I want to stop using web.xml descriptor and register old pure Servlet ("async-supported" enabled) and an associated ServletContextListener.
Spring Boot will automatically register any Servlet beans in your application context with the servlet container. By default async supported is set to true so there's nothing for you to do beyond creating a bean for your Servlet.
If, for whatever reason, you want to take more control over your servlet's registration, then, rather than exposing the Servlet itself as a bean, you can wrap it in a ServletRegistrationBean.
Put a #EnableAsync on your application class.
See here for more details.
servletRegistrationBean.isAsyncSupported() is by default true which decides whether the Async functionality is supported or not.
.
If you are facing below issue then follow the link
java.lang.IllegalArgumentException: Async support must be enabled on a
servlet and for all filters involved in async request processing. This
is done in Java code using the Servlet API or by adding
"true" to servlet and filter
declarations in web.xml. Also you must use a Servlet 3.0+ container
I am looking for using jersey with embedded Jetty for implementing web APIs for our service. I see code where ServletContextHandler , ServletHolder and all these classes are used to let Jetty know about the Jersey handlers. I am interested to know under the hood, like what happens when we compile this code, how jetty actually discovers the jersey handlers. I know that if I start reading the documentation, I will be able to figure out, however, looking for some quick links that covers this topic. Is there any such link?
Thanks.
Jetty can act as a http server and also a servlet container who deals with the lifecycle of servlets (init, service, destroy)
etc. A servlet is a java class that extends HttpServlet class and can override init, service, destroy methods etc. Once jetty
receives a request whose URL matches with that of a servlet, it loads the servlet in memory (if not already there), calls
service method, and keeps it in memory until it destroys it.
Jersey library has provided a standard way of writing RESTful APIs where classes are annotated with tags like say GET/POST
etc and the URL. These classes are called resource classes. It has also provided a servlet whose name is ServletContainer
to hook up with Jetty's servlet container, that intercepts Jetty's request to process servlet (like for any servlet request to jetty
this is the one class, that receives the request first).
What this servlet does is it examines the request, matches with the resource classes URL that it is informed about, and then transfers
control to that method of that resource class (i think it uses reflection for this routing). Therefore, the resource
classes are not servlet itself, but the ServletContainer class of jersey is the only servlet active in the system.
The list of resource classes ServletContainer knows about is configured by this property called "com.sun.jersey.config.property.packages"
The benefit of using Jersey is implementing your REST APIs is you are using standard way of writing your code that you can
deploy to any other standard servlet container if needed in future like tomcat, ...
Correct me if anything is wrong.
As I understand, all Spring functionality, namely DI works when beans are got thru
Spring Context, ie getBean() method.
Otherwise, none can work, even if my method is marked #Transactional and I will
create the owning class with a new operator, no transaction management will be provided.
I use Tomcat 6 as a servlet container.
So, my question is: how to make Servlet methods managed by Spring framework.
The issue here is that I use a framework, and its servlets extend the functionality of
basic java Servlets, so they have more methods. Still, web.xml is present in an app as usual.
The thing is that I do not control the servlets creation flow, I can only override a few methods
of each servlet, the flow is basically written down in some xml file, but I control this process
using a graphical gui.
So, basically, I only add some code to a few methods of each Servlet.
How to make those methods managed by Spring framework? The basic thing I need to do is
making these methods transactional (#Transactional).
comment to Bozho:
#Bozho Let's see. In these servlets' methods I work with framework capabilities, let's say special variables that are got and saved in the current session. And what is needed, is looping through those framework-based collections while saving some values in a database. What you suggest is introducing a new very complex object, so that it could be passed to a service layer. (Service layer will not know anything about framework, its classes and objects kept in current Session! First, we "wrap" framework based collections to such a object, so copy everything into it. Then, again, the Service layer method should either save changes in a database or, worse case, return a new complex object so that Servlet framework method could update framework variables depending on the result of Service layer method execution. It is a workaround but do you think it is a good idea?
You can also define your servlets directly in the Spring application context. You'll need a "proxy" servlet registered in web.xml and delegating to the servlet instance which is configured as bean in the applicationContext.xml. Proxy servlet is configured with the name of the target servlet bean, it discovers this bean via WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(...) and delegates all the processing to the target servlet. In this case an instance of your servlet is completely managed by Spring.
I'd suggest restructuring your code - making servlet methods transactional is not a good thing to do. Put the transactional logic in a separate, service class, and either
obtain these spring-managed classes by WebApplicationContextUtils.getRequiredWebApplicationContext().getBean(..) or
in your servlet init() method obtain the ApplicationContext with the above method and call appCtx.getAutowireCapableBeanFactory().autowireBean(this). This way you can inject the transactional classes in your servlet as if it was spring-managed.
Now, you can do all this, but it is definitely not a beautiful way to go. I'd suggest using Spring MVC or any other MVC framework (which support spring integration of its components)
If this is all not possible, as a last resort I think you can use #Configurable (on your servlets) with a <context:load-time-weaver/>.
You should take a look how Spring proxy filters:
http://grepcode.com/file/repository.springsource.com/org.springframework/org.springframework.web/3.0.2/org/springframework/web/filter/DelegatingFilterProxy.java
In theory you could easily make the same sort of proxy for servlets and DispatcherServlet is sort of a proxy.