how to get Requested URL on custom error page - spring

I got next problem with my application.
I have to make my own 404 page and I'd like to write there "Page {requestedPage} not found" but I have no idea how to get this value.
I created Controller with RequestMapping
#RequestMapping("404")
public String handle404(Locale locale, Model model ,HttpServletResponse response, HttpServletRequest request){
...
}
and set this page in web.xml as 404 error page
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
I found the same question on spring forum
http://forum.springsource.org/showthread.php?87670-Knowing-the-requested-URL-during-a-404
but without answer
I looked for all HttpSerletRequest methods and fields but not found anything what can help.
Does anyone know how to do this?

Related

External redirects in exception logic is not working on Tomcat 8.5.39

I'm setting up exception handling logic for a multipart project with common error page (that is hosted in other part of the project). When I tried to redirect to external URL on exception, tomcat 8.5.39 is showing default error instead. Funny thing is, this seems to work just fine in tomcat 8.5.38
I've tried many different exception handling techniques, but they all seem not to work for external redirects.
So currently, i have something like this in my web.xml file:
...
<error-page>
<error-code>404</error-code>
<location>/error/error404</location>
</error-page>
...
and for my Spring controller,
#Controller
#RequestMapping(value = "/error")
public class ErrorHandler{
...
#GetMapping(value = "error404")
public String error404(){
return "redirect:http://{myproject}/{404errorPage}";
}
...
}
I'm expecting this code to redirect the user to http://{myproject}/{404errorPage} when 404 error occurs, which works just fine in tomcat 8.5.38. But on 8.5.39, they seem to have changed error handling logic, and it will display default error page(browser default 404 page).
Any input or idea would be tremendously helpful.
This is a known regression in 8.5.39 which is fixed in the just released 8.5.40.

spring - how to deny the direct access to servlet mapping(POST method used) from the url

For example, I have a servlet mapping /servlet, and actually it is requested by a form using POST Method. If I type in the mapping directly without using the form in the browser, the server will give me a 405 page.
HTTP Status 405 - Request method 'GET' not supported
What I want to do is to catch this exception using spring security. I was thinking to restrict this servelet request by using POST method only so that the direct url access will be denied. However, I searched on the internet but I didn't find an answer. Please guide me how to do this, thanks.
If you want to override default error message you should create your own error page and map it into web.xml like this
<error-page>
<error-code>405</error-code>
<location>/internal-server-error.htm</location>
</error-page>
<error-page>
<error-code>404</error-code>
<location>/405.html</location>
</error-page>
and your 405.html will contain your personalized error message for the user.
Read more: http://mrbool.com/how-to-create-error-page-in-j2ee/26770

#ExceptionHandler + #ResponseStatus

I am handling my controlled exceptions using the following code:
#ExceptionHandler(MyException.class)
#ResponseStatus(HttpStatus.NOT_FOUND)
public ModelAndView handleMyException(MyException e) {
ModelAndView mav = new ModelAndView(ERROR_PAGE);
(...)
return mav;
}
That is, I want to both use custom views for different errors AND use response status code for the HTTP response.
At the same time, for pure 404 I have the following config in web.xml
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
<error-page>
<error-code>400</error-code>
<location>/400</location>
</error-page>
Which takes to a 404 specific view.
The problem is that when a NOT_FOUND is thrown from my #ExceptionHandled method, it is not showing my custom view, debugging shows that execution actually goes through the handleMyException method, but after it's done it also goes through the method that maps the /404 in web.xml, and that is the view that gets shown.
Also if I throw a different Response Code, I get the default behavior on Exceptions, instead of my custom view.
I can't reproduce your problem with Tomcat 6 ans Spring 2.3.4. That is correct, because accroding to Servlet specification 2.5, the deployment descriptor defines a list of error
page descriptions. The syntax allows the configuration of resources to be returned
by the container either when a servlet or filter calls sendError
on the response for specific status codes (...)
I tracked where Spring sets response code basing on #ResponseStatus(HttpStatus.NOT_FOUND)
It is here:
public class ServletInvocableHandlerMethod (...)
private void setResponseStatus(ServletWebRequest webRequest) throws IOException {
if (this.responseStatus == null) {
return;
}
if (StringUtils.hasText(this.responseReason)) {
webRequest.getResponse().sendError(this.responseStatus.value(), this.responseReason);
}
else {
webRequest.getResponse().setStatus(this.responseStatus.value());
}
// to be picked up by the RedirectView
webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, this.responseStatus);
}
In my case if error handler method is annotated
#ResponseStatus(HttpStatus.NOT_FOUND)
the following branch is selected:
else {
webRequest.getResponse().setStatus(this.responseStatus.value());
}
Because HttpServletResponse.setStatus is called and NOT HttpServletResponse.sendError, web container ignores error page defined in <error-code>404</error-code>
I hope my explanation will be useful to track the problem yourself. I suspect somewhere HttpServletResponse.sendError is called and it triggers web container to return default error page
It sounds like the problem is probably that the web container is trying to handle the 400/404's its seeing from the web application (because it doesn't understand the context of those errors). You probably need to get rid of the web.xml error page definitions and add more configuration to the Spring controllers to handle the generic 400/404 errors as well.
This guide helped me a lot when I was setting up exception handling in my app: http://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc
The web.xml tells the app container how to handle various response codes that are generated by the application. When you get an exception out of a controller method, it gets handled by the Spring #ExceptionHandler annotated method. At this point, the app container isn't involved so it has no idea what's going on yet.
My best understanding is that when you generate a 404 Http status from the exception handler method and return, Spring's basically done at that point, and the app container steps back in and says "I got a 404, what do I do with a 404? ah, redirect to /404". And then, control goes back to the web app itself to handle the /404 request.

