request.getRequestDispatcher() called recursively - java

I've encountered a strange problem where my servlet doGet method will be run three times.
I tested this in Chrome and Firefox, and it's the same. I also deployed the project on another computer and used apache server to see if also does it when the site is live, but no change.
I use a switch in my doGet and a getParameter request to find the proper method to be run. I've shortened the switch to just two cases. But everytime the action is "create" It'll run the method three times.
I know this is very narrow, and I'd wish I were able to give you more information, but I do not know where to dig after it.
EDIT: The problem has been found. A request.getRequestDispatcher is causing it. Any help with this issue is very appreciated.
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
String action = request.getParameter("action");
// To see that it runs 3 times.
System.out.println(action);
switch (action) {
case "create":
this.create(request, response);
break;
default:
this.greetGuest(request, response);
break;
}
}
protected void createEvent(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
request.setAttribute("AbstractUser", SessionUser);
// Here's the problem. This part will cause the doGet to be called multiply times.
request.getRequestDispatcher("/WEB-INF/jsp/view/Organisation/create.jsp").forward(
request, response);
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
//html
Create
//Configuration
#WebServlet(name = "eventHandler", urlPatterns = { "/eventHandler" }, loadOnStartup = 1)
//web.xml
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspf</url-pattern>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>false</scripting-invalid>
<include-prelude>/WEB-INF/jsp/base.jspf</include-prelude>
<trim-directive-whitespaces>true</trim-directive-whitespaces>
<default-content-type>text/html</default-content-type>
</jsp-property-group>
</jsp-config>

Related

How to mock RequestDispatcher so that it goes to the .jsp file?

I am trying to write the JUnit test case for the code:
In SearchController class
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
List<AlbumSimplified> items = spotifyService.searchAlbum(searchName);
request.setAttribute("items", items);
request.getRequestDispatcher("searchResult.jsp").forward(request, response);
}
as
public void SearchControllerTesting() throws ServletException, IOException {
HttpServletRequest request = mock(HttpServletRequest.class);
HttpServletResponse response = mock(HttpServletResponse.class);
//mocked myalbums
when(searchServiceMock.searchAlbum(anyString())).thenReturn(myalbums); when(request.getRequestDispatcher(anyString())).thenReturn(request.getRequestDispatcher("searchResult.jsp"));
searchController.doGet(request, response);
}
The error I am facing is:
java.lang.NullPointerException: Cannot invoke "jakarta.servlet.RequestDispatcher.forward(jakarta.servlet.ServletRequest, jakarta.servlet.ServletResponse)" because the return value of "jakarta.servlet.http.HttpServletRequest.getRequestDispatcher(String)" is null
I believe that it is due to the fact that the uri is not identified for the request and so, it is not able to find the "searchResult.jsp" located at "/app/src/main/webapp/searchResult.jsp" where app is the root of the project directory.
Hence I tried to set the
when(request.getRequestedURI()).thenReturn("app/search"), which is the URL of the request in the browser for non-testing usage.
However, I am not able to move ahead and solve the issue.
I want the items in the request to go to the searchResult.jsp, and return me a response of type "text/html".
Thanks.

Can't forward to jsp when handling an exception

So i got this problem, i do a servlet project using tomcat and I got this class that should handle the exception that was thrown and then display the jsp with error status code.
public class ErrorHandler extends HttpServlet {
private static final Logger LOGGER = Logger.getLogger(ErrorHandler.class);
#Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Throwable throwable = (Throwable) req.getAttribute("javax.servlet.error.exception");
Integer statusCode = (Integer) req.getAttribute("javax.servlet.error.status_code");
if (throwable != null) {
LOGGER.fatal("Exception: " + throwable);
}
if (statusCode != null) {
LOGGER.fatal("Error, status code: " + statusCode);
}
req.getRequestDispatcher("error.jsp").forward(req, resp);
}
#Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
This handler is mapped in the web.xml this way.
<servlet-mapping>
<servlet-name>ErrorHandler</servlet-name>
<url-pattern>/error</url-pattern>
</servlet-mapping>
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error</location>
</error-page>
The question is, why do i keep getting default tomcat exception page, instead of mine. My logger works just fine, so it's clear, that after exception was happened, method doGet is called, but when it comes to request dispatcher, it just doesn't work. My jsp pages are placed in webapp folder, near WEB-INF.
Because the request dispatcher for error.jsp is just a dispatcher. Java/tomat isn't going to realize that error.jsp means you intended for this to be the error handler. It's just a page, just like foo.jsp. So, that dispatcher picks up the call, so to speak, notices that the request involves an error state, and it, in turn, forwards the request to the error dispatcher.

