How do I execute multiple servlets in sequence? - servlets

I am just beginning with Servlets and managed to have some servlets that act as individual URLs for populating a database for some dummy testing. Something of the form:
public class Populate_ServletName extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
//Insert records
//Print confirmation
}
}
I have about 6 such servlets which I want to execute in a sequence. I was thinking of using setLocation to set the next page to be redirected but was not sure if this is the right approach because the redirects should happen after the records have been inserted. Specifically, I am looking for something like this:
public class Populate_ALL extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.setContentType("text/plain");
//Call Populate_1
//Call Populate_2
//Call Populate_3
//...
}
}
Any suggestions?

Use RequestDispatcher#include() on an URL matching the url-pattern of the Servlet.
public class Populate_ALL extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/plain");
request.getRequestDispatcher("/populateServlet1").include(request, response);
request.getRequestDispatcher("/populateServlet2").include(request, response);
request.getRequestDispatcher("/populateServlet3").include(request, response);
//...
}
}
Note: if those servlets cannot be used independently, then this is the wrong approach and you should be using standalone Java classes for this which does not extend HttpServlet. In your specific case, I think the Builder Pattern may be of interest.
The RequestDispatcher#forward() is not suitable here since it throws IllegalStateException when the response headers are already committed. This will be undoubtely the case when you pass the request/response through multiple servlets which each writes to the response.
The HttpServletResponse#sendRedirect() is absolutely not suitable here since it implicitly creates a brand new request and response, hereby trashing the original ones.
See also:
How do I call a second JSP servlet while in the first JSP servlet?
RequestDispatcher.forward() vs HttpServletResponse.sendRedirect()
communication between remote servlets

It looks like what you may need is a service that each of the servlets can use to perform some work. Then the servlets are not depending one and another, but rather all using the service.
However, here is an explanation of forwarding or redirecting requests.

Related

Can I write code after RequestDispatcher?

public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//some code here
}
public void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
//performTask(req, resp);
//some code here
}
private void insertRequestTemplate() {
HttpSession session = req.getSession();
responsePage = req.getParameter("ResponsePage");
ServletContext ctx = getServletConfig().getServletContext();
ctx.getRequestDispatcher(responsePage).forward(req,resp);
readMessage();
public void readMessage()
{
System.out.println("calling MessageTrigger_ABean");
MessageTrigger_ABean msg = new MessageTrigger_ABean();
msg.read();
}
msg.read() has the code to read messages from MQ. Inside insertRequestTemplate method, I am calling readMessage method after ctx.getRequestDispatcher(responsePage).forward(req,resp);is this the correct way of calling this?
But inside insertRequestTemplate method, the page is not getting forwarded to the next page untill readMessage() is executed because of which the page keeps on loading for a long time until message is read from MQ. Could you please help me on this.
Most examples I have seen of a servlet forwarding the request to another servlet have the dispatcher forward invocation at the end of the method. ie. there is no more code, other than closing braces at the end of the method.
I am guessing that the forwarding doesn't happen until the invoking method completes. So where you have your msg.read() will stop the insertRequestTemplate method from completing. This will more than likely be because the code inside msg.read is being performed synchronously. Leading to http timeouts on the http request.
How you solve this will depend on what you want to do with the messages you obtain from msg.read().

does returning from doGet() or doPost() automatically send a resonse

I have looked around and previously asked this question but did not get a full answer. When you explicity return from doGet() or doPost() does a response get sent regardless of if you have encoded anything or not. If so what is the default code ? Is it enough to simply response.setStatus() and return ? If not: so I have always manually send back a response ? What is the default way to just respond not using forward or redirect ?
If you do nothing, just return (or not even return) from a servlet, it will send back a status code 200(OK) empty response. Tested it in both tomcat and glassfish servers, using the servlet below:
#WebServlet("/a")
public class a extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return;
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
return;
}
}
Using the network profiler tool of Chrome you can see what I said:

how to get a path variable value in servlet

