Asynchronous service calls on server startup - java

I'm trying to create a simple RESTful application that helps people create and retrieve certain objects. The objective of the service is to serve up these objects as quickly as possible, which is why I'm considering cheating a little by "pre-creating" the objects during the server startup time in an asynchronous fashion. I can get away with this model because I know that there are only 500 different flavors of objects that people can ask for so i'd rather have them readily sitting in my persistent store (redis) warmed up such that by the time a user is asking for it, it's ready to serve.
My question is around how to enable this "background/async" processing right around the server startup (for a server like jBoss/tomcat in a RESTful service written in java). Putting it into a static block in the class serving results doesn't work, so I was wondering if there's a config in the catalina files that can link to loading a class which in turn could do the needful.

I think you may be looking for load-on-startup in your web.xml file, and then if you use the Init method in your HttpServlet class you may get the behavior you want.
Load-on-startup is a directive to tell the container to start that class immediately upon startup.
<servlet>
<servlet-name>ServletOne</servlet-name>
<servlet-class>com.yourcomp.MainServlet</servlet-class>
<description>This servlet is an example servlet</description>
<load-on-startup>1</load-on-startup>
</servlet>

Related

How do I perform one time actions in a Java Webapp AFTER all servlets have been initialized?

I have a standard Java 11 Web application, with multiple servlets in it. Some servlets are imported by libraries, others are written within the application itself.
I need to perform a task AFTER all web servlets have been initialized, preferably before any requests come in. The task requires access to ServletContext.
I have tried performing this by creating a ServletContextListener and it's corresponding contextInitialized method, but this performs the task BEFORE the servlets have been initialized.
I cannot add the task to the last servlet to load, as the last servlet loaded is imported from an external library.
It would be preferable if the solution does not involve creating a servlet with no mapping.
If you have access to your deployment descriptor (web.xml) and the servlets are eager loaded, then you could append your servlet in the servlet list and set a high number in load-on-startup element.
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>com.project.LastServlet</servlet-class>
<load-on-startup>99</load-on-startup>
</servlet>
I tried to find a workaround in the documentation, but I couldn't find it and the ServletContextListener is a no go:
"All ServletContextListeners are notified of context initialization before any filters or servlets in the web application are initialized."

Configuring servlet url-patterns without web.xml

I know this can be done in servlet 3.0 with the #Webservlet annotation where you just assign the url-patterns and not have to do any configurations within a web.xml. Is there a way to programmatically assign a servlets url-pattern for applications running servlet 2.5?
I am creating a library which multiple applications will depend on and trying to make it so each of these applications do not have to explicitly configure any servlet url mappings for the servlets in the library I am creating within their respective web.xml file.
Thanks,
Since the web.xml and #Webservlet are both mechanisms for the server to know where to route requests by examining the war, you would have to be able to manipulate the server if you wanted to do it in code. This is at least theoretically possible, since the server could offer for example a JMX endpoint for configuration or you could go directly into the innards of the server.
However while it might be possible, it would be a non-standard way and you would have to write different tricks for all the servers you want to support. That's not something you want to do.
Finally, if you're creating a library, why does it have servlets in it? It shouldn't be the responsibility of the library to create servlets or decide which urls they're assigned to.

How do I run arbitrary code when a Java HTTP Servlet session ends?

Our application requires that we serialize some of the user's session data to the filesystem if their session expires. We would serialize it as is coming in but that would be too expensive due to the nature of our application.
If we can figure out a way to hook some sort of 'onSessionEnd' method we could run the cleanup code then.
You need to setup a HttpSessionListener for your application.
There is a method on the interface called onSessionDestroy that shall be called when the session ends and you can perform serialization right then.
To setup the listener, you add into web.xml:
<listener>
<listener-class>com.example.app.session.MySessionListener</listener-class>
</listener>

retrieve jsf bean in axis2 web service as server request

