views:

206

answers:

3

I need to invoke a Servlet on application startup since it contains some application initialization logic.

I know I can set load-on-startup configuration, but this will only invoke Servlet’s init method. I need to invoke a doGet method and pass some Url parameters to it. Servlet doGet method expects ServletRequest and ServletResponse objects.

Also, since this is clustered application, I need to know exactly what node I am accessing (since one option is just to open a socket and invoke a Servlet).

What is the best option to perform this?

EDIT: As a clarification, Servlet already exist and can not be modified. Until now, someone would manually invoke the Servlet from the browser. I need to automatize this.

+3  A: 

The best option is to refactor whatever logic you have in the doGet method into a separate method that can be invoked both from init and doGet.

If you really can't refactor the logic (which really is the only good option), you can use some mock library. Google says Spring's mock objects are popular.

Having a usable implementation of HttpServletRequest and HttpServletResponse, make a servlet loaded with load-on-startup, and from its init method, locate the relevant servlet from the current ServletContext, and invoke doGet with the appropriate request and response objects. (Yes, it's a pretty bad kludge, but you'll have to do something like this.)

Edit: If you don't want to hack the WAR file, maybe you should check if your servlet container has the possibility to run some kind of hooks after you re/deploy a web app.

gustafc
+1: Never mix application logic with startup logic. A) first call of your app could take forever (which is somewhat irrelevant if you're using Google App Engine). B) It's a horrible kludge. Put your init stuff in Servlet::init()
Chris Kaminski
Unfortunately, this is not the option in my case.
Dan
@Dan, see my updated answer.
gustafc
I am not sure how mock objects come into play here?
Dan
Updated with clarification.
gustafc
thanks gustafc, I will try the option with mocks. It should work as long the code isn't doing anything weird with these objects.
Dan
Why not just use ServletContextListener instead of all this hacks with mocks and deployment hooks?!
Vasil Remeniuk
@Vasil, I agree that a context listener is cleaner than a servlet with `load-on-startup`, but the OP's problem is that they *have* to perform a `GET` request to a specific servlet.
gustafc
@gustafc. ServletContextListener may be used in conjunction with dummy HttpServletRequest/Response (I assume, only request parameter maps need to be implemented) that same way as load-on-startup -- get initialized servlet from the context and explicitly call doGet.
Vasil Remeniuk
@Vasil, yes - as I said, I agree. That doesn't reduce the kludginess of the solution by much, though, as the OP has to hack an existing WAR file.
gustafc
+3  A: 

Normally, bootstrup initialization / shutdown cleanup is achieved with ServletContextListener - did you consider this option?

Alternatively, as an ugly hack, you can implement a servlet superclass with the initializtion logics, that will be called just once.

Vasil Remeniuk
what do you mean by "you can implement a servlet superclass with the initializtion logics, that will be called just once."?
Dan
This approach is used in lots of web frameworks (e.g., Jersey). All the servlets are inherited from the super-servlet, that contains generic logics and bootstrupping functionality (which is invoked just once in a lazy-loading manner, when any child-servlet is called).
Vasil Remeniuk
A: 

This is in one word terrible, but you could use java.net.URL/java.net.URLConnection for this.

new URL("http://localhost/yourservlet").openStream();
BalusC
how do I get the servlet URL without configuring it?
Dan
By parsing web.xml.
BalusC