spring-boot application displaying html code for view when executed in the browser - spring

I am recently start to work with spring-boot in my spring projects, and right now I am facing this problem:
I have one spring-boot application with this main class:
#Configuration
#EnableAutoConfiguration
#ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
and this controller:
#Controller
public class AcessoController {
#RequestMapping(value = "/signin")
public String signin(Model model) {
return "acesso/signin";
}
#RequestMapping(value = "/admin")
public String admin(Model model) {
return "private/admin";
}
#RequestMapping(value = "/index")
public String index(Model model) {
return "public/index";
}
}
when I run the application and try access the url mapping /signin, for example, the browser display the html code for this view, instead of the actual content.
What I am doing wrong here?

Are you trying to render a view using a template engine, or just return a static HTML file?
If you are trying to render a template, then you most likely do not have the right dependency in place to pull in a template engine. (Per your code, I believe this is what you are trying to do.) Even if you don't intend to use the template engine for templates, you will want one to render the HTML for you. Depending on your spring-boot setup, try starting with spring-boot-starter-web, or pull in Thymeleaf (spring-boot-starter-thymeleaf) or Freemarker (spring-boot-starter-freemarker) specifically.
If you want to simply return static content and do not want do custom configuration, you'll need to place the files in a certain location and do not need specific controller request mappings.
http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#boot-features-spring-mvc-static-content

Related

I got this error White label Error Page while mapping multiple index into spring boot controller while trying to display more than one page

#Controller
public class HomeController {
#RequestMapping("/")
public String index() {
return "myAccount";
}
#RequestMapping("/myAccount")
public String myAccount() {
return "myAccount";
}
}
Project structure image
The above controller exposes two links which return the same html page.
i got the solution for my question,
mapping error occurred because of creating common header in src/main/resources/static
and in my controller during request mapping i couldn't get the page in static templates which i need to map it within the controller

Thymeleaf + Spring MVC + Rest

I don't understand, how to change #Controller to #RestController for RESTFull serivce, if html template linked with attributes that I get in ModelAndView
#Controller
public class MyController{
#GetMapping("/index")
public ModelAndView index(){
return new ModelAndView("/index", name, userService.getUser().getName());
}
}
and in thymeleaf template it's look like
<p th:text="'Hello, ' + ${name} + '!'" />
But I wanna go to index page, and in background get user name
#RestController
public class MyController{
#GetMapping("/api/user")
public String index(){
return userService.getUser().getName();
}
}
I can use ajax for update tag "p", but in this way it's nothing benefit of using thymeleaf, I can use jsp. So what the best way use thymeleaf with rest and is it rational?
I think the purpose of Thymeleafis for server-side rendering.
Thymeleaf is a Java template engine for processing and creating HTML, XML, JavaScript, CSS, and text.
When you are using JSON API and parse the JSON and use angular or any other client-side rendering framework for that. Thymeleaf with REST is not the approach.
But if you want to use both ways like provide data to Thymeleaf and also provide REST services to other application follow below approach.
#RequestMapping('/foobars')
abstract class FoobarBaseController {
#RequestMapping
abstract listAll()
}
#Controller
class FoobarHtmlController extends FoobarBaseController {
#Override ModelAndView listAll() {
new ModelAndView('foobars/foobarThymeleafTemplate', [foobars: foobarsList])
}
}
#RestController
#RequestMapping('/foobars', produces = MediaType.APPLICATION_JSON_VALUE)
class FoobarJsonController extends FoobarBaseController {
#Override Collection<Foobar> listAll() {
foobarsList
}
}
I hope this address your question properly.

Spring Boot Redirecting to another controller method from current controller method