how to call a html page from spring boot application

I have tried using servlet , but it is not working.
web.xml :
<display-name>Password</display-name>
<servlet>
<servlet-name>SetPassword</servlet-name>
<servlet-class>com.cx.view.SetPassword</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>SetPassword</servlet-name>
<url-pattern>/view/setPassword</url-pattern>
</servlet-mapping>
I have a HTML page in [email_templates/setPassword.html]
java code :
public class SetPassword extends HttpServlet {
private static final long serialVersionUID = 7514856921920494774L;
#Override
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher requestDispatcher = request
.getRequestDispatcher("email_templates/setPassword.html");
requestDispatcher.forward(request, response);
}
//tried for both get and post request
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestDispatcher requestDispatcher = request
.getRequestDispatcher("email_templates/setPassword.html");
requestDispatcher.forward(request, response);
}
}
Url trying to access: http://localhost:8080/view/setPassword
Spring boot serves automatically static resources from one of these directories:
/META-INF/resources/
/resources/
/static/
/public/
So try to save your page in one of these folders (I would suggest /static/ or /public/)

Inheriting Servlet instead of using filters

By reading this answer, I noted that the given exemple :
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
if (((HttpServletRequest) request).getSession().getAttribute("user") == null) {
// User is not logged in. Redirect to login page.
((HttpServletResponse) response).sendRedirect("login");
} else {
// User is logged in. Just continue with request.
chain.doFilter(request, response);
}
}
make us having to write in web.xml something like :
<filter>
<filter-name>RestrictionFilter</filter-name>
<filter-class>com.myproject.filters.RestrictionFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>RestrictionFilter</filter-name>
<url-pattern>/restrained/*</url-pattern>
</filter-mapping>
But I want to be totally free to choose which url have to be restrained to loged members (it's a bit annoying to specify, for each url-pattern, the filter which have to be activated).
I used to create a Servlet who inherits HttpServlet and surcharges service() in order to check if the session contains a member instance, and then, calls the "true" service() method :
public abstract class MembreHttpServletProjet1 extends HttpServlet{
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException{
if(req.getSession().getAttribute("membre") == null){
resp.sendRedirect(req.getContextPath() + "/accueil");
return;
}
super.service(req, resp);
}
}
By this way, if a servlet needs to be used only if the user is loged as a member, I make inherit this servlet by MembreHttpServletProjet1.
Is this way wrong ? I understood the utility of filters in some case but I still confused for this exemple.
Thank you.

Is it possible to redirect to the same JSP page from a Servlet?

A JSP page named Test.jsp is mapped to the following Servlet.
#WebServlet(name = "TestServlet", urlPatterns = {"/TestServlet"})
public final class TestServlet extends HttpServlet
{
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
//request.getRequestDispatcher("/WEB-INF/admin_side/Test.jsp").forward(request, response);
response.sendRedirect("TestServlet");
}
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
#Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
processRequest(request, response);
}
#Override
public String getServletInfo() {
return "Short description";
}
}
This Servlet is mapped to a JSP page Test.jsp. The doGet() method is invoked, when a URL like http://localhost:8080/Assignment/TestServlet is entered in the address bar.
The request can be forwarded to the given URL as commented out. Is it possible to redirect to the same JSP page, Test.jsp?
If an attempt is made to do so, Google Chrome complains,
This webpage has a redirect loop
It can however, redirect to other pages under WEB-INF/admin_side.
The POST-REDIRECT-GET pattern works like so: a client sends a POST request, your server handles it and responds with a redirect, ie. a response with a 302 status code and Location header to the appropriate URI. The client makes a GET request to that URI.
Currently, your server is redirecting on both GET and POSTS requests. What's worse is that your GET is redirecting to the same URI that it is handling, creating the redirect loop you are seeing.
Change your Servlet implementation so that the POST sends a redirect, but the GET actually serves up a normal 200 response with HTML, AJAX, etc.

Categories