#ResponseBody is not returning String message to error, throwing 404 WhiteLabel error page - spring

I am following a tutorial on Spring MVC and my project is not working as expected. I am using #ResponseBody to return a string message but it is throwing a whitelabel error page. I have scoured the Internet for last 2 days but still clueless about what could I possibly do wrong. Can anybody throw some light upon this?
Spring Framework boot : 2.5.4, Java version : 11
Code snippet for LoginController :
package com.in28minutes.springboot.web.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
public class LoginController {
#RequestMapping(value="/login", method=RequestMethod.GET, produces="text/plain")
#ResponseBody
public String loginMessage() {
return "Hello World";
}
}
2021-09-10 15:33:54.158 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/login", parameters={}
2021-09-10 15:33:54.158 DEBUG 8556 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/], Classpath [resources/], Classpath [static/], Classpath [public/], ServletContext [/]]
2021-09-10 15:33:54.160 DEBUG 8556 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
2021-09-10 15:33:54.160 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
2021-09-10 15:33:54.160 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
2021-09-10 15:33:54.161 DEBUG 8556 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2021-09-10 15:33:54.177 DEBUG 8556 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2021-09-10 15:33:54.178 DEBUG 8556 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
#SpringBootApplication
public class SpringBootFirstWebApplication {
public static void main(String[] args) {
SpringApplication.run(SpringBootFirstWebApplication.class,
args);
}
}

I will guess that your SpringBootFirstWebApplication is not placed in the parent package of all other packages in your application and therefore #Controller annotation in LoginController is not scanned.
If that is the case, change SpringBootFirstWebApplication to the parent package of all other packages in your application.

It seems like your requested URL in #RequestMapping is wrong. Your expected URL is value="/home", but your actual is value="/login"

Related

Error while configuring View Resolver for mustache template engine

