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.
Related
When I go to the first url, it calls my home() method in the controller but when I go to the second url it does not call my homeTest() method. Why is that?
I get 404 error.
http://localhost:9083/MYAPP/foo ------ first url
http://localhost:9083/MYAPP/foo/bar ------ second url
web.xml
<servlet>
<servlet-name>springServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springServlet</servlet-name>
<url-pattern>/foo/*</url-pattern>
</servlet-mapping>
Controller:
#RequestMapping(value="/foo", method = RequestMethod.GET)
public String home(Model model){
return "home";
}
#RequestMapping(value="/foo/bar", method = RequestMethod.GET)
public String homeTest(Model model){
return "home";
}
You need to configure your RequestMappingHandlerMapping.
The official documentation goes into detail about handler mappings and some of their properties. The relevant one here is alwaysUseFullPath:
alwaysUseFullPath If true, Spring uses the full path within the current Servlet context to find an appropriate handler. If false
(the default), the path within the current Servlet mapping is used.
For example, if a Servlet is mapped using /testing/* and the
alwaysUseFullPath property is set to true, /testing/viewPage.html
is used, whereas if the property is set to false, /viewPage.html is
used
In short, when trying to find a mapping for /foo/bar, it removes the part that was matched by the Servlet environment, the /foo, and only uses the /bar to find a handler. You have no handler mapped to /bar.
By setting the property above to true, it will use the full path.
You can configure this in a #Configuration annotated WebMvcConfigurationSupport subclass, by overriding requestMappingHandlerMapping
#Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
RequestMappingHandlerMapping handlerMapping = super.requestMappingHandlerMapping();
handlerMapping.setAlwaysUseFullPath(true);
return handlerMapping;
}
Or whatever mechanism is appropriate for your configuration (there's an XML equivalent for example).
There's a special case for the exact match of /foo. It's not particularly relevant here.
Just change:
<url-pattern>/foo/*</url-pattern>
To
<url-pattern>/foo/**</url-pattern>
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.
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.
I have two pages: home.jsp, and stylechoosertable.jsp. home.jsp has a simple link going to stylechoosertable.jsp. Both are in src - main - webapp - views. Starting the app runs fine, loading home.jsp is fine. However, when I click the link, it goes to a 404 Not Found page.
Here is HomeController.java
#Controller
public class HomeController {
private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
/**
* Simply selects the home view to render by returning its name.
*/
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
logger.info("Welcome home! The client locale is {}.");
return "home";
}
}
Here is CSSTableController.java
#Controller
public class CSSTableController {
private static final Logger logger = LoggerFactory.getLogger(CSSTableController.class);
private final CSSService cssService;
#Autowired
public CSSTableController(CSSService cssService) {
this.cssService = cssService;
}
#RequestMapping(value = "/stylechoosertable.jsp", method = RequestMethod.GET)
public List<StyleChooser> get() {
return cssService.getAllStyleChoosers();
}
}
servlet-context.xml
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
web.xml
<servlet-mapping>
<servlet-name>appServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
A couple of things I've noticed:
Only local:8080/myspringmvc/ brings up the home page. local:8080/myspringmvc/home.jsp brings up the same 404 error, which I don't get.
On start, I can see it doing the Request/Handler mappings properly:
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/stylechoosertable.jsp],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.util.List com.css.genapp.CSSTableController.get()
INFO : org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping - Mapped "{[/],methods=[GET],params=[],headers=[],consumes=[],produces=[],custom=[]}" onto public java.lang.String com.css.genapp.HomeController.home(org.springframework.ui.Model)
It doesn't throw any org.springframework.web.servlet.PageNotFound errors when I go to home.jsp or stylechoosertable.jsp, so I know the mapping is there.
I can't figure out why it doesn't "hit" my stylechoosertable.jsp. Any ideas?
Well I don't think I am able to get your question properly, still if you want to have simple navigation function from home.jsp, i.e on click of the link, it should go to stylechoosertable.jsp, then a definite solution would be just have a link like
SomeName
Now simply map this in controller
#RequestMapping(value = "/stylechoosertable")
public String goToSCT() {
return "stylechoosertable";
}
And if there is any stylechoosertable.jsp available in /WEB-INF/views/, it will simply get called.
Second Question the reason behind local:8080/myspringmvc/ working, not local:8080/myspringmvc/home.jsp is basically lack of RequestMapping for /home.jsp, where as for the root URL i.e /, a mapping is there in HomeController
Most Servlet containers register a Servlet implementation to handle JSPs. They would look like
<servlet>
<servlet-name>jspServlet</servlet-name>
<servlet-class>com.example.JspServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>jspServlet</servlet-name>
<url-pattern>*.jsp</url-pattern>
</servlet-mapping>
The *.jsp is known as an extension mapping. A Servlet container knows about this Servlet and the ones you've registered. The container doesn't know anything about your #Controller beans. That are relevant to Spring only.
When a Servlet container receives a request, it goes through an order specified in the Servlet specification for matching a particular Servlet based on its mapping(s). Basically, it first checks for an exact match, then it tries to do path matching (patterns like /something/*), then it does extension mapping, and finally, if no matches were found, uses the default servlet, a servlet mapped to /. In this case, your DispatcherServlet (which runs the Spring MVC stack) is mapped to /, so it is the default servlet.
When you send your request to
local:8080/myspringmvc/home.jsp
the path satisfies the extension mapping of *.jsp and therefore the container uses the JspServlet to handle the request. This JspServlet tries to find an appropriate resource, but doesn't. Remember that JSPs inside WEB-INF are not accessible publicly/externally. It therefore returns a 404.
When you send your request to
local:8080/myspringmvc/
the default servlet is chosen because nothing else can match that path. The DispatcherServlet looks up its handlers and finds
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(Model model) {
logger.info("Welcome home! The client locale is {}.");
return "home";
}
By returning the view name home and because you've registered the appropriate InternalResourceViewResolver, Spring will do a RequestDispatcher#forward(..) to that JSP. That request will again be matched by the Servlet container, but this time, to the JspServlet. Because this is an internal call (and the path is right), the request will be completed.
Similarly, for /stylechoosertable.jsp, the JspServlet is chosen before your DispatcherServlet could do anything about it.
It doesn't throw any org.springframework.web.servlet.PageNotFound
errors when I go to home.jsp or stylechoosertable.jsp, so I know the
mapping is there.
The DispatcherServlet is never involved, so it doesn't have the chance to log anything.
<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.