why autocomplete does not work with JSON and SPRING MVC - java

I am puzzled why autocomplete does not work. Here is the form in the .jsp code below:
<form:form method="post" action="save.html" modelAttribute="word">
<table>
<tr>
<th>German word</th>
<td><form:input path="german" id="german" /></td>
</tr>
<tr>
<td colspan="2"><input type="submit" value="Save" /></td>
</tr>
</table>
<br />
</form:form>
here are the javascript functions (in the same .jsp file)
$(document).ready(function() {
$( "#german" ).autocomplete({
source: '${pageContext. request. contextPath}/get_word_list.html'
});
});
and here is the relevant part of the controller:
#Autowired
private WordService wordService;
#RequestMapping(value = "/goToDictionary", method = RequestMethod.GET)
public ModelAndView index() {
Word word = new Word();
return new ModelAndView("dictionary", "word", word);
}
#RequestMapping(value = "/get_word_list", method = RequestMethod.GET, headers = "Accept=*/*")
public #ResponseBody
List<String> getCountryList(#RequestParam("term") String query) {
System.out.println(query);
return getMatch(query);
}
public List<String> getMatch(String query) {
query = query.toLowerCase();
List<String> matched = new ArrayList<String>();
for (Word v : wordService.getAllWord()) {
if (v.getGerman().toLowerCase().startsWith(query)) {
matched.add(v.getGerman());
}
}
return matched;
}
I know for sure that the getMatch(String query) gets called and works properly.
So I guess the problem is on the jsp. file
any help is greatly appreciated.

[For JSON to fill the list]
Maybe you should look at the produces property of the #RequestMapping annotation. It takes a String[] as value. Available since Spring 3.1.x version. I currently use the 3.1.2 and I can get some application/json without any problem.
And of course you should add the produces in the data provider of your country list.
[For JavaScript to fill the list]
Maybe the part ${pageContext. request. contextPath} is not evaluated correctly. Did you check inside the produced code of your JSP e.g. with Firebug.

OK, I have found the solution. it is in the spring-servlet.xml file. It did not work because i failed to add this.
xsi:schemaLocation="ttp://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
I added, and now everything is OK

Related

Http status 400 -The request sent by the client was syntactically incorrect. Spring MVC