I have the following configuration file in spring-boot project :
#Configuration
public class AppConfig {
#Bean
public ViewResolver mustacheViewResolver() {
MustacheViewResolver viewResolver = new MustacheViewResolver();
viewResolver.setPrefix("/templates/");
viewResolver.setSuffix(".mustache");
viewResolver.setOrder(1);
return viewResolver;
}
}
When I run my application, I am getting the following error:
Description:
The bean 'mustacheViewResolver', defined in class path resource [org/springframework/boot/autoconfigure/mustache/MustacheServletWebConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource [com/example/demo/AppConfig.class] and overriding is disabled.
Action:
Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
I am not sure if I am configuring the view Resolver properly
Error after removing the configuration class:
o.s.w.s.v.ContentNegotiatingViewResolver : Selected '*/*' given [*/*]
o.s.w.servlet.view.InternalResourceView : View name 'tweets.mustache', model {tweets=null}
o.s.w.servlet.view.InternalResourceView : Forwarding to [tweets.mustache]
o.s.web.servlet.DispatcherServlet : "FORWARD" dispatch for GET "/tweets.mustache?email=tim#gmail.com", parameters={masked}
o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]]
o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
o.s.web.servlet.DispatcherServlet : Exiting from "FORWARD" dispatch, status 404
o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error?email=tim#gmail.com", parameters={masked}
s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
o.s.w.s.m.m.a.HttpEntityMethodProcessor : Using 'application/json', given [*/*] and supported [application/json, application/*+json, application/json, application/*+json]
o.s.w.s.m.m.a.HttpEntityMethodProcessor : Writing [{timestamp=, status=404, error=Not Found, path=/tweet2}]
o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
#GetMapping("/tweet2")
public ModelAndView getTweetsByEmail(#RequestParam String email) {
HQLExample.insertRecords();
ModelAndView modelAndView = new ModelAndView("tweets.mustache");
List<Tweet> tweets = tweetMap.get(email);
modelAndView.getModel().put("tweets",tweets);
return modelAndView;
}
Assuming you have added spring-boot-starter-mustache as a dependency (to easily include all needed dependencies). When Spring Boot detects Mustache on the classpath it will automatically configure the MustacheViewResolver which will load Mustache templates from /templates on the classpath. The files should end with .mustache.
With this in mind, just remove your AppConfig class as it interferes with the auto configuration.
In your controller the name of the view is the name you have but without the .mustache that will be added by the ViewResolver.
So in short you should remove things and it will work. Do more with less in this case.

Gradle Spring Boot Application in IntelliJ is not recognizing web resources in WEB-INF folder

This is a new issue that derived from a previous question I had. I am writing a Spring Boot Application which is using a .jsp as the mvc view. My folder structure is:
My application.properties is as follows:
spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
spring.mvc.view.prefix= /WEB-INF/view/
spring.mvc.view.suffix= .jsp
Finally, my HomeController.java is as follows:
#Controller
#Slf4j
public class HomeController {
#RequestMapping(value="/", method= RequestMethod.GET)
public String showPage()
{
return "main-menu";
}
}
The program should render the main-menu.jsp file on my home page at localhost:8080, but instead I get an error. Here is the stack trace for the error:
2021-06-28 20:40:12.243 DEBUG 27388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/", parameters={}
2021-06-28 20:40:12.245 DEBUG 27388 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to com.example.springdemo.mvc.HomeController#showPage()
2021-06-28 20:40:12.257 DEBUG 27388 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/avif, image/webp, image/apng, application/xml;q=0.9, application/signed-exchange;v=b3;q=0.9, */*;q=0.8]
2021-06-28 20:40:12.257 DEBUG 27388 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView : View name 'main-menu', model {}
2021-06-28 20:40:12.258 DEBUG 27388 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView : Forwarding to [/WEB-INF/view/main-menu.jsp]
2021-06-28 20:40:12.261 DEBUG 27388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "FORWARD" dispatch for GET "/WEB-INF/view/main-menu.jsp", parameters={}
2021-06-28 20:40:12.263 DEBUG 27388 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to ResourceHttpRequestHandler [Classpath [META-INF/resources/], Classpath [resources/], Classpath [static/], Classpath [public/], ServletContext [/]]
2021-06-28 20:40:12.263 WARN 27388 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Path with "WEB-INF" or "META-INF": [WEB-INF/view/main-menu.jsp]
2021-06-28 20:40:12.263 DEBUG 27388 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
2021-06-28 20:40:12.263 DEBUG 27388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "FORWARD" dispatch, status 404
2021-06-28 20:40:12.264 DEBUG 27388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND
2021-06-28 20:40:12.265 DEBUG 27388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}
2021-06-28 20:40:12.266 DEBUG 27388 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#errorHtml(HttpServletRequest, HttpServletResponse)
2021-06-28 20:40:12.278 DEBUG 27388 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2021-06-28 20:40:12.281 DEBUG 27388 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404
As far as I can tell, it seems to be an issue with either the way IntelliJ is setup or the way Gradle is setup. Either way, the Resource directory or file is not being recognized.
Here's some of the things I've done/tried:
In Project Structure, I added the folder WEB-INF as a web resource directory in modules.
In Settings >>> Compiler, I added !?.jsp to the Resource Patterns
Finally, in gradle.build, I added sourceSets (this caused an error and I removed it).
Thank you for any help I can get.
Edit:
I've updated my project structure as follows.
I also added apply plugin: 'war' to my gradle.build and added the folder to my project facets.
I am still getting the same issue with resource not found.
I was able to figure it out with the help of a coworker. I had to make a few changes to my SpringMvcDemoApplication.java file and to my gradle.build. Here are the changes.
SpringMvcDemoApplication (added bean for InternalResourceViewResolver):
#SpringBootApplication(exclude=DataSourceAutoConfiguration.class)
public class SpringMvcDemoApplication extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SpringMvcDemoApplication.class);
}
#Bean
public ViewResolver internalResourceViewResolver() {
InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/view/");
bean.setSuffix(".jsp");
return bean;
}
public static void main(String[] args) {
SpringApplication.run(SpringMvcDemoApplication.class, args);
}
}
HomeController.java (Removed #Slf4j)
#Controller
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String showPage()
{
return "main-menu";
}
}
gradle.build (added tomcat and jstl dependencies):
plugins {
id 'org.springframework.boot' version '2.5.1'
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
id 'java'
}
group = 'com.example.springdemo'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
mavenCentral()
}
apply plugin: 'war'
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.projectlombok:lombok:1.18.18'
implementation group: 'javax.servlet', name: 'jstl', version: '1.2' //addee
implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-jasper'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
test {
useJUnitPlatform()
}
Everything works fine now.
Following through from last question
https://stackoverflow.com/a/68158449/14967681
please try changing your project structure as mentioned by bringing out WEB-INF out from resources into new folder as webapp. I am not sure of the reason why it fails to detect folder inside resources for that configuration mentioned but this should work for you.
Here is the project structure you should use: https://i.stack.imgur.com/IZXx1.png

