The controller loads only a String object, but not an html page. Page login.html is in directory templates. Effect is text 'login" on page. Project is in Spring Boot.
#RestController
public class Company {
#RequestMapping("login")
public String company() {
return "login";
}
}
#SpringBootApplication
public class ComJonkSpringBootMvcApplication {
public static void main(String[] args) {
SpringApplication.run(ComJonkSpringBootMvcApplication.class, args);
}
}
<!DOCTYPE HTML>
<html>
<head>
<title>Yahoo!!</title>
</head>
<body>
Name : <input name="name" type="text" /> Password : <input name="password" type="password" /> <input type="submit" />
</body>
</html>
Do not use #RestController if you plan to return a JSP.
Use #Controller instead, and read the documentation about #ResponseBody:
Annotation that indicates a method return value should be bound to the
web response body. Supported for annotated handler methods in Servlet
environments.
Related
**Hi everyone. I ran into a problem while developing a web application. The saveEmployee method does not work properly and throws the corresponding error. In the project I use Spring-boot + Thymeleaf. I think there is an error in these two files or a problem in the configuration. But so far I haven't found anything.
**
myRestController.java
#Controller
#RequestMapping("/shop")
public class myRestController {
#Autowired
private EmployeeService employeeService;
#GetMapping("/allEmployees")
public String allEmployees(Model model) {
List<Employee> employees = employeeService.getAllEmployees();
model.addAttribute("employeesList", employees);
return "allEmployees";
}
#GetMapping("/allEmployees/{name}")
public String getEmployeeByName(#PathVariable String name, Model model) {
List<Employee> employees = employeeService.findAllByName(name);
model.addAttribute("employeesList", employees);
return "allEmployees";
}
#GetMapping("/newEmployee")
public String addEmployee(Model model) {
Employee employee = new Employee();
model.addAttribute("employee", employee);
return "addNewEmployee";
}
#RequestMapping()
public String saveEmployee(#ModelAttribute("employee") Employee employee){
employeeService.saveEmployee(employee);
return "index";
}
addNewEmployee.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Add Employee</h1>
<form th:method="POST" th:action="#{shop/allEmployees}" th:object="${employee}">
<label for="name">Enter name:</label>
<input type="text" th:field="*{name}" id="name"/>
<br/>
<label for="surname">Enter surname:</label>
<input type="text" th:field="*{surname}" id="surname"/>
<br/>
<label for="department">Enter department:</label>
<input type="text" th:field="*{department}" id="department"/>
<br/>
<label for="salary">Enter salary:</label>
<input type="text" th:field="*{salary}" id="salary"/>
<br/>
<input type="submit" value="Create!">
</form>
<br><br>
</body>
</html>
In your myRestController.java, I am not seeing any #PostMapping defined. In addNewEmployee.html, it appears you are attempting to call shop/allEmployees with a POST rather than the GET method. If your intention is to pass a body or form to the shop/allEmployees endpoint, you may want to consider either changing your #GetMapping to a #PostMapping that accepts a #RequestBody or creating an entirely new #PostMapping that accepts a #RequestBody.
I am having some trouble getting form data in my controller when the form in my jsp contains the attribute enctype="multipart/form-data" . The attribute is needed because i am uploading a file. I simplified my code to make it easier to understand but assume I have the following.
My model:
public class EmployeeUpdateForm {
private String name;
private ContactInfo info;
//standard getters and setters
}
public class ContactInfo {
private String streetName;
private MultipartFile image;
//standard getters and setters
}
My controller is
#Controller
public class EmployeeController {
#RequestMapping(value = "/employee", method = RequestMethod.GET)
public ModelAndView showForm() {
//assume this sends you to updateEmployee.jsp
}
#RequestMapping(value = "/submit", method = RequestMethod.POST)
public String submit(#ModelAttribute("EmployeeUpdateForm")EmployeeUpdateForm form ) {
//here I expect form.getInfo().getStreetName() and form.getInfo().getImage() to return something but they are both null values.
}
}
updateEmployee.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
</head>
<body>
<h3>Update Employee Details</h3>
<form:form action="submit" method="post" enctype="multipart/form-data" id="EmployeeUpdateForm" modelAttribute="EmployeeUpdateForm">
<div>
Street Name: <form:input path="info.streetName" />
</div>
<div>
New Image: <form:input type="file" path="info.image"/>
</div>
</form:form>
</body>
</html>
When I submit my form and check the value of form.getInfo().getStreetName() and form.getInfo().getImage() within submit() in my controller, both values are null.
However if I remove method="post" enctype="multipart/form-data" from my form in jsp and also remove <form:input type="file" path="info.image"/> from my jsp and then proceed to submit, if I do form.getyInfo().getStreetName() it returns the value I filled in.
How do I get form data in my controller when the form in my jsp has the attribute method="post" enctype="multipart/form-data"??
A resolver was missing. Adding
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
</bean>
fixed the issue.
I would like to display the data I get from a search, personalized for my taste. At this moment, It is just plain text.
For example, I am searching for "Titanic", and I get the name, a few links, and some information from IMDB.
I have the following code:
search.html
<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>Getting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Form</h1>
<form action="#" th:action="#{/search}" th:object="${search}" method="post">
<p>Message: <input type="text" th:field="*{content}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
result.html
<!DOCTYPE HTML>
<html xmlns:th="https://www.thymeleaf.org">
<head>
<title>Getting Started: Handling Form Submission</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<h1>Result</h1>
<p th:text="'content: ' + ${main.content}"></p>
Submit another message
</body>
</html>
SearchController.java
#Controller
public class SearchController {
#GetMapping("/search")
public String greetingForm(Model model) {
model.addAttribute("search", new Main());
model.addAttribute("main", new Main().getContent());
return "search";
}
#PostMapping("/search")
public String greetingSubmit(#ModelAttribute Main main) {
return "result";
}
}
and Main.java
private String content;
private List<Result> finalList;
private List<Result> resultList;
public void setContent(String content) throws IOException {
//code to compute finalList
}
public List<Result> getContent() {
return this.finalList;
}
The main problem is that I have no ideea where to being with. finalList is a list of objects of type "Result", which have fields such as
private List<String> link = new ArrayList<>();
private String name;
private TitleProp titleProp;
and TitleProp has
private String trailer;
private String rating;
private String description;
private String genre;
I would like to manipulate each field to show it on a different way, such as a table with more rows, etc.
Any link or sample of code would help me a lot to understand Thymeleaf and Spring Boot more.
I am coming with an answer to my question. I managed to get the result I wanted using Ajax, as SnakeDoc suggested. It was a long road, mostly because even if I had a working code, I spent a few hours searching for the Forbidden 403 error on ajax post request.
So, for the js part:
function ajaxPost() {
// Here we prepare data for the JSON
var formData = {
moviename: $("#moviename").val()
}
$.ajax({
type: "POST",
contentType: "application/json",
url: "MYURL",
data: JSON.stringify(formData),
dataType: 'json',
success: function (result) {
{
$.each(result,
function (i, title) {
// do whatever you want with what you got from the server
});
console.log("Success: ", result);
}
console.log(result);
},
error: function (e) {
console.log("ERROR: ", e);
}
});
}
If this seems confusing, I access the fields you can see in my question by
title.name, title.link, title.titleProp.description, etc, inside function (i, title)'s body.
For the HTML,
<label for="moviename" style="margin-right:5px">Title:</label>
<input type="text" class="form-control" id="moviename" placeholder="Enter a title"/>
Where moviename is the variable name you get from the input.
Now, on the backend, we have to configure our path
#PostMapping("/MYURL")
public ResponseEntity<Object> addSearch(#RequestBody SearchCriteria searchCriteria)
throws IOException {
// do whatever you want to get a result. I used a custom class "SearchCriteria"
// which has a getter and a setter for the field
// **private String moviename;**
return ResponseEntity.ok(THIS GETS SENT TO AJAX);
}
The main problem was that I have web.security, and you have two choices. First one, you disabling csrf. You have to add this line to your security config.
http.csrf().disable();
in protected void configure(HttpSecurity http) method.
Or, you add csrf to the ajax request. More info on this topic was discussed here
With thymeleaf, you can display a list in html like so:
<tr th:each="student: ${students}">
<td th:text="${student.id}" />
<td th:text="${student.name}" />
</tr>
More info: https://www.baeldung.com/thymeleaf-iteration
I am trying to build an application with spring boot and java in eclipse.
What I have tried so far:
HomeController.class
#Controller
#ComponentScan(basePackages = {"project.tool.frontend"})
public class HomeController {
#GetMapping("/home")
public String home(){
System.out.println("open page");
return "home";
}
}
home.html
<!DOCTYPE HTML>
<html>
<head>
<head>
<title>Getting Started: Serving Web Content</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<form action="/home" method="get">
First name: <input type="text" name="fname"><br> Last
name: <input type="text" name="lname"><br> <input
type="submit" value="Submit">
</form>
</body>
</html>
Application.class
#SpringBootApplication
public class Application{
public static void main(String agrs[])
{
SpringApplication.run(Application.class);
}
}
When I run this Application I get the "Whitelabel ErrorPage" Error. I also enabled the whitelabel errorpage in my application.properties .
And a question for unserstandig: When I use #GetMapping("/home") in my HomeController and the <form action="/home" in my html file it will be mapped through the "/home" get method right?
Thank you all.
As a static resource, your home.html should be at resources/public/home.html (or /static/). Is it there?
Your Application should tell in which package your controller is located, so it gets picked up
Does adding a ComponentScan help?
#SpringBootApplication
#ComponentScan(basePackages = { "com.acme.controllers" })
public class Application{
}
If you have not configured any view resolver, try returning "/views/home.html" instead of just "home". Change "/views/home.html" to whatever be the path of the file.
I suggest using Thymeleaf as your viewresolver.
You can place the home.html in src/main/resources folder to be recognized.
As you are using .html extension then I suggest you to use the thymeleaf as a view resolver.
Using thymeleaf HTML:
<form th:action="#{/home}" th:method="get"
...
...
//Rest of your code goes here.
</form>
Use #ComponentScan annotation:
#SpringBootApplication
#ComponentScan(basePackages = { "<full package name where controller exists>" })
public class Application{
public static void main(String agrs[]){
SpringApplication.run(Application.class);
}
}
I try put 2 request mapping since i want to point to home/home since later i will be having another controller with same name which is about/home. But i not sure why it was not working. If have only home it is working but home/home or about/home not working. The class level not working.
This the controller
package com.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.constant.server.HelperConstant;
#Controller
#RequestMapping("/home")
public class HomeController
{
#RequestMapping("/home")
public String doDisplayPage()
{
return HelperConstant.VIEW_HOME;
}
}
This the jsp
<html>
<body>
<form action="home/home">
<input type="text" name="t1"><br>
<input type="text" name = "t2"><br>
<input type ="submit">
</form>
</body>
</html>
I am hitting HTTP Status 404 -
Edited
Attached the config files
package com.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebConfig extends AbstractAnnotationConfigDispatcherServletInitializer {
#Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
return null;
}
#Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
return new Class[] {SpringConfig.class};
}
#Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
return new String[] {"/"};
}
}
This another config file
package com.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
#Configuration
#ComponentScan({"com.controller"})
public class SpringConfig
{
#Bean
public InternalResourceViewResolver viewResolver()
{
InternalResourceViewResolver vr = new InternalResourceViewResolver();
//vr.setPrefix("/WEB-INF/");
vr.setSuffix(".jsp");
return vr;
}
}
Attached the picture of the folder structure
there is an additional findings as well whereby i trying to look for the jsp at home/home.jsp. can i know why such behaviour? by right should just look at home.jsp. If remvoe class level anotation, then it working fine or i create a folder inside webapp home it working fine but after click submit again it looks for home/home/home.jsp
I have added a method="POST"
now problem is after restart tomact
after click submit like this
if click submit again show eror 404
this my web.xml but i removed it already since i already use java or configurtion
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
<welcome-file-list>
<welcome-file>home.html</welcome-file>
<welcome-file>home.htm</welcome-file>
<welcome-file>home.jsp</welcome-file>
</welcome-file-list>
</web-app>
The problem is your action path <form action="home/home"> This is a relative path meaning it will do the following.
http://example.com/web_main/home - form action - >
http://example.com/web_main/home/home (200) - form action ->
http://example.com/web_main/home/home/home (404)
Others are suggesting /home/home but that isn't taking to account your application context path. The following would be the result.
http://example.com/web_main/home - form action - > http://example.com/home/home
Notice that the web_main is gone.
To fix your issue you need to leverage JSTL, add this to the JSP.
<%# taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %>
<c:url value="/home/home" var="homeUrl" />`
<form action="${homeUrl}">
Add the import to the top of the JSP.
There is one issue in the url.
Have you observed the actual url?
It is displaying /home/home/home after the context but url points to /home/home.
Solution might be removing one /home from the action url in the form tag
<html>
<body>
<form **action="home"**>
<input type="text" name="t1"><br>
<input type="text" name = "t2"><br>
<input type ="submit">
</form>
</body>
</html>
or
<html>
<body>
<form action="/home/home">
<input type="text" name="t1"><br>
<input type="text" name = "t2"><br>
<input type ="submit">
</form>
</body>
</html>
What does your Spring app class look like? If you do not have one you should create one.
Instead of having the #ComponentScan below the #Configuration tag, do something like below and it should be picked up easier, also maybe change your root tag to just / for easier for reading:
#SpringBootApplication
#ComponentScan(basePackages = {"com.*"})
class MyClass {
public static void main(String[] args) {
SpringApplication.run(MyClass.class)
}
}
#Controller
#RequestMapping("/")
public class HomeController
{
#RequestMapping("/home")
public String doDisplayPage()
{
return HelperConstant.VIEW_HOME;
}
}
When using RequestMapping default request mapping method value is GET method. Html form submit uses POST method by default. So you need to add post method to this url. You can give multiple method value for same request mapping.
in 404 tab there are 3 home not 2 as you want in URL so its showing 404 .
Instead of relative path home/home in submit form give absolute /home/home
This is works
#Controller
#RequestMapping("/home")
public class HomeController {
#RequestMapping(value = "/home")
public String doDisplayPage() {
return "../home";
}
}
#Controller
#RequestMapping("/about")
public class AboutController {
#RequestMapping(value = "/home")
public String doDisplayPage() {
return "../home";
}
}
<html>
<body>
<form action="/home/home">
<input type="text" name="t1"><br>
<input type="text" name = "t2"><br>
<input type ="submit">
</form>
</body>
</html>
Also you don't need web.xml since you have describe deployment descriptor in your WebConfig and SpringConfig
If you are only trying to make your current code work, then a simple solution is to append Context Root to your form action as shown below.
<html>
<head>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<c:set var="ctx" value="${pageContext.request.contextPath}" />
</head>
<body>
<form action="${ctx}/home/home">
<input type="text" name="t1"><br> <input type="text"
name="t2"><br> <input type="submit">
</form>
</body>
</html>