How to properly use multiple controllers in Spring MVC - java

I am trying to use 2 controllers with one dispatcher servlet in Spring MVC. But I am running into 404 errors when trying to render the views. The dispatcher is pretty straightforward, from web.xml:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
and with the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
...
<context:component-scan base-package="com.mycompany.azalea" />
<mvc:annotation-driven />
</beans>
The controllers are:
package com.mycompany.azalea;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping(value = "/home")
public class homeController {
#RequestMapping(value = "/")
public String home() {
return "index";
}
}
and
package com.mycompany.azalea;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping(value = "/data")
public class dataController {
#RequestMapping(value = "/")
public String home() {
return "index";
}
}
and I am using a pretty standard resolver:
#Configuration
public class AppConfig {
// Resolve logical view names to .jsp resources in the /WEB-INF/views directory
#Bean
ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
Views are set up under WEB-INF/views/home/ and WEB-INF/views/data/
However if I try to request a URL like http://localhost:8080/Azalea/home/
I get an entry in the GlassFish log:
SEVERE: PWC6117: File ".../build/web/home/WEB-INF/views/index.jsp" not found
instead of the expected request for
".../build/web/WEB-INF/views/home/index.jsp"
Same pattern for "/data". It essentially looks like the request mapping is inserted into the wrong position in the request.
My current work around is to modify the resolver to
resolver.setPrefix("../WEB-INF/views/");
and return the following from the controller:
public class homeController {
#RequestMapping(value = "/")
public String home() {
return "home/index";
}
}
But this seems to be a suboptimal solution. Please let me know if you have any suggestions.

You almost got it right. The prefix has to be absolute here to make it work the way you want it to. That is: The prefix for the view-resolver has to be set as an absolute:
resolver.setPrefix("WEB-INF/views/");
And, when you return the view names from the #RequestMapping methods, they have to be the paths relative to your view-resolver's prefix path. So, in the homeController, you should return home/index, and in your dataController, you should return data/index.

Related

Error saying : No mapping found for HTTP request with URI in DispatcherServlet due to Maven dependency

I am trying to authenticate and authorize using role base in spring using hibernate in java configuration. When I run the server then it gives me error sarying no mapping found for the URI in servlet.
public class ShoppingInitializerWeb implements WebApplicationInitializer {
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ShoppingServletConfig.class);
ctx.setServletContext(container);
ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx));
servlet.setLoadOnStartup(1);
servlet.addMapping("/*");
}
}
ShoppingServletConfig.java
#Configuration
#EnableTransactionManagement
#ComponentScan(basePackages = "com.project.shopping")
public class ShoppingServletConfig extends WebMvcConfigurerAdapter{
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/ui/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
WebConfigStatic.java
#EnableWebMvc
#Configuration
#ComponentScan(basePackages="com.project.shopping")
public class WebConfigStatic extends WebMvcConfigurerAdapter{
#Override
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/js/**").addResourceLocations("/ui/js/");
registry.addResourceHandler("/css/**").addResourceLocations("/ui/css/");
registry.addResourceHandler("/*.html/**").addResourceLocations("/ui/view/");
}
}
This is my controller:
#Controller
#RequestMapping("/")
public class UserController {
#RequestMapping(value = { "/", "/home" }, method = RequestMethod.GET)
public String homePage(ModelMap model) {
model.addAttribute("user", getPrincipal());
return "welcome";
}
And I have got welcome.jsp in webapp/WEB-INF/ui/view
Here is the error in console:
WARNING: No mapping found for HTTP request with URI [/Shoping/home] in DispatcherServlet with name 'dispatcher'
I looked up all the related errors and tried solving but couldn't get it solved.
I have faced a same project in my Spring project and I tried every possible way but no solution didn't work for that project however, finally I got a solution.
After adding maven dependencies into project deployment assembly, my project worked perfectly. So, you can try with below procedures, it should work if your code is perfect.
Right click on Project then select Properties > Deployment Assembly >
then click add button > Java Build path entries > Select Maven
dependencies > click Finish button.
then update maven project, and then mvn clean install ... then run.
I hope, it would work.

Using Spring Mvc WebApplicationInitializer, But No mapping found for HTTP request

I am setup a sample Code base using Spring MVC in Eclipse and JBoss 6.2.
But I get '404' with http://localhost:8080/rest/simple/main
Jboss log as below:
2015-07-29 11:51:27,356 ERROR [controller.simpleController] (http-/0.0.0.0:8080-1) get request
2015-07-29 11:51:27,391 WARN [org.springframework.web.servlet.PageNotFound] (http-/0.0.0.0:8080-1) No mapping found for HTTP request with URI [/rest/WEB-INF/views/main.jsp] in DispatcherServlet with name 'dispatcher'
Directory :
>rest-server-simple
> -src
> -main
-java
-config
-InitConfig.java
-ServletConfig.java
-controller
-simpleController.java
> -webapp
> -WEB-INF
-jboss-web.xml
>views
-main.jsp
InitConfig:
public class InitConfig implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
ctx.register(ServletConfig.class);
ServletRegistration.Dynamic registration = servletContext.addServlet("dispatcher",new DispatcherServlet(ctx));
registration.setLoadOnStartup(1);
registration.addMapping("/*"); }}
ServletConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages ="controller")
public class ServletConfig {
#Bean
public InternalResourceViewResolver internalResourceViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
jboss-web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<jboss-web>
<context-root>/rest</context-root>
</jboss-web>
simpleController:
#Controller
#RequestMapping(value = "/simple")
public class simpleController {
private static final Logger logger = LoggerFactory.getLogger(simpleController.class);
#RequestMapping(value = "/main", method = RequestMethod.GET)
public String hello(){
logger.error("get request");
return "main";
}
}
registration.addMapping("/*");
Change it to
registration.addMapping("/");
There is a difference between /* and / .
/* indicates that every request will be handled by DispatcherServlet, in this case retrieval of a jsp or anything like .../abc.xyz etc will also be forwarded to Dispatcher, so when controller requests for a view it actually looks for RequestMapping mapped for /WEB-INF/views/main.jsp but
/ tells container that only those requests that do not have pathinfo i.e /rest/simple/main will be handled by DispatcherServlet.
UPDATE#1
Hmm.. What I have found that jboss AS 7 doesn't like overriding default servlet i.e. / without web.xml and hence you are still getting 404 and not even getting anything on the logger, Reason being simple is that Dispatcher is never mapped to any url. If you want to check that just add following after addMapping("/*");
System.out.println("registration.getMappings() = " + registration.getMappings());
It works fine with Tomcat >= 7.0.15 or WildFly have checked on both.
To make it work on JBoss7 there are few options:
1. Change DispatcherServlet mapping from / to *.htm or something except DefaultServlet Mapping.
2. Switch your Configuration to web.xml. You will have to initialize DispatcherServlet there and pass Annotated class as `contextConfigLocation. Check here for REF

Unable to process parts as no multi-part configuration has been provided

I wrote a simple controller for uploading files:
#RestEndpoint
public class ImageController {
#Autowired
GridFsTemplate mTemplate;
#RequestMapping(value = "images", method = RequestMethod.POST)
public #ResponseBody String testPhoto(#RequestParam String name, #RequestParam String directory, #RequestParam MultipartFile file) throws IOException {
if(!file.isEmpty()){
final byte[] bytes = file.getBytes();
InputStream inputStream = new ByteArrayInputStream(bytes);
mTemplate.store(inputStream, "name");
return "uploaded photo";
}
return "failed";
}
}
#RestEndpoint annotation is:
#Target({ ElementType.TYPE })
#Retention(RetentionPolicy.RUNTIME)
#Documented
#Controller
public #interface RestEndpoint
{
String value() default "";
}
My ContextCOnfiguration class is:
#Configuration
#EnableWebMvc
#ComponentScan(
basePackages = "com.questter.site",
useDefaultFilters = false,
includeFilters =
#ComponentScan.Filter({RestEndpoint.class, RestEndpointAdvice.class})
)
public class RestServletContextConfiguration extends WebMvcConfigurerAdapter {
#Bean
public CommonsMultipartResolver multiPartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
return resolver;
}
...
}
--- UPDATED ---
web.xml file:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Spring Application</display-name>
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<url-pattern>*.jspf</url-pattern>
<page-encoding>UTF-8</page-encoding>
<scripting-invalid>true</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>
<!--<context-param>-->
<!--<param-name>spring.profiles.active</param-name>-->
<!--<param-value>development</param-value>-->
<!--</context-param>-->
<session-config>
<session-timeout>30</session-timeout>
<cookie-config>
<http-only>true</http-only>
</cookie-config>
<tracking-mode>COOKIE</tracking-mode>
</session-config>
<distributable />
</web-app>
---- UPDATED ----
public class Bootstrap implements WebApplicationInitializer
{
#Override
public void onStartup(ServletContext container) throws ServletException
{
container.getServletRegistration("default").addMapping("/resource/*");
AnnotationConfigWebApplicationContext rootContext =
new AnnotationConfigWebApplicationContext();
rootContext.register(RootContextConfiguration.class);
container.addListener(new ContextLoaderListener(rootContext));
AnnotationConfigWebApplicationContext webContext =
new AnnotationConfigWebApplicationContext();
webContext.register(WebServletContextConfiguration.class);
ServletRegistration.Dynamic dispatcher = container.addServlet(
"springWebDispatcher", new DispatcherServlet(webContext)
);
dispatcher.setLoadOnStartup(1);
dispatcher.setMultipartConfig(new MultipartConfigElement(
null, 20_971_520L, 41_943_040L, 512_000
));
dispatcher.addMapping("/");
AnnotationConfigWebApplicationContext restContext =
new AnnotationConfigWebApplicationContext();
restContext.register(RestServletContextConfiguration.class);
DispatcherServlet servlet = new DispatcherServlet(restContext);
servlet.setDispatchOptionsRequest(true);
dispatcher = container.addServlet(
"springRestDispatcher", servlet
);
dispatcher.setLoadOnStartup(2);
dispatcher.addMapping("/rest/*");
rootContext.refresh();
DbBootstrap dbBootstrap = rootContext.getBean(DbBootstrap.class);
dbBootstrap.init();
}
}
When perfoming a post request (using postman) i'm getting:
HTTP Status 500 - Request processing failed; nested exception is java.lang.IllegalArgumentException:Expected MultipartHttpServletRequest: is a MultipartResolver configured
I've looked over some similar questions over stackoverflow but none of the answers helped
me.
Spring version is: 4.0.4
Any help will be greatly appreciated (with a thumbs up of course).
Thanks
I don't know why they did this, but the MultipartResolver bean in the context needs to be named multipartResolver. Rename your #Bean method to
public CommonsMultipartResolver multipartResolver(){ // lowercase 'P'
Or give it the name explicitly
#Bean(name = "multipartResolver")
public CommonsMultipartResolver canBeCalledAnything(){
allowCasualMultipartParsing="true"
on context tag inside context.xml, it's work for me
It is straight forward from the exception that no multi-part configuration is found. Though you have provided multipartResolver bean.
The problem is that while specifying the MultipartFilter before the Spring Security filter, It tries to get the multipartResolver bean but can't find it. Because it expect the bean name/id as filterMultipartResolver instead of multipartResolver.
Do yourself a favor. Please change the bean configuration like following -
#Bean
public CommonsMultipartResolver filterMultipartResolver(){
CommonsMultipartResolver resolver = new
CommonsMultipartResolver();
return resolver;
}
or
#Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver multiPartResolver(){
CommonsMultipartResolver resolver = new
CommonsMultipartResolver();
return resolver;
}
The answer by R. Ali Ashik worked for me.
Following is the relevant part of pom.xml of the project that I am working on:
<properties>
<springframework.version>5.0.2.RELEASE</springframework.version>
<springsecurity.version>5.0.0.RELEASE</springsecurity.version>
<hibernate.version>5.2.17.Final</hibernate.version>
<mysql.connector.version>8.0.11</mysql.connector.version>
Since, I have a custom login page with persistent authentication setup, I also needed to have the following:
public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
#Override
protected void beforeSpringSecurityFilterChain(ServletContext servletContext) {
insertFilters(servletContext, new MultipartFilter());
}
}
But the actual clincher was this as pointed out by R. Ali Ashik:
#Bean(name = "filterMultipartResolver")
public CommonsMultipartResolver multiPartResolver(){
CommonsMultipartResolver resolver = new
CommonsMultipartResolver();
return resolver;
}
The relevant reference material in the context is this:
Class MultipartFilter
And the relevant text is as follows:
Looks up the MultipartResolver in Spring's root web application context. Supports a "multipartResolverBeanName" filter init-param in web.xml; the default bean name is "filterMultipartResolver". Looks up the MultipartResolver on each request, to avoid initialization order issues (when using ContextLoaderServlet, the root application context will get initialized after this filter).

How do I map Spring MVC controller to a uri with and without trailing slash?

I have a Spring Controller with several RequestMappings for different URIs. My servlet is "ui". The servlet's base URI only works with a trailing slash. I would like my users to not have to enter the trailing slash.
This URI works:
http://localhost/myapp/ui/
This one does not:
http://localhost/myapp/ui
It gives me a HTTP Status 404 message.
The servlet and mapping from my web.xml are:
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
My Controller:
#Controller
public class UiRootController {
#RequestMapping(value={"","/"})
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
#RequestMapping(value={"/other"})
public ModelAndView otherPage() {
DataModel model = initModel();
model.setView("otherPage");
return new ModelAndView("other", "model", model);
}
}
Using Springboot, my app could reply both with and without trailing slash by setting #RequestMapping's "value" option to the empty string:
#RestController
#RequestMapping("/some")
public class SomeController {
// value = "/" (default) ,
// would limit valid url to that with trailing slash.
#RequestMapping(value = "", method = RequestMethod.GET)
public Collection<Student> getAllStudents() {
String msg = "getting all Students";
out.println(msg);
return StudentService.getAllStudents();
}
}
If your web application exists in the web server's webapps directory, for example webapps/myapp/ then the root of this application context can be accessed at http://localhost:8080/myapp/ assuming the default Tomcat port. This should work with or without the trailing slash, I think by default - certainly that is the case in Jetty v8.1.5
Once you hit /myapp the Spring DispatcherServlet takes over, routing requests to the <servlet-name> as configured in your web.xml, which in your case is /ui/*.
The DispatcherServlet then routes all requests from http://localhost/myapp/ui/ to the #Controllers.
In the Controller itself you can use #RequestMapping(value = "/*") for the mainPage() method, which will result in both http://localhost/myapp/ui/ and http://localhost/myapp/ui being routed to mainPage().
Note: you should also be using Spring >= v3.0.3 due to SPR-7064
For completeness, here are the files I tested this with:
src/main/java/controllers/UIRootController.java
package controllers;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class UiRootController {
#RequestMapping(value = "/*")
public ModelAndView mainPage() {
return new ModelAndView("index");
}
#RequestMapping(value={"/other"})
public ModelAndView otherPage() {
return new ModelAndView("other");
}
}
WEB-INF/web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0" metadata-complete="false">
<servlet>
<servlet-name>ui</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
<!-- spring automatically discovers /WEB-INF/<servlet-name>-servlet.xml -->
</servlet>
<servlet-mapping>
<servlet-name>ui</servlet-name>
<url-pattern>/ui/*</url-pattern>
</servlet-mapping>
</web-app>
WEB-INF/ui-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:component-scan base-package="controllers" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:order="2"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/WEB-INF/views/"
p:suffix=".jsp"/>
</beans>
And also 2 JSP files at WEB-INF/views/index.jsp and WEB-INF/views/other.jsp.
Result:
http://localhost/myapp/ -> directory listing
http://localhost/myapp/ui and http://localhost/myapp/ui/ -> index.jsp
http://localhost/myapp/ui/other and http://localhost/myapp/ui/other/ -> other.jsp
Hope this helps!
PathMatchConfigurer api allows you to configure various settings
related to URL mapping and path matching. As per the latest version of spring, trail path matching is enabled by default. For customization, check the below example.
For Java-based configuration
#Configuration
#EnableWebMvc
public class AppConfig extends WebMvcConfigurerAdapter {
#Override
public void configurePathMatch(PathMatchConfigurer configurer) {
configurer.setUseTrailingSlashMatch(true);
}
}
For XML-based configuration
<mvc:annotation-driven>
<mvc:path-matching trailing-slash="true"/>
</mvc:annotation-driven>
For #RequestMapping("/foo"), if trailing slash match set to false, example.com/foo/ != example.com/foo and if it's set to true (default), example.com/foo/ == example.com/foo
Cheers!
I eventually added a new RequestMapping to redirect the /ui requests to /ui/.
Also removed the empty string mapping from the mainPage's RequestMapping.
No edit required to web.xml.
Ended up with something like this in my controller:
#RequestMapping(value="/ui")
public ModelAndView redirectToMainPage() {
return new ModelAndView("redirect:/ui/");
}
#RequestMapping(value="/")
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
#RequestMapping(value={"/other"})
public ModelAndView otherPage() {
DataModel model = initModel();
model.setView("otherPage");
return new ModelAndView("other", "model", model);
}
Now the URL http://myhost/myapp/ui redirects to http://myhost/myapp/ui/ and then my controller displays the introductory page.
Another solution I found is to not give the request mapping for mainPage() a value:
#RequestMapping
public ModelAndView mainPage() {
DataModel model = initModel();
model.setView("intro");
return new ModelAndView("main", "model", model);
}
try adding
#RequestMapping(method = RequestMethod.GET)
public String list() {
return "redirect:/strategy/list";
}
the result:
#RequestMapping(value = "/strategy")
public class StrategyController {
static Logger logger = LoggerFactory.getLogger(StrategyController.class);
#Autowired
private StrategyService strategyService;
#Autowired
private MessageSource messageSource;
#RequestMapping(method = RequestMethod.GET)
public String list() {
return "redirect:/strategy/list";
}
#RequestMapping(value = {"/", "/list"}, method = RequestMethod.GET)
public String listOfStrategies(Model model) {
logger.info("IN: Strategy/list-GET");
List<Strategy> strategies = strategyService.getStrategies();
model.addAttribute("strategies", strategies);
// if there was an error in /add, we do not want to overwrite
// the existing strategy object containing the errors.
if (!model.containsAttribute("strategy")) {
logger.info("Adding Strategy object to model");
Strategy strategy = new Strategy();
model.addAttribute("strategy", strategy);
}
return "strategy-list";
}
** credits:
Advanced #RequestMapping tricks – Controller root and URI Template
Not sure if this is the ideal approach, but what worked for me was to treat them as if they were two different paths and make them both accepted by each of my endpoints, such as.
#RestController
#RequestMapping("/api/mb/actor")
public class ActorController {
#GetMapping({"", "/"})
public ResponseEntity<Object> getAllActors() {
...
}
#GetMapping({"/{actorId}", "/{actorId}/"})
public ResponseEntity<Object> getActor(#PathVariable UUID actorId) {
...
}
There may be best ways to do this and to avoid this duplication, and I'd love to know that. However, what I found when I tried using configurer.setUseTrailingSlashMatch(true); is that broken paths also start becoming accepted, such as /api/mb////actor (with many slashs), and that's why I ended up going the multiple paths instead.

Spring MVC catch http errors (400.404, ....)

Good afternoon. For several days struggling over the issue. I would like to help with Spring beans (resolver) to catch all the errors in the application. Catching exceptions made almost immediately, but with capture http error is not handled.
The essence of the problem resolver can not intercept the http error.
I do not want to use the web.xml and controller, because I hope that the decision is still using the Spring context.
Implementation of catch exceptions:
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<map>
...
<entry key="java.lang.Throwable" value=".error" />
</map>
</property>
<property name="defaultErrorView" value=".error"/>
</bean>
I set up mappings for the 40x errors in web.xml then handle them in a controller (which extends SimpleMappingExceptionResolver and handles the 500 ones as well)
<error-page>
<error-code>404</error-code>
<location>/404</location>
</error-page>
#RequestMapping(value = "/404")
public String handle404(final HttpServletRequest request, final Model model) {
final String originalUri = (String)
request.getAttribute("javax.servlet.forward.request_uri");
// etc.
return "404";
}
I've got a question about the same thing here
One way is to use HandlerExceptionResolver interface.
An alternative to the HandlerExceptionResolver interface is the #ExceptionHandler annotation. You use the #ExceptionHandler method annotation within a controller to specify which method is invoked when an exception of a specific type is thrown during the execution of controller methods. For example:
package com.spring3;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class HelloWorldController {
#ExceptionHandler(Exception.class)
public ModelAndView handleMyException(Exception exception) {
ModelAndView mv = new ModelAndView("redirect:errorMessage.html?error=" + exception.getMessage());
return mv;
}
#RequestMapping(value = "/errorMessage", method = RequestMethod.GET)
public ModelAndView handleMyExceptionOnRedirect(#RequestParam("error") String error) {
ModelAndView mv = new ModelAndView("uncaughtExceptionSpring");
v.addObject("error", error);
return mv;
}
#RequestMapping("/hello")
public ModelAndView helloWorld() throws Exception {
String message = "Hello World, Spring 3.0!";
return new ModelAndView("hello", "message", message);
}
}
Spring MVC exception handling and show custom view Part1, 2, 3, 4

Categories