I want to get the path variable in servlet. Assume the url is www.demo.com/123/demo. I want to get the 123 value from the path without doing any string manipulation operation.
Note: the following servlet doesn't have any web.xml configurations. My code is:
#WebServlet(urlPatterns = { "/demo" })
public class DemoServlet extends HttpServlet {
public DemoServlet()
{
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doPost(request,response);
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
sysout("demo");
}
}
The portion of the URL you are referring to is the "context". Use request.getContextPath() to get this. In the case of your example, this would return /123. If you want exactly 123 you would have to remove the leading slash.
From the documentation:
Returns the portion of the request URI that indicates the context of
the request. The context path always comes first in a request URI. The
path starts with a "/" character but does not end with a "/"
character. For servlets in the default (root) context, this method
returns "". The container does not decode this string.

Create new bean instance on each servlet request

protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
homePageController = (HomePageControllerV2) BeanLoader.getBean("homePageControllerV2");
}
}
whenever i hit to servlet from multiple machine. i still get the same instance of homePageController. is there any way can get diffrent instance of object homePageControllerper servlet request.
i have tired with changing the scope of bean to prototype. but still faced the same issue.

<error-page> tag in web.xml doesn't catch java.lang.Throwable Exceptions

I have a web-app developed with servlet & JSP. I configured my app to throw an IllegalArgumentException if I insert bad parameters.
Then I configured my web.xml file in this way:
<error-page>
<error-code>404</error-code>
<location>/error.jsp</location>
</error-page>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error.jsp</location>
</error-page>
When I rise a 404 error, then it works and calls error.jsp, but when I rise a java.lang.IllegalArgumentException, then it does not work and I've a blank page instead of error.jsp. Why?
The server is Glassfish, and logs show really IllegalArgumentException rised.
You should not catch and suppress it, but just let it go.
I.e. do not do:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (IllegalArgumentException e) {
e.printStackTrace(); // Or something else which totally suppresses the exception.
}
}
But rather just let it go:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doSomethingWhichMayThrowException();
}
Or, if you actually intented to catch it for logging or so (I'd rather use a filter for that, but ala), then rethrow it:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (IllegalArgumentException e) {
e.printStackTrace();
throw e;
}
}
Or, if it's not an runtime exception, then rethrow it wrapped in ServletException, it will be automatically unwrapped by the container:
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
doSomethingWhichMayThrowException();
} catch (NotARuntimeException e) {
throw new ServletException(e);
}
}
See also:
How does server prioritize which type of web.xml error page to use?
Submitting form to Servlet which interacts with database results in blank page
Another (simplified) approach is not to declare multiple handlers for various <error-code> and <exception-type> situations but rather have one, sort of catch-all sink, e.g.
<error-page>
<location>/error-page.jsp</location>
</error-page>
Inside your error-page.jsp you can determine the cause, be it a return status code or an exception as described here: https://www.tutorialspoint.com/servlets/servlets-exception-handling.htm These constants are a part of the standard Servlet 3.0 API.
For instance a primitive error-page.jsp response handler placed into the root of your webapp can look like this:
Server encountered a situation
Status code: <%=(Integer) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_STATUS_CODE)%>
<br>
Exception: <%=(Throwable) request.getAttribute(javax.servlet.RequestDispatcher.ERROR_EXCEPTION)%>
For security reasons I wouldn't recommend sending the exact exception type to the client; this is just an example of how to handle different types of errors and response statuses inside a JSP handler; a servlet can be used instead of JSP.
One common catch-all handler vs one per status code is certainly dependent on the situation and requirements.
I have today the same issue. (JavaEE 7 and Glassfish 4.0)
The problem seems that the framework check it as String instead with the Class.
String based check (the hypothesis)
When a Exception is twrown, e.getClass() is compared with <exception-type> as string.
So you can't use inheritance.
Note that nested classes must be pointed as '$' instead '.' (same as getClass() method).
Class based check
The framework create an instance of the class, and <exception-type> text refer to it, and the class.isInstance() is used to check.
This will need reflection and policy file could break it.
I hope that this response solves future issues.

Resources