Can we call service() method from destroy() method in Servlet? - java

This is one of the interview questions I faced a few days ago:
Is it possible to call the service() method from destroy()?
Thanks in advance.

destroy() is a lifecycle method called by the Servlet container when unloading a specific instance of the Servlet. Similarly, the container will call service() when there's a client requesting the Servlet.
Can we call service() method from destroy() method in Servlet?
Short answer: Yes, as service() is a method like any other.
Long answer: You can, but it doesn't make sense. service() requires a request and a response parameters that are usually provided by the container when the Servlet is called. If you are calling service() by yourself, how are you gonna provide those parameters? What for? Are you gonna use null on both? What good is service() for two empty parameters?
Can we call destroy() method from service() method in Servlet?
Yes, again, you can call destroy() from within the service() as it is also a method like any other. Although still strange, this could make sense sometimes, as destroy() will do whatever logic you have defined (cleanup, remove attributes, etc.).
IMPORTANT: Just bear in mind that simply calling destroy() won't unload the Servlet instance. You do not manage the lifecycle of Servlets in the program, the Servlet Container does.

Purpose of destroy() is to de-allocated/free all the resources used by Servlet instance. By calling destroy() container deregister servlet and its service.
Yes you can call the service(request, response) like anyohter method from destroy() but it wont be executed so its useless to call service method from destroy() as those service method never going to be called/executed, request and response will be null as those objects will not be provided by container.
public void destroy() {
try
{
doPost(null, null); // will not be executed
doGet(null, null); // will not be executed
}
catch(Exception e)
{
e.printStackTrace();
}
}
From Java doc:
public void destroy()
Called by the servlet container to indicate to a servlet that the servlet is being taken out of service. This method is only called once all threads within the servlet's service method have exited or after a timeout period has passed.
After the servlet container calls this method, it will not call the service method again on this servlet.
This method gives the servlet an opportunity to clean up any resources that are being held (for example, memory, file handles, threads) and make sure that any persistent state is synchronized with the servlet's current state in memory.

Related

Forcing Dropwizard/Jersey to make a method call between to endpoints instead of a network call

Say I have a Dropwizard/Jersey resource defined like so:
// Pseudo-code
#Path("/fizz")
#Produces(MediaType.APPLICATION_JSON)
class FizzResource {
FizzDao fizzDao
#GET
List<Fizz> getFizzesByType(#PathParam("type") String type) {
// Do some stuff up here
return fizzDao.getFizzesByType(type)
}
#POST
Widget determineWidgetByFoobaz(#PathParam("foobaz") String foobaz) {
// Do some stuff
List<Fizz> fizzes = getFizzesByType(foobaz.type)
Widget w = new Widget(fizzes, true, blah)
// Do some more stuff
return w
}
}
What happens when I call one endpoint (getFizzesByType) from inside another endpoint (determineWidgetByFoobaz)?
Does the framework know to just make a Java method call? Or is an actual network call (to localhost/loopback/etc.) made? If a network call is made, does the framework provide any way to configure it so that just a local Java method invocation is called instead?
If you access the endpoint as a method (i.e. this.getFizzesByType(type)) then it will be called like any other Java method. If you access it via a URI (e.g. ClientBuilder.newClient().target("http://localhost/fizz/" + type).request().get()) then it will be accessed as a network resource.
The getFizzesByType call inside determineWidgetByFoobaz is just another local method call. There's nothing special in those methods, and you can also call them safely in, let's say, a unit test.
What Jersey does on it's bootstrapping process is to scan for classes annotated with #Path and then bind each method annotated with an HTTP method to it's endpoint (if any). That way, when someone fires a GET to /fizz, in a nutshell Jersey gets a FizzResource instance, call it's getFizzesByType method, serializes the returned object to JSON, creates the appropriate HTTP response and sends it back to the client.

Using CDI with AsyncResponse and ExecutorService

