I'm trying to find a way to process HTTP requests programmatically with Tomcat 7 — "programmatically" meaning without actually making a TCP connection and sending the request. Basically, if I have an HttpServletRequest, is there a way to get Tomcat to give me the corresponding HttpServletResponse?
I perused http://tomcat.apache.org/tomcat-7.0-doc/index.html but couldn't find any mention of this now. One possibility is that HttpServlet has a method service() that would work, so if I could get a reference to the servlet object itself I'd be all set. Unfortunately, I can't find a way to get that either.
I should note that the servlet in question is a Jersey 1.17 servlet, although I don't think that matters to the question I'm asking. (Tomcat is clearly capable internally of dispatching a request based just on the URL, which is basically what I'm after here.)
If I understand your question correctly, you want to forward a request to another servlet. Take a look at the RequestDispatcher class and its forward() method. Here are some explanations and examples.
Related
I am using jersey for REST service. I am deploying the REST service using apache tomcat. How do i set the session key in every response.
I have tried the below piece of code
return Response.ok(response.toString(), MediaType.APPLICATION_JSON).cookie(new NewCookie("JSESSIONID", request.getSession().getId())).build();
where request is instance of HttpServletRequest. I want to is there any configuration in web.xml so that the JSESSIONID is set for every response
Generally speaking (this holds true for many frameworks!) anything you want to be used in multiple places is best done with a filter. I'm not going to show you exactly how you do it, as it is very simple and it is better for you to read the docs, but have a look here:
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
You can apply these to both methods and classes, so you only need to place annotations in a couple of places.
A very useful thing for writing clean code!
i am running a tomcat server which has filters (and a servlet) mapped to /xxx/*
I have client that sends //xxx/* at the HTTP header as the uri. as a result, the servlet and the filters are not getting called.
I have tried putting a filter at /* that catches the request, wraps it with a requestWrapper and override the getURI() and getServletPath() methods (they just return the URI with a single / to whoever calls)
That doesn't seem to work, so i am assuming that once tomcat receives a request it decides which servlet/filters should be evaluated against this uri BEFORE even sending it to the first filter.
Is there a way to solve this? can i make tomcat reevaluate after every filter maybe? is there another way?
thanks in advance
If the URLs in the request header are not conforming to the spec, Tomcat is doing the right thing by dropping them.
If this is the problem, you need to fix the client so that it puts proper absolute URLs into the HTTP requests.
"Hacking" Tomcat to make it accept rubbish requests is a bad idea. It will limit your options for upgrading platforms, and/or deploying in different network environments.
As a developer of Java web application, when do I need to use URL Rewriting and what is the difference between URL Rewriting and Forwarding?
I searched on other websites, I get contradictory information depending upon whom you are talking to like SEO people would answer this question differently.
AFAIK in both cases the client (browser) is not informed of the change and the end user sees exactly same URL that the client originally requested when the repose is returned from the server.
Please that this question is in the context of Java Servlet API in which forward method and sendRedirect methods are defined in which redirecting and forwarding are completely 2 different things. This question is about the difference between forward (as defined by forward method in the Servlet API's) and URL rewriting. The question clearly states that the answer should be in the context of Java servlet. Most importantly when do I need to use URL rewriting, again in the context of developing Java web application.
The term "forwarding" is ambiguous in this question. In JSP/Servlet world, "forwarding" is more known from the MVC concept that the request URL (as visible in browser address bar) effectively calls the servlet (as matched by its URL pattern in web.xml or #WebServlet) which acts as a controller to prepare the model and uses a JSP as view to present the model. That JSP in turn is been called by "forwarding". This is done by RequestDispatcher#forward():
request.getRequestDispatcher("/WEB-INF/foo.jsp").forward(request, response);
This does indeed not reflect the JSP's URL in the browser address bar. This takes place entirely server side. Basically, the servlet "loads" the JSP and passes the request/response to it so that it can do its job of generating the HTML stuff. Note that the JSP in the above example is hidden in /WEB-INF folder which makes it inaccessible for endusers trying to enter its full path in browser address bar.
In general web development world, the term "forwarding" is also known from "URL forwarding" which is essentially the same as URL redirection. This in turn indeed causes a change in the browser address bar. This is in JSP/Servlet world more formally known as "redirecting" (although most starters initially confuse it with "forwarding"). This is done by HttpServletResponse#sendRedirect():
response.sendRedirect("another-servlet-url");
Basically, the server tells the client by a HTTP 3nn response with a Location header that the client should make a new GET request on the given Location. The above is effectively the same as the following:
response.setStatus(302);
response.setHeader("Location", "another-servlet-url");
As it's the client (the webbrowser) who is been instructed to do that job, you see this URL change being reflected back in the browser address bar.
The term "URL rewriting" is also ambiguous. In JSP/Servlet world, "URL rewriting" is the form of appending the session ID to the URL so that cookieless browsers can still maintain a session with the server. You'll probably ever have seen a ;jsessionid=somehexvalue attribute in the URL. This is by default not done automatically, but most Servlet based MVC frameworks will do it automatically. This is done by HttpServletResponse#encodeURL() or encodeRedirectURL():
String encodedURL = response.encodeURL(url); // or response.encodeRedirectURL(url)
// Then use this URL in links in JSP or response.sendRedirect().
(Which in turn is -again- an ambiguous term. With "URL encoding" you'd normally think of percent encoding. There's no Servlet API provided facility for this, this is normally to be done by URLEncoder#encode() or, MVC-technically more correct, in the JSP by JSTL's <c:url> and <c:param> or any UI component provided by the servlet-based MVC framework, such as JSF's <h:outputLink>)
In general web development world (especially with Apache HTTPD / PHP folks), "URL rewriting" is more known as whatever Apache HTTPD's mod_rewrite is doing: mapping incoming URLs to the concrete resources without reflecting the URL change in the client side. In JSP/Servlet world this is also possible and it's usually done by a Filter implementation which uses RequestDispatcher#forward(). A well known implementation is the Tuckey's URLRewriteFilter.
I admit that this has also confused me for long when I just started with JSP/Servlet, for sure while having my roots in the Apache HTTPD / PHP world.
Rewriting is a layer (often before your servlet) that causes a URL to be handled like a different URL by modifying the URL before the request is served. The servlet responds through a single request as if the rewritten URL was requested, usually having never known the rewrite occured.
Forwarding (or redirection) is performed by the browser (typically automatically) when instructed by the server via some 3xx error codes (when redirection is allowed by the client). In this case two requests would be served (not necessarily both from your servlet); the first responding with an error code and a URL to redirect to, and the second serving the proper request after the client redirects.
I am currently developing a RESTful Webservice in Java using the Jersey library.
For security reasons, we want a custom authentication similar to Amazons Simple Storage Service. This requires, however, that I calculate an MD5 hash of the body (if there is any) to authenticate the request.
So far, I have used a custom Authenticator and Realm and plugged them into my context.
Upon trying to calculate the hash I first used the request itself resulting in an IllegalStateException, since the body can only be read once.
After investigating the problem I tried to wrap the request inside a HttpServletRequestWrapper but hasn't been successful so far.
I am basically using a wrapper like the one shown here:
http://forums.oracle.com/forums/thread.jspa?threadID=2156814&tstart=0
Inside my realm, where I do the authentication, I am first creating the wrapper like so:
MyRequestWrapper requestWrapper = new MyRequestWrapper(request);
then I am calculating the MD5 using the requestWrapper
and finally forwarding it
request.getRequestDispatcher("/*").forward(requestWrapper, response);
The processing works fine but I get an error like this after that:
Servlet.service() for servlet Jersey REST Service threw exception
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:407)
at com.sun.jersey.spi.container.servlet.WebComponent$Writer.finish(WebComponent.java:285)
at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:241)
Note that there is no mentioning of the getReader or getInputStream being called before (like I got without using any wrapper at all).
Now I am sure I am doing something wrong here but I really don't know much about this and would be really glad if someone could help me out here :)
Best Regards,
Lukas
As stated in my comment to my question:
I was accessing getReader() from the request. Response I did not touch. However I found that the problem was forwarding the wrapper. I didn't explicitly state this in my question but I am using tomcat and tried to use the above code inside a valve. I am still interested in the question if this is also possible from a valve, since this fits better into the tomcat model. I have now moved to using a filter which is not so nice, but works
I found however that this solution is quite nice (using a filter) instead of a tomcat valve.
I have a servlet which copies the InputStream to the ServletOutputstream using the Apache IOUtils. The servlet is getting invoked twice. I have tested both on IE and Firefox. Did anybody encounter situation like this? Please let me know if you have any suggestions.
Check the outgoing HTTP requests using Firebug in Firefox. Ensure that you understand how servlets and filters work and how the url-pattern in the mappings should be configured/interpreted. Either the browser did actually send two HTTP requests, or any servlet or filter has forwarded/redirected the request to the servlet in question. More can't I be of assistance based on the as far given little information.