This question already has answers here:
Why does Spring MVC respond with a 404 and report "No mapping found for HTTP request with URI [...] in DispatcherServlet"?
(13 answers)
Closed 5 years ago.
Ok, I know there are like 20 posts here with the same problem, but none of them seem to help me, so this will probably be a duplicate, but I've gone over all the other posts and none of them solved my problem, so there must be something that I'm doing wrong or I'm not doing the right modifications from the answers of the previous mentioned questions.
I'm trying to make a small application using Spring, and I'm still experimenting with it, but I've spent like 4 days trying to figure what's wrong and I just can't. I still get a HTTP Status 404 whenever I try to get a jsp back from the controller. Nothing but 404 status through Tomcat, nothing else...
WebAppController:
#Controller
public class WebAppController {
#RequestMapping(value="/login", method = RequestMethod.GET)
public String login() {
System.out.println("You have entered the login maprequest");
return "test1";
}
}
web.xml:
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<display-name>Hotel Application</display-name>
<servlet>
<servlet-name>WebApp</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebApp</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>login.jsp</welcome-file>
</welcome-file-list>
</web-app>
webApp.xml:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 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.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">
<context:component-scan base-package="com.iquestgroup" />
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/jsp/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
This configuration works in a simple maven project with only the above mentioned in it. The problem is, the exact same thing isn't working in a maven project with 3 modules(persistence, service and webapp). In the webapp i've copied the exact same thing and when I run it on server I get 404 http status... even though the modules are building with success.
L.E. The first part of the accepted answer refers to a common servlet mapping mistake made by those who are starting with Spring. My problem was not related to it and I ended up removing it after initial answer. In order to not become confusing for readers, the first part of the accepted answer refers to the following code:
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
Change
<url-pattern>/*</url-pattern>
to
<url-pattern>/</url-pattern>
Currently, your mapped DispatcherServlet is marked as handling all requests because of /*. This means that it will also attempt to handle a request dispatched to /WEB-INF/jsp/test1.jsp. It obviously doesn't have a handler for that and will fail.
The pattern / is special in that it is the default fallback if no other pattern matches. If there's a Servlet that maps to the request path, that Servlet will be chosen before your mapped DispatcherServlet.
Most (probably all) Servlet containers come mapped with a Servlet to handle rendering JSPs with the url-pattern of *.jsp. That will take precedence over your DispatcherServlet mapped to /.
If you're still getting 404 after these changes, then there are a few possibilities.
Spring logs at the INFO level any handler methods (#RequestMapping annotated methods within #Controller beans) it registers. If you don't see any of those in your logs, then your web application hasn't been deployed correctly/successfully.
If your Servlet container is embedded in your IDE, check the appropriate tab/view on the apps that are deployed. If it's standalone, check that your generated .war file is in the appropriate directory and expanded correctly.
First of all, you can listen / request with any root controller like below.
#Controller
#RequestMapping ("/")
public class RootCtrl {
Logger logger = Logger.getLogger(RootCtrl.class);
#RequestMapping (value = "/", method = {RequestMethod.GET, RequestMethod.POST})
public String index(ModelMap model) {
// redirect to login page
return "redirect:admin/index";
}}
With that controller, you will map all requests to root. Than you may redirect request to your login controller.
It's all about request mapping. Your loginController or webController shold listen a request which should be specified before. In my application, login controller listens /admin request paths. Than, my login controller is like this:
#Controller
#RequestMapping ("/admin")
public class LoginCtrl {
#RequestMapping (value = "/index", method = {RequestMethod.GET, RequestMethod.POST})
public String index(#RequestParam (value = "captchaId", defaultValue = "") String captchaId, ModelMap model, HttpServletRequest request, HttpServletResponse response) {
if(StringUtils.isNullOrEmpty(captchaId)){
captchaId = RandomGUID.getRandomGUID();
}
model.addAttribute("captchaId", captchaId);
// redirect to login page
return "login";
}
When you will get request from this path : localhost/SampleProject/admin/index. Mappings will work.
Related
Basically I have a mapping like /A/B/something whose mapping is given as:
#Controller
#RequestMapping("/B")
public class BController {
...
#RequestMapping(value = "/something", method = RequestMethod.POST)
public ModelAndView func1()....
func1() gets called.
In web.xml, the definition is given only for A.
So its something like:
<servlet>
<servlet-name>A</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>A</servlet-name>
<url-pattern>/A/*</url-pattern>
</servlet-mapping>
In applicationcontext.xml, there is component scan for this BController.
<context:component-scan base-package="BController" />
So, my question is:
How does servlet know to move from /A's mapping to /B's mapping. How
is func1() getting called?
If applicationcontext.xml directly takes /B into
consideration, why is func1() not getting called after I delete /A from the call ( If I call /B/something from my application, it
gives an error. )?
Any help is appreciated.
Thanks :)
The spring DispatcherServlet is a central component which dispatches all requests to the registered handlers (the controllers). In your case, it has been mapped to the /A relative path:
<url-pattern>/A/*</url-pattern>
The line above basically tells the web container, that each and every request which starts with /A relative to the host should be handled by the spring DispatcherServlet. From this point further, it's up to Spring to handle the mappings.
#RequestMapping("/B")
The line above adds up to the DispatcherServlet, so to this point it maps to /A/B
#RequestMapping(value = "/something")
Similar to the previous request mapping, the line above adds up to the class level mapping, so the method func1 will finally be called with the following call:
POST <yourhost>/A/B/something
Hope that helps.
Before asking a new question, I have been reading this reference and more possibly duplicate questions:
No mapping found for HTTP request
I have already wasted hours hair-pulling just for this to work.
Here is my sample code:
Dispatcher-servlet
<context:component-scan base-package="springcodes.controller" />
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/WEB-INF/views/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Web.xml
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/dispatcher-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Controller (This controller appears to be working since my index.jsp successfully displays.)
#RequestMapping("/welcome")
public String displayIndex(#RequestParam(value="name", required=false, defaultValue="Guestxx") String name, Model model) {
model.addAttribute("name", name);
// returns the view name
return "welcome";
}
#RequestMapping("/")
public String displayIndex2(#RequestParam(value="name", required=false, defaultValue="Guesii") String name, Model model) {
model.addAttribute("name", name);
// returns the view name
return "welcome";
}
Controller in question: (when I enter this URL: http://localhost:8080/springcodes/functions.jsp something is supposed to be displayed, but currently not working)
#Controller
public class FunctionController {
#RequestMapping("/functions")
public String displayFunctionsPage(Model model) {
model.addAttribute("funcList", "Function List");
// returns the view name
System.out.println("are we inside?");
return "functions/functionpage";
}
}
There are two different problems here.
First, you have an InternalResourceViewResolver with a prefix of /WEB-INF/views/ (and a suffix of .jsp) so your return should be :
return "functions/functionpage";
Do not repeat the prefix nor the suffix.
But another thing smells. Your DispatcherServlet is mapped to /, not /*. Even if both looks like catchall, they are indeed different :
/* means : I want everything - normally you have to setup a /<mvc:resource> tag to allow serving static resources
/ means : I accept everything that nobody else wanted. That allows all static resources and JSP outside WEB-INF folder to be served directly by the servlet container.
So the servlet container should try to serve itself the URL http://localhost:8080/springcodes/functions.jsp and not even try to pass it to Spring DispatcherServlet. But if you fix first problem, http://localhost:8080/springcodes/functions should work.
Did you try just
http://localhost:8080/springcodes/functions ?
And
#RequestMapping("/functions")
public String displayFunctionsPage(Model model) {
model.addAttribute("funcList", "Function List");
// returns the view name
System.out.println("are we inside?");
return "functions/functionpage.jsp";
}
Edit --
Since you have not shared complete code , its not easy to guess , still please try below approach -
#Controller
#RequestMapping("/functions")
public class FunctionController {
#RequestMapping("/page")
public String displayFunctionsPage(Model model) {
model.addAttribute("funcList", "Function List");
// returns the view name
System.out.println("are we inside?");
return "functions/functionpage";
}
}
URL -
http://localhost:8080/springcodes/functions/page
Try to hit this [http://localhost:8080/springcodes/functions].
As you are trying to hit a URI which has no mapping associated because your controller is expecting springcodes/functions
Annotate your controller with #Controller
also be sure you have
<mvc:annotation-driven/>
<context:component-scan base-package="com.acss.springcodes.controller"/>
Pointing at correct package containing your controller.
The correct mapping for controller is:
#RequestMapping("/functions/**")
One has to learn this the hard way.
Try changing:
return "WEB-INF/views/functions/functionpage.jsp";
To:
return "functions/functionpage";
If your app is deployed correctly and you app name is springcodes then you only have to remove .jsp from your url as the mapping is just /functions:
http://localhost:8080/springcodes/functions
Also check that Controller class has no mapping at class level.
I'm having trouble configuring the Dispatcher for Spring. What I am trying to achieve is:
Build REST WebService to receive requests
Have HTML + Ajax pages consuming the data (Therefore, I don't have Views in my Spring project)
So far I have only 2 HTML pages: Login (using j_security_check) and Main page. Both very simple. I also have a simple controller:
MainController.java
#RestController //Or #Controller and #ResponseBody, no difference, right?
public class MainController {
#RequestMapping("rest/main/data")
public String getData () {
return "{data: \"DATA HUEHUE\"}"; // Yes, I'm brazilian
}
}
And I have tried the following configuration for web.xml and dispatcher-servlet.xml:
web.xml:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
dispatcher-servlet.xml
<context:component-scan base-package="com.example.controller"/>
This doesn't work. I get the message INFO: Mapped URL path [/rest/main/data] onto handler 'mainController' but when I try to access I get No mapping found for HTTP request with URI [/myapp/rest/main/data] in DispatcherServlet with name 'dispatcher'
I also have tried:
On web.xml: <url-pattern>/</url-pattern>
On dispatcher-servlet: The same
What happened: The controller DID work but the application also tried to map my login.html and couldnt find a match so I got 404 ;-;
I'm aware of that "standard" configuration using a prefix and a sufix, but since I dont have views here I dont think that's the right approach.
I'm kinda new at Spring (as you may have noticed), so please be gentle on the answers.
Any ideas?
Thanks in advance :)
My project tree:
-project
--src
---main
----webapp
-----WEB-INF
------web.xml
------weblogic.xml
------dispatcher-servlet.xml
-----www
------main.html
-----login.html
(Login is outside www)
With the first approach if you modify the controller code to have /rest/main/data It will work.
#RestController //Or #Controller and #ResponseBody, no difference, right?
public class MainController {
#RequestMapping("/rest/main/data")
public String getData () {
return "{data: \"DATA HUEHUE\"}"; // Yes, I'm brazilian
}
}
What is happening in happening in the second approach is that since you have Spring Security configured you need to be authenticated first but for that it finds the Login.html and can not find it. This may be because of incorrect configuration.
What is needed:
There is simple web application running on Tomcat at address http://localhost:8080/.
Handler for following URL should be added:
GET http://localhost:8080/request/report/custom_report?from=2013-10-12&to=2014-10-12&download=true
which will simply write to the HttpServletResponse some data i.e. no views are involved.
What was done:
As per official Spring MVC documentation following mapping of DispatcherServlet was added to web.xml
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/request/*</url-pattern>
<!-- PLEASE NOTE that mapping to /* is not an option -->
</servlet-mapping>
Now, because latest spring-webmvc-4.0.5.RELEASE is used I would like to add above mentioned handler with the minimum XML or Java configuration possible, so I create controller class:
package org.yura.servlet.spring;
#Controller
public class SpringRequestController {
#RequestMapping(value = "/report/custom_report",
method = GET,
produces = "application/pdf")
public void getCustomReport(
#RequestParam("from") #DateTimeFormat(pattern = "yyyy-MM-dd") final Date from,
#RequestParam("to") #DateTimeFormat(pattern = "yyyy-MM-dd") final Date to,
#RequestParam("download") final boolean download,
final HttpServletResponse response) throws IOException {
takeParamsAndWriteReportAsPdfToServletResponse(from, to, download, response.getOutputStream());
}
Then, in order for this Controller to be "picked up" by Spring I put springDispatcher-servlet.xml right next to web.xml in WEB-INF folder with following configuration (please advise if it can be simplified even more):
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<context:component-scan base-package="org.yura.servlet.spring" />
</beans>
The Problem
With this configuration, after starting Tomcat and navigating to above mentioned URL I get Error 404.
Question 1: Please advise what is wrong with handler URLs - should I specify them as relative or what? (because as per logs, DispatcherServlet is created normally)
Question 2: Is it possible to move configuration from springDispatcher-servlet.xml to my Controller class in order not to scatter request-handling logic across multiple files.
Thanks in advance...
You haven't enabled your MVC stack. Add
<mvc:annotation-driven />
to your springDispatcher-servlet.xml (along with the appropriate namespaces).
The configuration in springDispatcher-servlet.xml is not simply request handling configuration. It can contain any bean declaration. If anything, you can move it to a Java configuration, but it should not be part of your #Controller source code.
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/test/*</url-pattern>
</servlet-mapping>
If I hit /test/page the above will work. However, hitting /test or /test/ will not work. I'm using Spring MVC, and my request mapping is as follows:
#RequestMapping(value = {"","/"})
EDIT:
I'm in the process of verifying with an independent project, but this appears to be a bug with Spring's UrlPathHelper. The following method returns an incorrect path when there is both a context and a servlet path, and you hit the servlet without a trailing slash.
public String getPathWithinApplication(HttpServletRequest request) {
String contextPath = getContextPath(request);
String requestUri = getRequestUri(request);
if (StringUtils.startsWithIgnoreCase(requestUri, contextPath)) {
// Normal case: URI contains context path.
String path = requestUri.substring(contextPath.length());
return (StringUtils.hasText(path) ? path : "/");
}
else {
// Special case: rather unusual.
return requestUri;
}
}
Just as an example let's say I have a context of "admin" and the following servlet-mapping:
<servlet-mapping>
<servlet-name>usersServlet</servlet-name>
<url-pattern>/users/*</url-pattern>
</servlet-mapping>
Now I have a request mapping in one of my controllers like this:
#RequestMapping(value = {"","/"})
If I hit /admin/users it will not work. However, if I hit /admin/users/ it will work. Now if I change my request mapping to the following then they will both work:
#RequestMapping(value = {"/users","/"})
However, now the URL /admin/users/users will also work (which is not what I would want).
Yevgeniy is correct, but if your DispatcherServlet is taking over for the default servlet, you have to add this to your web.xml:
<welcome-file-list>
<welcome-file>/</welcome-file>
</welcome-file-list>
my setup usually looks like this:
<servlet-mapping>
<servlet-name>testServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
controller, where i assume you want to handle /test and /test/ equally:
#Controller
public class MyController {
#RequestMapping("/test")
public String test() {
return "redirect:/welcome";
}
#RequestMapping("/test/")
public String test() {
return "redirect:/welcome";
}
#RequestMapping("/welcome")
public void test(ModelMap model) {
// do your stuff
}
}
setup like this would cause DispatcherServlet to handle requests for *.css and *.js files, which is not desired in most cases. i think this is the problem Bhavik describes. For those resources you can you the ResourceController like this:
<mvc:resources mapping="/css/**" location="/resources/css/" />
<mvc:resources mapping="/js/**" location="/resources/js/" />
files from /resources/css and /resources/js will be served without forcing you to write a extra controller.
First of all, the difference between mapping dispatcher servlet to "/" and to "/*".
There is a difference!
When mapping to "/*", all URL requests (including something like this "/WEB-INF/jsp/.../index.jsp") are mapped to dispatcher servlet.
Secondly, when using Spring + Tiles, and returning some JSP in your tiles definition, it is treated as an internal forward request, and handled by the same servlet as the original request.
In my example, I invoke root URL "/", which is properly caught by home() method, and then forwarded to "index.jsp" by Tiles, which is again being handled by Dispatcher Servlet.
Obviously, dispatcher servlet cannot handle "index.jsp", because there is no controller for it.
Yeah, it is ugly, but looks like this is the way it works.
So, the only solution I've found so far: to change "/*" back to "/" in web.xml. This way JSPs are rendered properly by Tomcat's jsp servlet, I guess, and not dispatcher servlet.
Unfortunately, this fix will break the ROOT URL dispatching by Spring, so you need to leave the idea of using ROOT URL + Tiles for now.
Please note that adding explicit servlet mapping ".jsp -> Tomcat jsp in web.xml doesn't help, when using "/*", and it sucks.
Still the problem is not resolved.
Also this is the problem in Spring MVC 3.0
A way without touch the web.xml file is by set the map to the default welcome file path.
#RequestMapping("/index.html")
In my case, every url was working except of the root "/" url.
The problem was that i didn't deleted the index.htm file inside of my projects' webapp root folder.