I want to simply map my home page with a Spring Controller like this :
package com.douineau.testspringboot.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
#Controller
#RequestMapping("/")
public class HomeController {
#GetMapping
// #ResponseBody
public String home() {
return "index";
}
}
I also have index.html in src/main/webapp folder.
But the application does not recognize the mapping, whereas if comment this all, the app recognizes that it is my home page.
What am I missing?
You mention you placed the index.html in your src/main/webapp but as I remember spring boot default configuration, it should be under src/main/resources/templates if it should be handled through your #Controller.
Everything in webapp is exposed "as-is" for eg. assets
You can change #Controller to #RestController.
Your code should be like this.
#RestController
public class HomeController {
#RequestMapping(value = "/", method = RequestMethod.GET)
public String home() {
return "index";
}
}
or
#RestController
#RequestMapping(value = "/")
public class HomeController {
#GetMapping("")
public String home() {
return "index";
}
}
Related
file : CourseApiApp.java
package io.javabrains.springbootstarter;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
#SpringBootApplication
public class CourseApiApp {
public static void main(String[] args){
//this is the first step to convert the application into spring app
SpringApplication.run(CourseApiApp.class,args);
}
}
File HelloControllerTwo
package io.javabrains.springbootstarter.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
#RequestMapping("/hello")
public class HelloControllerTwo {
public String sayHi() {
return "Hi";
}
}
I have created a very basic spring app to get hi on /hello path. I but I am still getting a fallback /error message on /hello
Could anyone please let me know what am I doing wrong?
Your #RequestMapping annotation should be on your method, not your class.
You should also specify a method in your annotation.
Try this:
#RestController
public class HelloController {
#RequestMapping(value = "/hello", method = RequestMethod.GET)
public String sayHello() {
return "Hello";
}
}
I have a spring boot api. My problem is how do I actually create a page in my app?
I created a page in /resources/static/templates/index.html
and when I get to /api/lol I just see a string saying index and not the page.
How do I do this?
#RequestMapping("/api")
#RestController
public class Controller {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping("/lol")
String lol() {
return "index";
}
}
You annotated your class with #RestController.
What you want is a MVC Controller, so replace it with #Controller.
Here is an example of the documentation :
#Controller
public class HelloController {
#GetMapping("/hello")
public String handle(Model model) {
model.addAttribute("message", "Hello World!");
return "index";
}
}
Put your index.html in src/main/resources/static
and then in your controller
#RequestMapping("/api")
#RestController
public class Controller {
#Autowired
JdbcTemplate jdbcTemplate;
#GetMapping("/lol")
String lol() {
return "index.html";
}
}
I have a #Controller:
#Controller("/")
public class GreetingController {
#GetMapping("/greeting")
public String get() {
return "greeting";
}
}
Also a #RestController:
#RestController("/test")
public class TestRest {
#RequestMapping()
public List<TestDTO> get() {
List<TestDTO> dtos = new ArrayList<>();
dtos.add(new TestDTO("value1","value2"));
dtos.add(new TestDTO("value1","value2"));
return dtos;
}
}
The #Controller works correctly, and serves a static HTML page at src/main/resources/templates/greeting.html
But the #RestController does not work, all I get are 404s.
If I move the method from the #RestController into the #Controller and add a #ResponseBody annotation, it then starts working.
How can I have the controllers as different classes?
#RestController and #Controller do not take the path to the resource as a parameter. Perhaps try something along the lines of...
#RestController
#RequestMapping("/test")
public class TestRest {
#RequestMapping(method = RequestMethod.GET)
public List<TestDTO> get() {
List<TestDTO> dtos = new ArrayList<>();
dtos.add(new TestDTO("value1","value2"));
dtos.add(new TestDTO("value1","value2"));
return dtos;
}
}
You question itself has the answers, for the RESTController to work, you would need to have a #ResponseBody because, for all REST calls, there needs to be response body to return the data.
I hope adding #ResponseBody alone will solve the problem.
I'm building a spring boot application. My problem is that when I run the project, my login page is not shown. This is my code:
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class RestLogin {
#RequestMapping("/")
public String login() {
return "login";
}
}
I get only a white page and "login" is written in it. When I try to change the #RestController with #Controller I get this GET http://localhost:8080/ 404 (). My login.html page is located under the webapp>tpl>login.html
How can I display my login page?
Edit
This is my application class
#SpringBootApplication
public class ExampleApplication extends SpringBootServletInitializer {
private static Logger logger = LoggerFactory.getLogger(ExampleApplication.class);
#Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
return builder.sources(ExampleApplication.class);
}
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
I dont know your configuration but:
#Configuration
#EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Override
protected void configure(HttpSecurity http) throws Exception {
http.httpBasic().and().authorizeRequests()
.antMatchers("/**").permitAll();
http.authorizeRequests().antMatchers("/**").permitAll();
}
}
In the Application.properties file add:
spring.mvc.view.suffix: .html
Change #RestController to #Controller for RestLogin class. Also put your html file inside the static folder inside resources folder.
You need an application class with a main method. See this tutorial.
Here's a snippet:
package hello;
import java.util.Arrays;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
return args -> {
System.out.println("Let's inspect the beans provided by Spring Boot:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.sort(beanNames);
for (String beanName : beanNames) {
System.out.println(beanName);
}
};
}
}
This is the normal behavior.
New version of Spring web comes with #RestController annotation which nothing but #Controller + #ResponseBody. So when you have a return statement in a method you must use #RestController or annotate your method with #ResponseBody.
Here the problem is that Spring don't know a lot about the http method type, can you please try to use #GetMapping("/") to combinbe path and method at the same time.
According to your posted code and your description, you're getting an expected behavior.
When you annotate your controller with #RestController, that means that your methods on that controller will try to return their result as JSON.
According to your code:
#RestController
public class RestLogin {
#RequestMapping("/")
public String login() {
return "login";
}
}
You're returning the String "login", that's why you're getting empty white page with the word login as JSON
If you will change the #RestController to #Controller then it no longer will return your string as JSON,
but Spring will try to figure out from the that "login" string a view, and for that you'll need to add a view resolver bean to your project.
I use WebApplicationInitializer to initialize Spring Dispatcher, this is how it was set.
public class MyApplicationInitializer implements WebApplicationInitializer{
#Override
public void onStartup(final ServletContext servletContext) throws ServletException {
final XmlWebApplicationContext appconfig = new XmlWebApplicationContext();
appconfig.setConfigLocation("/WEB-INF/app-servlet.xml");
final ServletRegistration.Dynamic dispatcher =
servletContext.addServlet("my_app", new DispatcherServlet(appconfig));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/app/*.do");
System.out.println("Here I am ");
}
and I intention is to use controller class as namespace as
#Controller
#RequestMapping("app")
public class TestingController{
#RequestMapping("/{act}.do")
public ModelAndView getIndex(){ return new ModelAndView("/index.jsp"); }
}
it seems reasonable, but when I try to run this artifact from tomcat I got this error message.
Caused by: java.lang.IllegalArgumentException: Invalid <url-pattern> /app/*.do in servlet mapping
Question is why i can't define dispatching URI like this and if I want to achieve class URI + method URI for a dispatcher how should I set it?
It looks like your endpoints are formulated for struts. Spring does not support this. Probably because it is a non-standard REST technique.
The more RESTful way of doing this would be to design the URI like this:
/app/do/{action}
Or:
/app/do?action={action}
However, you can use regex PathVariables like this:
/app/{action:[A-Za-z\\d]+}.do
Then, within the method block evaluate the request path and redirect to different controllers conditionally based on pattern matching.
Here is the example I was able to get working:
package com.app.controller;
import com.fasterxml.jackson.databind.JsonNode;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;
#Controller
#RequestMapping(value = "/test")
public class TestController
{
#RequestMapping(value = "/{action:[A-Za-z\\d]+}.do")
public #ResponseBody
ModelAndView getDo(#PathVariable String action)
{
return new ModelAndView("redirect:/test/action/" + action);
}
#RequestMapping(value = "/action/a")
public #ResponseBody
ModelAndView getAction()
{
return new ModelAndView("/index.jsp");
}
}
The getAction method could be in another controller if you wanted it to, but by using regex and redirect I think you can accomplish what you are trying to do.