Before adding CDI into our application I had created a resource that used the #Suspended AsyncResponse object to implement long polling for a chat client. What I did was create a new newSingleThreadExecutor() and submit a Runnable to it that used .wait(30000) on a message list until notification that a new message was sent. Inside that task I used the HttpServletRequest which was obtained using #Context and everything worked perfectly.
However once we added CDI to our application and even without making the resource class a bean (scanning only annotated beans and we didn't give it any scope annotation) I got a runtime exception that the request object INSIDE the Runnable task couldn't be accessed because of an illegal state exception:
Method threw 'java.lang.IllegalStateException' exception. Cannot evaluate com.sun.proxy.$Proxy74.toString()
I'm not really sure why this happens but I know it is CDI related since it refers to a proxy object. One guess is that the resource class itself has become CDI scoped and that scope can't be accessed from a different thread? I read somewhere that manually started threads are not managed and thus can't have access to any scope related objects. However how did this use to work until CDI was implemented?
Right now I THINK I've solved the issue (that is releasing the thread servicing request I/O and having a worker take over the waiting until notified) using jersey's #ManagedAsync annotation which supposedly has the whole method be run in an internal jersey executor service. Is this correct? Also in that case, is there any need of the AsyncResponse object?
EDIT: I have NOT solved the issue. #ManagedAsync worked when the resource class was not defined as a CDI bean. After making it #RequestScoped, whenever I try to call the method I get the following exception
org.jboss.weld.context.ContextNotActiveException: WELD-001303: No active contexts for scope type javax.enterprise.context.RequestScoped
I think this is because the request can end before the async thread has finished which means all scope objects (like HttpServletRequest) will be destroyed and thus we won't have access to them. Is there a way to used #ManagedAsync in a #RequestScoped bean and make use of #Context HttpServletRequest??
TL;DR:
How can I have access to a context resource inside a manually started thread?
Why did I have access to the request object before CDI was implemented?
Is it possible to use #ManagedAsync in a #RequestScoped cdi bean?
Old method:
#GET
#Path("method")
public void method(#Context HttpServletRequest request, #Suspended AsyncResponse ar) {
//request object was accessible here
Executors.newSingleTHreadExecutor().submit(() -> {
//request object was also accessible here but lost access after implementing CDI.
Object o = foo.bar(request);
ar.resume(Response.ok(o).build());
});
}
Current non-working method:
#GET
#Path("method")
#ManagedAsync
public void method(#Context HttpServletRequest request, #Suspended AsyncResponse ar) {
Object o = foo.bar(request);
ar.resume(Response.ok(o).build()); //Is there any point to this?
}
To answer your question - no. You cannot use async and request scoped objects. Async support is lacking in CDI - see also https://issues.jboss.org/browse/CDI-452

Why do we need Init() method in servlets when servlets has it Construtor?

in java Constructor is used for initialization why we need init() for initialization.... This question was asked in an Interview
The constructor is for normal Java initialization of an object (though typically a Servlet implementation is expected to have a no-arg constructor).
The init() method is a method provided by the Servlet interface which a Servlet container will run to configure the Servlet. The Servlet container will provide a ServletConfig object which gives the Servlet instance access to the ServletContext and other configuration elements from the deployment descriptor.
the init() method is a part of Servlet and ServletConfig protocol. you can do what is related to the web-context in init() and what is private to Servlet class in constructor.
1) Constructors are used by "Web Container(e.g of Tomcat, WebSphere etc.) to instantiate GenericServlet/HttpServlet.
2) Role of "Servlet.init()" method is to inject defined in web.xml. Yes, you can define servlet level parameters in constructor as well, but then, as a developer you shall unnecessarily invest time in doing the same stuff which can be done implicitly for you by (Container+Servlet API).
3) Moreover, "Servlet.init()" is also used by web container to inject "ServletContext" object where you can't use constructor for that purpose.
Init() method is called by the servlet container to indicate to a servlet that the servlet is being placed into service.
The servlet container calls the init method exactly once after instantiating the servlet. The init method must complete successfully before the servlet can receive any requests. This is the reason we need init() method.
Refer these links:
http://www.tutorialspoint.com/servlets/servlets-life-cycle.htm
http://docs.oracle.com/javaee/5/api/javax/servlet/Servlet.html
The constructor is not part of the servlet lifecycle.
As per the javadocs
init and destroy, to manage resources that are held for the life of the servlet
and
The ServletConfig object can still be retrieved via getServletConfig().
In JDK 1.0 (for which servlets were originally written), constructors for dynamically loaded Java classes (such as servlets) couldn't accept arguments. So, in order to provide a new servlet any information about itself and its environment, a server had to call a servlet's init() method and pass along an object that implements the ServletConfig interface.
Also, Java doesn't allow interfaces to declare constructors. This means that the javax.servlet.Servlet interface cannot declare a constructor that accepts a ServletConfig parameter. It has to declare another method, like init().
It's still possible, of course, for you to define constructors for your servlets, but in the constructor you don't have access to the ServletConfig object or the ability to throw a ServletException.
I used init method to prepare my PreparedStatement once, so that the next time my servlet is called, the prepared statement already created. Please note that when a servlet first loaded in the app server, the init method will be executed. The subsequent called to the servlet, the init method will be ignored. It's only called once for the lifecycle of the servlet

How to get request parameters from a servlet init method

I am writing a Servlet that retrieves request parameters but needs to use them in the init method. Since the init method would be called before the doGet method and since the init method does not have a HttpServletRequest object as an argument, I don't know how to get the request parameters.
public class OpenIdServlet extends HttpServlet
{
...
...
private OpenIdManager manager;
#Override
public void init() throws ServletException
{
super.init();
manager = new OpenIdManager();
manager.setRealm("http://localhost:8080/OpenIDSample");
manager.setReturnTo("http://localhost:8080/OpenIDSample/openid"); //I need to append the value of a request parameter here...
}
...
...
}
So the question is: is there any way I can get HttpServletRequest parameters in the init() method of a servlet? If no what other better approach can one use to solve this problem? Thanks.
The init is called once on startup. So you have to live with a partial returnTo, and on request handling (doGet/doPost) complete it with the request parameters.
In fact the manager seems to be request dependent and hence should be created in the request - never as field. As there might be several requests. Maybe persisting as session attribute.
Your question doesn't make sense. There is no request when the init() method is called. It is called during container initialisation.
Do you mean initial parameter? They are available via the ServletContext provided as an argument to init().

Init method invocation in filter

Could anyone please tell me why the following line about filter init method invocation is incorrect:
The init method on a filter is called
the first time a servlet mapped to
that filter is invoked.
Because it's called when filter is loaded and initialized by servlet container, which happens during web application startup. Filter's init() method will be called even if it will never intercept a single request.
From the API documentation:
void init(FilterConfig filterConfig) throws ServletException
Called by the web container to indicate to a filter that it is being placed into service. The servlet container calls the init method exactly once after instantiating the filter. The init method must complete successfully before the filter is asked to do any filtering work.

Categories