Spring MVC: Show data in a dialog after making an AJAX call - java

I am new to Spring and web technology.
I have an table which contains a column with hyperlink. When I click on the hyperlink of a row, I need to display that rows data along with other details in a dialog. My controller method returns a ModelAndView which contains the data I need to show and the display page.
Problems:
How to show the dialog? and
How to pass the data to the dialog?
Table.jsp
<script type="text/javascript">
function showDialog(ref, date) {
$ajax({
type: "POST",
url: "/example/show.htm",
data: {
ref: ref,
date: date
}
success: function(data) {
},
error: function(data) {
}
});
}
</script>
Mapping
#RequestMapping(value = "show.htm", method=RequestMethod.POST)
public ModelAndView show(#RequestParam("ref") String ref, #RequestParam("date") String date,
HttpServletRequest request, HttpServletResponse response) {
ModelAndView modelAndView = new ModelAndView();
try {
SampleDTO SampleDTO = new SampleDTO();
sampleDTO.setDate(sdf.parse(date));
sampleDTO.setRef(ref);
SampleDTO billDto = // server call modelAndView.addObject("showBill", sampleDto);
modelAndView.setViewName("Dialog");
}
return modelAndView;
}

Your code is wrong, you are messing things, if you want to use jQuery and ajax calls then don't use ModelAndView in your Spring controller. Instead of that, use the following and return your bean or dto as a json using Jackson library from Java:
Include this jar in your lib project folder:
http://www.java2s.com/Code/JarDownload/jackson/jackson-all-1.9.9.jar.zip
Java code:
#RequestMapping(value = "businessBill.htm", method = RequestMethod.POST)
#ResponseBody
public String handleBusinessBillDetails(#RequestParam("reference") String billReference, #RequestParam("invoiceDate") String billDate,
HttpServletRequest request, HttpServletResponse response) {
String json = null;
try {
//1. Create 'jackson' object mapper
ObjectMapper objectMapper = new ObjectMapper();
BusinessBillDTO businessBillDTO = new BusinessBillDTO();
businessBillDTO.setBillDate(sdf.parse(billDate));
businessBillDTO.setBillReference(billReference);
BusinessBillDTO billDto = accountStatementBO.getBusinessBillDetails(businessBillDTO);
//2. Convert your 'bean' or 'dto' as 'json' string
json = objectMapper.writeValueAsString(billDto);
} catch (Exception ex) {
LOGGER.error(ex);
}
return json;
}
Then, in Table.jsp put the div used in Dialog.jsp as hidden, this will be your modal dialog in future (note that there are some changes in the span tags also):
<div id="BusinessBill" style="display:none;">
<h2>Bill Details</h2>
<em>Business Ltd</em>
<div class="row">
<span class="spanAsLabel">Account number</span>
<span id="dlg-account-number" class="spanAsLabel"></span>
</div>
<div class="row">
<span class="spanAsLabel">Bill date</span>
<span id="dlg-bill-date" class="spanAsLabel"></span>
</div>
</div>
Now fix your getBusinessBill(..) method like this:
You can also use $.ajax and maybe handle more states like onerror and others but this way is simpler (at least for me, you just need to evaluate if the returned data is null or not and let know the user - if null - that something happened at server side, maybe showing an alert with a generic message) - please read comments.
function getBusinessBill(billReference, billInvoiceDate) {
$.post("/AccountStatement/businessBill.htm", {
reference: billReference,
invoiceDate: billInvoiceDate
}, function (data) {
/* You can implement more validations for 'data', in my case I just used these 'if' conditionals but can vary. */
if(data != null) { //returned 'data' is not 'null'
/* parse 'data' as 'json' object
* will be good to console.log(data) and take a look. */
var obj = $.parseJSON(data);
if(obj != {}) { //check if 'data' is not an empty 'json' object once transformed
//set the 'data' in the dialog
$('#dlg-account-number').text(obj.accountNumber);
$('#dlg-bill-date').text(obj.billDate);
/* open modal dialog, you can simulate it this way (for this case)
* but the correct way is to use 'jquery-ui' dialog or any plugin you prefer.
* At this point you will see the hidden 'div' in a visible way with your 'data'.
*/
$('#BusinessBill').fadeIn();
} else {
//show 'generic' message
alert('No results found.');
}
} else {
//show 'generic' message
alert('An error occurred, try again.');
}
});
}
Finally, if everything is correct, you will see at the same page (Table.jsp) the modal dialog with your data, all made by an ajax call to avoid redirection pages like (Table.jsp to => Dialog.jsp).

Related

Why is this JSON String invalid? jQuery.parseJSON function throws invalid character

