spring boot views not working without file extension? - java

I'm new to Spring Boot, I have files under webapp resource folder, login.xhtml, index.xhtml, register.xhtml they are working fine with http://localhost:8080/login.xhtml, http://localhost:8080/register.xhtml, http://localhost:8080/index.xhtml but they are not working without the file extension, http://localhost:8080/login, http://localhost:8080/index, http://localhost:8080/register gives error for /login.
Request URI: /login Ajax request: No Status code: 500 Exception type:
class org.thymeleaf.exceptions.TemplateInputException Message: Request
processing failed; nested exception is
org.thymeleaf.exceptions.TemplateInputException: Error resolving
template [login], template might not exist or might not be accessible
by any of the configured Template Resolvers
My application.properties is configured propertly:
spring.thymeleaf.prefix=classpath:/webapp/
spring.thymeleaf.suffix=.xhtml
Controller for login:
public class LoginController {
#GetMapping("/login")
public String login()
{
return "login";
}
}
I wan to access both with extension and without extension. localhost:8080/login and localhost:8080/login.xhtml should work.
you comments and solutions could solve my problem.

You can use many path links to a single controller action, e.g.
#RequestMapping(path = {"/login", "/login.xhtml"})
public String login() {
return "login";
}
Also, don't forget to add #Controller annotation to your class.

Related

Spring Boot 2.7.5 + Angular 15 as a single war

I'm working on a full-stack app having spring boot v2.7.5 as the backend and Angular v15 as the front end. I use IntelliJ IDEA IDE for development. Locally, spring boot runs on http://localhost:8080 and angular runs on http://localhost:4200. I use Gradle to build the project a single war file and which would be deployed on an external tomcat server.
Following is the project structure:
I have 3 build.gradle files, 1 for frontend , 1 for backend, and 1 for global. When I run the global build.gradle file, it would call call build.gradle from fronend folder which builds angular project and copies all the build files and put them into backend/src/main/resources/static folder. Next, build.gradle from the backend gets called which would build the final war file to be deployed on the external tomcat server.
The reason I'm putting frontend build files (index.html, some .js files) into backend/src/main/resources/static is the fact that Spring Boot Serves static content from that location. more details .
So the static directory looks like this after adding frontend build files:
When I try to access http://localhost:8080, it loads index.html from the static folder.
So far it is good. When I click the login button, internally it calls the backend API and moves to the next page (home page i.e., http://localhost:8080/fe/appInstances).
Now if I refresh the page, it gives me the following 404 Whitelabel Error Page.
I understand that since this is spring-boot as it is looking for a definition of the http://localhost:8080/fe/appInstances API endpoint in the java code.
To fix this, I have created the following IndexController.java class which should redirect all the frontend rest endpoints to index.html which is present in main/resources/static folder.
IndexController.java
#Controller
public class IndexController {
#GetMapping("/")
public String index() {
return "redirect:/index";
}
#GetMapping("/fe/*")
public String anyFrontEndApi() {
return "index";
}
}
But now, I get the following Whitelabel error page about Circular view path [index]: would dispatch back to the current handler URL [/fe/index] again.
I have tried changing #Controller to #RestController and changing the return type to ModelandView or something like this. But irrespective of all, it is still giving me the Whitelabel Error Page about Circular view path...
#RestController
public class IndexController {
#GetMapping("/")
public String index() {
return "redirect:/index";
}
#GetMapping("/fe/*")
public ModelAndView anyFrontEndApi() {
ModelAndView mv = new ModelAndView();
mv.setViewName("index");
return mv;
}
}
Am I missing something here? Can someone please suggest me a fix for this?
PS: #justthink addressed this situation here. But I don't know how to do reverse proxy way.
We had this situation of page refresh for Angular and Springboot and we resolved this by adding the below Configuration class extending WebMvcConfigurerAdapter
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/**/*")
.addResourceLocations("classpath:/static/")
.resourceChain(true)
.addResolver(new PathResourceResolver() {
#Override
protected Resource getResource(String resourcePath, Resource location) throws IOException {
Resource requestedResource = location.createRelative(resourcePath);
return requestedResource.exists() && requestedResource.isReadable() ? requestedResource
: new ClassPathResource("/static/index.html");
}
});
}
}
So basically, we are telling Springboot that if we have the resource, use the same if not then redirect it to index.html.
Now, to handle the path in Angular, it depends on how you would have written your routes. If the path is available, you show the page, if not, display 404 page.
Hope this helps.
Update 1:
WebMvcConfigurerAdapter is deprecated. If this causes any trouble, then instead of extending the class WebMvcConfigurerAdapter, you can implement WebMvcConfigurer
If you see the whitelabel error says that "this application has no explicit mapping for /error".
That means if no path is matched with the paths that are defined in controller mappings, it forwards the request to "/error" route. So we can override this default behaviour.
Spring provides ErrorController interface to override this functionality
import org.springframework.boot.web.servlet.error.ErrorController;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
public class CustomErrorController implements ErrorController {
#RequestMapping("/error")
public String handleError() {
return "forward:/";
}
}

Spring Boot - Remove external "/error" endpoint access

