I am learning Spring MVC and I try to get some experience. I wrote an app and deployed it to Tomcat serve. At run time, the browser gets a 404 code for the CSS and Tomcat "WARNING [http-nio-8080-exec-12] org.springframework.web.servlet.DispatcherServlet.noHandlerFound No mapping for GET /SpringC5BuildingSpringWebApplication/resources/style.css"
Can you please give me some hints of what could be wrong?
Below is my code:
App initializer
public class SpittrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer{
#Override
protected String[] getServletMappings() {
return new String[] {"/"};
}
#Override
protected Class<?>[] getRootConfigClasses() {
return new Class<?>[] {RootConfig.class};
}
#Override
protected Class<?>[] getServletConfigClasses() {
return new Class<?>[] {WebConfig.class};
}
}
WebConfig
#Configuration
#EnableWebMvc
#ComponentScan(basePackageClasses = HomeController.class)
class WebConfig extends WebMvcConfigurationSupport{
#Bean
public ViewResolver viewResolver(){
InternalResourceViewResolver resolver =
new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
#Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**")
.addResourceLocations("/resources/");
}
}
Controller
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home(){
return "home";
}
}
Webpage
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# page session="false" %>
<html>
<head>
<title>Spitter</title>
<link rel="stylesheet"
href="<c:url value="/resources/style.css" />" >
</head>
<body>
<h1>Welcome to Spitter</h1>
Spittles |
Register
</body>
</html>
WebXML
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd"
version="3.0">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
</web-app>
Folder structure
The CSS file is inserted in many places with the home that the server will read it from somewhere. Any hint could be helpful and appreciated! Thank you and I wish you good health!
The problem was in the WebConfig.class.
I need to change the inherited entity. From class WebConfig extends WebMvcConfigurationSupport to public class WebConfig implements WebMvcConfigurer.
Related
I am working on a springboot project that consumes a weather api and shows the data on the browser using react, Anyway, It seems that I am missing some configurations or I might need to move files around in my project, The error in the browser shows that the js/css files are not reachable :
GET http://localhost:8080/demo/resources/css/neo.css
browser.min.js:4 GET http://localhost:8080/demo/resources/js/WeatherManager.js 404 ()
browser.min.js:4 Uncaught Error: Could not load http://localhost:8080/demo/resources/js/WeatherManager.js
at XMLHttpRequest.xhr.onreadystatechange (browser.min.js:4)
* WebConfig *
#Configuration
#ComponentScan
#EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ViewResolver getViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
return resolver;
}
/**
* We need to define 3 things to implement
* 1- Define message resource
* 2- Define Local resolver internationalization
* 3- Override interceptor
*/
#Bean
public MessageSource messageSource(){
ResourceBundleMessageSource messageSource=new ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
#Bean
public LocaleResolver localeResolver(){
SessionLocaleResolver resolver =new SessionLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
//you can add more resources here
registry.addResourceHandler("/css/**").addResourceLocations("/resources/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/resources/js/");
}
#Override
public void addInterceptors(InterceptorRegistry registry)
{
LocaleChangeInterceptor changeInterceptor=new LocaleChangeInterceptor();
changeInterceptor.setParamName("language");
registry.addInterceptor(changeInterceptor);
}
}
* WebAppInitializer *
public class WebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("*.html");
dispatcher.addMapping("*.pdf");
//Enable JSON response
dispatcher.addMapping("*.json");
dispatcher.addMapping("*.jsx");
}
private WebApplicationContext getContext() {
AnnotationConfigWebApplicationContext context =new AnnotationConfigWebApplicationContext();
context.register(WebConfig.class);
return context;
}
* DemoApplication *
#SpringBootApplication
#EnableAutoConfiguration
#EnableAsync
public class DemoApplication extends AsyncConfigurerSupport {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
#Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(2);
executor.setMaxPoolSize(2);
executor.setQueueCapacity(500);
executor.setThreadNamePrefix("WeatherService-");
executor.initialize();
return executor;
}
}
JS/CSS files live under /resources/css/ /resources/js/
JSP pages live under WEB-INF/jsp
** weather.jsp page **
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html >
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link rel="stylesheet" type="text/css" href="resources/css/neo.css">
<title>Weather </title>
</head>
<body>
<div id="main" class="container">
</div>
<script type="text/babel" src="resources/js/WeatherManager.js"></script>
</body>
</html>
I have the source code at
github : [https://github.com/saifmasadeh/WeatherBoard][1]
You should add this to your question:
<script type="text/babel" src="resources/js/WeatherManager.js"></script>
<link rel="stylesheet" type="text/css" href="resources/css/neo.css">
This is where the problem is. You're importing via the wrong URL.
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry){
//you can add more resources here
registry.addResourceHandler("/css/**").addResourceLocations("/resources/css/");
registry.addResourceHandler("/js/**").addResourceLocations("/resources/js/");
}
The above method says when a user tries to access a url with the path /js/** look in /resources/js/.
Basically, if the user were to request localhost/context-root/js/script.js
Spring would view this as localhost/context-root/resources/js/script.js
(That is not literally the case, but it explains the idea well enough.)
So when you try to import your script file resources/js/WeatherManager.js the resource handler doesn't know where to look. It doesn't know about anything with the path resources/**
What you want to do is import this way:
<script type="text/babel" src="/js/WeatherManager.js"></script>
This maps to the resource handler's "/js/** and looks up WeatherManager.js in /resources/js/. You need to do the same thing with your CSS file.
For another example of how this works, view my answer here.
(Also, you may need to use classpath:/resources/(js|css) as your resource location if this doesn't work.)
Hi i have simple Spring app:
WebConfig.java:
package spittr.web;
#Configuration
#EnableWebMvc
#ComponentScan("spittr.web")
public class WebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
}
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
#Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
registerForm.jsp:
<%# taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%# taglib uri="http://www.springframework.org/tags/form" prefix="sf" %>
<%# page session="false" contentType="text/html; charset=UTF-8" %>
<html>
<head>
<title>Spittr</title>
<link rel="stylesheet" type="text/css"
href="<c:url value="/resources/style.css" />" >
</head>
<body>
<h1>registration</h1>
<sf:form method="POST" commandName="spitter" >
<sf:errors path="*" element="div" cssClass="errors" />
<sf:label path="firstName"
cssErrorClass="error">name</sf:label>:
<sf:input path="firstName" cssErrorClass="error" /><br/>
....
<input type="submit" value="register" />
</sf:form>
</body>
</html>
and when i GET above register form with:
#RequestMapping(value="/register", method=GET)
public String showRegistrationForm(Model model) {
model.addAttribute("spitter", new Spitter());
return "registerForm";
}
the CSS file is not loading and I get JSP page but without CSS style and with error in Tomcat console:
127.0.0.1 - - [22/Nov/2016:18:04:48 +0100] "GET /Spittr-0.0.1-SNAPSHOT/resources/style.css HTTP/1.1" 405 1045
Where is the problem? The CSS file is in the path /Spittr-0.0.1-SNAPSHOT/resources/style.css and i specified default resource handler, so why JSP page cannot get this static file.
Thanks for any advices:)
ok i got this:
1- overriding resourceHandlerMapping() from WebMvcConfigurationSupport
#Override
#Bean
public HandlerMapping resourceHandlerMapping() {
AbstractHandlerMapping handlerMapping = (AbstractHandlerMapping) super.resourceHandlerMapping();
handlerMapping.setOrder(-1);
return handlerMapping;
}
2 - overriding addResourceHandlers() from WebMvcConfigurationSupport / WebMvcConfigurerAdapter :
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
i collided with some problems when i was writing web app.
When i use URL like this http://localhost:8080/user i have no problems and my app work correctly, but when i use URL such as http://localhost:8080/some-intermediate-node/user i have pages without any style and java-script code.
Belong i show my dispatcher servlet config
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = "com.excbooks.controller")
public class ServletConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/css/**").addResourceLocations("/css");
registry.addResourceHandler("/js/**").addResourceLocations("/js");
}
#Bean
public InternalResourceViewResolver setupViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix("");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
and my controller
#Controller
public class MainController {
{
BasicConfigurator.configure();
}
#RequestMapping(value = "/d/login", method = RequestMethod.GET)
public String login(Model model){
return "log-in.html";
}
#RequestMapping(value = "/d/user", method = RequestMethod.GET)
public String userProfile(Model model){
User user = new User();
user.setId(new BigInteger("1"));
user.setUsername("Sashko");
model.addAttribute("user",user);
return "index.jsp";
}
}
Link to my JSP index https://drive.google.com/file/d/0B42ezhAKqwZlcUEyVkR5amNIaDg/view?usp=sharing
Within your JSP, I suspect the javacsript/css files are pulled in roughly like...
<link rel="stylesheet" href="css/my.css">
<script src="js/my.js"></script>
The issue is that the href and src attributes specify relative URLs. They correctly point to your files when the URL is http://localhost:8080/user, but when the URL is http://localhost:8080/some-intermediate-node/user the browser will look for...
http://localhost:8080/some-intermediate-node/css/my.css
http://localhost:8080/some-intermediate-node/js/my.js
respectively.
Change the href and src attributes so that they start with a forward slash (/) character.
Change CSS and javascript href to /css/** and /js/**
For example :
<link rel="stylesheet" href="/css/bootstrap.min.css">
<script src="/js/jquery-1.12.3.min.js"></script>
I'm trying to serve an static resource (css file).
I already register the location and handler
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");
}
}
so the Tomcat's Logger displays the correct mapping to resource
Mapped URL path [/resources/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
When the browser renders the view, the inspector displays a 404 error trying to get the static resource.
AppInitializer.java
#Configuration
#ComponentScan("com.learning")
#EnableWebMvc
public class ApplicationInitializer extends WebMvcConfigurerAdapter implements WebApplicationInitializer {
private final Logger LOGGER = Logger.getLogger(ApplicationInitializer.class.getName());
public static final String DISPATCHER_SERVLET_NAME = "dispatcher";
#Autowired
private ApplicationContext applicationContext;
public ApplicationInitializer() {
}
//region Context Initialization Area
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext springContext = getSpringApplicationContext();
MyDispatcherServlet dispatcherServlet = new MyDispatcherServlet(springContext);
servletContext.addListener(new ContextLoaderListener(springContext));
servletContext.setSessionTrackingModes(EnumSet.of(SessionTrackingMode.COOKIE));
servletContext.getSessionCookieConfig().setHttpOnly(true);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet(DISPATCHER_SERVLET_NAME, dispatcherServlet);
dispatcher.addMapping("/");
dispatcher.setLoadOnStartup(1);
}
private WebApplicationContext getSpringApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
LOGGER.info(String.format("Registering springApplicationContext: %s", context));
// Loads into container first
context.register(ApplicationInitializer.class);
LOGGER.info(String.format("Registration success of springApplicationContext: %s", context));
return context;
}
//endregion
//region ViewResolver Region
#Bean
public ViewResolver viewResolver() {
//Runs after coontroller ends its execution. It receives the view name to be processed.
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(templateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
#Bean
public TemplateEngine templateEngine() {
// Processes the template
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setEnableSpringELCompiler(true);
engine.setTemplateResolver(templateResolver());
return engine;
}
private ITemplateResolver templateResolver() {
//Resolves templates with provided prefix and suffix
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
//endregion
//region ResourceHandler Region
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");
}
//endregion
}
Hello.html
h1 {
color: red;
text-align: center;
}
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="/resources/css/MyCss.css" th:href="#{/resources/css/MyCss.css}"/>
</head>
<body>
<h1 th:text="'Hello ' + ${name}">Hello World</h1>
</body>
</html>
It supposed to displays as the running snippet... but as I mentioned, the app is not able to find and load the resource.
Log File
Any help?
http://localhost:8080/resources/css/MyCss.css
you are missing the webapp name:
http://localhost:8080/webapp_name/resources/css/MyCss.css
Within your: link rel="stylesheet" ...
Use the Spring URL tag, in order to resolve your URL better.
Here is how i use to import bootstrap.min.css:
<link rel="stylesheet" href='<spring:url value="/resources/bootstrap/bootstrap.min.css"/>' type="text/css" />
Don't forget to add the taglib, like this:
<%# taglib prefix="spring" uri="http://www.springframework.org/tags" %>
this is my project structure:
these are all classes of my sample to use spring i18n internationalization, but spring only use en_US for application localization:
SpringWebInitializer
public class SpringWebInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
rootContext.register(SpringWebConfig.class);
rootContext.setServletContext(servletContext);
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", new DispatcherServlet(rootContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
servletContext.addListener(new RequestContextListener());
servletContext.addListener(new ContextLoaderListener(rootContext));
}
}
SpringWebConfig
#EnableWebMvc
#Configuration
#ComponentScan("com.rgh.web")
public class SpringWebConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/view/");
viewResolver.setSuffix(".jsp");
viewResolver.setViewClass(JstlView.class);
return viewResolver;
}
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver();
localeResolver.setDefaultLocale(new Locale("fa"));
localeResolver.setCookieName("lang");
return localeResolver;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
return localeChangeInterceptor;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
index.jsp
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%# taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<%# page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>Welcome</title>
</head>
<body>
<spring:message code="app.name" />
${pageContext.response.locale}
</body>
</html>
messages_fa.properties
app.name=MyAppFarsi
messages.properties
app.name=MyApp