When trying to parse the JSON being returned by my Serlvet to my JSP page the following line of code is throwing a invalid character exception :
var obj = jQuery.parseJSON(data);
CLIENT SIDE CODE
<script type = "text/javascript">
function updateProgrammerDetails(site, Id) {
$.post('EngineAdminServlet',
{
action: "updateProgrammerMenu",
siteDetails: site,
ID: Id,
},
function(data, status){
var pid, name, sky, ip, eleven;
var obj = jQuery.parseJSON(data);
.........
}
}).fail(function(error) {
alert("Error retrieving details from server");
}); //end ajax call
}
</script>
JSON STRING GENERATED USING GSON
I've imported the GSON library in my Servlet class in order to convert my Java object 'ProgrammerForJSP' to a JSON string. This was recommended on other posts to avoid any typos when creating the JSON string myself. This is the string it returned:
{"ID":123,"siteName":"VEGAS","skyl":"WZ0019","ipAddress":"0.0.0.0","code":"L/BEG"}
SERVLET CODE
....
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
String gson = new Gson().toJson(myObject);
response.getWriter().write(gson);
} //end of method
I don't know if I'm missing a step or doing something wrong? My thought is that the IP address field might be throwing off the parser and breaking the code (hence the invalid character exception) because it contains period characters in it? I really have no idea.
EDIT
I'm using jquery-1.11.3.js
The error is because the $.post method has already detected a JSON response and parsed the result to an object for you. You are then trying to call parseJSON on an object instead of a JSON string, which results in the error you've seen. You simply need to remove the call to $.parseJSON. Try this:
function updateProgrammerDetails(site, Id) {
$.post('EngineAdminServlet', {
action: "updateProgrammerMenu",
siteDetails: site,
ID: Id,
}, function(data, status) {
var pid, name, sky, ip, eleven;
// work with the object in 'data' here, E.g:
console.log(data.ID, data.siteName); // = 123, 'VEGAS'
}).fail(function(error) {
alert("Error retrieving details from server");
}); //end ajax call
}

How pass a List to JSP page without loading the JSP

