I have 2 web apps, no front-end(i.e html/Jsp) in either. Both have one servlet each.
Lets call them WebApp1/WebApp2 and ServiceServlet1/ServiceServlet2.
I have 2 war files, WebApp1.war and WebApp2.war and both deployed.
I call the ServiceServlet1 directly from the browser with -
http://localhost:8080/WebApp1/ServiceServlet1
Obviously the doGet method will be called(POST is associated only with FORM, correct me if I am wrong).
The ServiceServlet1 is build something like -
public class ServiceServlet1 extends HttpServlet {
#Override
protected void doGet(HttpServletRequest httpRequest, HttpServletResponse httpResponse)
throws ServletException, IOException {
doPost(httpRequest, httpResponse);
}
#Override
protected void doPost(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse) throws ServletException,
IOException {
RequestDispatcher requestDispatcher;
try {
// Process something
requestDispatcher = getServletContext().getRequestDispatcher("/WebApp2/ServiceServlet2");
requestDispatcher.forward(httpServletRequest, httpServletResponse);
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ServletException servletException) {
servletException.printStackTrace();
}
}
}
Essentially, what I require is to call the doPost() of ServiceServlet2
I have tried few different ways with httpReq.getRequestDispatcher(), sendRedirect etc. but have failed so far.
So how can I make it happen?
Thank you.
In addition to the answer of ckuetbach, you can't change the request method when dispatching the request. If the second servlet cannot be changed to execute the same business logic on doGet() as well, then you have to fire a POST request yourself programmatically.
HttpURLConnection connection = (HttpURLConnection) new URL("http://localhost/WebApp2/ServiceServlet2").openConnection();
connection.setRequestMethod("POST");
InputStream response = connection.getInputStream();
// ... Write to OutputStream of your HttpServletResponse?
See also:
How to use URLConnection to fire and handle HTTP requests?
The two servlets don't share the same Classloader, because they are in different ´*.WAR´-files.
As far as I know, you have to chances to do what you want:
Disable Classloader-Separation in tomcat (I've never done this tomcat)
Repackage the two aplication within one *.WAR
Related
I am writing a Servlet Controller.If I dont pass any parameter, it will catch Exception and response will sendRedirect to index.jsp
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, Exception {
response.setContentType("text/html;charset=UTF-8");
RequestDAO requestDAO = new RequestDAOImpl();
try (PrintWriter out = response.getWriter();) {
// get request
int rId = Integer.parseInt(request.getParameter("rId"));
Request req = requestDAO.getRequestById(rId);
sendDispatcher(request, response, "viewRequestMentor.jsp");
} catch (Exception e) {
Logger.getLogger(ViewMentorRequestDetailController.class.getName()).log(Level.SEVERE, null, e);
session.setAttribute("error", "Cant view request detail");
response.sendRedirect("index.jsp");
}
}
But the redirect does not work and the logger display an Exception
Severe: java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:518)
at controller.ViewMentorRequestDetailController.processRequest(ViewMentorRequestDetailController.java:76)
at controller.ViewMentorRequestDetailController.doGet(ViewMentorRequestDetailController.java:103)
The problem you are having is that you are using try with resources here:
try (PrintWriter out = response.getWriter();) {
And that means that when the try/catch block is finished the PrintWriter is closed. The PrintWriter is what is used to print the response (the body, the headers and everything that conforms an HTTP Response), and if it is closed, no one can print anything to it.
sendRedirect is just a normal HTTP response with code 302 that should be written to the response object (HttpServletResponse), and has a header Location informing where it should be redirected to. If you open the "Network" tab in you browser's debug you will see that two requests are being made, one for your original Servlet, and another one for the redirect.
You actually don't have to close the PrintWriter, as it is the Servlet container (or Application Server, or whatever you are using) the responsible to do that, after everything is properly set. The HttpServletResponse implies much more that the things we do in the doGet/doPost methods, it has a full lifecycle in which we intervene in the middle, we receive it in the doGet/doPost/do... and hand it back to the next Servlet Container bean responsible to do stuff in there.
So, just remove the try with resources and obtain the PrintWriter without closing it. The redirect should then work fine.
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException, Exception {
response.setContentType("text/html;charset=UTF-8");
RequestDAO requestDAO = new RequestDAOImpl();
try {
PrintWriter out = response.getWriter();
// get request
int rId = Integer.parseInt(request.getParameter("rId"));
Request req = requestDAO.getRequestById(rId);
sendDispatcher(request, response, "viewRequestMentor.jsp");
} catch (Exception e) {
Logger.getLogger(ViewMentorRequestDetailController.class.getName()).log(Level.SEVERE, null, e);
session.setAttribute("error", "Cant view request detail");
response.sendRedirect("index.jsp");
}
}
I am trying to do the following: I create a servlet to handle all requests, and if the url contains the word "hello", then set the response code to 403, otherwise forward the request to an html page. Here is my servlet:
#WebServlet("/*")
public class AllRequestsHandlerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String url = request.getRequestURL().toString();
if(url.contains("hello")) {
response.setStatus(HttpServletResponse.SC_FORBIDDEN);
} else {
RequestDispatcher dispatcher = request.getRequestDispatcher("/static-html-page.html");
dispatcher.forward(request, response);
}
}
}
But after forwarding, since this servlet handles the forwarded request too, it causes an infinite loop. How can I avoid that?
This will never work because /* maps to every request - including your forward to /static-html-page.html and path mappings take priority over all other mappings.
There are a couple of ways around this. The simplest (assuming no other content in the web app) would be:
rename /static-html-page.html to /static-html-page.jsp
change the mapping from /* to /
That does mean that /static-html-page.jsp would be directly accessible. If you don't want that, move it under /WEB-INF. request.getRequestDispatcher("/WEB-INF/static-html-page.html") will still work.
I've done my java web app in Java EE with HttpServlet and JSP. I normally map my Servlet like this:
#WebServlet(urlPatterns = "/main")
public class MainServlet extends HttpServlet{
I do my servlet stuff and would like to pass data to JSP file like this:
RequestDispatcher dispatcher = req.getRequestDispatcher("/main.jsp");
dispatcher.forward(req, resp);
The main.jsp is in my web app folder (I use IntelliJ Idea).
The question is, I've initially made my UI with Vaadin 8. Using following:
#Theme("mytheme")
#CDIUI("users")
#SuppressWarnings("serial")
public class Vaadin extends UI
and then override init.
Now I would like to add a single HttpServlet and override doGet and then call the dispatcher to forward data to jsp. Here's the problem adding Vaadin somehow broke the path to tsp, as jsp does not display, instead a standard vaadin
Request was not handled by any registered handler.
appears, I know the servlet was mapped properly as the servlet starts and does work, what does not work is the running the JSP file.
Can anyone advise?
It seems that you need to implement yet a WebFilter to process JSP. Your dispatcher forwards the request but it is then a request that is again handled by some filter by Vaadin I guess. Also I am not sure if you need any servlet and/or dispatcher (not sure what your actual use is).
Anyway, with WebFilter it is possible to intercept this processing. Check the following example
#WebFilter(filterName="jspFilter", urlPatterns="*")
public class JspFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest hreq = (HttpServletRequest)request;
String path = hreq.getPathTranslated();
if(path.toLowerCase().endsWith(".jsp")) {
try(Writer writer = response.getWriter();
Reader reader = new FileReader(path) ) {
processJsp(reader, writer);
return;
} catch (Exception e) { /* TODO: handle exception */};
}
} catch (Exception e) { /* TODO: handle exception */};
chain.doFilter(request, response); // forward to filter chain by default
}
#Override public void destroy() {}
#Override public void init(FilterConfig filterConfig)
throws ServletException {}
}
This filter checks all request. If URI (here checked from translated/absolute path) is ending with .jsp it is processed with processJsp(reader, writer) that you might want to implement to do the forwarding to JSP parser or so.
I am new to servlet and reading some text about filters and wrappers. I can understand filters but got confused about wrappers. In the book, the author gives an example:
In case no wrapper:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
String name = request.getParameter("name").trim();
try {
chain.doFilter(request, response);
PrintWriter out = response.getWriter();
if (name.length() == 0) {
out.println("Some message");
out.println("</body>");
out.println("</html>");
out.close();
}
} catch (Throwable t) {
}
}
In case of wrapper:
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain)
throws IOException, ServletException {
String name = request.getParameter("name").trim();
HttpServletResponse httpRes = (HttpServletResponse) response;
HttpServletResponseWrapper resWrapper = new HttpServletResponseWrapper(httpRes);
try {
chain.doFilter(request, response);
PrintWriter out = resWrapper.getWriter(); // why dont we just use response.getWriter();
if (name.length() == 0) {
out.println("<h3>Some message");
out.println("</body>");
out.println("</html>");
out.close();
}
} catch (Throwable t) {
}
}
Why we need HttpServletResponseWrapper while we can do the same thing with ServletResponse in case 1? Can anyone give me a clear example that we MUST use HttpServletResponseWrapper instead of ServletResponse? I have tried to google but found no luck.
BalusC's answer is good, but it might be a little overwhelming if you're just starting out.
Put simply: SerlvetResponse and its extension, HttpServletResponse, are interfaces telling you what methods are available to call to do the things you need. In the normal course of working with Filters, Servlets, et al., you'll use HttpServletResponse often to tell your app how to respond to requests.
HttpServletResponseWrapper is one particular implementation of HttpServletResponse which gives you a convenient way to wrap an existing response with some logic of your own without having to write a whole new implementation of the interface. It has a lot of methods, so this is really nice. As a trivial example, suppose you wanted to disallow calls to response.flushBuffer(). This code, using HttpServletResponseWrapper, will do that:
class DisallowFlushResponseWrapper extends HttpServletResponseWrapper {
public DisallowFlushResponseWrapper(HttpServletResponse response) {
super(response);
}
#Override
public void flushBuffer() {
throw new UnsupportedOperationException("Don't call this!");
}
}
The typical way to use such a wrapper would be to create a filter like this:
class DisallowFlushFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) {
if (response instanceof HttpServletResponse) {
HttpServletResponse newResponse =
new DisallowFlushResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, newResponse);
}
...
}
...
}
Note that we wrap the response coming into the filter with an instance of our own wrapper. Then we hand the wrapper down to the next item in the filter chain. Thus anything that comes after this filter will get an exception if it calls flushBuffer() because it will be calling it on our wrapper. The wrapper, due to its default behavior, will delegate any other call to the wrapped response, which is the real one, so everything except calls to that one method will work normally.
That's really a stupid example which does not show the benefit of request/response wrapper. Actually, the whole filter example is poor. Emitting HTML should be done by a JSP or at highest a servlet (but also that is still poor). Go through our filters wiki page to get some ideas about what a filter can be used for.
A response wrapper is useful if you want to modify the response's behaviour or just want to collect information about the response while it is been used in the request-response chain. The modified behaviour takes then place whenever some servlet or JSP calls a certain method on the response. If you have overriden it in your wrapper class, then this one will be called instead. You could alter the behaviour or collect information there.
Here on Stackoverflow you can find some concrete examples of useful HttpServletResponseWrapper implementations.
How to insert response size and time into the page itself, at least partially?
MD5 Signing a HttpServletResponse
How to configure Tomcat to not encode the session id into the URL when HttpServletResponse.encodeURL() is invoked
How to add response headers based on Content-type; getting Content-type before the response is committed
How is annotations support in jsp implemented in sitebricks?
Capture and log the response body
Log only http servlet response headers
How to include a JSP page in a Facelets page?
Capture generated dynamic content at server side
I've got this issue, recently I read about the REST arquitecture and it makes a perfect sense, so I'd like to achieve a RESTful web application.
Now, I'm following the Front Controller pattern that means that all of the URL mappings go to the controller.java servlet, I map the by specific URLs, not by using the /* wildcard,
the controller implements the four HTTP methods POST,GET,PUT,DELETE, each method calls the controllers service method and there I determine based on the HttpServletRequest and pathInfo the action to execute.
Controller.java
#Override
protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
IAction action;
View view;
try {
action = ActionFactory.produceAction(req);
view = action.execute(req, resp);
switch (view.getDispatchMethod()) {
case REDIRECT:
resp.sendRedirect(resp.encodeURL(view.getResource()));
break;
case FORWARD:
req.getRequestDispatcher(view.getResource()).forward(req, resp);
break;
case INCLUDE:
req.getRequestDispatcher(view.getResource()).include(req,resp);
break;
default:
}
} catch (ActionFailedException uae) {
req.setAttribute("ActionName", "Action");
req.setAttribute("FailCause", uae.getMessage());
req.getRequestDispatcher(VIEW_FAIL.getResource()).forward(req, resp);
}
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
#Override
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.service(req, resp);
}
I've run into a particular issue when loading a specific order by the URI /orders/*, it is mapped to the controller servlet, the the action is executed and I load the appropriate order the action returns a View.java class
//ommited accessors and mutators for brevety.
public class View {
public enum DispatchMethod {
INCLUDE, FORWARD, REDIRECT
}
private DispatchMethod dispatchMethod;
private String resource;
public View(DispatchMethod dispatchMethod, String resource) {
this.dispatchMethod = dispatchMethod;
this.resource = resource;
}
}
Then the request is dispatched according to the getDispatchMethod() of the returned view.
Now, here is where the loop gets triggered, I use the following URL, myapp/orders/78965 /orders/* gets mapped to controller.java the appropriate action is executed and the correct order is found by the pathInfo() the returned view is new View(View.DispatchMethod.FORWARD,"order_details.jsp") the problem is that with the three available dispatch methods REDIRECT,FORWARD and INCLUDE a request is re-triggered on the URL and so on and on and on I never reach the order_details.jsp that renders the data.
So, how would you avoid the looping, as I'd like to preserve the URI displaying the order number I use the forward method, also, I'd like to do it using servlets, I've heard of the UrlRewriteFilter maybe in the future, but right now, how would it be done using "Plain Vanilla" since I'm using the Front Controller pattern, will it be necessary to add an additional servlet in the /orders/ URI ?
Any help or insights is truly appreciated.
EDIT 1:
Pasted the source code of the controller, a very basic one, I have my suspicions that the way the service method calls all of the overriden do[Method] of the servlet is triggering the loop and that it may be solved by splittig them.
Implementing a RESTful HTTP interface in Java is a lot easier using a JAX-RS implementation like RESTEasy or Jersey.
Using a Front Controller to dispatch requests to the right resource is a good approach, it's exactly the approach taken by these JAX-RS frameworks. I fear you may be re-inventing the wheel here by writing a bespoke URL parsing and dispatching mechanism when this can be taken off-the-shelf.
JAX-RS is a lightweight way to expose resources. By using a couple of simple annotations you can expose a REST interface without any plumbing required. For example:
public class Order {
#GET
#Path("/orders/{orderId}")
#Produces("text/html")
public void getOrder(#Context HttpServletResponse response,
#Context HttpServletRequest request,
#PathParam("orderId") String orderId) throws ServletException, IOException {
// ... create view and add to request here
request.getRequestDispatcher("orders.jsp").forward(request, response);
}
}
You can see how simple it is to attach this class to a URL path (using the #Path annotation), and how easily you can parse values from the URL using #PathParam. Since you get all the plumbing/dispatching/parsing off-the-shelf, you can concentrate on the bits of your app that are specific to your domain (such as what an order contains).