Introduction
I have a custom ErrorController implementation to handle all exceptions and create a custom error message:
#RestController
public class CustomErrorController implements ErrorController {
#RequestMapping("/error")
public ResponseEntity handleError(HttpServletRequest request) {
HttpStatus status = HttpStatus.valueOf((Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE));
String body = ... // Code to calculate the body based on the request
return ResponseEntity.status(status.value()).body(body);
}
#Override
public String getErrorPath() {
return "/error";
}
}
Problem Description
However, this also enables access to the path /error which I would like to disable.
When trying to access https://localhost:8443/error, a NullPointerException is thrown by the HttpStatus.valueOf() method, because the status code could not be extracted. As a result, an Internal Server Error (500) is created, which is run through my custom controller, creating a custom 500 error response.
Temporary Fix
As a workaround, I can check if the status code attribute exists, and handle that case separately. But it is a work-around and not an actual fix.
The Question
What I would like is to disable the /error mapping from external access. If attempted, the result should be Not Found (404) which is then run through my custom controller.
Is the #RequestMapping("/error") necessary or could this be implemented differently?
Edits
Spring Boot version is 2.1.2.RELEASE
The server.error.whitelabel.enabled property is set to false. The issue does not seem to be related with it.

Spring Boot 2.0.2 MultipartConfigElement not being configured for MultipartFile

I'm using Spring Boot 2.0.2.RELEASE, and not being able to upload files for a REST controller endpoint.
Following this getting starter, it says:
As part of auto-configuring Spring MVC, Spring Boot will create a
MultipartConfigElement bean and make itself ready for file uploads.
So, theoretically, It should work without any additional configurations, but it looks like this MultipartConfigElement is not being configured at all.
I'm getting this warn:
WARN .a.w.r.e.DefaultErrorWebExceptionHandler: Failed to handle request [POST http://localhost:8080/upload]: Response status 400 with reason "Required MultipartFile parameter 'file' is not present"
My Spring application starter is as simple as:
#SpringBootApplication
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
And my endpoint is:
#RestController
public class MyController {
#PostMapping("/upload")
public String hash(#RequestParam("file") MultipartFile file) {
final String test = file.getContentType();
}
This is the way I'm sending with postman:
I also made sure to unmark any default content type set by postman, with no success.
What possibly am I doing wrong?
First, add this to your properties file
servlet.multipart.enabled=true
servlet.multipart.max-file-size=20M
And create CommonsMultipartResolver bean as
(name = "multipartResolver")
Same question,but I got these files by this way.
You can found these files in this github repository:
gs-uploading-files
All you need to do is just download the zip file of this application,and find the files you need.

Why doesn't my spring boot error controller work?

I have a simple spring boot web application (running under Tomcat) and I cannot figure out how to get an error handler to work. So far I've created the web application and controllers and they all work fine. That is, they display Thymeleaf templates. Upon error. I get the default white label error page.
I first disabled this white label error page by adding an EnableAutoConfiguration annotation, thus:
#SpringBootApplication(scanBasePackages="au.com.sample")
#EnableAutoConfiguration(exclude = {ErrorMvcAutoConfiguration.class})
public class SampleWebApp extends SpringBootServletInitializer {
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SampleWebApp.class);
}
}
Now, if I browse to an unknown page I get a generic 404 HTML error page containing:
<html>...<body><h1>HTTP Status 404 – Not Found</h1></body></html>
So that step worked. Now when I try and add my own error controller it does not trigger when I browse to an end point that does not exist:
#Controller
#RequestMapping("/")
public class ErrorHandlingController implements ErrorController {
#Override
public String getErrorPath() {
return "/error";
}
#RequestMapping(/"error")
public ModelAndView handleError() {
ModelAndView mav = new ModelAndView();
mav.addObject("title", "Error");
mav.setViewName("layout");
return mav;
}
}
"layout" is my existing thymeleaf template that works fine for my other end points.
I've tried several variations of the error controller, eg. changing the endpoint to "error" (not "/error"), using #RestController instead of #Controller but with no luck. In every case, I get the same generic 404 HTML instead of my hand-crafted template.
Can anyone see what I'm doing wrong or have any tips on how to track down my problem.
To show a custom error page for a specific status is pretty easy in Spring Boot. Just add an <error-code>.html into the src/main/resources/templates/errors directory to have it resolved. Or add a generic error.html as a fallback. See the reference guide for this feature (see also this).
If you want to add your own error handling just add a bean of type ErrorController or if you want to only add attributes add an ErrorAttributes typed bean to your configuration. See this section for more information.
A late answer to the original question of why Spring doesn't call your error controller: I think you are excluding the magic that makes the custom ErrorController work. In a Spring-Boot v2.1.6 app I had to allow (NOT exclude) the ErrorMvcAutoConfiguration class, then it used a custom MyController-implements-ErrorController class on page-not-found situations etc. It seems to be an either-or situation. I think you should only exclude the ErrorMvc.. class if you are using Thymeleaf templates AND you have published template files in a templates/ directory, because in that case you don't really need a custom error controller. HTH.

returning string instead or returning the ModelView is not working in spring MVC

i have tried to write an upload option in my web application following mentioned is my code
#RequestMapping( value="/group/import/upload", method=RequestMethod.GET )
public String GroupImportInfo( Model model )
{
System.out.println("in controller");
return "upload-File-import";
}
i have a upload-File-import.jsp file, but when i try to access that page am getting an exception saying..
type Status report
message /corept/WEB-INF/views/upload-File-import.jsp
description The requested resource (/corept/WEB-INF/views/upload-File-import.jsp) is not available.
JBoss Web/7.0.13.Final
Thanks for helping.
It seems the ViewResolver is unable to locate the view. Hence, I suggest you to check configuration of the ViewResolver bean's prefix property(in the spring-servlet-config.xml) if it is matching the path of the requested view.
Apart from that I dont see any issue with your code.

Categories

Resources