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>
Related
I am learning spring boot. I created this super simple project, but I keep getting a 404 Whitelabel error page when I try to return an HTML page with the #GetMapping annotation.
Here is my only controller:
package com.example.springplay;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
#Controller
public class MainController {
#GetMapping(value = "/")
public String hello(){
return "hello";
}
}
Here is the spring application:
package com.example.springplay;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class SpringplayApplication {
public static void main(String[] args) {
SpringApplication.run(SpringplayApplication.class, args);
}
}
Here is the directory
Here is the hello.html page:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>hello world</h1>
</body>
</html>
The hello.html page is in the resources/templates folder, I don't know what's going on.
I copied this part which has the exact same structure from another working project, yet mine just gives me this Whitelabel error page.
Move hello.html to static folder in resource and change controller like this:
#GetMapping(value = "/")
public String hello(){
return "hello.html";
}
or like this:
#GetMapping(value = "/")
public ModelAndView hello(){
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("hello.html");
return modelAndView;
}
Remplace here
#GetMapping(value = "/")
public String hello(){
return "hello";
}
or like this
#RequestMapping(path = "/", produces = MediaType.TEXT_HTML_VALUE)
public String welcomepage() {
return "hello";
}
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.
the result when examining messages.gettmessage() is null using the model.addAttribute to get the message to display it on thymeleaf page.
I have a registrationConfirm Controller to allow users to confirm their emails
Here is my Registration Controller:
#RequestMapping(value = "/registrationConfirm", method = RequestMethod.GET)
public String confirmRegistration(final HttpServletRequest request, final
Model model, #RequestParam("token") final String token) throws
UnsupportedEncodingException {
Locale locale = request.getLocale();
final String result = userService.validateConfirmationToken(token);
if (result.equals("valid")) {
final User user = userService.getUser(token);
authWithoutPassword(user);
model.addAttribute("message",
messages.getMessage("message.accountVerified", null, locale));
return "redirect:/home.html?lang=" + locale.getLanguage();
}
model.addAttribute("message", messages.getMessage("auth.message." +
result, null, locale));
model.addAttribute("expired", "expired".equals(result));
model.addAttribute("token", token);
return "redirect:/wrong.html?lang=" + locale.getLanguage();
}
My MvcConfig Class:
#Configuration
public class MvcConfig extends WebMvcConfigurerAdapter{
#Autowired
private MessageSource messageSource;
#Override
public void addViewControllers(final ViewControllerRegistry registry) {
super.addViewControllers(registry);
registry.addViewController("/index");
registry.addViewController("/registration");
registry.addViewController("/wrong.html");
registry.addViewController("/home.html");
#Override
public void configureDefaultServletHandling(final
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
#Bean
public LocaleResolver localeResolver() {
final CookieLocaleResolver cookieLocaleResolver = new
CookieLocaleResolver();
cookieLocaleResolver.setDefaultLocale(Locale.ENGLISH);
return cookieLocaleResolver;
}
#Bean
public LocaleChangeInterceptor localeChangeInterceptor() {
LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
lci.setParamName("lang");
return lci;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(localeChangeInterceptor());
}
Note that when trying to confirm the email with an invalid token that will redirect to badUser.html which is:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title th:text="#{label.wrong.title}">wrong</title>
</head>
<body>
<div class="container">
<div class="alert alert-info" th:text="${param.message[0]}">error</div>
<br/>
</div>
</body>
</html>
I cannot get the param.message and get the error below in logs
Request processing failed; nested exception is
org.thymeleaf.exceptions.TemplateProcessingException: Exception evaluating
SpringEL expression: "param.message[0]" (wrong)
Root Cause: org.springframework.expression.spel.SpelEvaluationException:
EL1012E: Cannot index into a null value
Sorry for the long code, I was trying to fix this issue for long time. ANY HELP IS REALLY APPRECIATED!!!!
If your message variable is a view model, you shouldn't use the param. prefix for it in the html (Thymeleaf view). From thymeleaf documentation:
param : for retrieving request parameters. ${param.foo} is a String[] with the values of the foo request parameter, so ${param.foo[0]} will normally be used for getting the first value.
So, in the end just use message.
UPDATE
You should also avoid redirection, since your message variable will be lost as soon as you redirect. In addition to that, you should redirect to the controller itself.
Replace the line:
return "redirect:/home.html?lang=" + locale.getLanguage();
With:
if (request.getParameterMap().size() == 0)
return "redirect:/registrationConfirm?lang=" + locale.getLanguage();
// ...
return "home";
However, for efficiency move the if block in the above code to the first line of your registrationConfirm() method body.
I tested this with spring-boot 1.5.6 and Spring MVC 4.3
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.)
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" %>