Hi all am new to spring boot. Am stuck in the middle of my learning path. I have two controllers(#Controller) with some methods define in them. Am submitting form data to a method in index controller and wants to move to the method in home controller if form submission gets successful(on succesfull login). while loading http://localhost:9090/method of index controller it loads all the static content correctly, but when i redirectreturn "redirect:/dashboard/index" then it navigates to http://localhost:9090/dashBoard/index. And /dashboard/index method is as follow
#Controller
public class HomeController {
#GetMapping(value = "/dashBoard/index")
public String hello(Model model, #RequestParam(value = "name", required = false, defaultValue = "World") String name) {
model.addAttribute("name", name);
return "index";
}
}
this method return "index" which is .jsp page but redirecting to this method changes static content path like http://localhost:9090/dashBoard/assets/images/avatar/1.jpg
it seems like appending /dashBoard/ in path of static content. Am not understanding what to do please help. Am adding my project properties and structure please have a look
application.properties
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.resources.static-locations=file:/var/www/static,classpath:static
spring.mvc.static-path-pattern=/resources/**
server.port=9090
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL57InnoDBDialect
spring.jackson.serialization.fail-on-empty-beans=false
main class
[#SpringBootApplication
#EnableAutoConfiguration
public class SchoolpageApplication extends SpringBootServletInitializer {
public static void main(String\[\] args) {
SpringApplication.run(SchoolpageApplication.class, args);
}
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(SchoolpageApplication.class);
}
}
Project Structure
Static content path
#Controller
#RequestMapping("/dashBoard")
public class HomeController {
#GetMapping("index")
public String hello(Model model, #RequestParam(value = "name", required = false, defaultValue = "World") String name) {
model.addAttribute("name", name);
return "index";
}
}
You could try this method, everytime you get throught an url with /dashboard you will get inside this controller, and you can control every option you want with the next income like /foo (in this case /index) and in the return it will get you into /dashboard/+your return value(in this case index).
I´m not an expert with spring boot, I´m pretty new with it too but I hope this can help you.

Spring sending user to a view when no view is being requested

I have written a book catalog in Spring.
It collects books (pdf, epub, mobi, ebook) from a directory, collects some metadata from them, stores them in a DB and then puts them in a List that is made available to my views:
#Slf4j
#Controller
public class BookCatalogController {
// == Fields ==
private final BookService bookService;
#Autowired
public BookCatalogController(BookService bookService){this.bookService = bookService; }
// == Model attributes ==
#ModelAttribute
public List<Book> bookData(){ return bookService.getBooksFromMemory(); }
public static final File bookDirectory= new File("D:\\edu_repo\\ebooks_test\\");
.
.
.
// Catalog Simple View
#GetMapping(Mappings.CATALOG_SIMPLE)
public String catalogSimple(Model model){
log.info("catalogSimple method called");
// This is adding the entire BookManager book list into the model.
model.addAttribute(AttributeNames.BOOK_DATA, bookData());
return ViewNames.CATALOG_SIMPLE;
}
// Catalog Detail View
#GetMapping(Mappings.CATALOG_DETAIL)
public String catalogDetail(Model model){
log.info("catalogDetail method called");
// This is adding the entire BookManager book list into the model.
model.addAttribute(AttributeNames.BOOK_DATA, bookData());
return ViewNames.CATALOG_DETAIL;
}
.
.
.
#GetMapping(Mappings.LOAD_BOOKS)
public void loadBooks(Model model) {
bookService.loadBooksFromDirectory(bookDirectory);
}
}
Obviously I'm not using #GetMapping(Mappings.LOAD_BOOKS) properly as you can see in the error below:
The error:
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [load-books], template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [load-books], template might not exist or might not be accessible by any of the configured Template Resolvers
How does one invoke a method like I am doing but without Spring trying to redirect the user to another view?
I'm not expecting the page to update at all since I'm not returning a View!
When you click a link in your browser with a load-books anchor, your browser sends it to the server and waits for result, which causes your page to be reloaded. Once the request to a load-books endpoint reached to the server, Spring MVC handles this and starting to looking up an appropriate controller with its method. It founds public void loadBooks(Model model) in your case. When Spring MVC invokes the method, it expects to obtain a view name to resolve and return back to your browser.
Since you haven't provided a View or String as a return type, Spring MVC used the endpoint's path as a view name (I'm not seeing your Mappings.LOAD_BOOKS constant, but it supposed to be load-books).
If you're not going to return any view back to the browser, you can annotate the method like that:
#GetMapping(Mappings.LOAD_BOOKS)
#ResponseBody
public void loadBooks(Model model) {
which tells Spring to treat void as a response body.
But it's not preventing a page refreshing, you'll just see an empty page after clicking the link. In order to fix this you can redirect a user to another page by returning the following string (without ResponseBody annotation on the method)
return "redirect:/path-to-redirect";
When Spring MVC sees this prefix it redirects you to another controller, but user going to notice that too.
If you really don't want to see a blank page for a moment, you'll have to use some JavaScript to perform AJAX request to the server when button is clicked.
Actually, it seems that you want to preload some files in a service by a given path. If it's all you want to do, you can use Spring's runners like that:
#Component
class Preloader implements ApplicationRunner {
private final BookCatalogService bookService;
#Autowired
public Preloader(BookCatalogService service) {
this.bookService = service;
}
#Override
public void run(ApplicationArguments args) throws Exception {
bookService.loadBooksFromDirectory(BookCatalogController.bookDirectory);
}
}
Spring automatically calls all registered runners when application is ready, so your code will be executed without having a user to visit load-books endpoint.

"Circular view path" with simple spring-boot app using #PathVariable

I have a simple spring-boot application that serves up static content. I have an index.html page and some js/css in /src/main/resources/public. I have a single simple controller as follows:
#Controller
public class PublicController {
#RequestMapping(value="/", method=RequestMethod.GET)
public String index() {
return "index";
}
}
That works as expected. I run curl http://localhost:8080/, and it delivers my html.
Now I want to modify the controller to take a path variable:
// ...
#RequestMapping(value="/{word}", method=RequestMapping.GET)
public String index(#PathVariable("word") String word) {
return "index";
}
But now I get a 500 with a big long "Circular view path" exception.
I presume what's happening is the view resolver is seeing that my controller can handle "/index", and realises that's not going to end well.
Is it possible to tell the view resolver to give the static resources priority?
When you use Thymeleaf and declare declare a ThymeleafViewResolver and a ServletContextTemplateResolver with a specific prefix and suffix, it builds the View differently, giving it a path like
WEB-INF/static/index.html
ThymeleafView instances locate the file relative to the ServletContext path by using a ServletContextResourceResolver
templateInputStream = resourceResolver.getResourceAsStream(templateProcessingParameters, resourceName);
which eventually
return servletContext.getResourceAsStream(resourceName);
This gets a resource that is relative to the ServletContext path. It can then use the TemplateEngine to generate the HTML. There's no way an endless loop can happen here.

Resources