How to get object from http request in servlet? - java

I use jquery to send a json object servlet
It send the following data in the request
Form Dataview URL encoded
stringArray[]:s1
stringArray[]:s2
stringArray[]:s3
objectArray[0][key1]:val1
objectArray[0][att1]:att val1
objectArray[1][key2]:val2
objectArray[1][att2]:att val2
objectArray[2][key3]:val3
objectArray[2][att3]:att val3
for the string array, I can use request.getParameterValues["stringArray"]
but the object array is cannot. How I can get the json array in the servlet?
var json={"stringArray":["s1", "s2", "s3"],
"objectArray":[{"key1":"val1", "att1":"att val1"},
{"key2":"val2", "att2":"att val2"},
{"key3":"val3", "att3":"att val3"}]
};
$.ajax
(
{
url:'../test',
data:json,
type:'post',
cache:false,
dataType:'json',
success:function(data)
{
},
error:function(){alert('error');}
}
);

You first need parse the JSON array in the servlet, then you can use this.
http://answers.oreilly.com/topic/257-how-to-parse-json-in-java/
;-)

Related

String param in a REST service using POST method [duplicate]

In the code below, the AngularJS $http method calls the URL, and submits the xsrf object as a "Request Payload" (as described in the Chrome debugger network tab). The jQuery $.ajax method does the same call, but submits xsrf as "Form Data".
How can I make AngularJS submit xsrf as form data instead of a request payload?
var url = 'http://somewhere.com/';
var xsrf = {fkey: 'xsrf key'};
$http({
method: 'POST',
url: url,
data: xsrf
}).success(function () {});
$.ajax({
type: 'POST',
url: url,
data: xsrf,
dataType: 'json',
success: function() {}
});
The following line needs to be added to the $http object that is passed:
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
And the data passed should be converted to a URL-encoded string:
> $.param({fkey: "key"})
'fkey=key'
So you have something like:
$http({
method: 'POST',
url: url,
data: $.param({fkey: "key"}),
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}
})
From: https://groups.google.com/forum/#!msg/angular/5nAedJ1LyO0/4Vj_72EZcDsJ
UPDATE
To use new services added with AngularJS V1.4, see
URL-encoding variables using only AngularJS services
If you do not want to use jQuery in the solution you could try this. Solution nabbed from here https://stackoverflow.com/a/1714899/1784301
$http({
method: 'POST',
url: url,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: xsrf
}).success(function () {});
I took a few of the other answers and made something a bit cleaner, put this .config() call on the end of your angular.module in your app.js:
.config(['$httpProvider', function ($httpProvider) {
// Intercept POST requests, convert to standard form encoding
$httpProvider.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
$httpProvider.defaults.transformRequest.unshift(function (data, headersGetter) {
var key, result = [];
if (typeof data === "string")
return data;
for (key in data) {
if (data.hasOwnProperty(key))
result.push(encodeURIComponent(key) + "=" + encodeURIComponent(data[key]));
}
return result.join("&");
});
}]);
As of AngularJS v1.4.0, there is a built-in $httpParamSerializer service that converts any object to a part of a HTTP request according to the rules that are listed on the docs page.
It can be used like this:
$http.post('http://example.com', $httpParamSerializer(formDataObj)).
success(function(data){/* response status 200-299 */}).
error(function(data){/* response status 400-999 */});
Remember that for a correct form post, the Content-Type header must be changed. To do this globally for all POST requests, this code (taken from Albireo's half-answer) can be used:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
To do this only for the current post, the headers property of the request-object needs to be modified:
var req = {
method: 'POST',
url: 'http://example.com',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: $httpParamSerializer(formDataObj)
};
$http(req);
You can define the behavior globally:
$http.defaults.headers.post["Content-Type"] = "application/x-www-form-urlencoded";
So you don't have to redefine it every time:
$http.post("/handle/post", {
foo: "FOO",
bar: "BAR"
}).success(function (data, status, headers, config) {
// TODO
}).error(function (data, status, headers, config) {
// TODO
});
As a workaround you can simply make the code receiving the POST respond to application/json data. For PHP I added the code below, allowing me to POST to it in either form-encoded or JSON.
//handles JSON posted arguments and stuffs them into $_POST
//angular's $http makes JSON posts (not normal "form encoded")
$content_type_args = explode(';', $_SERVER['CONTENT_TYPE']); //parse content_type string
if ($content_type_args[0] == 'application/json')
$_POST = json_decode(file_get_contents('php://input'),true);
//now continue to reference $_POST vars as usual
These answers look like insane overkill, sometimes, simple is just better:
$http.post(loginUrl, "userName=" + encodeURIComponent(email) +
"&password=" + encodeURIComponent(password) +
"&grant_type=password"
).success(function (data) {
//...
You can try with below solution
$http({
method: 'POST',
url: url-post,
data: data-post-object-json,
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj) {
var str = [];
for (var key in obj) {
if (obj[key] instanceof Array) {
for(var idx in obj[key]){
var subObj = obj[key][idx];
for(var subKey in subObj){
str.push(encodeURIComponent(key) + "[" + idx + "][" + encodeURIComponent(subKey) + "]=" + encodeURIComponent(subObj[subKey]));
}
}
}
else {
str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
}
}
return str.join("&");
}
}).success(function(response) {
/* Do something */
});
Create an adapter service for post:
services.service('Http', function ($http) {
var self = this
this.post = function (url, data) {
return $http({
method: 'POST',
url: url,
data: $.param(data),
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
}
})
Use it in your controllers or whatever:
ctrls.controller('PersonCtrl', function (Http /* our service */) {
var self = this
self.user = {name: "Ozgur", eMail: null}
self.register = function () {
Http.post('/user/register', self.user).then(function (r) {
//response
console.log(r)
})
}
})
There is a really nice tutorial that goes over this and other related stuff - Submitting AJAX Forms: The AngularJS Way.
Basically, you need to set the header of the POST request to indicate that you are sending form data as a URL encoded string, and set the data to be sent the same format
$http({
method : 'POST',
url : 'url',
data : $.param(xsrf), // pass in data as strings
headers : { 'Content-Type': 'application/x-www-form-urlencoded' } // set the headers so angular passing info as form data (not request payload)
});
Note that jQuery's param() helper function is used here for serialising the data into a string, but you can do this manually as well if not using jQuery.
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
Please checkout!
https://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
For Symfony2 users:
If you don't want to change anything in your javascript for this to work you can do these modifications in you symfony app:
Create a class that extends Symfony\Component\HttpFoundation\Request class:
<?php
namespace Acme\Test\MyRequest;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\ParameterBag;
class MyRequest extends Request{
/**
* Override and extend the createFromGlobals function.
*
*
*
* #return Request A new request
*
* #api
*/
public static function createFromGlobals()
{
// Get what we would get from the parent
$request = parent::createFromGlobals();
// Add the handling for 'application/json' content type.
if(0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/json')){
// The json is in the content
$cont = $request->getContent();
$json = json_decode($cont);
// ParameterBag must be an Array.
if(is_object($json)) {
$json = (array) $json;
}
$request->request = new ParameterBag($json);
}
return $request;
}
}
Now use you class in app_dev.php (or any index file that you use)
// web/app_dev.php
$kernel = new AppKernel('dev', true);
// $kernel->loadClassCache();
$request = ForumBundleRequest::createFromGlobals();
// use your class instead
// $request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);
Just set Content-Type is not enough, url encode form data before send.
$http.post(url, jQuery.param(data))
I'm currently using the following solution I found in the AngularJS google group.
$http
.post('/echo/json/', 'json=' + encodeURIComponent(angular.toJson(data)), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
}
}).success(function(data) {
$scope.data = data;
});
Note that if you're using PHP, you'll need to use something like Symfony 2 HTTP component's Request::createFromGlobals() to read this, as $_POST won't automatically loaded with it.
AngularJS is doing it right as it doing the following content-type inside the http-request header:
Content-Type: application/json
If you are going with php like me, or even with Symfony2 you can simply extend your server compatibility for the json standard like described here: http://silex.sensiolabs.org/doc/cookbook/json_request_body.html
The Symfony2 way (e.g. inside your DefaultController):
$request = $this->getRequest();
if (0 === strpos($request->headers->get('Content-Type'), 'application/json')) {
$data = json_decode($request->getContent(), true);
$request->request->replace(is_array($data) ? $data : array());
}
var_dump($request->request->all());
The advantage would be, that you dont need to use jQuery param and you could use AngularJS its native way of doing such requests.
Complete answer (since angular 1.4). You need to include de dependency $httpParamSerializer
var res = $resource(serverUrl + 'Token', { }, {
save: { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }
});
res.save({ }, $httpParamSerializer({ param1: 'sdsd', param2: 'sdsd' }), function (response) {
}, function (error) {
});
In your app config -
$httpProvider.defaults.transformRequest = function (data) {
if (data === undefined)
return data;
var clonedData = $.extend(true, {}, data);
for (var property in clonedData)
if (property.substr(0, 1) == '$')
delete clonedData[property];
return $.param(clonedData);
};
With your resource request -
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
This isn't a direct answer, but rather a slightly different design direction:
Do not post the data as a form, but as a JSON object to be directly mapped to server-side object, or use REST style path variable
Now I know neither option might be suitable in your case since you're trying to pass a XSRF key. Mapping it into a path variable like this is a terrible design:
http://www.someexample.com/xsrf/{xsrfKey}
Because by nature you would want to pass xsrf key to other path too, /login, /book-appointment etc. and you don't want to mess your pretty URL
Interestingly adding it as an object field isn't appropriate either, because now on each of json object you pass to server you have to add the field
{
appointmentId : 23,
name : 'Joe Citizen',
xsrf : '...'
}
You certainly don't want to add another field on your server-side class which does not have a direct semantic association with the domain object.
In my opinion the best way to pass your xsrf key is via a HTTP header. Many xsrf protection server-side web framework library support this. For example in Java Spring, you can pass it using X-CSRF-TOKEN header.
Angular's excellent capability of binding JS object to UI object means we can get rid of the practice of posting form all together, and post JSON instead. JSON can be easily de-serialized into server-side object and support complex data structures such as map, arrays, nested objects, etc.
How do you post array in a form payload? Maybe like this:
shopLocation=downtown&daysOpen=Monday&daysOpen=Tuesday&daysOpen=Wednesday
or this:
shopLocation=downtwon&daysOpen=Monday,Tuesday,Wednesday
Both are poor design..
This is what I am doing for my need, Where I need to send the login data to API as form data and the Javascript Object(userData) is getting converted automatically to URL encoded data
var deferred = $q.defer();
$http({
method: 'POST',
url: apiserver + '/authenticate',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
transformRequest: function (obj) {
var str = [];
for (var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
},
data: userData
}).success(function (response) {
//logics
deferred.resolve(response);
}).error(function (err, status) {
deferred.reject(err);
});
This how my Userdata is
var userData = {
grant_type: 'password',
username: loginData.userName,
password: loginData.password
}
The only thin you have to change is to use property "params" rather than "data" when you create your $http object:
$http({
method: 'POST',
url: serviceUrl + '/ClientUpdate',
params: { LangUserId: userId, clientJSON: clients[i] },
})
In the example above clients[i] is just JSON object (not serialized in any way). If you use "params" rather than "data" angular will serialize the object for you using $httpParamSerializer: https://docs.angularjs.org/api/ng/service/$httpParamSerializer
Use AngularJS $http service and use its post method or configure $http function.

How to include multiple rendered JSP into response to AJAX?

I need to send ajax request to java back-end and to response (from java back-end) with two html-blocks as answer. I want to generate those two html-blocks using two different JSPs. I do this as following:
req.setAttribute(...);
...
resp.setContentType("text/html");
RequestDispatcher dispatcher = req.getRequestDispatcher("one.jsp");
dispatcher.include(req, resp);
dispatcher = req.getRequestDispatcher("two.jsp");
dispatcher.include(req, resp);
And it works. But on the front-end I receive an answer like one solid html code (rendered one.jsp + rendered two.jsp). But I need to receive it as two separate html blocks to put each block to it's own .
What is the proper way to do this?
Ajax code:
function addNew() {
var request = $.ajax({
url: "myUrl",
type: "post",
dataType: "html",
success: function(data) {
$("#divNameOne").html(<one part of data>);
$("#divNameTwo").html(<second part of data>);
},
error:function() {
alert("fail");
}
});
}
In your success function ,
var reponseHtml = $(data); // or you can use $($.parseHtml(data));
$("#divNameOne").html(responseHtml.find("#div1").html());
$("#divNameTwo").html(responseHtml.find("#div2").html());
It might work.

ajax POST cannot send data to servelet

I am working on a simple tomcat web application. The client side just send the username data in json to server side and server side return if this username is already registered.
Here is my code.
ajax part:
var udata = new Array();
udata.push({ name: uname});
$.ajax({
url: '/TestProj/Controller?action=checkuname',
type: 'POST',
dataType: 'json',
data: udata,
//contentType:'application/json, charset=utf-8',
success: function(data){
checkstatus = data.status;
},
error: function(x,y,z){ console.log(JSON.stringify(x)); }
});
servlet part:
I am using a controller to dispatch the request to checkname servlet.
String username = request.getParameter("name");
if (checkuser(username)){
status = "false";
}else{
status = "true";
}
response.setContentType("application/json");
PrintWriter o = response.getWriter();
o.println("{\"status\":\""+status+"\"}");
//o.println("{\"status\":\""+username+"\"}");
I try print out the content of "status" and "username", but they are both null. Does it mean that I did not successfully send out the data via ajax to servlet. I may mess up the json data part.
Any help will be appreciated.
Updated:
I change the ajax part to this and it works. Can someone let me know how to do it in the json way?
ajax part:
var udata = new Array();
udata.push({ name: uname});
$.ajax({
url: '/TestProj/Controller?action=checkuname&uname='+uname,
type: 'POST',
dataType: 'json',
data: udata,
//contentType:'application/json, charset=utf-8',
success: function(data){
checkstatus = data.status;
},
error: function(x,y,z){ console.log(JSON.stringify(x)); }
});
It doesn't really make sense to use a JSON object for such a simple thing as posting a username to a servlet. Just use a simple request parameter and save yourself a lot of trouble. But if you must do it with JSON, there are a few problems you'll need to resolve.
Unless you're handling multiple users at the same time, a javascript array is not a good choice of data type. A simple object would be better.
var udata = {name: uname};
Your post data should be a string, not a javascript object (array or otherwise). Use JSON.stringify() as in your error function.
$.ajax({
url: '/TestProj/Controller',
type: 'POST',
dataType: 'json',
data: 'action=checkuname&jsonObject=' + JSON.stringify(udata),
success: function(data){
checkstatus = data.status;
},
error: function(x,y,z){ console.log(JSON.stringify(x)); }
});
However, udata is such a simple javascript object that you might as well stringify it yourself, as the native JSON object is not going to be available in older browsers.
var udata = '{name:"'+uname+'"}';
$.ajax({
url: '/TestProj/Controller',
type: 'POST',
dataType: 'json',
data: 'action=checkuname&jsonObject=' + uname,
success: function(data){
checkstatus = data.status;
},
error: function(x,y,z){ console.log(JSON.stringify(x)); }
});
Also, although it may boil down to personal preference, the action parameter is better off in the post body rather in the query string. This is a post, after all.
request.getParameter() is not going to help you inspect a JSON string. It can only get the value of request parameters. So
String json = request.getParameter("jsonObject")
// this variable will have a value like "{name: 'somedude'}"
You'll need to parse this JSON string on the server. You could try to do this yourself with String methods, by a library like Gson is a much better option. You could obtain the username value like this:
String username = (String)(new Gson().fromJson(json, Map.class).get("name"));

how to read parsed json data in ajax success call

On Ajax success call, I'm getting already parsed data in JSON format from a Controller.
I want to read that data, so while I'm doing below one, I am getting undefined as an error.
How can I solve this?
success : function(response) {
alert(response.operatorId);
},
Here is an example of working code
success: function(json) {
console.log(JSON.stringify(json.topics));
$.each(json.topics, function(idx, topic){
$("#nav").html('' + topic.link_text + "");
});
}
It appears that the response coming into success function is not a JSON object. COuld you check if you have following set in your ajax call.
dataType: 'json',
contentType : 'application/json'
Alternatively, you may use the following to parse the json string to json object and then use dot notation to access the properties
success : function(response) {
var jsonData = $.parseJSON(response)
alert(jsonData.operatorId);
},

Need help getting this Spring 3/AJAX/JSON drop down population working

I am trying to do a Spring MVC 3 ajax call to populate a drop down from json serialized data.
The problem I am seeing is I am not sure what format of JSON Spring is returning for my list, and why.
The method which returns the Ajax data looks like this:
#RequestMapping(value="/getMyObjects", method=RequestMethod.POST)
#ResponseBody
public List<MyObject> getMyObjects () {
List<MyObject> myobjects = // populate list
return myobjects;
}
And as far as I understand that should be all I need to do, right?
In my app logs I see it is indeed converting the response to JSON, as follows:
2012-06-20 11:08:21,125 DEBUG (AbstractMessageConverterMethodProcessor.java:139) - Written [[MyObject [id=1376, name=Something test], MyObject [id=1234 name=More test]]] as "application/json;charset=UTF-8" using [org.springframework.http.converter.json.MappingJacksonHttpMessageConverter#d1b7e5]
But that JSON string looks odd to me, is that valid?
I was expecting stuff like [{ id : 1376, name="Something test"}, { id : 1234, name="More test"}]
On the client side when I get the response and do an alert I see it says its an array of objects like this: [Object object] [Object object] and I dont know how to deal with this data.
I try:
alert(data); -- gives the output I just described above
$(data).each(function() {
alert(this.id); // undefined!
});
How do I use this kind of JSON data or how do I convert it to something more manageable?
[Edit] Attaching my client side code with current alert responses I am trying:
$.ajax({
type : "POST",
url : "getMyObjects",
success : function(data) {
alert(data); // [Object object] [Object object]
alert(data.value); // Undefined
$(data).each(function() {
alert(this.id); // Undefined for each iteration
});
},
error : function (XMLHttpRequest, textStatus, errorThrown) {
alert(textStatus);
}
});
Spring 3 provides integration with DWR(direct web remoting) which is very cool framwrork for AJAX calls. In DWR you can handle lists very easily just like in core java.
This is it! you should get the json format that you were expected. no more code (parser, formatting ) in necessary.
What you dont see is the actual json returned. well you try your url right away in the browser without calling it by ajax like http://yourdomain/yourservlet/getMyObjects you then will see your json as it is.
or else, use firfox with firebug, and you can see your ajac call (request & and response)
UPDATE
$.ajax({
url: "path/to/your/url",
cache: false,
async: false,
success: function(data){
for (var i = 0; i < data.length; i++) {
alert(data[i].id);
alert(data[i].name);
}
}
});

Categories

Resources