I am porting my Java servlet front controller from a large if-else if block to the command pattern and have created a command interface with an execute method. Currently, I am instantiating an instance of each command in the init() method of my servlet and storing them in a HashMap. I am wondering how I can run the necessary command.execute() within the context of a given request?
Do I add a setContext(HttpServletRequest request, HttpServletResponse response); method to the interface and call command.setContext(request, response) from my doGet()/doPost() methods before I execute or should I not be instantiating the commands in init() to begin with? instead, having a constructor that takes request and response as args?
Obviously, the aim of the command is to set various attributes for a given user/session and determine the correct JSP to forward to, which it can't really do without the context.
You should use:
command.execute(HttpServletRequest request, HttpServletResponse response);
All state can (and should) be recorded in the request. This is easy to do by storing attributes.
Sometimes you may need to use:
command.execute(this, HttpServletRequest request, HttpServletResponse response);
but probably only if your commands are enum rather than real objects.
Related
I'm working on a RESTful API, using Apache CXF as my JAX-RS implementation. I have a POST endpoint that's supposed to receive a request with three parameters. Here's a snippet of my code (modified and shortened):
#Path("endpoint_path")
public class MyResource {
#Context
private HttpServletRequest request;
#POST
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response postEndpoint(#QueryParam("param1") String param1,
#FormParam("param2") String param2,
#FormParam("param3") String param3) {
(use request as input for some library)
}
}
Inside that method, param2 and param3 both have the expected values, but if I check the request object's parameters (by using request.getParameterNames()), I only get one parameter -param1- instead of all three. I know for sure that I'm receiving all 3 parameters, param1 as a query parameter, and param2 and param3 as form parameters, because as I just said, I get their values passed as method parameters. They just don't seem to exists inside the request object.
This puzzled me so much, that I created a Filter that only does one thing, it peeks inside the request for the parameter names and does nothing else:
public class TestCXFPostParamsFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
servletRequest.getParameterNames();
filterChain.doFilter(servletRequest, servletResponse);
}
(init() and destroy() empty methods)
}
and in my web.xml file, I set the filter to apply to every request to my endpoint. Now here's where things get weird - for some reason, that makes everything work, by which I mean, if I check the request object back in the endpoint method, it'll contain all three expected parameters. What sorcery is this?
As a side note, some of you may be wondering why would I bother to check the request object, when I just said I have access to the parameter values that are passed to the method by CXF's servlet? The answer is that I'm using a library that expects you to pass the request object to it, instead of just the necessary values. So I really need the request to keep its parameters inside (like I always assumed it would).
Finally, I'm using Java 6, and CXF 2.7.10 (which comes with Apache Camel CXF 2.13.0). And yes, those are more or less set in stone for all intents and purposes, so if the reason all of this is happening is because of a bug in one of these pieces, I'm stuck with an useless filter as a "solution".
I have passed the HttpServletRequest to another method in the servlet. Could I keep the servlet thread-safe? Is the below code thread-safe with er() method?
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().append("Your session Id: ").append(er(request));
}
public String er(HttpServletRequest request){
return request.getSession().getId();
}
it is perfectly fine, you are not modifying any state within the Servlet itself, the servlet lifecycle creates one instance of the servlet and calls the init() method, any additional requests come through the same instance. so if you don't have any unprotected instance variables, you should be fine.
Because request.getSession() optionally creates a session, the answer is that you may have a race condition where to "simultaneous" calls from the same client may result in different session objects created for that client and consequently, different IDs returned.
See also here
I read the servlet-3.0 specification and have got one question about the ServletRequest object. Currenctly I have a filter chain
public class MyFilter implements Filter{
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
//do filter
}
}
after doing filters the javax.servlet.Servlet's
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
comes into play. Is it reliable that both in the filter's method and the service method operate on the same object reference? The servlet specification said this:
Each request object is valid only within the scope of a servlet’s
service method, or within the scope of a filter ’s doFilter
method, unless the asynchronous processing is enabled for the
component and the startA sync method is invoked on the request object
But it;s not obvious to me that the ServletRequest object is a singleton per one request handling.
Upd: To be more specific, I need to return the HttpSession instance within Filter's doFilter method and Servlet's do_HttpMethod_ method. Is it always the same? I mean httpServletRequest.getSession()
A container uses a single request object for a given request. However any filter can wrapper the request object so your filter or servlet may be getting a wrapper depending on what other filters do. Usually as an app developer you would know if this is the case. If no wrappers are used the filter and servlets get the same request object.
For info on request wrappers see:
http://docs.oracle.com/javaee/7/api/javax/servlet/http/HttpServletRequestWrapper.html
So when you call getSession() you may get the container implementation of the method or that provided by a wrapper. However note that an HttpServletRequestWrapper object provides a getRequest() method which returns the request object it wraps so you can recurse through wrappers until you get the original and then call it. Lots of examples how to do this on the web.
ServletRequest is an interface and the same is used in doFilter method as well as service method. So both are going to return the same session object (if you call getSession()).
Servlet as well as Filter uses same interface so it's going to behave same way. I am not sure why you are curious to know if it's singleton ? May be you can check servlet specification to know more about it.
I have question:
Look, When user goes to my web page I want to get info about the user from his cookie or special ID which is in database and render for example hello User1 on my page when user on the page.
Where I have to perform this operations in filter.init() before user will request the servlet or on servlet.init() or would be fine to get this particular info in servlet.doGet()???
Thank you.
With best regards.
Generally, you want to use filters to transform input or output, or to set up pre-conditions for your servlets.
In your particular case, because it's so simple, it probably doesn't really matter which one you choose. However having filters perform authentication and authorization is very common, so you could have your filter check the cookie and / or query the database for the user information, and add it as a request attribute. After that, have the servlet do the work of preparing or writing the message, using the prepared request attribute. As a general rule, you don't want to write output in a filter.
In either case, you won't be using the init method of either the filter or the servlet for this task. The init method is called to initialize the filter or servlet when the application server creates the object, and may or may not be called for every request (in fact, it's probably not called for every request).
in your Filter , use method doFilter
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws java.io.IOException, ServletException {
//check cookie or anything you want
}
How can an HttpServletRequest parameter (especially in JSP) be unset or removed (like in PHP using the unset($_POST['index']) function)? I have tried the following.
Map requestMap=request.getParameterMap();
requestMap.remove("index");
but it says
No modifications are allowed to a locked ParameterMap
Is there a way to unset request parameters?
Is there a way to unset request parameters?
AFAIK, not within the JSP itself (or any Servlet for that matter).
But you could write a Filter that wrapped the current Request in a way that replaces the parameter map.
What you have to do is write a HttpFilter, write a HttpRequestWrapper of yours(MyRequestWrapper). Override the getParameter method of HttpRequestWrapper in your MyRequestWrapper such that you don't return parameters(may be always return null).
Within filter code, you should override the doFilter method and create a new MyRequestWrapper from ServletRequest Object, then do chanin.doFilter(myRequestWrapper, response)