Ajax JQuery to Spring #RequestBody? How do I pass data? - java

Ajax JQuery to Spring #RequestBody? How do I pass data? I being doing spring for sometime now with passing form fields but I am working on a new system and we would like to use Ajax and RESTful to pass data. My controller looks like the sample one below but can someone please me with the ajax call to post it?? how do I post to the Spring controller and put the data in the body
#RequestMapping(method=RequestMethod.PUT, value="/employee/{id}")
public ModelAndView updateEmployee(#RequestBody String body) {
Source source = new StreamSource(new StringReader(body));
Employee e = (Employee) jaxb2Mashaller.unmarshal(source);
employeeDS.update(e);
return new ModelAndView(XML_VIEW_NAME, "object", e);
}

When using REST, it's important to understand the distinction between the different HTTP methods. PUT generally means that you're going to create a new collection or replace an existing one. POST generally means that you're adding a record to a collection. The main difference between the two is that PUT is idempotent, which means that repeating the same operation repeatedly doesn't change the state of the server.
In your code below, you're method is called "updateEmployee", which implies you're replacing a collection with a new one. Thus, PUT is the most appropriate HTTP Method to use in this scenario. However, you have a bug in your code. You didn't define the "id" in the parameter list:
// Added String id as a PathVariable
#RequestMapping(method=RequestMethod.PUT, value="/employee/{id}")
public ModelAndView updateEmployee(#RequestBody String body, #PathVariable String id) {
// You really don't need to do this. The Spring Framework can deserialize
// objects for you. However, one issue at a time ;)
// also, changed e to "employee" so the variable has a better name.
Source source = new StreamSource(new StringReader(body));
Employee employee = (Employee) jaxb2Mashaller.unmarshal(source);
employeeDS.update(employee);
return new ModelAndView(XML_VIEW_NAME, "object", employee);
}
To make the request to the server, use jQuery AJAX:
$.ajax({
url: "/employee/2?t="+new Date().getTime(),
contentType: 'application/x-www-form-urlencoded',
type: "PUT",
data: dataString,
context: document.body,
success: function(e){
alert(e);
},
error: function(jqXHR, textStatus, errorThrown) {
alert(" + textStatus + " : " + errorThrown);
}
});
dataString is a string representation of your data. You can either serialize the form, use JSON, or send a url-encoded form. Without seeing more code and more error messages in your question, it's unclear how you're representing your data when attempting to send it to the server. If you start here and fix the above errors in your Java code, this should get you past this specific error.
Another way to submit data to your REST method, just for testing, is to use a standard form, but use method="PUT", since that's what you're using in Spring:
<form name="test" action="/employee/2" method="PUT">
<input type="text" name="firstname" />
<input type="text" name="lastname" />
<input type="submit" name="submit" value="submit" />
</form>
This will use application/x-www-form-urlencoded. If you're unable to deserialize that, then try using JSON instead. Good luck!

Hope gives you a start!
$.ajax({
contentType : "application/json",
dataType : 'json',
type : "PUT",
url : targetUrl,
data : $(this).serializeObject(), //json serialization (like array.serializeArray() etc)
async : false,
success : function(data) {
// response
},
error : function(request, status, error) {
// any errors
}
});

Related

How to access form parameters using RestEasy REST.Request?

I have my form below:
<form id="form1" name="form1">
<fieldset>
<ol>
<li>
<label>Project:</label>
<select id="project" name="project" required></select>
</li>
</ol>
<input type="button" onclick="request();">
</fieldset>
</form>
I created a request() function on the onclick event of the input button. I changed the input type to button because I didn't want the page to reload.
The request function uses the RestEasy REST.Request class to create a custom rest request. I used setEntity on the REST.Request object but I don't know how to access that information on the server side.
Below is the request function:
request: function() {
var myRequest = new REST.Request();
var form1 = document.forms["form1"];
var projectTxt = form1.elements["project"].value;
myRequest.setURI(REST.apiURL + "/request/item");
myRequest.setMethod("GET");
myRequest.setEntity({project:projectTxt});
myRequest.execute(function(status, request, entity) {
if (status === 200 && request.readyState === 4) {
// entity is always null
sessionStorage.setItem("project", entity);
console.log("entity=" + entity);
}
});
},
In the above code, entity in the function passed to myRequest.execute() is always null.
Here is the Java code:
#Path("item")
#GET
public String itemFormatRequest(#FormParam("project") String project)
{
// project is always null
return "blarg!!! project is " + project;
}
In the above code, project is null. I've tried using #QueryParam and that doesn't work either. Am I just using this incorrectly or is there something else I'm missing? I've done much trial and error by changing #GET to #POST in both the javascript and java codes. Have also tried adding #Consumes("application/x-www-form-urlencoded") in the java code and that didn't work.
The only thing I did get to work is adding query parameters to the REST.request object like this:
myRequest.addQueryParameter("project", projectTxt);
And then I'm able to retrieve this using (#QueryParam("project") String project).
Thanks!
You are using GET as request method. A GET is intended to retrieve data and so you don't pass an entity. If you just want to read data of a selected project you can use a GET in conjunction with a #QueryParam. But then you don't pass an entity. Just add the queryParameter:
myRequest.addQueryParameter('project', projectTxt);
If you want to pass data to the server you should change the method of the request to POST (in the client and the server code). Also your entity is JSON but your server code expects a #FormParam. The REST.Request object has a addForm and add addFormParameter method. So one of the following should also work (untested):
myRequest.addForm('form1', form1);
or
myRequest.addFormParameter('project', projectTxt);

Post form without name preferably with JSoup

I am building an Android app and I want to post a html form that looks like this:
<form onsubmit="ShoutBox.postShout(); $('shout_data').value = ''; return false;">
Shout: <input type="text" id="shout_data" size="50"> -
<input type="submit" value="Shout Now!" id="shouting-status"></form>
I am using Jsoup in the rest of the application and I would preferably use it for this aswell.
I know about the .data(name, value) method, but since the html text and button don't have name attributes, that's not working. I can extract the field by using the ids and fill the field with: Element.val(String val); But I don't know how to post the form after that. Can anyone help me?
This is the JavaScript code for posting it:
postShout: function() {
message = $("shout_data").value;
if (message == "") {
return false;
}
$("shouting-status").value = ShoutBox.lang[0];
postData = "shout_data="+encodeURIComponent(message).replace(/\+/g, "%2B");
new Ajax.Request('xmlhttp.php?action=add_shout', {method: 'post', postBody: postData, onComplete: function(request) { ShoutBox.postedShout(request); }});
},
The post is not done via a form submit and post variables but via JavaScript and an XML HTTP request. JSoup is incapable to execute JavaScript. You need a browser that you can remote control. To do this headless in Java HTMLUnit is a good choice.

How to validate a form with the Play Framework 2 using javascript, i.e. jquery.ajax, and pass the rendered response to the view?

I am using The play framework 2.1.3 and have a question concerning form validation using jquery and ajax. I have followed the advice in this post (http://franzgranlund.wordpress.com/2012/03/29/play-framework-2-0-javascriptrouter-in-java/) for setting up JavaScript routing and that part is working great! I need help with the second part, returning a rendered form containing error messages and displaying it on my page. I have created the following example to illustrate my problem.
The routes file looks as follows:
# AJAX calls
POST /validateForm controllers.Application.validateForm()
# JavaScript Routing
GET /assets/javascripts/routes controllers.Application.javascriptRoutes()
The Application Controller looks as follows:
private static Form<User> form = Form.form(User.class);
public static Result validateForm() {
Form<User> boundForm = form.bindFromRequest();
if (boundForm.hasErrors()) {
return badRequest(user_form.render(boundForm));
} else {
return ok();
}
}
public static Result javascriptRoutes() {
response().setContentType("text/javascript");
return ok(Routes.javascriptRouter("jsRoutes", controllers.routes.javascript.Application.validateForm()
));
}
Without getting too technical, I am using Twitter Bootstrap to render my forms so I have created the following view element (see this post for more information Form validation and form helper) which is rendered by the validateForm action and returns it to the calling jquery.ajax() .
#(userForm: Form[User])
#import helper._
#implicitFieldConstructor = #{ FieldConstructor(twitterBootstrapInput.f) }
#form(routes.Application.createUser(), 'id -> "createUserForm") {
<fieldset>
<legend>New User</legend>
#inputText(userForm("name"), 'class -> "form-control", 'placeholder -> "First Name")
#inputText(userForm("surname"), 'class -> "form-control", 'placeholder -> "Last Name")
<button id="createUserBtn" type="button" class="btn">Create User</button>
</fieldset>
}
I am using jquery and my javascript file looks as follows. For the purposes of this question, assume validation fails and a badRequest is returned.
$("#createUserBtn").click(function() {
jsRoutes.controllers.Application.validateForm().ajax({
type: "POST",
data: $("#createUserForm").serialize(),
success: function(response) {
// something here
},
error: function(response) {
$("#createUserForm").html(response);
}
});
});
Without going into too much detail on the view, I correctly include the JavaScript file in the view and there is an element called #createUserForm.
The communication between client-side and server-side seems to be working great, however, I am unable to load the rendered view element contained in the response onto the page through .html(response). So, how does one accomplish this? Where have I gone wrong? I am fairly new to many of these concepts and would appreciate any helpful input. Thanks.
UPDATE:
Two changes changes will allow this code to work beautifully. (1) Since we are replacing the entire form, including the button, we need to make use of the jQuerys .on() to handle the button click event. (2) Calling responseText property will correctly return the html contained within the result.
$(document).on("click", "#createUserBtn", function() {
jsRoutes.controllers.Application.validateForm().ajax({
type: "POST",
data: $("#createUserForm").serialize(),
success: function(response) {
// something here
},
error: function(response) {
$("#createUserForm").html(response.responseText);
}
});
});
Any comments? How would you do this better?

How to send values of the select box to servlet using ajax or jquery?

Im new to ajax. I want to redirect to servlet with the parameter value of the select box to my servlet. This is my code and its not retrieving values when I use request.getParameter("type") it gives me a null.
<script>
$(document).ready(function() {
$('#type').change(function() {
$.get('pickasset', function(responseJson) {
var type = $('#type').val();
$.ajax({
type:'POST',
url: 'PickAssetServlet',
data: type
});
});
});
});
</script>
<form action="pickasset" method="post">
<select id="type" name="type">
<option value="Non-Sap">Non Sap</option>
<option value="Sap">Sap</option>
</select>
</form>
When i change the select box, it must go to servlet and do logic there.
send your data like this-
data: { type : type }
If you're not getting the selected option from the select field, you need to use
$('#type').find(":selected").text() to retrieve the selected option. val() doesn't work with select fields. Also do what pXL said because that's how you send data with jQuery ajax methods
Check box value must be obtained from checkbox in the right way, as mentioned in jQuery docs (http://api.jquery.com/val/), just pay attention to multiple select, you're gonna have an array of values. You are doing it right, according to docs.
var varValue = var type = $('#type').val();
Then sending data as 'json' you will be able to read them with request.getParameter('type')
data: { "type" : varValue }
If you still get null, try to check if your "type" param and his value are in the request (chrome request inspector will be usefull, then check it in the debugger).
.
P.S.
Just check if you have something in your webapp filterchain that may wrap you request or hide some params, in some large web-app you get lost very easly.

Avoiding html in servlet

I'm on a jsp page and I am doing an ajax call to a servlet which in return provides full html code to be displayed on page. It works fine but looks cluttered in servlet file to have multiple printWriter.write(...) lines with html code in it. It becomes hard to maintain as I have to create a large html code via servlet. Is there any other proper/better way to do this? I have cmobination of write html lines and logic in servlet and it will be hard to separate them.
The ajax call in jsp page:
$.ajax({
type: 'POST',
url: 'myServlet',
data: requestData,
dataType: "text",
}).done(function(responseData) {
$(divId).html(responseData);
});
Some code from servlet class:
.....
String username = user.getName();
if (username != null && !username.trim().isEmpty())
username = username.substring(0, username.indexOf(" "));
else
username = "";
printWriter.write("<span id=\"username_"+i+"\" style=\"display: none;\">"+ username +"</span>");
printWriter.write("<form action=\"\" method=\"post\" name=\"userClickForm_"+i +"\" id=\"userClickForm_"+i +"\">");
printWriter.write(" <input type=\"hidden\" name=\"userId\" value=\""+userId +"\"/>");
printWriter.write("</form>");
......
The main reason of mixing html code and business logic is I have to provide div id based on conditions and loop structure.
You should use some form of template or transformation technology. Since you're using jQuery and JSPs this can be either a server-side JSP or a client-side jQuery template plugin.
Early JSP MVC patterns take this form:
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// read inputs
String foo = request.getParameter("foo");
// perform business logic
SomeResults results = new SomeDataSource().lookupDatabase(foo);
// place results into scope
request.setAttribute("results", results);
// dispatch to JSP to render results
request.getRequestDispatcher("result.jsp")
.forward(request, response);
}
This approach can be used with an AJAX call.
Alternatively, you can respond with JSON or XML data and parse this in the JavaScript, then use a JavaScript template engine to do something similar to the logic performed in the JSP.
You can avoid that by using MVC framework like STRUTS or SPRING.
Use xml rather than html on servlet and on jsp use success attribute of ajax call using jquery.... In my case its working, bt i have used type as 'GET'.
$.ajax({
url: ,
data: ,
type: ,
dataType: 'xml',
async: true,
success:function(xmlDoc)
{
var message = xmlDoc.getElementsByTagName("message");
message = message[0].firstChild.data;
}
});
And in Servlet use::
res.getWriter().write("<response><message>abcdefg</message></response>");
You should use JSP's. It will be on different pair of servlet/jsp request, not the request initiating ajax call.

Categories

Resources