I have Spring application,I want to set parameter in URL and forward to URL.
For example,I click "Show detail" in index.html.Then go to /employees/show/1111.
ShowController.java get 1111.Now I click "show detail",result is white page error.
And I set break point ShowController.java,break point cannot was not working.
Where I should fix it?
Controller
#Controller
#RequestMapping("/employees/show/{employee.empId}/")
public class ShowController {
#Autowired
EmployeeService empService;
#GetMapping
public String details(#RequestParam("empId") String empId, Model model) {
Employee employee = empService.getEmployeeInfo(Long.parseLong(empId)); // break point at this row
model.addAttribute("employee", employee);
return "view/show";
}
index.html
<body>
<table>
<tr>
<th>Id</th>
<th>Name</th>
<th></th>
</tr>
<tr th:each="employee : ${employees}">
<td th:text="${employee.empId}"></td>
<td th:text="${employee.empName}"></td>
<td><a th:href="#{'/employees/show/' + ${employee.empId}}">Show detail</a></td>
</tr>
</table>
<br>
</body>
show.html
<body>
<div th:text="${employee.empId}"></div>
<div th:text="${employee.empName}"></div>
</body>
This folder structure.
The problem is the url. You are using /employees/show/{employee.empId}/ as a base url. And #GetMappingis not mapped to any url, so it takes the exact url from #RequestMapping("/employees/show/{employee.empId}/").
#RequestParam is to extract query parameters, form parameters, and even files from the request, while #PathVariable is used to tell Spring that part of the URI path is a value you want passed to your method.
So, in your case it seems mixed, you are using #RequestParam instead of #PathVariable.
#Controller
#RequestMapping("/employees/show/{employee:.*}/") //since spring will skip anything after a dot(.)
....
#GetMapping
public String details(#PathVariable("empId") String empId, Model model) {....}
Related
I have a table in my Thymeleaf template which shows database data. I have additional two columns which contain Like and Dislike buttons for each row. I want to enable liking/disliking "posts". My idea was to simply increment Like/Dislike count in a database by updating database entity. So, in my template I got this:
<table id="css-serial" class="table table-striped table-inverse">
<tbody>
<tr>
<th>#</th>
<th>Kategorija</th>
<th>Vic</th>
<th>Likes</th>
<th>Dislikes</th>
<th>Razlika</th>
<th>Like</th>
<th>Dislike</th>
</tr>
<tr th:each="joke : ${jokes}">
<form method="POST" th:object="${updateJoke}" th:action="#{/}">
<td></td>
<td> <pre th:text="${joke.getCatName()}"></pre> </td>
<td> <div class="preforma" th:text="${joke.getContent()}" th:field="*{content}"></div> </td>
<td th:text="${joke.getLikes()}" th:field="*{likes}"></td>
<td th:text="${joke.getDislikes()}" th:field="*{dislikes}"></td>
<td th:text="${joke.likesDislikesSubtraction()}"></td>
<td><input type="submit" value="Svidja mi se" name="like"/></td>
<td><input type="submit" value="Ne svidja mi se" name="dislike"/></td>
</form>
</tr>
</tbody>
</table>
Controller GET and POST methods:
#RequestMapping(value="", method=RequestMethod.GET)
public String showJokes(Model model){
model.addAttribute("jokes", jokeService.listAllJokes());
return "jokestable";
}
#RequestMapping(params="like", method=RequestMethod.POST)
public String likeJoke(Joke joke, Model model){
model.addAttribute("updateJoke", joke);
jokeService.likeJoke(joke);
return showJokes(model);
}
#RequestMapping(params="dislike", method=RequestMethod.POST)
public String dislikeJoke(Joke joke, Model model){
model.addAttribute("updateJoke", joke);
jokeService.dislikeJoke(joke);
return showJokes(model);
}
Relevant methods in service layer:
public void likeJoke(Joke joke){
jokeRepository.likeJoke(joke.getContent());
}
public void dislikeJoke(Joke joke){
jokeRepository.dislikeJoke(joke.getContent());
}
Repository:
public interface JokeRepository extends CrudRepository<Joke, Long> {
Joke findByContent(String content);
#Modifying
#Query("UPDATE Joke j SET j.likes = j.likes+1 WHERE j.content=:content")
void likeJoke(#Param("content") String content);
#Modifying
#Query("UPDATE Joke j SET j.dislikes=j.dislikes+1 WHERE j.content=:content")
void dislikeJoke(#Param("content") String content);
}
This obviously doesn't work, and every time I hit the Like button, nothing happens, but when I go to IntelliJ, I see "Request method 'GET' not supported" (first time after refresh it shows this two times for each button, then every next time, only once). Is this solution even possible, or I have to change my approach? Any ideas?
P.S. Service class is annotated with #Transactional
If anyone wonders why do I
return showJokes(model);
it's because if I return template name, it doesn't show database data anymore when I hit the buttons, there's just empty table then (only th elements).
I suppose that possible problem could be that every Like button for every row is named the same, as well as Dislike buttons. But I don't know how to solve this.
i have problem with display data on jsp page from using jstl.
This is my page, and displayed information:
EMPTY !!!
Name Email Action
get-user.jsp
<html>
<head>
<title>All users</title>
</head>
<body>
<c:if test="${empty webModels}">
<h3>EMPTY !!!</h3>
</c:if>
<table>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<c:forEach items="${webModels}" var="web">
<tr>
<td>${web.userName}</td>
<td>${web.userEmail}</td>
<td>${web.Action}</td>
</tr>
</c:forEach>
</tbody>
</table>
</body>
</html>
controller print information size 4
#RequestMapping(value = "/get-user", method = RequestMethod.GET)
public List<WebModel> getWebModels(){
List<WebModel> webModels = serviceWeb.getAllUser();
System.out.println(webModels.size()); //not empty
return webModels;
}
WebModel i getting data from database from a few table and main data i set in WebModel
public class WebModel {
private String userName;
private String userEmail;
private String Action;
//getter setter constructor
}
The documentation about return types of controller methods says:
Any other return type is considered to be a single model attribute to be exposed to the view, using the attribute name specified through #ModelAttribute at the method level (or the default attribute name based on the return type class name). The model is implicitly enriched with command objects and the results of #ModelAttribute annotated reference data accessor methods.
So, if I read it correctly, you should use list instead of webModels in your JSP, or you should annotate the method with
#ModelAttribute("webModels")
I am new to Spring and I get this exception, when entering campaigns.jsp with browser.
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'campaign' available as request attribute
I have this controller :
#Controller
#RequestMapping(value = "/admin")
public class AdminIndexController {
#RequestMapping(value = "/secure/campaigns.jsp", method = RequestMethod.GET)
public String campaigns() {
return "campaigns";
}
#RequestMapping(value = "/secure/create", method = RequestMethod.POST)
public String addContact(#ModelAttribute("campaign")
Campaign campaign) {
return "campaigns";
}
}
Campaings.jsp (if I remove this part, it shows the page correctly) :
<form:form method="post" action="create" commandName="campaign">
<table>
<tr>
<td><form:label path="question">Question</form:label></td>
<td><form:input path="question" />
</td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="Add Campaign"/>
</td>
</tr>
</table>
</form:form>
I suppose there is a problem with mapping action="create", I am not sure where it is pointing to. I thought it is pointing to the same place as the .jsp is. This is address I use http://localhost:8080/server/rest/admin/secure/campaigns.jsp
This
<form:form method="post" action="create" commandName="campaign">
expects a model attribute (or command object), an HttpServletRequest attribute in reality, with the name campaign to use as a template for the form fields.
You haven't added a request attribute with that name. You need to do that before the view is rendered. For example
#RequestMapping(value = "/secure/campaigns.jsp", method = RequestMethod.GET)
public String campaigns(Model model) {
model.addAttribute("campaign", new Campaign());
return "campaigns";
}
The object doesn't need to have any fields set since it is only used as a template.
I am teaching myself Spring Form tags, and have run into what is probably a simple error that I haven't been able to solve. I get the following error when I launch this app in a browser:
java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'index' available as request attribute
I've tried most of the fixes that came up in a Google search to no avail. Can someone spot where I went wrong? Below are the relevant components. Thanks very much.
Controller:
#Controller
#RequestMapping("/registration")
public class LoginController {
#RequestMapping(method = RequestMethod.GET)
public String setupForm(ModelMap model) {
Registration registration = new Registration();
model.addAttribute("registration", registration);
return "index";
}
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("registration") Registration registration, Map model) {
return "success";
}
}
JSP (/index.jsp):
<form:form commandName="index">
<table border="0" cellspacing="12">
<tr>
<td>
<form:input path="email"/>
</td>
</tr>
<tr>
<td>
<form:password path="password"/>
</td>
</tr>
<tr>
<td>
<input type="submit" value="Submit"/>
</td>
</tr>
</table>
</form:form>
Command Object (Registration.java) :
public class Registration {
private String password;
private String email;
// getters,setters
Facing same issue few days back, What i understood from hit and trail is, Index page is a static page and no processing happens before the same is rendered. In case i want to use a form model binding in index page i should have a controller's handler method which will create a Registration object and place the same in ModelAndView before index.jsp is rendered
add a method in your controller like the below and try
#RequestMapping(method = RequestMethod.GET, value="/")
public ModelAndView initiate(){
ModelAndView objModView = new ModelAndView("/index.jsp");
objModView.addObject("registration",new Registration());
return objModView;
}
In your index page correct the following and try
<form:form commandName="index"> to <form:form commandName="registration">
You can also do it like this if the above does not work
<form:form modelAttribute="registration" commandName="registration">
Thanks
The error which is seen is because when you submit the form you have to have a Binding Result associated with the #ModelAttribute annotation.
Try changing you code to this :
#RequestMapping(method = RequestMethod.POST)
public String onSubmit(#ModelAttribute("registration") Registration registration, BindingResult result, Map model){
return "success";
}
Also note that the Binding Result object should be followed immediately after the Model Attribute.
And if you are using two #ModelAttributes then each one should have its own binding result object which follows it.
Please refer the spring source guide for all the related documentation
http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html
I am trying out a sample project using Spring MVC annotated Controllers. All the examples I have found online so far bind the JSP to a particular model and the controller uses #ModelAttribute to retrive the model object in the handler method.
How do I go about passing other parameters (not present in the Model object) from the JSP to Controller? Do I use JavaScript to do this? Also can someone clarify what the HttpServletRequest object should be used for.
Thanks.
Just remove the "path" from the jsp input tag and use HttpServletRequest to retrieve the remaining data.
For example I have a bean like
public class SomeData {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Then in the jsp i will have the additional data fields to be send in normal html tag
<form:form method="post" action="somepage" commandName="somedata">
<table>
<tr>
<td>name</td>
<td><form:input path="name" /></td>
</tr>
<tr>
<td>age</td>
<!--Notice, this is normal html tag, will not be bound to an object -->
<td><input name="age" type="text"/></td>
</tr>
<tr>
<td colspan="2">
<input type="submit" value="send"/>
</td>
</tr>
</table>
</form:form>
Notice, the somedata bean has the name field the age is not. So the age field is added without "path". Without the path attribute the object property wont be bound to this field.
on the Controller i will have to use the HttpServletRequest like,
#RequestMapping("/somepage")
public String someAction(#ModelAttribute("somedata") SomeData data, Map<String, Object> map,
HttpServletRequest request) {
System.out.println("Name=" + data.getName() + " age=" + request.getParameter("age"));
/* do some process and send back the data */
map.put("somedata", data);
map.put("age", request.getParameter("age"));
return "somepage";
}
while accessing the data on the view,
<table>
<tr>
<td>name</td>
<td>${somedata.name}</td>
</tr>
<tr>
<td>age</td>
<td>${age}</td>
</tr>
</table>
somedata is the bean which provides the name property and age is explicitly set attribute by the controller.
If one doesn't want to create another class (bean) though it should be there, then apart from #ModelAttrbute one can also use #RequestParam.
public String someAction(#RequestParam("somedata") String data)
{
------
}