I'm currently working on a Docker-deployed Spring application with an nginx-reverse proxy and want to access a subdomain via #GetMapping & #PostMapping.
What is the correct way to access e.g. the /entity/add subdomain?
Is this a code error or might my server be malconfigured? Is there anything else needed in order to correctly review this problem? I'll gladly add it.
I've looked up the official documentation, guides, other StackOverflow posts etc., but none of them seem to work.
Controller.java:
public class EntityController {
private Repository repository;
#ModelAttribute("entity")
public Entity newEntity() {
return new Entity();
}
// Overview.
#GetMapping("/entity")
public String index(Model model) {
final Iterable<Entity> all = repository.findAll();
model.addAttribute("all", all);
return "index";
}
// New entity.
#GetMapping("/entity/add")
public String loadAddPage(Model model) {
model.addAttribute("entity", new Entity());
return "add";
}
#PostMapping("/entity/add")
public String submitEntity(#Valid #ModelAttribute Entity entity, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
return "add";
}
repository.save(entity);
return "redirect:/index";
}
index.html:
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Overview</title>
<meta charset="UTF-8" />
</head>
<body>
<div class="container">
<h2>Entities</h2>
<form action="/entity/add" method="get">
<input type="submit" value="New Entity"/>
</form>
<div class="content" th:each="entity: ${all}">
<h2 th:text="${entity.name}">Name</h2>
<form th:href="#{/entity/details?id={entityId}(entityId=${entity.id})}">
<input type="submit" value="Edit"/>
</form>
<!--<button><a th:href="#{/entity/update?entityId={entityId}(entityId=${entity.id})}"></a></button>-->
</div>
</div>
</body>
</html>
add.hmtl:
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>New entity</title>
<meta http-equiv="Content-Type" content="text/html" charset="UTF-8" />
</head>
<body>
<div class="container">
<form action="/entity/add" method="post" th:object="${entity}">
<table>
<tr>
<td><label for="name">Name</label></td>
<td><input id="name" type="text" th:text="Name" th:field="*{name}" /></td>
</tr>
</table>
</form>
</div>
</body>
</html>
I expect that a click on the /entity/add-form in index.html correctly links me to entity/add, but it just displays a 404 error. Same with other tested subdomains.
Edit 01: Title updated. (access subdomains -> access URLs)
I understand your question as you need to submit the form to this action url "/entity/add" with method POST. Consider using the Thymeleaf view templates for rendering the server side actions. Check with the following
Change the HTML action attribute to th:action attribute.
Provide the Submit action button to submit the form.
Check this url for more information: https://spring.io/guides/gs/handling-form-submission/
Disclaimer: This is my comment for your question. As I don't have the reputation, I am posting as answer.
I suppose you are using thymeleaf for templating.
Add following in application.properties file:
spring.application.name: my-app-context-path
In Controller :
#GetMapping({"/", "/index"})
public String defaultPage(final Model model, final Locale locale) throws MyException {
addGameInfo(model);
return "index";
}
#GetMapping({"/match/{gameId}"}){
--------
------
}
In view:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
....
....
<h1 class="text-primary">Featured Games</h1><a class="btn btn-flat btn-primary" th:href="#{/match/2944107874}">Game Info 2944107874</a>
....
.....
</html>
You should checkout Thymeleaf Standard URL Syntax
So your url will be resolved to
1.http://localhost:2223/my-app-context-path/
2.http://localhost:2223/my-app-context-path/match/2944107874
It depends on your context path, if you are not providing one, you can access mappings directly.
Related
Issue : I have developed a Spring-Boot rest api which I can call from POSTMAN. Now I am requesting the same REST API method from a Thymleaf page. But it renders only a string. The actual page doesn't gets loaded..
This is my controller :
#RestController
#RefreshScope
#RequestMapping("/shopping")
public class ShoppingController {
#RequestMapping(value="/productList")
public String listAllProducts(ModelMap model){
logger.info("ShoppingMS : listAllProducts()");
ResponseEntity<List<Product>> responseProductList = prodServ.listAllProducts();
List<Product> products = responseProductList.getBody();
if(products.isEmpty()) {
logger.info("No Products Found");
}
logger.info("No of products fetched : " +products.size());
model.addAttribute("products", products);
return "productList";
}
}
This is my Thymleaf page productsList.html :
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
<meta charset="UTF-8">
<title>Product List</title>
<link rel="stylesheet" type="text/css" th:href="#{/css/styles.css}">
</head>
<body>
<th:block th:include="/_header"></th:block>
<th:block th:include="/menu"></th:block>
<div class="page-title">Product List</div>
<div class="product-preview-container"
th:each="prodInfo : ${products.list}">
<ul>
<li>Product Code: <span th:utext="${prodInfo.productCode}"></span></li>
<li>Product Name: <span th:utext="${prodInfo.productName}"></span></li>
<li>Product Price: <span th:utext="${#numbers.formatDecimal(prodInfo.productPrice,3,2,'COMMA')}"></span></li>
<li><a th:href="#{|/buyProduct?code=${prodInfo.code}|}">Buy Now</a></li>
</ul>
</div>
<br />
<div class="page-navigator">
<th:block th>
<a th:href="#{|/productList|}" class="nav-item"></a>
<span class="nav-item" > ... </span>
</th:block>
</div>
<th:block th:include="/_footer"></th:block>
</body>
</html>
Maven Dependency for Thymleaf
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Project Structure Image
Output :
Calling URL : http://localhost:1000/shopping/productList
It returns only the string `productList` in the page.
Please tell me where I am doing wrong. I am able to render a index.html page. But not this page.
That's because you are using #RestController annotation on top of your controller, which is nothing but #Controller+#ResponseBody.
Try to use only #Controller and then based on your method use #ResponseBody exclusively.
For example . If you want to return json response body then use #ResponseBody on method.
If you want to render thymeleaf page then don't use #ResponseBody.
I have an problem about that taking a passcode value from user, i want to use this passcode in url path, i am using thymeleaf as template engine.
This is my controller
#RequestMapping(value = "/findEvent/{passcode}", method = RequestMethod.POST)
public String findEvent(#PathVariable("passcode") String passcode,
final RedirectAttributes redirectAttributes, Model model) {
Event event=eventService.findByPassCode(passcode);
List<Question> questions=questionService.findQuestionsByPasscode(passcode);
model.addAttribute("questions",questions);
return "questions";
}
and these is my html pages
addEvent.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<title>Hello World!</title>
</head>
<body>
<form method="post" th:action="#{/eventSave}" th:object="${eventRegister}">
Name:<br>
<input type="text" th:field="*{eventName}"><br>
Passcode:<br>
<input type="text" th:field="*{eventPasscode}"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
passcode.html
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="post" th:action="#{/findEvent/{passcode}}">
Passcode:<br>
<input type="text" th:text="*{passcode}" ><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
questions.html
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div class="col-12">
<table class="table table-bordered">
<tr>
<th>Question </th>
<th>Votes </th>
</tr>
<tr th:each="questions : ${questions}" th:object="${question}">
<td th:text="*{text} "></td>
<td th:text="*{voteValue} "></td>
<a th:href="#{/voteQuestion/{id} (id=${question.questionId})}">Vote the question</a>
</tr>
</table>
</div>
and this is my result http://localhost:8080/findEvent/%7Bpasscode%7D
If you want the form action URL to contain a value from the form itself, then you need an onSubmit handler to update the URL from the form field.
Form values are only included automatically in the body of a POST request, or as query parameters of a GET request.
Anything else you have to do with JavaScript code.
Controller:
#Controller
public class WeatherController {
#GetMapping("/weather")
public String weatherForm(Model model){
model.addAttribute("weather",new WeatherServiceImpl());
return "weather";
}
#PostMapping("/weather")
public String weatherSubmit(#ModelAttribute WeatherServiceImpl weather) {
return "result";
}
}
template
<!DOCTYPE HTML>
<html xmlns:th="http://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="#{/weather}" th:object="${weather}" method="post">
<p>City: <input type="text" th:field="*{city}" /></p>
<p><input type="submit" value="Submit" /> <input type="reset" value="Reset" /></p>
</form>
</body>
</html>
result template
<!DOCTYPE HTML>
<html xmlns:th="http://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="'city: ' + ${weather.city}" />
Submit another message
</body>
</html>
So I am trying to get city name from user using a form and parse it to object. It parses to object. But I try to show the city name that I got from /weather it wont go to /result and will show an error message
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Wed Jun 20 20:42:53 EEST 2018
There was an unexpected error (type=Internal Server Error, status=500).
An error happened during template parsing (template: "class path resource [templates/result.html]")
Change post method as this.
#PostMapping("/weather")
public String weatherSubmit( WeatherServiceImpl weather,Model model) {
model.addAttribute("weather",weather);
return "result";
}
Find working code here. https://gitlab.com/supun/spring-boot-app/commit/b322644255e044ca5959460dd7d9f7a048a5f6d3
Please try closing paragraph tag.
<p th:text="'city: ' + ${weather.city}" ></p>
I am trying to create a sample registration page with Spring MVC and JSP pages.
While opening the url on tomcat server, I am getting following error
root cause
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'register' available as request attribute
org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getBindStatus(AbstractDataBoundFormElementTag.java:168)
org.springframework.web.servlet.tags.form.AbstractDataBoundFormElementTag.getPropertyPath(
I have a JSP register.jsp
<%# taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Registration</title>
</head>
<body>
<form:form action="/register/process" method="POST" modelAttribute="register">
<table style="text-align: center;">
<tr>
<td><form:label path="fname">First Name</form:label></td>
<td><form:input path="fname" name="fname"
id="fname" /></td>
</tr>
<tr>
<td><form:label path="lname">Last Name</form:label></td>
<td><form:input path="lname" name="lname" id="lname" />
</td>
</tr>
<tr>
<td></td>
<td>
<input type="submit" value="CREATE AN ACCOUNT"/>
</td>
</tr>
</table>
</form:form>
</body>
</html>
I have a controller class UserController.java
package vnfhub.supplier.controller;
#Controller
public class UserController {
#RequestMapping(value = "/register", method = RequestMethod.GET)
public String getRegisterForm(Model model) {
model.addAttribute("register", new Register());
return "register";
}
#RequestMapping(value = "/register/process", method = RequestMethod.POST)
public String processRegistration(#ModelAttribute("register") Register register, BindingResult result) {
return "success";
}
}
and a success.jsp page
<%# page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Success Form</title>
</head>
<body>
<font color="green"><h1>Hello</h1></font>
<h1>You have successfully registered</h1>
<font color="green"><h1>Welcome to Spring world !</h1></font>
</body>
</html>
I have tried many solution on stackoverflow.... but none of them worked.
I find your code okay so far as you given here. I mimic the situation with your code but unfortuantely found No Exception.
Things that you might have doing wrong is you are running some old build code in your tomcat. try to clean build and re-deploy in your container.
NB: one friendly suggestion. You are doing one thing wrong that is having action of your form to /register/process that will send the request to the container root (e.g. localhost:8080/register/process). And you will get 404 for that. You are not probably want that. register/process should be your URL and this will POST the request relative to your application-context. If your application context is something localhost:8080/test, this will send the request to localhost:8080/test/register/process
I am studying Managed Beans right now. I need to use html file to get the data and post them on the next page. I need to use ManagedBean. I am required to use .html file. I can't use JSF because we haven't began to study it yet.
Question: How can I set the value first name in the Voter.java class and then post it the new page?
I tried to use:
First Name:<input action="UserInfo.setFirstName()" type="text" name="fname" maxlength="30"
value="" pattern="[a-zA-Z]{1,30}" title="Please enter first name! Min 1
letter"required/><br>
but it doesn't work after I deploy the program.
welcome.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html>
<head>
<title>Welcome Form</title>
</head>
<body>
<div style="text-align:center">
<h1>Welcome</h1>
<form action="summary.html">
<fieldset>
<legend>Form:</legend>
<fieldset>
<legend>Personal Information:</legend>
First Name:<input action="UserInfo.setFirstName()" type="text" name="fname" maxlength="30"
value="" pattern="[a-zA-Z]{1,30}" title="Please enter first name! Min 1
letter"required/><br>
</fieldset>
<p></p>
<input type="submit" value="Submit" />
</fieldset>
</form>
</div>
</body>
</html>
summary.html
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html>
<head><title>Thank you</title></head>
<body>
<h1>Information Summary</h1>
<li action="SubmissionController.getFirstName()"><b>First Name:</b>
</body>
</html>
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
#ManagedBean(name="userinfo")
#SessionScoped
public class UserInfo {
private String fname;
public UserInfo() {}
public String getFirstName() {
return fname;
}
public void setFirstName(String fname) {
this.fname = fname;
}
}
So the answer is yes I can use simple HTML with ManagedBeans.
I just used Java Servlets, HTML and CDI managed beans. I had to use #Inject the reference of class type where is the bean and I used it in the class where I use Servlets. In the bean class I used Named and SessionScoped beans. So the beans store the info that is submitted by the user.