Init method invocation in filter - java

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.

Related

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().

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

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.

Jetty setInitParameter is NOT initializing any parameter

I've embedded Jetty, and I'm trying to set an initialization parameter.
The main class Main creates a servlet of Cgi which extends CGI.
Within Main, I have the following code:
ServletContextHandler context2 = new ServletContextHandler(ServletContextHandler.SESSIONS);
context2.setContextPath("/cgi");
context2.setResourceBase("./cgi-bin");
context2.setInitParameter("commandPrefix", "perl");
context2.addServlet(new ServletHolder(new Cgi()), "/");
server.setHandler(context2);
Within Cgi, I check to see the parameter:
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println(servletConfig.getInitParameter("commandPrefix"));
super.init(servletConfig);
}
Each time, it prints out null for the getInitParameter call. Then when the Cgi does indeed NEED to use this, it doesn't, because it's not set. Why could this be happening?
You're setting the InitParameter on the ServletContextHandler, but you should be setting it on the ServletHolder.
(It's somewhat confusing, I know)
You've set a context init parameter, not a servlet init parameter. So you need to retrieve it as a context init parameter instead of as a servlet init parameter.
System.out.println(servletConfig.getServletContext().getInitParameter("commandPrefix"));
Alternatively, you can of course also set it as a servlet init parameter instead, but this way the parameter will only be available to the associated servlet only, not to all other servlets running in the same context. This may or may not be what you want, depending on the concrete functional requirement.

Why do I need an HttpSession to get the ServletContext?

In the Java Servlet API, the only way to get the ServletContext is through an instance of HttpSession (Javadoc).
What if I don't want to create a session and only need the servlet context? In other words, why is there no getServletContext() method in the HttpServletRequest class?
EDIT
I know I can get the ServletContext from the servlet itself, since it receives it during its initialization. However, I cannot get it from a HttpServletRequest alone, even though it's linked to a servlet. So what if I have a request, but no reference to any servlet?
getServletContext() is part of GenericServlet which is the parent class for HttpServlet so you should be able to call it in your servlet implementation.
Edit:
HttpServletRequest inherits getServletContext() from ServletRequest since servlet 3.0, so it looks like you will have to pass a context along with the request and response objects if you have to use a version prior to 3.0.
It's just that every entity working with requests (servers, filters, pages) has its own getServletContext (or init())
Your servlet class has a getServletContext() method you don't need to go to the request.
This makes sense, the servlet itself has a context provided by the container, this is independent of any particular request.

Categories