Sample code I have:
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" version="3.0">
<servlet>
<servlet-name>springDispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>springDispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
springDispatcher-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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="myController" class="biz.tugay.springWebOne.MyController"/>
</beans>
MyController.java
package biz.tugay.springWebOne;
/* User: koray#tugay.biz Date: 08/07/15 Time: 15:25 */
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class MyController {
#RequestMapping(value = "/hello")
public String helloWorld(){
return "index.jsp";
}
}
Well, everything works fine with this code. However when I remove the
#Controller
from MyController class I will get:
HTTP ERROR 404
Problem accessing /hello. Reason:
Not Found
I am not using component-scan, I am using an xml based configuration. Why do I need the #Controller annotation?
from spring reference documentation here
The #Controller annotation acts as a stereotype for the annotated
class, indicating its role. The dispatcher scans such annotated
classes for mapped methods and detects #RequestMapping annotations
so #Controller is required to tell dispatcher to scan mapping in this class not only for component scan.
If you are using component scanning, Spring will not know where to scan for #RequestMapping without the #Controller annotation. If you would like to configure your requestmappings with XML, that should be able to be done similar to one of the answers here: #RequestMapping with XML
Your example will not work because the #Controller annotation is essentially the "entry point" telling the component scanner to scan this class, without #Controller all other spring controller annotations (eg. #RequestMapping) will be ignored.
I noticed that you pointed out that you are not using component-scan and you are using xml-based configuration, but in reality you are attempting to mix xml-based and annotation-based configuration for a single class, which will lead to very sloppy code. I would recommend removing your xml bean definition and using only the #Controller annotation and adding the component-scan tag in your xml to clean up your code.
If you decide you still want to do xml only configuration you should remove the #RequestMapping annotation and replace it with the following xml.
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<map>
<entry key="/hello" value-ref="myController"/>
</map>
</property>
</bean>
If you want to use Spring without annotations, so you can use a BeanNameUrlHandlerMapping to indicate the controller class to the Dispatcher. So, just add the following bean to your XML and you do not have to include the #Controller anymore:
<bean id="handlerMapping" class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
Related
In my Spring Integration webapp configuration I've added a property placeholder:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:ctx="http://www.springframework.org/schema/context"
...
xsi:schemaLocation="http://www.springframework.org/schema/context
...
">
<ctx:component-scan ... />
<ctx:annotation-config />
<mvc:annotation-driven />
<ctx:property-placeholder location="classpath:config.properties" trim-values="true" />
This is that file content:
apiPath=/requests
I'm sure this configuration works because I've tried using that value in a http inbound-channel-adapter:
<int-http:inbound-channel-adapter id="/api${apiPath}"
channel="httpRequestsChannel"
path="${apiPath}"
...>
</int-http:inbound-channel-adapter>
and if I change the property value the frontend application cannot reach the endpoint.
However, further in the context I have an endpoint so configured:
<int:header-value-router input-channel="httpRequestsChannel" ... >
<int:mapping value="POST" channel="httpRequestsPostChannel" />
...
</int:header-value-router>
<int:channel id="httpRequestsPostChannel" />
<int:chain input-channel="httpRequestsPostChannel">
<int:transformer method="transform">
<bean class="transformers.RequestToMessageFile" />
</int:transformer>
...
where I want to read the property value:
public class RequestToMessageFile {
#Autowired
private Environment env;
// ...
public Message<?> transform(LinkedMultiValueMap<String, Object> multipartRequest) {
System.out.println("Value: " + env.getProperty("apiPath"));
But on the console I see:
Value: null
I supposed once declared the property source in the XML that would be part of the whole web app environment, what am I missing? Should I declare the source in another place?
I noticed that if I add the following annotations:
#Configuration
#PropertySource("classpath:config.properties")
public class RequestToMessageFile {
the property is correctly found so I guess this is just a configuration problem.
In case it matters, here's the web.xml portion that configures integration:
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/META-INF/spring.integration/context.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
UPDATE
Partly following this answer I removed <ctx:property-placeholder> from the XML file and I added the following bean:
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("classpath:config.properties")
public class WebappConfig {
}
And now both beans and the XML file can see the properties.
Quoting Martin Deinum:
No it isn't a configuration issue that is how it is supposed to work. The doesn't add properties to the environment. Where as the #PropertySource does.
Therefore you should remove <ctx:property-placeholder> from your XML configuration. Continue to use #PropertySource("classpath:config.properties") and also add this bean definition:
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
Pay attention how it has to be static do not load eagerly all other beans in the same #Configuration.
I have a very simple problem. When in my .jsp files I have a link to **/registration the method viewRegistration is executed and everything is working fine. If I have a link to **/registration/getTags?tagName=blahblah page is not found. I have no idea why, because I think my requestMapping annotation looks correct... I would be very grateful for your help!
CONTROLLER:
#Controller
#RequestMapping(value = "/registration")
public class HelloController {
final static Logger logger = Logger.getLogger(HelloController.class);
#RequestMapping(method = RequestMethod.GET)
public String viewRegistration(Map<String, Object> model, HttpSession session) {
...
}
#RequestMapping(value = "/getTags", method = RequestMethod.GET)
public #ResponseBody
List<Tag> getTags(#RequestParam String tagName) {
....
}
}
WEB.XML:
<?xml version="1.0" encoding="UTF-8"?>
<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_3_0.xsd" version="3.0">
<display-name>aa</display-name>
<servlet>
<servlet-name>xxx</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/registration/*</url-pattern>
</servlet-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/xxx-servlet.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
</web-app>
xxx-servlet.xml :
<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"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd">
<context:component-scan base-package="movies.controller" />
<context:property-placeholder location="/WEB-INF/properties/website.properties" />
<context:component-scan base-package="com" />
<context:annotation-config />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.tiles3.TilesConfigurer"
id="tilesConfigurer">
<property name="definitions">
<list>
<value>/WEB-INF/tile/tilesJsp.xml</value>
</list>
</property>
</bean>
<mvc:resources mapping="/resources/**" location="/resources/" />
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver"
id="viewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.tiles3.TilesView" />
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="website" />
</bean>
</beans>
EDIT EDIT EDIT:
I even tried sth more simple:
#RequestMapping(value = "/getTags")
#ResponseBody
public List<Tag> getTags() {
String tagName="";
return simulateSearchResult(tagName);
}
but still /registration/getTags does not work..., page not found.
the servlet url mapping is as follows :
<servlet-mapping>
<servlet-name>xxx</servlet-name>
<url-pattern>/registration/*</url-pattern>
</servlet-mapping>
which means that all urls that begin with /registration/* will be handled by the servlet, what comes after it , it will be handled by the controller.
So if you configure your controller with a #RequestMapping(value="/otherURL") it will serve the following Url :
http://localhost:xxxx/<appname>/registration/otherURL
And in this case in order to access the right method you should either:
#RequestMapping("/registration) from the controller, cause it is already mapped on the servlet level, and calling :
http://localhost:xxxx/<appname>/registration/getTags?tagName=blahblah will work correctly.
OR:
Call this URL : http://localhost:xxxx/<appname>/registration/registration/getTags?tagName=blahblah
If you want to handle requests to **/registration/getTags, change your controller method mapping to
#RequestMapping(value = "**/registration/getTags", method = RequestMethod.GET)
Your mapping should be fine. However, I believe you're running into this because you're requesting "/registration/getTags?name=blahblah" and yet your handler's parameter is "tagName". Try changing your request to "/registration/getTags?tagName=blahblah".
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html#mvc-ann-requestparam
As Nick Cromwell mentioned the issue with your mapping is the mismatch between the name of the parameter in your request and in your mapping. So either change in the request as he mentions, rename the argument in the handler method, or use the value attribute of the #RequestParam annotation, e.g.
List<Tag> getTags(#RequestParam(value="name") String tagName)
Use the requestParam as following:
List<Tag> getTags(#RequestParam("tagName") String tagName)
Update your url to
/registration/getTags/{blahblah}
and in controller -
#RequestMapping(value = "/getTags/{blahBlah}")
public #ResponseBody List<Tag> getTags(#PathVariable String blahBlah) {
String tagName="";
return simulateSearchResult(tagName);
}
I'm suspecting this is related to the view resolver configuration, you are using
org.springframework.web.servlet.view.UrlBasedViewResolver
You only have one view resolver which returns jsp pages. And in your method you are trying to return a List object which I believe you want to be serialized as JSON in http body.
To return a json response you can try to use #JSONView
Spring #JsonView
and add another viewResolver like org.springframework.web.servlet.view.json.MappingJacksonJsonView on the xml config, such as illustrated by this blog
multiple view resolvers
You have servlet url mapping at /registration/*
In class you have mapping at /registration
In method you have mapping at /getTags
So, your url is /registration/registration/getTags?name=blahblah
i've problems in order to autowire a service in my controller. I've this error:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private es.unican.meteo.service.UserService es.unican.meteo.controller.MyController.userService; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [es.unican.meteo.service.UserService] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
It seems that the userService is not registered, so that, the controller can't get the bean. I thought that my config was ok because it works with the tests. In the tests i have this:
ClassPathXmlApplicationContext("/WEB-INF/app-config.xml");
and i can get the bean ok from the ApplicationContext.xml
My package structure is the following:
es.unican.meteo.controller
|---- MyController.java
es.unican.meteo.service
|---- UserService.java
es.unican.meteo.service.impl
|---- UserServiceImpl.java
.....
WebContent/WEB-INF
|---- MyDispatcherServlet-servlet.xml
|---- app-config.xml
|---- web.xml
.....
The clases:
== UserServiceImpl.java ==
#Service
public class UserServiceImpl implements UserService{
#Autowired
private UserMapper userMapper;
public void setUserMapper(UserMapper userMapper) {
this.userMapper = userMapper;
}
== MyController.java ==
#Controller
public class MyController {
#Autowired
private UserService userService;
#RequestMapping(method=RequestMethod.GET, value="/home")
public String handleRequest(){
return "welcome";
}
#RequestMapping(method=RequestMethod.GET, value="/getUsers")
public #ResponseBody List<User> getUsersInJSON(){
return userService.getUsers();
}
}
== web.xml ==
<display-name>Spring MVC</display-name>
<servlet>
<servlet-name>MyDispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyDispatcherServlet</servlet-name>
<url-pattern>*.go</url-pattern>
</servlet-mapping>
</web-app>
== app-config.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:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:mvc="http://www.springframework.org/schema/mvc"
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
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- Scans the classpath of this application for #Components to deploy as beans -->
<context:component-scan base-package="es.unican.meteo" />
<!-- Configures the #Controller programming model -->
<mvc:annotation-driven/>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
p:driverClassName="org.apache.derby.jdbc.EmbeddedDriver"
p:url="jdbc:derby:C:\tools\derbydb"
p:connectionProperties=""
p:username="APP"
p:password="" />
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="/mybatis-config.xml" />
</bean>
<bean id="usersMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.unican.meteo.dao.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="rolesMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="es.unican.meteo.dao.RoleMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
</beans>
== MyDispatcherServlet.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:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- Enabling Spring beans auto-discovery -->
<context:component-scan base-package="es.unican.meteo.controller" />
<!-- Enabling Spring MVC configuration through annotations -->
<mvc:annotation-driven />
<!-- Defining which view resolver to use -->
<bean class= "org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
Spring mvc logger trace:
19:38:54,119 DEBUG http-8080-1 support.DefaultListableBeanFactory:430 - Creating instance of bean 'myController'
19:38:54,170 DEBUG http-8080-1 annotation.InjectionMetadata:60 - Found injected element on class [es.unican.meteo.controller.MyController]: AutowiredFieldElement for private es.unican.meteo.service.UserService es.unican.meteo.controller.MyController.userService
19:38:54,174 DEBUG http-8080-1 support.DefaultListableBeanFactory:504 - Eagerly caching bean 'myController' to allow for resolving potential circular references
19:38:54,206 DEBUG http-8080-1 annotation.InjectionMetadata:85 - Processing injected method of bean 'myController': AutowiredFieldElement for private es.unican.meteo.service.UserService es.unican.meteo.controller.MyController.userService
19:38:54,224 DEBUG http-8080-1 support.DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'userServiceImpl'
19:38:54,226 DEBUG http-8080-1 support.DefaultListableBeanFactory:430 - Creating instance of bean 'userServiceImpl'
19:38:54,234 DEBUG http-8080-1 annotation.InjectionMetadata:60 - Found injected element on class [es.unican.meteo.service.impl.UserServiceImpl]: AutowiredFieldElement for private es.unican.meteo.dao.UserMapper es.unican.meteo.service.impl.UserServiceImpl.userMapper
19:38:54,237 DEBUG http-8080-1 support.DefaultListableBeanFactory:504 - Eagerly caching bean 'userServiceImpl' to allow for resolving potential circular references
19:38:54,256 DEBUG http-8080-1 annotation.InjectionMetadata:85 - Processing injected method of bean 'userServiceImpl': AutowiredFieldElement for private es.unican.meteo.dao.UserMapper es.unican.meteo.service.impl.UserServiceImpl.userMapper
19:38:54,268 INFO http-8080-1 support.DefaultListableBeanFactory:433 - Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory#56088b29: defining beans [myController,roleService,userServiceImpl,org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping#0,org.springframework.format.support.FormattingConversionServiceFactoryBean#0,org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#0,org.springframework.web.servlet.handler.MappedInterceptor#0,org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver#0,org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver#0,org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver#0,org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping,org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter,org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter,org.springframework.web.servlet.view.InternalResourceViewResolver#0,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
19:38:54,279 ERROR http-8080-1 servlet.DispatcherServlet:457 - Context initialization failed
I've reviewed some questions about this topic but i don't find a solution to my problem. Maybe i'm skipping something but i don't know certainly. I tried to change the component-scan with no results.
When i try to access to /SPRING-MVC/getUsers.go appears those errors.
I don't know if the beans must be placed in app-config (applicationContext) or in the servlet.xml because it is a little bit confusing...
Thank you
Your configuration is very strange...
First rule out the obvious
I don't see root web application context configuration in your web.xml. Could it be that you forgot to add this piece of code?
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
WEB-INF/app-config.xml
</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Now a little bit of theory
Bit of Spring theory - Spring uses application context hierarchy for web applications:
top level web application context is loaded by ContextLoaderListener
then there are separate contexts for each DispatcherServlet instances
When a new bean is being instantiated, it can get dependencies either from the context where it is being defined or from parent context. This makes possible to define common beans in the root context (services, DAO, ...) and have the request handling beans in servlet application contexts as each servlet can have its own set of controllers, view handers, ...
Last, but not least - your errors
You are configuring MVC in your root context. That is just wrong. Remove the <mvc: context from there.
You are also registering your controllers in the root context via the <context:component-scan> on your base package. Make the component scan just on the services package or separate your classes into two top level packages core (for the root beans) and servlet (for servlet beans).
Make sure that your UserServiceImpl is in same package as defined in context:component-scan. If it's not, spring will not be able to detect it. Also, try removing value attribute from UserServiceImpl definition, since there is only 1 bean of that type. Spring will be able to autowire it by type.
You need to change the way you have autowired the service in the controller.
Change the following code
#Autowired
private UserService userService;
with following
#Resource(name="userService")
private UserService userService;
Because in the UserServiceImpl you have defined the #Service annotation with alias "userService".
I hope this would resolve your problem. :)
when ever you face such kind of problem kindly check, what is the path for context:component-scan basepackage
it should be root name Like if I am taking com.mike as package name & which contain bean,controller,dao,service folder in its structure then, in such condition you have to follow Like ----context:component-scan basepackaage="com.mike.*"
where * means all the folder (bean,service,dao,controller and theie corresponding classes) will be scaned.
You can use the #Qualifier annotation as follows:
#Autowired
#Qualifier("userService")
private UserService userService;
On first glance the config seems ok, yet there may be some smaller tripwires that might be not that obvious.
a) implemented UserService interface, is it the same as the controller needs? Dumb question, I know, but just be on the safe side.
b) bean name: Try eradicating the value-value (ba-da-tush) from the #Service annotation, its superflous anyway. Or be more specific with the help of an #Qualifier.
c) package scanning: Double check if your implemented service is really within es.unican.meteo. Sometimes its the small things.
Add #Component annotation on your service. It should work fine
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.
I'm going crazy and can't understand what the problem is:
I have the following structure:
SpringMVC
+WebContent
-web-inf
-web.xml
-springMVC-servlet.xml
-index.jsp
-security
-login.jsp
web.xml
<display-name>springMVC</display-name>
<servlet>
<servlet-name>springMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>springMVC</servlet-name>
<url-pattern>/index.html</url-pattern>
</servlet-mapping>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
springMVC-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans 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
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans">
<context:annotation-config/>
<context:component-scan base-package="com.vanilla.springMVC"/>
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
<property name="prefix">
<value>/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
</beans>
My Controller:
package com.vanilla.springMVC;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.portlet.ModelAndView;
#Controller
public class DefaultController {
#RequestMapping(value="/index.html", method=RequestMethod.GET)
public ModelAndView index(){
ModelAndView mv = new ModelAndView("index");
return mv;
}
#RequestMapping(value="/login.html", method=RequestMethod.GET)
public ModelAndView loginPage(){
ModelAndView mv = new ModelAndView("/security/login");
return mv;
}
}
I have no problem to navigate to /index.html
http://localhost:8080/SpringMVC/index.html
works perfect.
however when I'm navigating to
http://localhost:8080/SpringMVC/login.html
i have 404 error.
HTTP Status 404 - /SpringMVC/login.jsp
type Status report
message /SpringMVC/login.jsp
description The requested resource (/SpringMVC/login.jsp) is not available.
I don't want to move login.jsp on the same level as index.jsp, but why do I have this problem?
I'll just add this in here, because it solved my 404 issue. It turned out my problem was the url-mapping value in web.xml. Using Spring WebMVC version org.springframework:spring-webmvc:4.1.6.RELEASE
I was using the following (which didn't work):
<url-pattern>/rest</url-pattern>
I should've been using the following value (which works):
<url-pattern>/rest/*</url-pattern>
or
<url-pattern>/</url-pattern>
Reference: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/mvc.html
HTTP 404 means that the resource is not found.
This means the controller or a direct accessed resource (like a CSS file) is not found
It does NOT mean that the JSP referred in the controller is not found (this would be a 500 Internal Server Error)
HTTP Status 404 - /SpringMVC/login.jsp
It looks like that you send a HTTP request /SpringMVC/login.jsp but your controller method is bound to .html, so you need to change your HTTP request to /SpringMVC/login.html
Because of the name (login) may your Spring Security configuration is not correct.
create a folder under WEB-INF "jsps" for all your views, and under "jsps" a "security" folder for your case.
NOTICE: Moving the JSP files into WEB-INF, you can prevent direct access on these files. It is needed for application security. Think about a situation, in which your JSPs gives personal informations about your customer and the access has to be granted/checked by your controller. If your JSPs are existing out of WEB-INF, they are accessible with a request directly on them.
configure your view resolver like this:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/jsps"/>
<property name="suffix" value=".jsp"/>
</bean>
next, put your login JSPs into the "WEB-INF/jsps/security"
and return "security/login" from your loginPage.
Now, the view resolver searchs for the views under "WEB-INF/jsps". Because your method return "security/login", the view resolver expects a directory under jsps called "security" and a JSP file under this, which is called "login.jsp" (suffix = jsp)
I suspect that ModelAndView mv = new ModelAndView("/security/login"); is where the problem is. Make sure you have a directory 'security' folder in your root directory and it contains a login.jsp file. Or try moving the security folder inside WebContent
Provide the contextConfigLocation init parameter of your DispatcherServlet
<servlet>
<servlet-name>appServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/springMVC-servlet.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
I am using Spring MVC with eclipse and a MacOS X system and encountered a 404 error when controller returning the correct jsp name. I later figured out that the problematic jsp file has no x(execution) right on the file system. I then `chmod +x some.jsp' and the issue is resolved.
Adding this ans here just in case someone else faces the same issue.
My app was working fine earlier, then I upgraded Spring version and in the process also upgraded spring-security version. When I tried to access my login html page I was facing this issue. I had made all the necessary configurations changes because of the change of spring-security version from 3 to 4. I referred to this link and it was very helpful.
I was facing this problem because of the below configuration in my web-servlet.xml file
<mvc:resources mapping="/app/*.html" location="/app/*.html" cache-period="0"/>
<mvc:resources mapping="/app/**/*.html" location="/app/**/*.html" cache-period="0"/>
It worked after I modified both location values to "/app/". It seems like newer version of spring matches either the whole string or checks if the requested location starts with the location value configured above.
I found the below code in org.springframework.web.servlet.resource.PathResourceResolver:
if (locationPath.equals(resourcePath)) {
return true;
}
locationPath = (locationPath.endsWith("/") || locationPath.isEmpty() ? locationPath : locationPath + "/");
if (!resourcePath.startsWith(locationPath)) {
return false;
}
The second if condition was evaluating to false in my case and hence the 404 HTTP response
Another tip, if you face such error try enabling highest level of springframework logging. You might get to know the error reason from there.
This answer may be outdated for the above question, but it will help others who are just starting with spring.
I was also struggling with 404 WEB-INF/welcome.jsp page not found error.
Here issue is with ModelAndView import
Replace
import org.springframework.web.servlet.ModelAndView;
With
import org.springframework.web.portlet.ModelAndView;
Trying to configure spring 3 MVC, here is what I did so far:
I added all the spring 3.0 libraries to my netbeans project.
My web.xml is:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
<servlet>
<servlet-name>WebApplication1</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>WebApplication1</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
Next I created a WebAppliation1-servlet.xml, also in my /web-inf folder:
<?xml version="1.0" encoding="UTF-8"?>
<!--
- DispatcherServlet application context for PetClinic's web tier.
-->
<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"
xmlns:oxm="http://www.springframework.org/schema/oxm"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/oxm http://www.springframework.org/schema/oxm/spring-oxm-3.0.xsd">
<!--
- The controllers are autodetected POJOs labeled with the #Controller annotation.
-->
<context:component-scan base-package="org.springframework.Hi"/>
<!--
- The form-based controllers within this application provide #RequestMapping
- annotations at the type level for path mapping URLs and #RequestMapping
- at the method level for request type mappings (e.g., GET and POST).
- In contrast, ClinicController - which is not form-based - provides
- #RequestMapping only at the method level for path mapping URLs.
-
- DefaultAnnotationHandlerMapping is driven by these annotations and is
- enabled by default with Java 5+.
-->
<!--
- This bean resolves specific types of exceptions to corresponding logical
- view names for error views. The default behaviour of DispatcherServlet
- is to propagate all exceptions to the servlet container: this will happen
- here with all other types of exceptions.
-->
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.web.servlet.PageNotFound">pageNotFound</prop>
<prop key="org.springframework.dao.DataAccessException">dataAccessFailure</prop>
<prop key="org.springframework.transaction.TransactionException">dataAccessFailure</prop>
</props>
</property>
</bean>
<!--
- The BeanNameViewResolver is used to pick up the visits view name (below).
- It has the order property set to 2, which means that this will
- be the first view resolver to be used after the delegating content
- negotiating view resolver.
-->
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" p:order="1"/>
<!--
- This bean configures the 'prefix' and 'suffix' properties of
- InternalResourceViewResolver, which resolves logical view names
- returned by Controllers. For example, a logical view name of "vets"
- will be mapped to "/WEB-INF/jsp/vets.jsp".
-->
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver" p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" p:order="2"/>
</beans>
I then created a simple welcome.jsp in the folder /WEB-INF/jsp/welcome.jsp
I then created a package:
org.springframework.Hi
And I created a TestController.java file:
package org.springframework.Hi;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
#Controller
public class TestController {
#RequestMapping("/")
public String welcomeHandler(){
return "welcome";
}
}
I wanted this to work w/o any file extensions, so I don't have to end my urls with xxx.htm etc.
So when I run the netbeans project I get the error:
type Status report
message Servlet WebApplication1 is not available
description The requested resource (Servlet WebApplication1 is not
available) is not available.
What exactly am I missing here?
Tomcat logs
Thanks for the feedback
My tomcat logs show this:
SEVERE: Servlet /WebApplication1 threw load() exception
java.lang.ClassNotFoundException: org.apache.commons.logging.LogFactory
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1387)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1233)
at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:316)
at org.springframework.web.servlet.DispatcherServlet.<clinit>(DispatcherServlet.java:207)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
I'm asuming that error message you quoted was the error message the browser sees when it tries to access the application. This is because it didn't deploy properly.
You need to look through the web server startup logs, that will give you much more information as to why it didn't deploy.
edit: OK, that helps a lot... you need to add Apache Commons Logging to your classpath.
I used to encounter a similar problem... except it happened only when I try to run the Spring Web MVC app via the STS IDE (version 2.3.2). However, if I packaged as a WAR and deployed it to a running instance of tcServer or even Tomcat, the app worked just fine.
I ended up adding commons-logging and some other JARs to the server's launch configuration in STS IDE, in the User Entries section under the Classpath tab. This solved my problem. Why some JARs don't get added to the Java EE module dependency while running within STS, I don't still understand.
Hope this helps.