I am using eclipse axis2 to create web service client from wsdl.
My impl method is:
public Output[] startProcess(Message[] Messages){
MyApplicationBean managementBean = (MyApplicationBean) FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get("myapp");
...
}
However when I execute:
http://localhost:8080/MyProject/services/portStartProcessService with method startProcess
I see in tomcat debug that it reaches my method, however the FacesContext.getCurrentInstance() returns null.
My web.xml (part of it)
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
<url-pattern>/services/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>AxisServlet</servlet-name>
<url-pattern>/servlet/AxisServlet</url-pattern>
</servlet-mapping>
How can I use JSF beans (like application scope) in web services call?
I know you do not want to hear this just yet, but you got the architecture wrong. JSF application context is useless with web service calls, because the whole idea of JSF is that GUI is built of stateful components stored:
in user session, or:
in a hidden form field.
Since neither session nor forms are available to web service calls, JSF does not apply here. You might as well ask how to make a web service that presses a JButton or inserts a CD into your CD-ROM.
I understand that you do not need the JSF components, but rather need some application logic that resides inside one of the managed beans, right?
Well, The easiest solution is to get a time machine, go back in time to when the project was planned and tell the architect that YOU NEVER PUT APPLICATION LOGIC INTO MANAGED BEANS. One of the reason is that they are unavailable to web service calls. Your application logic should reside in the service layer, provided by Spring or EJB.
Both Spring beans and EJBs are easy to reach from Axis services and from managed beans, and so you never need to access JSF managed beans from any place else than JSF front-end. If you do not like Spring and can't use EJB for some reason, build your service layer from POJOs, set it up in ApplicationContextListener and register in the application scope.
If such clean solution is unavailable and refactoring is impossible, you have two choices:
if the managed beans you try to reach are application scoped and eager, then they can be accessed in a JSP way, from the application context, using the venerable getAttribute method (you can access application context through the servlet context, which afaik you access through the message context, which in turn you access by the static MessageContext.getCurrentMessageContext method in Axis).
if the managed beans you want to use are request scoped and require some JSF plumbing (so you can not instantiate them by yourself) then you can pretend to be a FacesServlet and create the faces context by yourself; it is tricky but doable, a good and quite famous description is here: http://www.thoughtsabout.net/blog/archives/000033.html. You need will need servletrequest and servletresponse (from MessageContext). You can probably skip the parts required to pass the FacesContext on, because you will not require it to process any views.
Disclaimer: I never tried the last solution - it seems to work, although it is pretty dirty (and actually causes your web services to depend on JSF, which is bizzare).

Scheduled task in a web application? [duplicate]

This question already has answers here:
What is recommended way for spawning threads from a servlet in Tomcat
(5 answers)
Closed 8 years ago.
I'm building a statistics apps for an online game, built using the servlet API in Java (to be deployed on Tomcat). It's easy enough to let the game send a message to the stats server every time a user logs in, because handling requests is what Servlets/Tomcat are for.
I also need to periodically initiate requests on the stats server though, for example to retrieve the number of online users from the game server or the number of fans from our Facebook page.
It would be easy to just start a thread in the app's main servlet and let that do the data retrieval once in a while, but it feels a bit strange because all other threads are created by Tomcat.
Is doing it like that ok?
If not, what is the recommended way of doing this?
Is it even correct to use servlets for something like this? What's the alternative?
Note after first answers: I'm not looking for a solution to the problem of timing or concurrency, because I can easily handle both. I just need to know how to properly start a pro-active process in a servlet container.
Quartz is your best bet, and most highly configurable. It has CRON based interface or a more dynamic way to generate jobs that are relative from a specific event, if your use case calls for it Quartz can do it. It has the ability to persist jobs to the database so they can survive restarts.
http://www.quartz-scheduler.org/
Make configurations in web.xml like this to auto-start it:
<servlet>
<servlet-name>QuartzInitializer</servlet-name>
<display-name>Quartz Initializer Servlet</display-name>
<servlet-class>org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<init-param>
<param-name>shutdown-on-unload</param-name>
<param-value>true</param-value>
</init-param>
<init-param>
<param-name>start-scheduler-on-load</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
You should consider:
Quartz
The "regular" TimerTask
If you're using spring on your webapp, there is a dedicated part for it
Don't bother reinventing the wheel, Quartz and other products already handle Threads/timeouts/concurrency issues for you!

Categories