I'm new to Spring MVC and trying to learn from some web tutorials and Spring's PetClinic. When I was just starting I was using some tutorials from some really old releases of Spring. I didn't know it at the time, so it has been a lot of back and an regroup attempts. I am having trouble with the way my test site finds the Controller classes. The site finds my index.jsp file and executes that just fine. But when I try to click on a link that maps to one the the Controller classes I get a page not found (404) error.
Everything compiles and deployes with no errors on JBoss EAP 6.1.
I'm attaching some of the snippets from my config files. Can somebody look at them and see what I'm doing wrong>
Web.xml snippet:
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:resources/spring/core-config.xml
</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
the dispatcher servlet.xml snippet:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/" p:suffix=".jsp" />
<bean class="org.S2Me.MyHealth.controller.CustomMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="org.springframework.web.servlet.PageNotFound">notFound</prop>
<prop key="java.lang.Exception">failure</prop>
</props>
</property>
</bean>
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource"
>
<property name="basename" value="/WEB-INF/messages" />
</bean>
the core-Servlet snippet:
<import resource="view-config.xml"/>
<context:component-scan base-package="org.S2Me.MyHealth.controller" />
<mvc:resources mapping="/resources/**" location="/resources/" />
<mvc:resources mapping="/webjars/**" location="classpath:/META-INF/resources/webjars/"/>
<mvc:view-controller path="/" view-name="index" />
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource"
p:basename="messages/messages" />
<bean
class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"
>
<property name="defaultErrorView" value="exception" />
<!-- results into 'WEB-INF/jsp/exception.jsp' -->
<property name="warnLogCategory" value="warn" />
</bean>
the view-Servlet snippet:
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
>
<property name="contentNegotiationManager" ref="cnManager" />
<property name="viewResolvers">
<list>
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
>
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<bean
class="org.springframework.web.servlet.view.BeanNameViewResolver" />
</list>
</property>
</bean>
<bean id="cnManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="true"/>
<property name="ignoreAcceptHeader" value="true"/>
<property name="defaultContentType" value="text/html"/>
<property name="mediaTypes">
<map>
<entry key="html" value="text/html" />
<entry key="xml" value="application/xml" />
<entry key="atom" value="application/atom+xml" />
</map>
</property>
</bean>
The index.jsp snippet:
<div class="navbar-inner">
<ul class="nav">
<li style="width: 100px;"><a href="<spring:url value="/" htmlEscape="true" />"><i class="icon-home"></i>
Home</a></li>
<li style="width: 130px;">
Login
</li>
</ul>
</div>
The Login Controller class:
package org.S2Me.MyHealth.controller;
import org.S2Me.MyHealth.server.LoginForm;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.validation.BindingResult;
import java.util.Map;
import javax.validation.Valid;
#Controller
#RequestMapping("/login")
public class LoginController
{
#SuppressWarnings({ "rawtypes", "unchecked" })
#RequestMapping(method = RequestMethod.GET)
public String showForm(Map model)
{
LoginForm loginForm = new LoginForm();
model.put("loginForm", loginForm);
return "loginform";
}
#RequestMapping(method = RequestMethod.POST)
public String processForm(#Valid LoginForm loginForm, BindingResult result,
Map model)
{
String userName = "UserName";
String password = "password";
if (result.hasErrors())
{
return "loginform";
}
loginForm = ( LoginForm) model.get("loginForm");
if (!loginForm.getUserName().equals(userName)
|| !loginForm.getPassword().equals(password))
{
return "loginform";
}
model.put("loginForm", loginForm);
return "loginsuccess";
}
}
Any syntax errors are my cutting and pasting like I said no error in compile or deployment, just 404 errors on navigation.
Any help would be appreciated. Thanks
Your configuration is ignoring the dispatcher-servlet.xml file.
Upon initialization of a DispatcherServlet, Spring MVC looks for a file named [servlet-name]-servlet.xml in the WEB-INF directory of your web application and creates the beans defined there, overriding the definitions of any beans defined with the same name in the global scope. Source: Spring Reference
One can override this by specifing an init-param with the name contextConfigLocation.
As you are specifing this parameter your dispatcher-servlet.xml is thus ignored and with that the configuration inside of it.
Related
This question already has an answer here:
What is a NoSuchBeanDefinitionException and how do I fix it?
(1 answer)
Closed 2 years ago.
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.home.dao.ProductDao' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {#org.springframework.beans.factory.annotation.Autowired(required=true)}
package com.home.dao;
#Repository
#Transactional
#Service
public class ProductDao implements proDaoInterface{
#Autowired
private SessionFactory sessionFactory;
public void addProduct(ProductModel product)
{
Session session= sessionFactory.getCurrentSession();
session.saveOrUpdate(product);
session.flush();
}
public ProductModel getProductByID(String ID)
{
Session session = sessionFactory.getCurrentSession();
ProductModel product = (ProductModel)session.get(ProductModel.class,ID);
session.flush();
return product;
}
#SuppressWarnings("unchecked")
public List<ProductModel> getProductList()
{
Session session= sessionFactory.getCurrentSession();
List<ProductModel> listProduct;
listProduct = session.createQuery("from ProductModel").getResultList();
session.flush();
return listProduct;
}
public void deleteProuct(String ID)
{
Session session = sessionFactory.getCurrentSession();
session.delete(getProductByID(ID));
session.flush();
}
}
controller class
#EnableWebMvc
#Controller
public class homeController {
#Autowired
private ProductDao dao;
#RequestMapping("/test")
public String home(Model model) {
List<ProductModel> productList = dao.getProductList();
model.addAttribute("productList", productList);
return "home";
}
#RequestMapping("/view/{productID}")
public String viewProduct(#PathVariable String productID, Model model) throws IOException {
ProductModel product = dao.getProductByID(productID);
model.addAttribute(product);
return "viewProduct";
}
}
Spring Configuration file
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName"
value="oracle.jdbc.driver.OracleDriver"></property>
<property name="url"
value="jdbc:oracle:thin:#localhost:1521:xe"></property>
<property name="username" value="system"></property>
<property name="password" value="admin"></property>
</bean>
<bean id="sessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="hibernateProperties">
<props>
<prop key="hbm2ddl.auto">update</prop>
<prop key="dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="connection.pool_size">1</prop>
<prop key="show_sql">true</prop>
</props>
</property>
<property name="packagesToScan">
<list>
<value>com.home.controllers</value>
<value>com.home.dao</value>
<value>com.home.model</value>
</list>
</property>
</bean>
<bean id="hibernateTransactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
Dispatcher -Servlet.xml
<context:component-scan base-package="com.home.controllers"></context:component-scan>
<mvc:annotation-driven/>
<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/view/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
<mvc:resources mapping="/images/**" location="/WEB-INF/resources/images/" />
<mvc:resources mapping="/css/**" location="/WEB-INF/resources/css/" />
<mvc:resources mapping="/fonts/**" location="/WEB-INF/resources/fonts/" />
<mvc:resources mapping="/js/**" location="/WEB-INF/resources/js/" />
<mvc:resources mapping="/view/**" location="/view/" />
<tx:annotation-driven />
</beans>
web
<display-name>Product</display-name>
<listener>
<listener-class>
*org.springframework.web.context.ContextLoaderListener*
</listener-class>
</listener>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/ApplicationConfig.xml,
/WEB-INF/DispatcherServlet.xml
</param-value>
</context-param>
<servlet>
<servlet-name>dad-frontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>dad-frontController</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
</web-app>
I believe your error is coming in fact you are restricting your component scan on dispatcher-servlet.xml.
Change the following:
<context:component-scan base-package="com.home.controllers"></context:component-scan>
To:
<context:component-scan base-package="com.home.*"></context:component-scan>
Checkout the official doc: https://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-annotation-config
One more thing, your ProductDao has #Service and #Repository. Both say the same to Spring, so leave only #Repository.
Besides that, I would advise you to use Spring Boot, or, make those configurations via programmatically, it's way more clear =)
Here is my controller
#RequestMapping(value = "/download/{product}/{topic}/{key:.*}")
//#ResponseBody
public AjaxResult download(#PathVariable("product") String product, #PathVariable("topic") String topic,
#PathVariable("key") String key, HttpServletRequest request, HttpServletResponse response) {
Since the key path variable may contains dot, so regular expression is used, and class AjaxResult extends LinkedHashMap and all getter and setter are added, so it can return json result. the view resolver is as follow:
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
</list>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
</list>
</property>
</bean>
and the converter:
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
<bean id="fastJsonHttpMessageConverter"
class="com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
<value>text/plain;charset=UTF-8</value>
<value>application/json;charset=UTF-8</value>
</list>
</property>
<property name="features">
<array>
<!--<value>WriteMapNullValue</value> -->
<value>QuoteFieldNames</value>
<value>DisableCircularReferenceDetect</value>
</array>
</property>
</bean>
<bean id="stringHttpMessageConverter"
class="org.springframework.http.converter.StringHttpMessageConverter">
<constructor-arg value="UTF-8" index="0" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
and <mvc:annotation-driven /> <mvc:default-servlet-handler /> are added.
The problem is when i access like: /download/product/topic/key.abc, it works fine, but when access: /download/product/topic/key.txt, error happens:
javax.servlet.ServletException: Could not resolve view with name '/download/product/topic/key' in servlet with name ''
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1227)
at org.springframework.test.web.servlet.TestDispatcherServlet.render(TestDispatcherServlet.java:105)
Please notice the difference between the two url, in a word when access a url that contains a dot and a correct file extension, error happens.
You may see that i comment the annotation #ResponseBody of the controller, if a add #ResponseBody and access url /download/product/topic/key.txt, error happens:
org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
at org.springframework.web.servlet.mvc.method.annotation.AbstractMessageConverterMethodProcessor.writeWithMessageConverters(AbstractMessageConverterMethodProcessor.java:137)
Can anyone help? Thanks.
Update
add trailing slash as said in Spring MVC #PathVariable getting truncated can solve my problem, that is :
#RequestMapping(value = "/download/{product}/{topic}/{key:.*}/")
and when access using /download/product/topic/key.txt/, but is there any other solution that won't change the value in #RequestMapping and url?
add below conde into .xml
file of your Spring Configuration:
<context:annotation-config/>
<mvc:annotation-driven />
<bean id="jacksonMessageConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<ref bean="jacksonMessageConverter"/>
</list>
</property>
</bean>
you can try to add DispatcherServlet into your web.xml file, you can find code below:
<servlet>
<servlet-name>myServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:ApplicationContext.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/api/*</url-pattern>
</servlet-mapping>
I solve the problem as follow:
for in my spring servlet config xml, there is a bean ContentNegotiatingViewResolver, so i add a bean ContentNegotiationManagerFactoryBean and set it property favorPathExtension to false, so below is my config file:
<bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean">
<property name="favorPathExtension" value="false"/>
<property name="favorParameter" value="true"/>
</bean>
<bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="contentNegotiationManager" ref="contentNegotiationManager"/>
<property name="viewResolvers">
<list>
<bean class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
</list>
</property>
<property name="defaultViews">
<list>
<bean
class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
</list>
</property>
</bean>
And you don't need #ResponseBody in your controller
I,m using SpringMVC and i have different design for each device type Desktop/Tablet/Mobile
<!-- START of MOBILE -->
<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean
class="org.springframework.mobile.device.site.SitePreferenceWebArgumentResolver" />
<bean class="org.springframework.mobile.device.DeviceWebArgumentResolver" />
</mvc:argument-resolvers>
</mvc:annotation-driven>
<mvc:interceptors>
<!-- Resolve the device which has generated the request -->
<bean
class="org.springframework.mobile.device.DeviceResolverHandlerInterceptor" />
<!-- User's site preference -->
<bean
class="org.springframework.mobile.device.site.SitePreferenceHandlerInterceptor" />
<!-- Redirects users to the device specific site -->
<bean
class="org.springframework.mobile.device.switcher.SiteSwitcherHandlerInterceptor"
factory-method="urlPath">
<constructor-arg value="/m" />
<constructor-arg value="/t" />
<constructor-arg value="/" />
</bean>
</mvc:interceptors>
<!-- Device aware view resolving -->
<bean id="liteDeviceDelegatingViewResolver"
class="org.springframework.mobile.device.view.LiteDeviceDelegatingViewResolver">
<constructor-arg>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
</constructor-arg>
<property name="mobilePrefix" value="m/" />
<property name="tabletPrefix" value="t/" />
<property name="normalPrefix" value="/" />
<property name="enableFallback" value="true" />
</bean>
<!-- END of MOBILE -->
I have /m /t and / folders views in /WEB-INF/views/ folder for each device and all works fine, but this configuration not applies only to welcome page, ie I open page with phone and see desktop-version of login.jsp (/WEB_INF/views/login.jsp but not /WEB-INF/views/m/login.jsp)
<welcome-file-list>
<welcome-file>/WEB-INF/views/login.jsp</welcome-file>
</welcome-file-list>
What I have to do to change to fix it.
Just don't specify page... and handle 'home' request by controller :)
modify your web.xml to:
<welcome-file-list>
<welcome-file></welcome-file>
</welcome-file-list>
or just remove tag
now, your HomeController should look like this:
#Controller
public class HomeController {
#RequestMapping("/")
public String home(SitePreference sitePreference, Model model) {
return "login";
}
}
hope this helps.
I am creating a Spring MVC application for the first time.
It seems like when I start up the server, the applicationContext.xml loads the first time even before I run any mvc controller; This is what I want.
BUT once I run a controller that is loaded with context:component-scan in the dispatcher.xml ....IT SEEMS that the applicationContext.xml gets loaded again...
Why is this happening and how do I disable this? I only want my applicationContext.xml to run once.
Right after I run a controller, I see the logs below...
ClassPathXmlA I org.springframework.context.support.AbstractApplicationContext prepareRefresh Refreshing org.springframework.context.support.ClassPathXmlApplicationContext#65cb65cb: startup date [Tue Feb 15 16:29:21 EST 2011]; root of context hierarchy
XmlBeanDefini I org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions Loading XML bean definitions from class path resource [WEB-INF/applicationContext.xml]
I think this is also causing my jms DefaultMessageListenerContainer to be created twice...
thanks
xxxdispatcher-servlet.xml
<context:component-scan base-package="com.something.web" />
<mvc:annotation-driven />
<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:interceptors>
<bean class="com.something.SomeInterceptor" />
</mvc:interceptors>
<mvc:resources mapping="/js/**" location="/js/" />
<bean class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver">
<property name="exceptionMappings">
<props>
<prop key="java.lang.Exception">common/error</prop>
</props>
</property>
<property name="warnLogCategory" value="abcdefg"/>
</bean>
applicationContext.xml
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/application.properties" />
</bean>
<!-- Local Data Holder -->
<bean id="propertyHolder" class="com.common.PropertyHolder">
<property name="baseURL" value="${url.base}" />
</bean>
<bean id="messageListener" class="com.something.SomeListener" />
<bean id="xxxDAO"
class="com.XXXDAOImpl"
scope="prototype">
<property name="dataSource" ref="dataSourceQA" />
</bean>
<bean id="xxxServiceTarget" class="com.XXXServiceImpl">
<property name="xxxDAO" ref="xxxDAO"/>
</bean>
<bean id="xxxService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="txManager"/>
<property name="target" ref="xxxServiceTarget"/>
<property name="transactionAttributes">
<props>
<prop key="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
<!-- and this is the message listener container -->
<bean id="jmsContainer"
class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<property name="connectionFactory" ref="xxxCF" />
<property name="destination" ref="xxxInboundQueue" />
<property name="messageListener" ref="messageListener" />
</bean>
WEB.xml
<servlet>
<servlet-name>xxxdispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>xxxdispatcher</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
</listener>
<context-param>
<param-name>log4jConfigLocation</param-name>
<param-value>/WEB-INF/log4j.properties</param-value>
</context-param>
Controller
#Controller
public class XXXController {
#Autowired
private IXXXService xxxService;
#RequestMapping("/xxx")
public String xxxHandler() throws Exception {
return "xxxView";
}
Please remove ContextLoaderListener from your Web.xml I beleive this is the reason why your context is created twice.
I've got a problem with my View Mapping in the Spring Web MVC.
Dispatcher-servlet.xml:
...
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
<context:component-scan base-package="de.bigbohne.smartmeter.controller" />
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>
<property name="prefix" value="/WEB-INF/views/"/>
</bean>
...
My Controller:
#Controller
public class FrontPage {
#RequestMapping("/index.htm")
public ModelAndView Index(Model mdl){
ModelAndView mav = new ModelAndView("frontPage.jsp");
return mav;
}
}
I get an 404 Error saying that it's missing /SmartMeter/WEB-INF/views/index
In my oppinion it must be: /SmartMeter/WEB-INF/views/frontPage.jsp
What am I missing? (I'm using Jetty 7.2 and Spring 3.0.5)
Edit 1:
web.xml:
<servlet>
<servlet-name>FrontController</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>FrontController</servlet-name>
<url-pattern>*.htm</url-pattern>
</servlet-mapping>
Try to change
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
to
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" >
You need to specify a suffix to the view resolver:
<property name="suffix" value=".jsp" />