Why jsp cannot reach its css file in SpringMVC? - spring

I have a SpringMVC project. Upon running the project in tomcat7 I get the following message:
No mapping found for HTTP request with URI [/myproject/resources/css/welcome.css] in DispatcherServlet with name 'DispatcherServlet'
CSS does not get applied:
I've tried available solutions but none of them worked and none of them actually explained what was going on.
I have a simple welcome.jsp in /WEB-INF/jsp. Here it is:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<link type="text/css"
href="${pageContext.request.contextPath}/resources/css/welcome.css"
rel="stylesheet">
<title>Welcome!</title>
</head>
<body>
<div id="font-HarabaraHand">
<p class="centrify">Poem Collection</p>
</div>
<div id="font-Goodfoot">
<p class="centrify2">What would you like to do?</p>
</div>
</body>
</html>
My welcome.css file lies in src/main/webapp/resources/css/.
My Spring configuration is java based, DispatcherServlet class is in AppInit.java file:
public class AppInit implements WebApplicationInitializer {
// this method is automatically invoked on application startup
public void onStartup(ServletContext container) throws ServletException {
WebApplicationContext webcntx = getWebCntx();
container.addListener(new ContextLoaderListener(webcntx));
ServletRegistration.Dynamic dispatcher = container.addServlet(
"DispatcherServlet", new DispatcherServlet(webcntx));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
private AnnotationConfigWebApplicationContext getWebCntx() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(WebAppConfiguration.class);
return context;
}
}
And finally in WebAppConfig.java file:
#Bean
public InternalResourceViewResolver getInternalResourceViewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/jsp/");
resolver.setSuffix(".jsp");
resolver.setViewClass(JstlView.class);
return resolver;
}
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
if (!registry.hasMappingForPattern("/resources/**")) {
registry.addResourceHandler("/resources/**").addResourceLocations(
"/resources/").setCachePeriod(CACHE_PERIOD);;
}
}
My welcome page controller:
#Controller
public class WelcomeController {
#RequestMapping(value="/")
public ModelAndView welcomePage() {
return new ModelAndView("welcome");
}
}
Here is my project structure:
1. Why my welcome.css file cannot be reached?
2. How I can correct my mappings configuration?
I would really appreciate an explanation or a link about Spring url mappings config.