I spent a lot of time on this problem, but can`t resolve it. Please Help! When I submit form from JSP I get this error.
My code:
<form action="/albums/add" method="post">
<%--<div><input type="file"></div>--%>
<div>Name: <input type="text" name="name" placeholder="Name"></div>
<div>Year: <input type="text" name="year" placeholder="Release year"></div>
<div>
<select name="singer" id="singer">
<c:forEach items="${singers}" var="s">
<option value="${s.id}">${s.name}</option>
</c:forEach>
</select>
</div>
<input type="submit" >
And my controller code:
#RequestMapping(value = "", method = RequestMethod.GET)
public String albumsGET(ModelMap map) {
List<Album> albums = albumDAO.getAllAlbums();
map.addAttribute("albums", albums);
return "forward:/Albums.jsp";
}
#RequestMapping(value = "/add", method = RequestMethod.GET)
public String albumsAddGET(ModelMap map) {
map.put("singers", singerDAO.getAllSingers());
return "forward:/WEB-INF/Pages/Album/AddAlbum.jsp";
}
#RequestMapping(value = "/add", method = RequestMethod.POST)
public String albumsPOST(#ModelAttribute Album album, HttpServletRequest req) {
Singer s = singerDAO.getSingerById(Long.valueOf(req.getParameter("singer")));
s.getAlbumList().add(album);
album.setSinger(s);
singerDAO.updateSinger(s);
return "redirect:/albums";
}
}
You can throw custom exception provided by spring, create class with #ControllerAdvice annotation and throws custom exception with different HTTP status code
That is parameter mapping error for #ModelAttribute which HTTP return code 400.
There are some reasons that rises this error.
There is no parameter name for your Album Object.
There are NULL value for mapping Album Obejct.
So, if you can check item ${singers}, you should check substituted properly value.
Next, in Album Object, you should check getter/setter method.
I could have resolved that issue to setting default values for Object (etc. VO)

Passing object's variable to controller in thymeleaf

I'm trying to create my very first CRUD ever.
Here's my journeySite.html table code.
<table>
<tr th:each="trip : ${trips}">
<td th:text="${trip.title}"></td>
<td th:text="${trip.destination}"></td>
<td th:text="${trip.id}"></td>
<form th:action="#{/journeys}" th:object="${trip}" method="post">
<input type="hidden" th:field="${trip.id}" />
<button type="submit">Delete</button>
</form>
</tr>
</table>
And make a my controller looks now like that.
#RequestMapping(value = {"/journeys"}, method = RequestMethod.GET)
public String journeysPage(Model model){
tripRepository.save(new Trip("Asian Trip", "Asia"));
tripRepository.save(new Trip("European Trip", "Europe"));
tripRepository.save(new Trip("African Trip", "Africa"));
model.addAttribute("trips", tripRepository.findAll());
return "journeysSite";
}
#RequestMapping(value = {"/journeys"}, method = RequestMethod.POST)
public String journeysPageTripDeleting(#RequestParam Long id) {
tripRepository.delete(id);
return "journeysSite";
}
All i want is to show my all my trips on the /journeys in table. In each row there'd be a delete button which would POST trip.id, delete it from db and redirect to the exact same page, but with trip deleted.
But obviously error has occured: java.lang.IllegalStateException: Neither BindingResult nor plain target object for bean name 'id' available as request attribute
at org.springframework.web.servlet.support.BindStatus.<init>(BindStatus.java:144) ~[spring-webmvc-4.3.6.RELEASE.jar:4.3.6.RELEASE]
Would anyone give me a tip how to do it? Thanks.
At your form, you defined a th:object="${trip}" object which means whenever this form gets submitted this trip object will be sent as request body.
So, to receive this object you have to accept it in controller's method.
#RequestMapping(value = {"/journeys/"}, method = RequestMethod.POST)
public String journeysPageTripDeleting(#ModelAttribute Trip trip){
tripRepository.delete(trip.getId());
return "redirect:/journeys";
}
The th:field="${id}" will be included with the object that model attribute provides so, trip object will have the id you're looking for.
More on this.
UPDATE:
With your current controller's method implementation, I think all you need to change is this,
<input type="hidden" th:field="*{id}" /> // No trip.id
You need to change your controller method post code from #RequestMapping(value = {"/journeys/"}, method = RequestMethod.POST) to #RequestMapping(value = {"/journeys/{id}"}, method = RequestMethod.POST).
As you can see,You forgot to add {id} in your RequestMapping which is required.
Also its standard to use DELETE http method for deleting an entity not POST method.
This is not good practice to create form for each row. Instead do it this way:
<table>
<tr th:each="trip : ${trips}">
<td th:text="${trip.title}"></td>
<td th:text="${trip.destination}"></td>
<td th:text="${trip.id}"></td>
<td><button class='delete' data-id="${trip.id}">Delete</button></td>
</tr>
</table>
Add this js in your html:
<script>
$(document).ready(function () {
$(document).on('click', '.delete', function () {
$.ajax({
url: "<c:url value="/journeys/delete"/>",
data: {
id: $(this).data("id")
},
success: function(data) {
location.reload();
}
})
})
})
</script>
And change your controller method like this:
#RequestMapping(value = {"/journeys/delete"}, method = RequestMethod.GET)
#ResponseBody
public String journeysPageTripDeleting(#RequestParam Long id) {
tripRepository.delete(id);
return "success";
}

Hibernate Spring: inserting multiple entries at once

Currently I am struggling with the problem as below:
I have a program that will hold information on the electricity meters and their readings.
I wanted to create a form in which I can insert all the readings for all registered meters at once.
I am currently stuck at this point:
Here is my controller:
#RequestMapping("/registerEnergyReading")
public ModelAndView registerEnergyReading(#ModelAttribute("reading") Reading reading, BindingResult result) {
List<ElectricityMeter> meters= meterService.getMeterList();
Map<String, Object> model = new HashMap<String, Object>();
model.put("meters", meters);
System.out.println("Register Form");
return new ModelAndView("RegisterEnergyReading", "model", model);}
Now the jsp file would create a table dynamically based on how many meters are there.
That would be done by < c:forEach items="${meters}" var="meters" >
But the tricky part for me is how to pass these multiple entries for the next controller to be saved? What form should be used here?
#RequestMapping("/saveReadings")
public ModelAndView saveReadings(
#ModelAttribute("reading") List<Reading> reading, BindingResult result) {
for(Reading i:reading) {
readingService.saveReading(i);
}
return new ModelAndView("redirect:/najemcaLista.html");
}
Am I going the right direction here?
Appreciate your help,
Maciej
I got a bit further but got stuck.
My controller looks now:
#RequestMapping("/registerEnergyReading")
public ModelAndView registerEnergyReading(
#ModelAttribute("listReadingModel") ListReadingModel listReadingModel, BindingResult result) {
List<EnergyMeter> energyMetersList= meterService.getMeters();
List<EnergyReading> readings= new ArrayList<EnergyReading>();
for (int i = 0; i < energyList.size(); i++) {
EnergyReading reading= new EnergyReading ();
reading.setMeter(energyList.get(i));
readings.add(reading);
}
listReadingModel.setEnergyReadings(readings);
Map<String, Object> model = new HashMap<String, Object>();
model.put("energyMetersList", energyMetersList);
model.put("readings", readings);
return new ModelAndView("registerEnergyReading", "model", model);
}
#RequestMapping("/saveEnergyReading")
public ModelAndView saveEnergyReading(
#ModelAttribute("listReadingModel") ListReadingModel listReadingModel, BindingResult result) {
List<EnergyMeter> energyMetersList=listReadingModel.getEnergyReadings()
for (EnergyReading i : reading) {
readingService.saveReading(i);
}
return new ModelAndView("redirect:/energyReadingsList.html");
}
here is my view file:
<c:url var="listReadingModel" value="listReadingModel.html" />
<form:form id="listReadingModel" modelAttribute="listReadingModel" method="post" action="${listReadingModel}">
<table width="400px" height="150px">
<c:forEach items="${model.readings}" var="readings">
<tr>
<td>${readings.meter.description}</td>
<td><form:label path="${readingValue}">Reading Value</form:label></td>
<td><form:input path="${readingValue}" /></td>
<td><form:label path="${readingDate}">date</form:label></td>
<td><form:input type="date" path="${readingDate}" /></td>
</tr>
</c:forEach>
<tr>
<td colspan="6"><input type="submit" value="Save" /></td>
</table>
</form:form>
'
When I open the page in browser it all looks ok (there are as many fields as there should be) but when I press "save" I get java.lang.NullPointerException. It seems the form doesn't pass listReadingModel to controller. Any ideas how to solve it? Appologies for any typos. The code is in different language so I translated it on the go.
Regards, Maciej
If I understand you right, I think what you need is to create a wrapper class as
public class ListReadingModel {
private List<Reading> readings;
// Getter, setter
}
And then under your registerEnergyReading method, add this ListReadingModel to your Model.
ListReadingModel listReadingModel = new ListReadingModel ();
model.put("listReadingModel", listReadingModel);
You can bind your ListReadingModel to your form element in the jsp file.
<form:form method="POST" commandName="listReadingModel">
// add meters and readings here
When submitted your jsp you can call your controller like that:
#RequestMapping("/saveReadings")
public ModelAndView saveReadings(
#ModelAttribute("listReadingModel") ListReadingModel listReadingModel , BindingResult result) {
List<Reading> reading = listReadingModel.getReadings();
for(Reading i:reading) {
readingService.saveReading(i);
}
return new ModelAndView("redirect:/najemcaLista.html");
}
This can work but I did not try it. You can search named wrapper class on google to find more information.

Spring, IllegalStateException when opening page with form

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.

Spring Form Tag Error (Binding Result)

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

Categories

Resources