Use thymeleaf template of another project

There seems to be problem if using thymeleaf for multiple projects.
Let's say I have a spring application in project 2 & the controller in project 1. With proper #ComponentScan defined, the application able to display the view/html in my template folder. But once I added the thymeleaf-layout-dialect maven dependency, it failed with "There was an unexpected error (type=Not Found, status=404)." error.
My projects:
The prj1 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>macrohard.org</groupId>
<artifactId>prj1</artifactId>
<version>0.0.1-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>nz.net.ultraq.thymeleaf</groupId>
<artifactId>thymeleaf-layout-dialect</artifactId>
</dependency>
</dependencies>
</project>
The prj2 pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>macrohard.org</groupId>
<artifactId>prj2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>macrohard.org</groupId>
<artifactId>prj1</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
The hello-world.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>HW</title>
</head>
<body>
Hello World!!
</body>
</html>
The App2 in prj2:
package prj2;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;
#SpringBootApplication
#ComponentScan(basePackages = { "prj1"} )
public class App2 {
public static void main(String[] args) {
SpringApplication.run(App2.class, args);
}
}
The Controller1 in prj1
package prj1.web;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
#RestController
#RequestMapping(value="/api")
public class Controller1 {
// this can be run by App2 & App1
#GetMapping(value="/hello")
public String hello() {
return "hello world";
}
// this can be run by App1 only
#GetMapping(value="/hello2")
public ModelAndView hello2() {
ModelAndView mav = new ModelAndView();
mav.setViewName("hello-world");
return mav;
}
}
As in Controller1, The "api/hello" can be requested successfully because it doesn't involve the template. But for the "api/hello2" request, it unable to render the hello-world.html. Here are the error stacks:
2019-07-02 22:21:28.758 INFO 19680 --- [ main] prj2.App2 : Started App2 in 1.89 seconds (JVM running for 2.454)
2019-07-02 22:21:51.807 INFO 19680 --- [nio-8080-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2019-07-02 22:21:51.807 INFO 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2019-07-02 22:21:51.807 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Detected org.springframework.web.multipart.support.StandardServletMultipartResolver#2ded92
2019-07-02 22:21:51.810 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : No LocaleResolver 'localeResolver': using default [AcceptHeaderLocaleResolver]
2019-07-02 22:21:51.811 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : No ThemeResolver 'themeResolver': using default [FixedThemeResolver]
2019-07-02 22:21:51.814 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : No RequestToViewNameTranslator 'viewNameTranslator': using default [DefaultRequestToViewNameTranslator]
2019-07-02 22:21:51.817 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : No FlashMapManager 'flashMapManager': using default [SessionFlashMapManager]
2019-07-02 22:21:51.817 DEBUG 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2019-07-02 22:21:51.817 INFO 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 10 ms
2019-07-02 22:21:51.829 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : GET "/api/hello2", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2019-07-02 22:21:51.834 TRACE 19680 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.web.servlet.ModelAndView prj1.web.Controller1.hello2()
2019-07-02 22:21:51.843 TRACE 19680 --- [nio-8080-exec-1] .w.s.m.m.a.ServletInvocableHandlerMethod : Arguments: []
2019-07-02 22:21:51.851 DEBUG 19680 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, application/xhtml+xml, image/webp, image/apng, application/signed-exchange;v=b3, application/xml;q=0.9, */*;q=0.8]
2019-07-02 22:21:51.851 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.web.servlet.view.InternalResourceView: name 'hello-world'; URL [hello-world]]
2019-07-02 22:21:51.851 DEBUG 19680 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView : View name 'hello-world', model {}
2019-07-02 22:21:51.853 DEBUG 19680 --- [nio-8080-exec-1] o.s.w.servlet.view.InternalResourceView : Forwarding to [hello-world]
2019-07-02 22:21:51.857 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "FORWARD" dispatch for GET "/api/hello-world", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2019-07-02 22:21:51.860 TRACE 19680 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapped to HandlerExecutionChain with [ResourceHttpRequestHandler ["classpath:/META-INF/resources/", "classpath:/resources/", "classpath:/static/", "classpath:/public/", "/"]] and 3 interceptors
2019-07-02 22:21:51.862 DEBUG 19680 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : Resource not found
2019-07-02 22:21:51.862 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : No view rendering, null ModelAndView returned.
2019-07-02 22:21:51.862 DEBUG 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "FORWARD" dispatch, status 404, headers={}
2019-07-02 22:21:51.864 DEBUG 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Completed 404 NOT_FOUND, headers={}
2019-07-02 22:21:51.865 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : "ERROR" dispatch for GET "/error", parameters={}, headers={masked} in DispatcherServlet 'dispatcherServlet'
2019-07-02 22:21:51.865 TRACE 19680 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : 2 matching mappings: [{ /error, produces [text/html]}, { /error}]
2019-07-02 22:21:51.866 TRACE 19680 --- [nio-8080-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
2019-07-02 22:21:51.875 TRACE 19680 --- [nio-8080-exec-1] .w.s.m.m.a.ServletInvocableHandlerMethod : Arguments: [org.apache.catalina.core.ApplicationHttpRequest#6fdc83, org.apache.catalina.connector.ResponseFacade#119a78b]
2019-07-02 22:21:51.885 DEBUG 19680 --- [nio-8080-exec-1] o.s.w.s.v.ContentNegotiatingViewResolver : Selected 'text/html' given [text/html, text/html;q=0.8]
2019-07-02 22:21:51.886 TRACE 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Rendering view [org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$StaticView#216e30]
2019-07-02 22:21:51.908 DEBUG 19680 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Exiting from "ERROR" dispatch, status 404, headers={}
I am certain that it is due to thymeleaf-layout-dialect, because if I remove it from pom.xml everything work fine.
The problem is I need it to layout thymeleaf page. How to display the template in another different project from spring application?
As you have published an example project, I can't follow the issue :/
Are you sure you did not just confuse the "hello world" messages from the controller with the message from the template?
When I modify: \prj1\src\main\resources\templates\hello-world.html
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>HW</title>
</head>
<body>
Hello World!! (from Template in prj1)!
</body>
</html>
I had to add this into pom.xml of prj1 because of some weird classpath issue:
(the thymeleaf-layout-dialect lib you use seems to bring in an additional thymeleaf jar - did not investigate that)
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf</artifactId>
<version>3.0.11.RELEASE</version>
</dependency>
When I run prj2 app and call: http://localhost:8080/api/hello3 or http://localhost:8080/api/hello2
I get:
Hello World!! (from Template in prj1)!
Which is what we want?
When I call: http://localhost:8080/api/hello
I get an error because of some not found template ("hello world" is of course not a template file).
So I'm not sure why it does not work for you :/
I'm not sure how this works without that dependency. The controllers that work with templates can return the template name directly. And you are implementing rest controllers which suggest different defaults than required for working with templates (like the content types).
So a controller that would invoke a template looks like (this is my way of doing it, can't claim I know its the only one):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
#Controller
public class MyController {
#Autowired
public MyController() {
}
#RequestMapping("/hello-world")
public String hello(Model model) {
model.addAttribute("someKey", "someValue");
return "hello-world"; // this is the template name in src/main/resources
}
}
And this way it is also possible to have controllers / templates bundled in one jar and use them in a different spring boot application as dependencies. Since it is all classpath based (there is a property to configure this: spring.thymeleaf.prefix) this just worked for me.
I think the reason really is your rest controller - which might confuse things a bit.

UTF-8 decoding in Spring Boot GET request to static resource

I have this #Bean redirecting requests to my Spring Boot backend.
#Bean
WebMvcConfigurer configurer () {
return new WebMvcConfigurerAdapter() {
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/data/static/images/**")
.addResourceLocations("file:" + System.getProperty("user.dir") + "/static/img/");
}
};
}
It works perfectly for URLs such as:
http://localhost:4200/data/static/images/champion/tiles/Ahri_0.jpg
But not for URLs such as:
http://localhost:4200/data/static/images/champion/tiles/Tahm%20Kench_0.jpg
The image is correctly shown in my Angular2 front end if the champion name does not contain any of: space, ampersand or single quote characters.
I ran a trace level logging debug and made both types of requests -- one with and without a "bad" character. Currently, it seems as if the backend searches for the correct file. However, it turns out that it claims it can't find it. I quintuple checked the file in my insanity, I know it is there and that the path printed is correct.
Here is an example log message:
2018-11-18 05:07:14.496 TRACE 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler map [org.springframework.web.servlet.handler.SimpleUrlHandlerMapping#4d0bdef0] in DispatcherServlet with name 'dispatcherServlet'
2018-11-18 05:07:14.497 DEBUG 9897 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/data/static/images/champion/tiles/Tahm Kench_0.jpg] are [/data/static/images/**, /**]
2018-11-18 05:07:14.497 DEBUG 9897 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/data/static/images/champion/tiles/Tahm Kench_0.jpg] are {}
2018-11-18 05:07:14.497 DEBUG 9897 --- [nio-8080-exec-1] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/data/static/images/champion/tiles/Tahm Kench_0.jpg] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[URL [file:/home/nuradin/Development/Java/riot-api-interface/static/img/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#5b5b59]]] and 1 interceptor
2018-11-18 05:07:14.497 TRACE 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#132f4851]
2018-11-18 05:07:14.497 TRACE 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#5b8d72dc]
2018-11-18 05:07:14.498 DEBUG 9897 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/data/static/images/champion/tiles/Tahm%20Kench_0.jpg] is: -1
2018-11-18 05:07:14.498 DEBUG 9897 --- [on(7)-127.0.0.1] sun.rmi.transport.tcp : RMI TCP Connection(7)-127.0.0.1: (port 34127) op = 82
2018-11-18 05:07:14.498 TRACE 9897 --- [nio-8080-exec-1] o.s.w.s.resource.PathResourceResolver : Resolving resource for request path "champion/tiles/Tahm Kench_0.jpg"
2018-11-18 05:07:14.498 TRACE 9897 --- [nio-8080-exec-1] o.s.w.s.resource.PathResourceResolver : Checking location: URL [file:/home/nuradin/Development/Java/riot-api-interface/static/img/]
EDIT: I've implemented the class in the accepted answer, and it's definitely working because I printed the resource name (after encoding the characters I had trouble with.) However, the result is still a 404 error.
Log is below. The champion/Aatrox2Epng bit is due to a println statement in the method #slimane posted below.
2018-11-18 05:56:40.509 TRACE 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#465ac973]
2018-11-18 05:56:40.509 TRACE 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Testing handler adapter [org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter#37df7ae5]
2018-11-18 05:56:40.509 DEBUG 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/data/static/images/champion/Aatrox.png] is: -1
2018-11-18 05:56:40.509 TRACE 12951 --- [nio-8080-exec-1] o.s.w.s.r.CachingResourceResolver : Resolving resource for request path "champion/Aatrox.png"
2018-11-18 05:56:40.510 TRACE 12951 --- [nio-8080-exec-1] o.e.r.c.EncodedPathResourceResolver : Resolving resource for request path "champion/Aatrox.png"
2018-11-18 05:56:40.510 TRACE 12951 --- [nio-8080-exec-1] o.e.r.c.EncodedPathResourceResolver : Checking location: URL [file:/home/nuradin/Development/Java/riot-api-interface/static/8.23.1/img]
champion/Aatrox2Epng
2018-11-18 05:56:40.511 TRACE 12951 --- [nio-8080-exec-1] o.e.r.c.EncodedPathResourceResolver : No match for location: URL [file:/home/nuradin/Development/Java/riot-api-interface/static/8.23.1/img]
2018-11-18 05:56:40.511 TRACE 12951 --- [nio-8080-exec-1] o.s.w.s.r.ResourceHttpRequestHandler : No matching resource found - returning 404
2018-11-18 05:56:40.511 DEBUG 12951 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Null ModelAndView returned to DispatcherServlet with name 'dispatcherServlet': assuming HandlerAdapter completed request handling
another EDIT -- sorry for the confusion, I changed the path because I thought paths with periods would work now.
#Bean
WebMvcConfigurer configurer () {
return new WebMvcConfigurerAdapter() {
#Override
public void addResourceHandlers (ResourceHandlerRegistry registry) {
registry.addResourceHandler("/data/static/images/**")
.addResourceLocations("file:" + System.getProperty("user.dir") + "/static/8.23.1/img")
.resourceChain(true)
.addResolver(encodedPathResourceResolver());
}
};
}
define your own PathResourceResolver as below:
import org.springframework.core.io.Resource;
import org.springframework.web.servlet.resource.PathResourceResolver;
import org.springframework.web.servlet.resource.ResourceResolver;
import java.io.IOException;
public class CustomPathResourceResolver extends PathResourceResolver implements ResourceResolver {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
//fixes problems with whitespaces in url
resourcePath = resourcePath.replace(" ","%20");
return super.getResource(resourcePath, location);
}
}
and then register it in your configuration:
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/data/static/images/**")
.addResourceLocations("file:" + System.getProperty("user.dir") + "/static/img/")
.resourceChain(true)
.addResolver(new CustomPathResourceResolver())
;
}
This fixed the Problem for me. Somehow the path was encoded 2 times.
This removes all URI encoding not just whitespaces.
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry
.addResourceHandler("/resources/**")
.addResourceLocations("file:/Q:/Technik/")
.resourceChain(true)
.addResolver(new CustomPathResourceResolver());
}
public class CustomPathResourceResolver extends PathResourceResolver implements ResourceResolver {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
//fixes problems with special chars in url
log.debug(resourcePath);
resourcePath = UriUtils.decode(resourcePath, "UTF-8");
log.debug(resourcePath);
resourcePath = UriUtils.decode(resourcePath, "UTF-8");
log.debug(resourcePath);
return super.getResource(resourcePath, location);
}
}

Define ParameterizableViewController to auto redirect path url with view

I'm using spring boot 1.2.1 and I would like to configure a ParameterizableViewController like I was doing in xml style :
for example before I was doing :
<mvc:view-controller path="/ie7"/>
That code redirects an url like http://mywebsite.com/mycontext/ie7 to a jsp placed in /WEB-INF/views/ie7.jsp without creating a controller directly.
I would like to do the same thing with spring boot. After checking on the net I had this in my config file :
#Bean(name = "ie7Controller")
public ParameterizableViewController getIe7ControllerView() {
ParameterizableViewController viewController = new ParameterizableViewController();
viewController.setViewName("ie7");
return viewController;
}
In my application.properties I configure the view like this :
spring.view.prefix=/WEB-INF/views/
spring.view.suffix=.jsp
I try to add also :
#Bean
public InternalResourceViewResolver getViewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/views/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
But when I try http://mywebsite.com/mycontext/ie7 I got a 404.
Here is the logs I got :
During app launch :
Rejected bean name 'ie7Controller': no URL paths identified
When I try to call the page :
2015-02-11 09:01:42.693 DEBUG 1160 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : DispatcherServlet with name 'dispatcherServlet' processing GET request for [/stdapps/ie7]
2015-02-11 09:01:42.699 DEBUG 1160 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Looking up handler method for path /ie7
2015-02-11 09:01:42.704 DEBUG 1160 --- [nio-8080-exec-2] s.w.s.m.m.a.RequestMappingHandlerMapping : Did not find handler method for [/ie7]
2015-02-11 09:01:42.706 DEBUG 1160 --- [nio-8080-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping : Matching patterns for request [/ie7] are [/**]
2015-02-11 09:01:42.708 DEBUG 1160 --- [nio-8080-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping : URI Template variables for request [/ie7] are {}
2015-02-11 09:01:42.712 DEBUG 1160 --- [nio-8080-exec-2] o.s.w.s.handler.SimpleUrlHandlerMapping : Mapping [/ie7] to HandlerExecutionChain with handler [ResourceHttpRequestHandler [locations=[ServletContext resource [/], class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/]], resolvers=[org.springframework.web.servlet.resource.PathResourceResolver#39689892]]] and 1 interceptor
2015-02-11 09:01:42.714 DEBUG 1160 --- [nio-8080-exec-2] o.s.web.servlet.DispatcherServlet : Last-Modified value for [/stdapps/ie7] is: -1
do I miss something ? I feel like I need to specify and url somewhere, I try to add #RequestMapping(value="ie7") with #Bean(name = "ie7Controller") with no luck
thanks for your help
If I understand your requirement correctly then the following code should do the trick:
#Configuration
#ComponentScan
#EnableAutoConfiguration
#EnableWebMvc
public class Application extends WebMvcConfigurerAdapter {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/ie7").setViewName("ie7");
};
}

Resources