By using Java Config:
Create the following subdirectory structure: src/main/webapp/public/css
Put your css files in src/main/webapp/public/css (e.g. src/main/webapp/public/css/welcome.css)
Define an handler for public resources:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
super.addResourceHandlers(registry);
if (!registry.hasMappingForPattern("/public/**")) {
registry.addResourceHandler("/public/**")
.addResourceLocations("/public/")
.setCachePeriod(CACHE_PERIOD); // You have to define a cache period.
}
}
Add a security exception:
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/public/**");
}
Link you css files (by defining a relative path):
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%# taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
...
<head>
<c:set var="url">${pageContext.request.requestURL}</c:set>
<base href="${fn:substring(url, 0, fn:length(url) - fn:length(pageContext.request.requestURI))}${pageContext.request.contextPath}/" />
<link rel="stylesheet" href="public/css/welcome.css" />
</head>

#vdenotaris answer is correct
My configuration didn't work because of my pom.xml file setup.
maven-war-plugin had <warSourceDirectory>WebContent</warSourceDirectory> and my /src/main/webapp/resources/css has never been detected by maven. Once I moved my jsp files to /src/main/webapp/ all was ok.
So, either you leave everything (css resources and other stuff) in WebContent\WEB-INF\ folder or move everything to /src/main/webapp

Related

Why internalization is not working with JHIpster Microservices application

I developed one spring boot microservice application using jhipster
tool and we have one quotation.html form it contains name and details
of the product I am trying to apply langauage translations to the name
and details labels based user language
for that i made changes in these classes
#Configuration
public class LocaleConfiguration implements WebMvcConfigurer {
#Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver slr = new SessionLocaleResolver();
slr.setDefaultLocale(Locale.US);
return slr;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
}
added language messages files at this location
i am sending user language key as request param like this
localhost:8080/api/pord/quotation?lang=de
based on this lang value it shoud read keys from respective messages file
Note: The issue is it is always reading language keys from
messages_en.properties file
sample quotation.html file
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<body>
<div class="page-content container-fluid">
<div class="title">
<h3>
<center>
<th:block>
<span th:text="#{invoice.quotation}"></span >
</th:block>
</center>
</h3
</div>
</body>
</html>
Have a look at src/main/resources/templates/error.html template it includes th:lang="${#locale.language}" while your template does not.
It's probably not the solution but it will help debugging by showing the value of lanaguage.

Thymeleaf cannot get Spring #ApplicationScope Bean

According to Spring document, #ApplicationScope Beans are visible as ServletContext attributes if Spring IOC container is web-aware.
I know i can access to #ApplicationScope Beans using ${#beanName} in thymeleaf template, but why can't I access to them using ${#servletContext.getAttribute('myAttribute')} as thymeleaf document show?
Below is my code snippet.
#SpringBootApplication
public class Application {
#Autowired
private BranchService branchService;
public static void main(String[] args) {
SpringApplication.run(RetailStoreApplication.class, args);
}
#ApplicationScope
#Bean(value = "branches")
public List<Branch> branches() {
return branchService.queryAllBranches();
}
}
#Controller
public class HomeController {
#GetMapping(value = { "/", "/home" })
public String home() {
return "home.html";
}
}
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Test</title>
</head>
<body>
Below are all the branch, please choose one for this branch.
<span th:if="${#servletContext.getAttribute('branches')} == null">NULL</span>
<ul th:each="branch : ${#servletContext.getAttribute('branches')}">
<li th:text="${branch.name}" />
</ul>
</body>
</html>
The returning 'branches' result is null. I'm using spring-boot2 with web-starter and thymeleaf-starter.
Have already try this, but not work in my case.
Any response is welcome, thanks!

spring boot thymeleaf does not work with LiteDeviceDelegatingViewResolver

I am working with spring boot 2.0.1.RELEASE, using spring-boot-starter-thymeleaf. And I have two version of pages for PC and Mobile phone.
Here is a simple version of my project structure
project structure
I would like to have the site automatically detect the PC browser and Mobile phone browser so that it can map the same requesting URL to different pages according to the type of the browsers
The html file is very simple as the following.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<p>This is from PC web browser</p>
</body>
</html>
Here is the code of my controller.
#Controller
public class MyController {
#RequestMapping("/")
public String mainDefault(){
return "home";
}
#RequestMapping("/home")
public String main(){
return "home";
}
}
To detect the device I wrote the following configuration class
#Configuration
public class Config implements WebMvcConfigurer {
#Autowired
private ApplicationContext applicationContext;
#Bean
public LiteDeviceDelegatingViewResolver liteDeviceDelegatingViewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
LiteDeviceDelegatingViewResolver resolver = new LiteDeviceDelegatingViewResolver(viewResolver);
resolver.setNormalPrefix("web/");
resolver.setMobilePrefix("mobile/");
resolver.setTabletPrefix("web/");
resolver.setOrder(1);
resolver.setEnableFallback(true);
return resolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addDialect(new LayoutDialect());
templateEngine.setTemplateResolver(templateResolver());
templateEngine.setEnableSpringELCompiler(true);
return templateEngine;
}
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(this.applicationContext);
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setPrefix("/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(".HTML5");
templateResolver.setCacheable(false);
return templateResolver;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
DeviceResolverHandlerInterceptor deviceResolverHandlerInterceptor = new DeviceResolverHandlerInterceptor();
SitePreferenceHandlerInterceptor sitePreferenceHandlerInterceptor = new SitePreferenceHandlerInterceptor();
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
localeChangeInterceptor.setParamName("lang");
registry.addInterceptor(localeChangeInterceptor);
registry.addInterceptor(deviceResolverHandlerInterceptor);
registry.addInterceptor(sitePreferenceHandlerInterceptor);
WebMvcConfigurer.super.addInterceptors(registry);
}
}
Then when I tried to run the Application. I always get the following error. It seems it can map to the right resource which is [/templates/web/home.html]. But it always say Could not open ServletContext resource [/templates/web/home.html]
If I visit from a mobile browser it map to [/templates/mobile/home.html] which is also correct.
Can any one help me? Thank you in advance.
2018-04-19 17:18:57.040 ERROR 17732 --- [nio-9020-exec-9] org.thymeleaf.TemplateEngine : [THYMELEAF][http-nio-9020-exec-9] Exception processing template "web/home": An error happened during template parsing (template: "ServletContext resource [/templates/web/home.html]")
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "ServletContext resource [/templates/web/home.html]")
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:235) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parseStandalone(AbstractMarkupTemplateParser.java:100) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.engine.TemplateManager.parseAndProcess(TemplateManager.java:666) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
.........
Caused by: java.io.FileNotFoundException: Could not open ServletContext resource [/templates/web/home.html]
at org.springframework.web.context.support.ServletContextResource.getInputStream(ServletContextResource.java:159) ~[spring-web-5.0.5.RELEASE.jar:5.0.5.RELEASE]
at org.thymeleaf.spring5.templateresource.SpringResourceTemplateResource.reader(SpringResourceTemplateResource.java:103) ~[thymeleaf-spring5-3.0.9.RELEASE.jar:3.0.9.RELEASE]
at org.thymeleaf.templateparser.markup.AbstractMarkupTemplateParser.parse(AbstractMarkupTemplateParser.java:223) ~[thymeleaf-3.0.9.RELEASE.jar:3.0.9.RELEASE]
... 52 common frames omitted
2018-04-19 17:18:57.047 DEBUG 17732 --- [nio-9020-exec-9] o.s.web.servlet.DispatcherServlet : Error rendering view [org.thymeleaf.spring5.view.ThymeleafView#139a953a] in DispatcherServlet with name 'dispatcherServlet'
org.thymeleaf.exceptions.TemplateInputException: An error happened during template parsing (template: "ServletContext resource [/templates/web/home.html]")
You are trying to configure something that is already being configured for you.
Make sure you have the spring-boot-starter-thymeleaf and that you have the spring-mobile-autoconfguration in your list of dependencies.
NOTE: I assume you are using the snapshot builds so that you are compatible with regards to Spring and Spring Boot version.
Remove your Config class
Add the following to your application.properties
spring.mobile.devicedelegatingviewresolver.normalPrefix=web/
spring.mobile.devicedelegatingviewresolver.tabletPrefix=web/
spring.thymeleaf
Restart your application

unable to load static file in spring 4

Hi I am trying to load the jquery file in jsp but getting 404
Find below the project structure
I have configured the following in configuration too
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "common.spring.controller" })
public class WebConfig {
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
//viewResolver.setViewClass(JstlView.class);
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("classpath:/resources/");
}
}
below is how i include file in jsp
<script type="text/javascript" src="/resources/jsFiles/jquery-3.3.1.min.js"></script>
Dono why its not working.
UPDATE: I am able to see the resources folder under target/project snapshot/resources but getting 404 for url
http://localhost:8080/resources/jsfiles/jquery-3.3.1.min.js
directly hitting below Url didnt work either
http://localhost:8080/Sample/resources/jsfiles/jquery-3.3.1.min.js
Finally was able to resolve the issue
removing addResourceHandlers method and including the below code did the trick
#Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configure) {
configure.enable();
}
in jsp i used the include like below
<script type="text/javascript" src="resources/jsFiles/jquery-3.3.1.min.js"></script>

Root Context path in spring application

I am running application using tomcat server, when server start i will get url
http://localhost:8080/TestApp/
and displaying index.jsp file but when i click link in index file it is displaying url like
http://localhost:8080/testsuccess
but it should display like
http://localhost:8080/TestApp/testsuccess
can any please help me to solve this.
SpringConfiguration.java
#Configuration
#EnableWebMvc
#ComponentScan("com.testapp")
#EnableTransactionManagement
public class SpringConfiguration {
#Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
}
SpringWebAppInitializer.java
public class SpringWebAppInitializer implements WebApplicationInitializer {
#Override
public void onStartup(ServletContext container) throws ServletException {
AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
appContext.register(SpringConfiguration.class);
ServletRegistration.Dynamic dispatcher = container.addServlet(
"SpringDispatcher", new DispatcherServlet(appContext));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
}
}
MyController.java
#Controller
public class MyFirstController
{
#RequestMapping(value = "/" , method = RequestMethod.GET)
public String testApp() throws Exception{
return "index";
}
#RequestMapping(value = "/testsuccess", method = RequestMethod.GET)
public String testAppSuccess() {
Map<String, Object> model = new HashMap<String, Object>();
return "success";
}
}
got it i should use
Next
it will give the context path.
I think your problem comes from the link inside your index.jsp. They might look like ... You should use either jstl or spring tag lib to handle links / urls in your pages. They both have the ability to prepend the deployment / context path of your application.
jstl example:
with taglib xmlns:c="http://java.sun.com/jsp/jstl/core" included you can create an anchor like ..
spring example:
with taglib xmlns:spring="http://www.springframework.org/tags" your link will be created in two steps:
<spring:url value="/testsuccess" var="myurl" htmlEscape="true"/>
...
Update: Wrong function name in jstl taglib version.

Resources