I am using the Spring MVC framework ModelAndView method in controller to display a page. On the page, I have an element dropdown element and table. On selection of an option in the dropdown, I am passing the Id of the element to the controller and querying the results for the selected option. I am using Hibernate to fetch data from the db. So, the result is in the form a list of objects. I have to populate this result in the table.
The following code will display a JSP and pass a list reference to JSP. I am using that reference to populate options on the page.
Code:
List<String> users = new ArrayList<String>();
ObjectMapper objectmapper = new ObjectMapper();
String string = "";
ModelAndView model = new ModelAndView("xxxx");
containerList = mapper.writeValueAsString(users);
List<Intermediate> list = getIntermediateList();
model.addObject("IntermediateList" , List);
return model;
JSP code:
<td>Intermediate</td>
<td>
<select class="form-control margin" id = "dpd" >
<option value="0" selected>--Select--</option>
<c:forEach var="list" items="${IntermediateList}">
<option label="${list.name}" value="${item.id}"></option>
</c:forEach>
</select>
</td>
On select of an option from the dropdown, it will make a ajax call and pass the selected Id to the controller method:
Ajax call code:
$("#dpd").change(function(e){
var intermediate = $("#dpd").val();
var data = {
Intermediate : intermediate
};
$.ajax({
method : 'POST',
url : 'intermediateUsers',
data : data ,
success : function(result) {
alert("Success");
}
,
error : function(result) {
alert('An error occurred.');
}
});
Controller code for querying the list:
#RequestMapping("/intermediateUsers")
#ResponseBody
public List<Users> intermediateUsers(#RequestParam(value = "intermediate" ,required = false) String intermediate) {
List<Users> users = null;
int selection = Integer.parseInt(intermediate);
users = service.intermediateUsers(selection);
return users;
}
It is working fine to this point and I am able to get the list of users based on the selected option.
Please suggest how I may pass this list to the JSP, not by loading the entire page but by loading only the table element to populate the list. I tried many ways, like converting that list into a JSONObject, but nothing has worked.
You can use something like this
function showContacts(response){
$("#tableid tbody tr").remove();
$.each(response.contacts, function(i, contact) {
$("#tableid tbody").append(
$('<tr>').append($('<td>').text(contact.name),
$('<td>').text(contact.phoneNumber),
$('<td>').text(contact.address)
));
});
}
function loadContacts(){
$.ajax({
type: "GET",
url: "url/contacts",
success: function( response ){
showContacts(response);
}
});
}

How to get ArrayList data from action class inside a javascript?

I'm gong to making an autocompleter using jquery autocompleter. In my case I need to load some data from a method. That method(return a list) has a parameter and I need to pass the textfield input as the method argument. Is this possible? If it is how can I do this?
Method is,
public List<Item> getSuggestedData(String def) {
EntityManager em = getEntityManager();
try {
Query q = em.createQuery("select o from Item o WHERE o.itemName like :def");
q.setParameter("def", def + "%");
return q.getResultList();
} finally {
em.close();
}
}
index.jsp,
<script>
$(function() {
var availableTags = [/*I need to load data to here*/];
$( "#tags" ).autocomplete({
source: availableTags
});
});
</script>
<div class="ui-widget">
<s:textfield id="tags"/>
</div>
try this
$.ajax({
async:settings.Async,url:Url,cache:false,type:'POST',data:$("#tags").val()
}).done(function (result) {
$( "#tags" ).autocomplete({
source: result
});
});
jQuery is a client side script and java code is on server side. You need to send a HTTP request from client to the server to get your list of tags. You can do this by AJAX. jQuery has a good support for AJAX.

json string can't be posted as plain string through jquery ajax?

I want to post a json string as plain string to a action ,then convert the string to List using gson, but the string is still treated as json object by jquery/webwork, I'm using jquery 1.43+webwork+gson, no jquery json plugin or something.
here is action:
public class ImageAction extends BaseAction {
private String pks;
public void setPks(String pks) {
this.pks = pks;
Gson gson=new Gson();
List<Map> list=gson.fromJson(pks,new TypeToken<List<Map<String,String>>>(){}.getType());
System.out.println(list.size());
}
......
}
jquery code:
j$.ajax({
url:approveUrl,
data: {pks:'[{"userName":"theoffspring"}]'},
// dataType:'json',
type:'post',
// traditional: true,
success:function (response) {
hideProgressBar(parent.document)
if (response.result==false){
alert(response.msg);
return;
}
// document.location.reload();
}
})
I want pks posted as a common string instead of json object. But setPks method turns out not to be invoked when I invoke the jquery code. So strange.
you have'nt serialized the data you are sending through ajax.serialize it at client using JSON.stringify() and send it will be converted to a single string.
modify your code to:
$.ajax({
url:approveUrl,
data:JSON.stringify(yourdata),
// dataType:'json',
type:'post',
// traditional: true,
success:function (response) {
hideProgressBar(parent.document)
if (response.result==false){
alert(response.msg);
return;
}
// document.location.reload();
}
})
this might work.
Have a look at this: http://jsfiddle.net/flocsy/vuGL9/
You'll see that your pks is actually sent as a string as you want it, when it's not sent as a string (pks2) it'll look different.
PS: look at the network tab in firebug or inspect element, depending on your browser:
pks: '[{"userName":"theoffspring"}]'
pks2[0][userName2]:'hehe'
So probably your server side does some magick...

JavaScript - how to display error message from backend system based on Spring MVC

I have a web application with HTML / jQuery which ic connected with AJAX / JSON to a backend system with Java EE / Spring MVC.
In the frontend, a Person can be created by fill in the form fields and then it is submitted and this jQuery code executed:
var person = $(this).serializeObject();
$.postJSON("add/", person, function(data) {
alert("Person with ID "+data.person.id+"' added successfully");
});
In the best case, the Person is created and I'll get a Person object and I can access the values with data.person.*.
Now I want to validate the data which is sent to the backend system and in a case of an error, I want to display in the first step an alert error message.
I did this in the backend system:
#RequestMapping(value="add/", method=RequestMethod.POST)
public #ResponseBody Map<String, ? extends Object> addPerson(#RequestBody Person p, HttpServletResponse response) {
Set<ConstraintViolation<Person>> failures = validator.validate(p);
if (!failures.isEmpty()) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return validationMessages(failures);
} else {
Person person = this.personService.addPerson(p);
return Collections.singletonMap("person", new SerialPerson(person.getId(), person.getName(), ...));
}
}
// internal helpers
private Map<String, String> validationMessages(Set<ConstraintViolation<Person>> failures) {
Map<String, String> failureMessages = new HashMap<String, String>();
for (ConstraintViolation<Person> failure : failures) {
failureMessages.put(failure.getPropertyPath().toString(), failure.getMessage());
System.out.println(failure.getPropertyPath().toString()+" - "+failure.getMessage());
}
return failureMessages;
}
My Person object is annotated, and I get the System.out.println(failure.getPropertyPath().toString()+" - "+failure.getMessage()); on the console, that for example, "name - must be between 1-30 chars"
But how can create an alert message in jQuery in the frontend system?
Thank you in advance for your help & Best Regards.
Update: Link to the Spring MVC AJAX example, where I found the validationMessages method. But there is also no solution how to get the error message.
SOLUTION:
I have to call:
jQuery.ajax({
'type': 'POST',
'url': "add/",
'contentType': 'application/json',
'data': JSON.stringify(person),
'dataType': 'json',
'success': function(data) {alert("success");},
'error': function(xhr) {alert(xhr.responseText);}
});
You can do something like this:
var person = $(this).serializeObject();
$.postJSON("add/", person, function(data) {
if(data.person) {
alert("Person with ID "+data.person.id+"' added successfully");
}
else {
var errors = "";
for(var key in data) if(data.hasOwnProperty(key)) {
errors += data[key] + "\n";
}
alert(errors);
}
});
You shouldn't need to send back a bad request either. Is this what you want?
UPDATE
You can use the code shown in Spring Source, but you'd have to use jQuery.ajax
jQuery.ajax({
type: 'POST',
url: "add/",
data: person,
dataType: "json",
success: function(data) {
alert("Person with ID "+data.person.id+"' added successfully");
},
error: function(XMLHttpRequest, textStatus, errorThrown) {
var errorJSON = JSON.parse(XMLHttpRequest.responseText); //if this is JSON otherwise just alerting XMLHttpRequest.responseText will do
var errors = "";
for(var key in errorJSON) if(errorJSON.hasOwnProperty(key)) {
errors += errorJSON[key] + "\n";
}
alert(errors);
}
});

Categories