No mapping found for HTTP request

I am back with working in Springs. I used to work in Springs but blindly, didn't understand much. I used to get a lot of errors, very basic ones, and I am getting them again.
My problem is that, I don't know how the configuration of the Spring-MVC work.
What happens when I run the project from my STS?
I am working on the spring template project in STS.
I am getting this when I run the project.
WARN : org.springframework.web.servlet.PageNotFound - No mapping found for HTTP request with URI [/common/] in DispatcherServlet with name 'appServlet'
I am totally fed up and broken.
Just 2 months of break from work, I am back at the starting block.
I don't want to post my code and make the question specific.
I want an answer that explains the way in which the server executes a spring project. Right from the running of an application(basic hello world application) to the display of the home page.
This will be helpful for all the beginners.
I tried searching for such an explanation in the net but I didn't get any proper explanation, but got a lot of basic samples. Those samples are easy to understand but are not explaining the way in which the server goes about.
Note: I am looking for an answer that explains the Springs concept. From the running of an application to the display of a home page. What all happens in this process? Where does the server start with? How does it go about?
Here is the flow initially servlet container loads the web.xml file.In web.xml we will specify that all the requests are handled by the spring FrontController that is DispatcherServlet.
We include it by adding the following code
<servlet>
<servlet-name>dispatcher</servlet-name>
<servletclass>org.springframework.web.servlet.DispatcherServlet</servletclass>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
Here it indicate if the url request is of *.htm it is handled by dispatcherServlet then dispatcherServlet load dispatcher-servlet.xml . Where we need to mention the mapping to controller by writing the specific url request such as
<bean name="/insert.htm" class="com.controller.MyController"></bean>
So in bean we mention that for request of /insert.htm it tells the servlet to look in the mentioned class.You need use the Annotation of #RequestMapping above the method for ex
#RequestMapping("/insert.htm")
public ModelAndView insert(HttpServletRequest req,Student student)
{
String name=req.getParameter("name");
int id=Integer.parseInt(req.getParameter("id"));
student.setId(id);
return new ModelAndView("display","Student",student);//It returns a view named display with modelclass name as `Student` and model object student
}
So when a Request url of /insert.htm appears it executes the above method it returns a ModelAndView object nothing but an view.It again goes to dispatcher-servlet.xml and looks for view Resolver the normal code that is to be added is
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
So from this it gets the logical view name and appends the prefix and suffix to it .Finally it displays the content in the view.so it looks for display in view resolver prefixes and suffixes the things and finally returns /WEB-INF/jsp/display.jsp .Which displays the jsp content
You are mapping your Spring servlet only for requests that end with .htm. The request for the root of your application does not end with .htm and so, it does not get picked up by Spring. Edit your web.xml as follows, in order to use Spring for all requests:
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Then, use this as the controller:
package com.mkyong.common;
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView helloWorld() {
ModelAndView model = new ModelAndView("index");
model.addObject("msg", "hello world");
return model;
}
}
The controller intercepts the requests for the context root of the application, adds the msg attribute to the model and redirects to the index view.
So, you need to add the index.jsp file in the /WEB-INF/views/ directory. Inside your jsp, you will be able to use the value of the msg attribute.
From what every you have posted you do no have a request mapping for the url /common/.
You will have to create another request mapping function like the one below in your controller class and create a view file also.
#RequestMapping(value = "/common/", method = RequestMethod.GET)
public ModelAndView common(HttpServletRequest request,
HttpServletResponse response) {
ModelAndView model = new ModelAndView("common");
model.addObject("msg", "hello world");
return model;
}

Tomcat 404 Page With Spring Form

In my web.xml page I have the 404 error mapped to a jsp page as:
<error-page>
<error-code>404</error-code>
<location>/WEB-INF/jsp/errorPages/error404.jsp</location>
</error-page>
The redirect on 404 works fine. I get to error404.jsp. The problem is that I have a spring form on the page (a search form that is on EVERY page) which causes errors because the target object is not in the model. I get the following exception:
Caused by: java.lang.IllegalStateException: Neither BindingResult nor
plain target object for bean name 'searchCriteria' available as request attribute
I'd like to have this search form on every page, including the error pages. Is there any way to do this? I realize that 404 as I have it configured above doesn't go to a servlet... so how do I get the request attribute into the model?
One solution is to code the search form as plain HTML in your JSP/template, so that you remove any dependency on the form binding object. For a simple search form with a text input and submit button, this should not be a problem.
The way to do this is to map the error pages to a servlet. Within the servlet you can add things to your model just like you can in any other servlet. To map error pages to a servlet, add something like the following to your web.xml file:
<error-page>
<error-code>404</error-code>
<location>/error/generalError</location>
</error-page>
where "error" is the servlet name and "generalError" is the request mapping.

Resources