I'm starting an embedded tomcat via spring-boot and want to serve a static index.html page as part of a running application.
But the following does not work:
#SpringBootApplication
public class HMyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
}
#RestController
public class HomeContoller {
#RequestMapping("/")
public String index() {
return "index";
}
}
src/main/resources/static/index.html
Result: when I call localhost:8080, I just see the word "index", but not my html page. Why?
My fault: I had an additional class with #EnableWebMvc annotation. This somehow messed up the spring-boot autoconfiguration. I removed it and now it works returning index.html.
For me this worked, i am sure there is a better way ( like without .html ).
#RequestMapping("/")
public String index() {
return "index.html";
}
You can use ModelAndView in order to serve static HTML content in spring boot.
#RequestMapping("/")
public ModelAndView home()
{
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("index");
return modelAndView;
}
application.properties:-
spring.mvc.view.suffix = .html
HTML File : - src/main/resources/static/index.html
Thats because of #RestController annotation, just removing this annotation works for me.
Related
I am learing SpringBoot and Rest api just now and in all examples I have seen, in every controller classes they have a #RequestMapping("/api/v1") and then some #GetMapping or simular.
But it feels like why am I writing a RequestMapping for every controller if the first URI mapping is the same for all controllers.
Is it possible to have a #RequestMapping in the SpringBootApplication that maps "/api/v1" and then in the controller classes then have another ®RequestMapping for subfolders like "/products" and simular.
I have tried to solve this, but I cant make it function.
#SpringBootApplication
#RestController
#RequestMapping("/api/v1")
public class CommonApplication {
public static void main(String[] args) {
SpringApplication.run(CommonApplication.class, args);
}
}
#RestController
#RequestMapping()
public class ProductController {
private ProductService productService;
#GetMapping("/products")
public String getProducts()
{
return "Hello from getProducts 12";
}
}
I want this full URI "/api/v1/products" to function and return the String text. But I only get 404.
It is possible to have request mapping in both application and controller class. Go through the documentation which is attached below once for having better understanding.
https://zetcode.com/spring/requestmapping/
This works, I am able to make a request in postman for this Service.
#RestController
#Path("sample")
public class SampleClass {
#GET
#Path(value = "/s1")
public Object get() {
//Something
}
}
The problem is when I try to use #RequestMapping instead of #Path, I get a
404 Not Found
Error.
#RestController
#RequestMapping("sample")
public class CommonService {
#GetMapping(value = "/s1", produces = MediaType.APPLICATION_JSON)
public Object get() {
//Something
}
}
What I am doing wrong here?
After a while, I found out that for the JAX-RS (#Path) I had configured in web.xml file a different route "something".
JAX-RS: localhost:8080**/something**/sample/s1
Spring Rest Services: localhost:8080/sample/s1
I was also missing a "/" in the Spring Rest Service.
#RequestMapping("**/**sample")
Full code bellow:
#RestController
#RequestMapping("/sample")
public class CommonService {
#GetMapping(value = "/s1", produces = MediaType.APPLICATION_JSON)
public Object get() {
//Something
}
}
I recently migrated to Spring boot. I used Spring MVC before. When I go to a site after the application starts, this throws 404 page not found. The controller handles the request, but for some reason does not find the jsp page.
My Application.java:
package com.myapp.webapp;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication(scanBasePackages = "com.myapp")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
application.properties
# Spring MVC configuration
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
spring.datasource.url=jdbc:mysql://us-cdbr-iron-east-05.cleardb.net/heroku_4663e71bc0d567a?reconnect=true
spring.datasource.username=bb1a6d3ce29ada
spring.datasource.password=******
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
#spring.datasource.url=jdbc:mysql://localhost:3306/socialnet?autoReconnect=true&useSSL=false
#spring.datasource.username=root
#spring.datasource.password=123
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
debug=true
And controller for example
package com.myapp.webapp;
//imports
#Controller
#SessionAttributes({"accountInSession", "base64Photo"})
public class MainController {
private static final Logger logger = LoggerFactory.getLogger(MainController.class);
#Autowired
private AccountService accountService;
#Autowired
private AuthenticationTrustResolver authenticationTrustResolver;
#RequestMapping(value = {"/login", "/"})
public ModelAndView loginPage(#RequestParam(value = "error", required = false) String error,
#RequestParam(value = "logout", required = false) String logout,
#RequestParam(value = "noLogin", required = false) String noLogin) {
ModelAndView modelAndView = new ModelAndView("/login");
if (error != null) {
modelAndView.addObject("error", "Incorrect mail and/or password");
//modelAndView.setViewName("login");
}
if (logout != null) {
modelAndView.addObject("msg", "You've been logged out successfully!");
//modelAndView.setViewName("login");
}
if (noLogin != null) {
modelAndView.addObject("error", "Please log in to view this page");
}
if (!isCurrentAuthenticationAnonymous()) {
//modelAndView.setViewName("login");
modelAndView.setViewName("redirect:/account");
return modelAndView;
}
return modelAndView;
}
#RequestMapping("/test")
public String test() {
return "redirect:/registration";
}
}
For example if I go to http://localhost:8080/test controller redirected me to http://localhost:8080/registration
I used a multi module maven project with models: common(for models), dao, service and webapp.
So controllers located in
java/com/myapp/webapp/controllers
Jsp pages located in
src/main/webapp/WEB-INF/jsp
And path to files:
java/com/myapp/Application.java
src/main/resources/application.properties
And structure of wepapp module
You need to provide your implementation of view resolver using WebMvcConfigurer.
WebMvcConfigurer has replaced the old, deprecated WebMvcConfigurerAdapter.
#EnableWebMvc
#Configuration
#ComponentScan
public class CustomWebConfig implements WebMvcConfigurer {
#Override
public void configureViewResolvers(ViewResolverRegistry registry) {
registry.jsp("/WEB-INF/jsp/", ".jsp");
}
}
You need to provide prefix(/WEB-INF/jsp/) and suffix(.jsp) explicitly as registry.jsp()method takes default prefix as /WEB-INF/ and suffix as .jsp.
Refer Spring Framework: ViewResolverRegistry class
I have solve this problem. I move all jsp files from src/main/wepapp/WEB-INF/jsp/
to src/main/resources/META-INF/resources/WEB-INF/jsp/. I have no idea why it not works before, but now it works
I am a Spring Boot newbie and one thing bothers me: if I have a simple Spring Boot application like this:
package hello;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
I can call the default web page of the application from a browser by using URL:
http://localhost:8080/greeting
To return a page called greeting.html which is specified by the controller:
#RequestMapping("/greeting")
public String greeting() Model model) {
return "greeting";
}
Is there a way to have Spring Boot automatically open greeting.html in the browser? Can I tell Spring boot which controller method I want it to run when the project starts?
Not sure if there is a setting you can set for this case but what you can do is using redirection.
Just map "/" and redirect to "/greeting":
#RequestMapping("/")
public String index(Model model) {
return "redirect: greeting";
}
But if you want that the browsers open any page after lunching the application you should lookup if your IDE can do that.
Just map your greeting page to the root:
#RequestMapping("/")
public String greeting() Model model) {
return "greeting";
}
Then when you call http://localhost:8080/ you will be redirected to the greeting page as a default page.
I'm building a RESTful API and have a Spring REST Controller (#RestController) and an annotation-based configuration. I'd like to have my project's welcome-file be a .html or .jsp file with the API documentation.
In other web projects I would place a welcome-file-list in my web.xml, but in this particular project I can't seem to get it to work (preferrably using Java and annotations).
This is my WebApplicationInitializer
public class WebAppInitializer implements WebApplicationInitializer {
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(ApplicationConfig.class);
context.setServletContext(servletContext);
ServletRegistration.Dynamic dynamic = servletContext.addServlet("dispatcher",
new DispatcherServlet(context));
dynamic.addMapping("/");
dynamic.setLoadOnStartup(1);
}
}
This is my WebMvcConfigurerAdapter
#Configuration
#ComponentScan("controller")
#EnableWebMvc
public class ApplicationConfig extends WebMvcConfigurerAdapter {
#Bean
public Application application() {
return new Application("Memory");
}
}
And this is a small part of my REST Controller
#RestController
#RequestMapping("/categories")
public class CategoryRestController {
#Autowired
Application application;
#RequestMapping(method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<Integer, Category>> getCategories(){
if(application.getCategories().isEmpty()) {
return new ResponseEntity<Map<Integer, Category>>(HttpStatus.NO_CONTENT);
}
return new ResponseEntity<Map<Integer, Category>>(application.getCategories(), HttpStatus.OK);
}
}
So far I've tried:
Adding just a web.xml with a <welcome-file-list> with a <welcome-file>. (no luck there)
Moving the #RequestMapping("/categories") in the Controller from the class level to all of the methods, and adding a new method with #RequestMapping("/"), which returns either a String or a ModelAndView with the view name. (the former just returned a blank page with the String, for the latter no mapping could be found)
As suggested here: a combination of both, where my web.xml <welcome-file> is "/index", combined with #RequestMapping(value="/index") returning a new ModelAndView("index"), and a ViewResolver in my configuration class. (returns a Warning: No mapping found in DispatcherServlet with name 'dispatcher', even though "/index" is successfully mapped. Manually adding "/index" to the URL successfully resolves it to index.jsp)
When specifying a controller to handle your index page you should use a #Controller not a #RestController. Although the #RestController is a #Controller it doesn't resolve to a view but returns the result as is to the client. When using a #Controller when returning a String it will resolve to the name of a view.
#Controller
public class IndexController {
#RequestMapping("/")
public String index() {
return "index";
}
}
However there is an easier way to configure this and you don't need a controller for it. Configure a view controller. In your configuration class simply override/implement the addViewControllers method.
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/").setViewName("index");
}
That way you don't even need to create a class for it.