Java Jersey get POST array - arrays

I am trying to retrieve an array of numbers through POST, the raw data being sent to the server is:
bucket2=0&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&buckets%5B%5D=6&bucket1=0&currPlayer=0&bucketID=0
this contains an array buckets = [6, 6, 6, ...], from the javascript console:
Object { bucket2: 0, buckets: Array[12], bucket1: 0, currPlayer: 0 }
to post I use the following code:
$.ajax({
type: "POST",
url: baseUrl + "move",
data: game,
success: function(data) {
// console.log(data);
update(data);
}, error: function(jqXHR, textStatus, errorThrown) {
console.log(errorThrown);
}
});
And my server code is:
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces(MediaType.APPLICATION_JSON)
#Path("/move")
public String move(#PathParam("currPlayer") int currPlayer,
#PathParam("bucket1") int bucket1,
#PathParam("bucket2") int bucket2,
#PathParam("buckets") List<Integer> buckets,
#PathParam("bucketID") int bucketID){
System.out.println("currPlayer: " + currPlayer);
System.out.println("bucket1: " + bucket1);
System.out.println("bucket2: " + bucket2);
System.out.println("buckets: " + buckets);
System.out.println("bucketID: " + bucketID);
return "";
}
With the server output being:
currPlayer: 0
bucket1: 0
bucket2: 0
buckets: []
bucketID: 0
Why doesn't it get the array values?
EDIT: I tried using #FormParam before creating this thread, but it still doesn't work

You are consuming:
#Consumes(MediaType.APPLICATION_FORM_URLENCODED) //Meaning the content-type is `application/x-www-form-urlencoded`.
And yet, you are retrieving the parameters using #PathParam. For Content-Type application/x-www-form-urlencoded, you can read the parameters by using the #FormParam annotation.
Oh, your HTTP multi value form parameters must be of the form:
buckets=6&buckets=6
There is no need for %5B%5D in front of the = sign.
I hope this helps.

Related

PostgresSql + Nodejs (ClaudiaJS) : How to cast array of string to array of timestamp

I am writing API which insert into a table with multiple rows, I am using UNNEST to make it work.
What I have done:
in js file:
api.post(PREFIX + '/class/insert', function (request) {
var db = pgp(dbconnect);
//Params
var data = request.body; //should be an array
var classes = [];
var starts = [];
var ends = [];
for (var i = 0; i < data.length; i++) {
classes.push(data[i].class_id);
starts.push(data[i].timestamp_start);
ends.push(data[i].timestamp_end);
}
const PQ = require('pg-promise').ParameterizedQuery;
var sql =
"INSERT INTO sa1.class(class_id, timestamp_start, timestamp_end) " +
"VALUES( "+
"UNNEST(ARRAY" + JSON.stringify(classes).replace(/"/g, "'") + "), " +
"UNNEST(ARRAY" + JSON.stringify(starts).replace(/"/g, "'") + "), " +
"UNNEST(ARRAY" + JSON.stringify(ends).replace(/"/g, "'") + ")"
const final_sql = new PQ(sql);
return db.any(final_sql)
.then(function (data) {
pgp.end();
return 'successful';
})
.catch(function (error) {
console.log("Error: " + error);
pgp.end();
});
}
Request body
[{
"class_id":"1",
"timestamp_start":"2017-11-14 14:01:23.634437+00",
"timestamp_end":"2017-11-14 15:20:23.634437+00"
}, {
"class_id":"2",
"timestamp_start":"2017-11-14 15:01:23.634437+00",
"timestamp_end": "2017-11-14 16:20:23.634437+00"
}]
When I run api in postman, I get the error is:
column "timestamp_start" is of type timestamp with time zone but
expression is of type text
Issue is obviously from ARRAY of string that I used in sql, my question is how to create ARRAY of timestamp for UNNEST, or any suggestion are appreciated.
Thanks
Never initialize the database inside the handler, see: Where should I initialize pg-promise
Never call pgp-end() inside HTTP handlers, it destroys all connection pools.
Use static ColumnSet type to generate multi-insert queries.
Do not return from db.any, there is no point in that context
You must provide an HTTP response within an HTTP handler
You are providing a confusing semantics for column class_id. Why is it called like that and yet being converted into a timestamp?
Never concatenate objects with strings directly.
Never concatenate SQL strings manually, it will break formatting and open your code to SQL injection.
Use Database methods according to the expected result, i.e. none in your case, and not any. See: https://github.com/vitaly-t/pg-promise#methods
Initialize everything needed only once:
const db = pgp(/*connection*/);
const cs = new pgp.helpers.ColumnSet([
'class_id',
{
name: 'timestamp_start',
cast: 'timestamp'
},
{
name: 'timestamp_end',
cast: 'timestamp'
}
], {table: {table: 'class', schema: 'sa1'}});
Implement the handler:
api.post(PREFIX + '/class/insert', request => {
const sql = pgp.helpers.insert(request.body, cs);
db.none(sql)
.then(data => {
// provide an HTTP response here
})
.catch(error => {
console.log('Error:', error);
// provide an HTTP response here
});
}
Many thanks to #JustMe,
It worked after casting array
var sql =
"INSERT INTO sa1.class(class_id, timestamp_start, timestamp_end) " +
"VALUES( "+
"UNNEST(ARRAY" + JSON.stringify(classes).replace(/"/g, "'") + "), " +
"UNNEST(ARRAY" + JSON.stringify(starts).replace(/"/g, "'") + "::timestamp[]), " +
"UNNEST(ARRAY" + JSON.stringify(ends).replace(/"/g, "'") + "::timestamp[])"

Angular and spring REST API : NULL POINTER EXCEPTION

I GET NullPointerException with status code : 400
I am pushing data into a JsonObject and then post it to my back end (Spring ) and get the field using Json mapper (data.get("Field name").asText;.
I also tried get(index) and data.path but this return null, where as in the debug console It indicates that Json objects were received, what is it that makes these fields to be null?
Is it because this data is not directly from ng-model, or is it because I have pushed it into json object using Angular, because I am getting 400 erro code.
MY ANGULAR JS :
app.controller("OrderOperationsCtrl", function($scope, $http,$window) {
$http.get(productURL).then(function(response) {
$scope.productData = response.data;
$scope.newData = [];
$scope.total = 0.0;
$scope.sync = function(bool,productData,submit){
if(bool === true){
var numberOrdered = 0;
numberOrdered++;
$scope.total = $scope.total + productData.price;
var newD = $scope.newData.push({
"numberOrdered":numberOrdered,
"customerId":localStorage.getItem('takealot_customer'),
"id":productData.id,
"total":$scope.total
});
$scope.sender = $scope.newData;
console.log(" NewD " + $scope.newData);
}
if(submit === true){
$http.put(orderURL,JSON.stringify($scope.sender)).then(function(response){
if(response.data)
console.log("Order created !");
},function(response){
console.log("Error creating Order !");
console.log(response.status);
});
MY SPRING CONTROLLER UPDATE
public ResponseEntity createOrder(#RequestBody OrderOperations[] operation) throws OrderOperationsNotFoundException, IOException{
logger.info("recieved json String " + operation);
services.createOrder(operation);
return new ResponseEntity(HttpStatus.OK);
}
CONSOLE OUTPUT :
Hibernate: select products0_.id as id1_3_, products0_.category as category2_3_, products0_.description as descript3_3_, products0_.name as name4_3_, products0_.price as price5_3_, products0_.quantity as quantity6_3_, products0_.supplier as supplier7_3_ from products products0_
2017-11-03 11:34:41.689 INFO 10504 --- [nio-8080-exec-9]
c.p.C.OrderOperationsController : recieved json String
[{"numberOrdered":1,"customerId":null,"id":1,"total":78.32,"$$hashKey":"object:17"},
{"numberOrdered":1,"customerId":null,"id":2,"total":156.70999999999998,"$$hashKey":"object:19"},
{"numberOrdered":1,"customerId":null,"id":1,"total":235.02999999999997,"$$hashKey":"object:21"}]
THanks in advance
First of all you dont need to map the json into the OrderOperation Object.
Spring will automatically convert the JSON Object into OrderOperations by passing as Parameter
public ResponseEntity createOrder(#RequestBody OrderOperations operation)
And i think you get the Nullpointer while you parsing the Data
Finally I have got a solution. some weeks ago.
- For those who are still struggling to save multiple objects from JSON array
see below ... I hope this helps someone else.
public List<String> createOrder(#RequestBody OrderOperations[] json) throws OrderOperationsNotFoundException, IOException{
logger.info("recieved json String " + json);
List<String> response = new ArrayList<String>();
for(OrderOperations op : json){
services.createOrder(op);
response.add("saved order : " + op.toString());
}
return response;
}

Number format exception - not able to convert string to long value

JSP code --- I have used Angular js in scripting. The issue is that the form Data is not being sent to the resource method in portlet class. Also when I log the form data in console it displays empty. It takes up JSON data and append into form data. the json value is passed as transaction data { 1: "1", purchaseRegisterId: 33411, undefined: "book3.jpg" } and documentId is passed as documentId :: documents33411. these data is taken from the console log.
$scope.savePurchaseRegisterEntry=function(documentId, json){
console.log("documentId :: "+documentId);
//console.log("json");
console.log(json);
var fd = new FormData();
fd.append('auditDetailesId',$scope.auditDetailesId);
console.log(fd);
var documentcollection=[];
for(var key in json){
fd.append(key,json[key]);
if("purchaseRegisterId"!=key && key!=='undefined'){
documentcollection.push(key);
}
}
$.each( $("#"+documentId), function( input_key, input_value ) {
$.each( input_value.files, function( file_key, file_value ) {
fd.append('myFiles', file_value);
});
});
fd.append("documentCollectionIds",documentcollection.join(','));
console.log("fd");
console.log(fd);
console.log("documentcollectionids :: "+documentcollection.join(','))
//return false;
$http({
method:'POST',
url:'<%=savePurchaseRegisterEntry%>',
type:"json",
data:fd,
headers: {'Content-Type': undefined},
transformRequest:angular.identity
}).success(function(response){
console.log(response);
var response=angular.fromJson(response.selectedTransactionList);
$scope.dataList=angular.fromJson(response.data);
$scope.ariaValuenow =response.currentCount;
$scope.ariaValuemin=0;
$scope.ariaValueMax=response.data[0]['maxInputDocCount']* response.total;
$scope.percentageComplete=(($scope.ariaValuenow - $scope.ariaValuemin) * 100) / ($scope.ariaValueMax - $scope.ariaValuemin);
if($scope.percentageComplete==100){
$scope.saveStatus();
$scope.readyForAudit=true;
}else{
$scope.readyForAudit=false;
}
});
}
Resurces Method --- the data is being fetched here to store the values into database table.
public void savePurchaseRegisterEntry(ResourceRequest req,
ResourceResponse res) throws SystemException, IOException {
_log.info("i am in savePurchaseRegisterEntry!!!");
ThemeDisplay themeDisplay = (ThemeDisplay) req
.getAttribute(WebKeys.THEME_DISPLAY);
_log.info(" ----- " + ParamUtil.getString(req, "purchaseRegisterId"));
_log.info(" ----- " + ParamUtil.getLong(req, "purchaseRegisterId"));
String documentCollectionIds=ParamUtil.getString(req, "documentCollectionIds");
String[] documentCollectionIdArray=documentCollectionIds.split(",");
MultiDocumentUploadUtil.createFolder(req, themeDisplay ,ParamUtil.getLong(req, "purchaseRegisterId") , "purchaseRegisterId");
String fileIds=MultiDocumentUploadUtil.fileUpload(themeDisplay, req);
_log.info("fileIds : "+fileIds);
long purchaseRegisterId =ParamUtil.getLong(req, "purchaseRegisterId");
for(String s : documentCollectionIdArray){
System.out.println("s is "+Long.parseLong(s));
_log.info(Long.parseLong(s)+"long sssss "+ s+" s :: "+ParamUtil.getLong(req, s));
_log.info(Long.valueOf(s)+"long sssss "+ s+" s :: "+ParamUtil.getLong(req, s));
AuditDocumentCollection adc= AuditDocumentCollectionLocalServiceUtil.fetchByPurchaseRegisterIdAnddocumentCollectionId(purchaseRegisterId, Long.valueOf(s));
AuditDocumentCollection adc1=adc;
if(adc==null){
adc=AuditDocumentCollectionLocalServiceUtil.createAuditDocumentCollection(CounterLocalServiceUtil.increment());
}
adc.setDocumentCollectionId(Long.valueOf(s));
adc.setPurchaseRegisterId(purchaseRegisterId);
adc.setValue(ParamUtil.getLong(req, s));
if(adc1==null){
adc.setCreateDate(new Date());
adc.setCreatedBy(themeDisplay.getUserId());
adc.setModifiedBy(themeDisplay.getUserId());
adc.setModifiedDate(new Date());
AuditDocumentCollectionLocalServiceUtil.addAuditDocumentCollection(adc);
}else{
adc.setModifiedBy(themeDisplay.getUserId());
adc.setModifiedDate(new Date());
AuditDocumentCollectionLocalServiceUtil.updateAuditDocumentCollection(adc);
}
}
PurchaseRegister purchaseRegister=PurchaseRegisterLocalServiceUtil.fetchPurchaseRegister(purchaseRegisterId);
if(!fileIds.isEmpty()){
purchaseRegister.setDocumentIds(fileIds);
}
PurchaseRegisterLocalServiceUtil.updatePurchaseRegister(purchaseRegister);
JSONObject jsonobject = JSONFactoryUtil.createJSONObject();
long auditDetailesId=ParamUtil.getLong(req, "auditDetailesId");
jsonobject.put("selectedTransactionList",CommonUtil.getAuditProcessInfo( auditDetailesId));
PrintWriter out = res.getWriter();
out.write(jsonobject.toString());
out.flush();
out.close();
}
I suppose the data present in form data is being sent to resource method. it is not taking documentCollectionIds and its empty. The error I get is this,
[http-bio-3030-exec-10][PurchaseRegisterPortlet:644] i am in savePurchaseRegisterEntry!!!
05:58:34,050 INFO [http-bio-3030-exec-10][PurchaseRegisterPortlet:648] -----
05:58:34,050 INFO [http-bio-3030-exec-10][PurchaseRegisterPortlet:649] ----- 0
Folder is already Exist
fileEntryList.toArray().toString() :: 34529
05:58:34,255 INFO [http-bio-3030-exec-10][PurchaseRegisterPortlet:657]fileIds : 34529
Exception in thread "liferay/document_library_image_processor-3"05:58:34,256 ERROR [DispatcherPortlet:559] Could not complete request
java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:453)
at java.lang.Long.parseLong(Long.java:483)
at com.auditcompliance.purchaseregister.controller.PurchaseRegisterPortlet.savePurchaseRegisterEntry(PurchaseRegisterPortlet.java:660)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
check your file first the typscript file of your component if you give
it exactly the type Number, then your service
Or if it's through the html file of your component that you give it
the right type in parameter
For me it was in the html file that I gave him another type
different from number

checking database and validate form with angular

I can use ajax to check infomation in database with jquery but I dont know do same with angularjs . I use
$http({
type : "post",
dataType : "JSON",
url : "register.php",
data : data,
success : function(result)
{
....
}
php code
$errors = array(
'error' => 0
);
$username = $_POST['username']
$password = $_POST['password']
$email =$_POST['email']
$fullname = $_POST['fullname']
$sql = "SELECT * "
. "FROM USERS "
. "WHERE username='".$username."' "
. "OR email='".$email."'";
if (mysqli_num_rows($result) > 0)
{
$row = mysqli_fetch_assoc($result);
if ($row['username'] == $username){
$errors['username'] = 'Tên đăng nhập đã tồn tại';
}
if ($row['email'] == $email){
$errors['email'] = 'Email đã tồn tại';
}
}
if (count($errors) > 1){
$errors['error'] = 1;
die (json_encode($errors));
}else{
//insert database
}
$result = mysqli_query($conn, $sql);
but I dont know do next step . I want check in database if have user name show message error else show succes .Pls help me
Using success is deprecated but you're on the right path. Here's how you would do it now:
$http({
type : "post",
url : "register.php",
data : data
}).then(function(response){
// If data is returned, do stuff with it here
console.log('Yay, my data was POSTed', response.data);
}, function(response){
console.log('Aww, it failed.');
});
It would be easier to help you further, if you add a bit more information on what you're actually trying to achieve. For instance what is returned by this "register.php" endpoint, and what you intent to do after this.
check the DOC for $http.
The $http service is a function which takes a single argument — a configuration object — that is used to generate an HTTP request and returns a promise.
The response comes under promise (.then).
$http({
type : "POST",
url : "register.php",
data : data,
}).then(function successCallback(response) {
// this callback will be called asynchronously
// when the response is available/success
console.log(response.data)
}, function errorCallback(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log(response.data)
});

angular/node.js POST for payumoney integration

I'm using angular/node.js stack for payumoney integration.
On the angular side, an order is placed using $http.post to a route endpoint at the server side (node.js) as follows:
$http.post('/placeOrder',order).success(function(data, status, headers, config){
//handle responses on client side
console.log("Successfully POSTED to payment gateway");
window.location = "https://test.payu.in/_payment";
}).error(function(data, status, headers, config) {
console.log("Error in posting");
});
The actual heavy lifting is done on the node.js (server side):
router.post('/placeOrder', function(req, res, next){
hash_data = MERCHANT_KEY+'|'+txnid+'|'+amount+'|'+productinfo+'|'+firstname+'|'+email+'|'+udf1+'|'+udf2+'|'+udf3+'|'+udf4+'|'+udf5+'||||||'+SALT;
var data = querystring.stringify({
'key': MERCHANT_KEY,
'txnid': txnid,
'amount': amount,
'productinfo': productinfo,
'firstname': firstname,
'email': email,
'phone': phone,
'surl': SUCCESS_URL,
'furl': FAILURE_URL,
'curl': FAILURE_URL,
'hash': hash,
'service_provider': SERVICE_PROVIDER
//'salt': SALT
});
//POST options
var POST_OPTIONS = {
hostname: PAYU_BASE_URL,
port: 443,
path: '/_payment',
method: 'POST',
//json: true,
agent: false,
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
//'Content-Length': Buffer.byteLength(data)
'Content-Length': data.length
}
};
var resp_status = "";
var req = https.request(POST_OPTIONS, function(response) {
console.log('STATUS: ' + response.statusCode);
console.log('HEADERS: ' + JSON.stringify(response.headers));
response.setEncoding('utf8');
response.on('data', function (chunk) {
console.log("body: " + chunk);
resp_status = 200;
res.json(chunk);
});
response.on('error', function (err) {
console.log("Got error: " + err.message);
resp_status = 500;
return res.send(err);
});
});
req.end(data);
However, this doesn't seem to work as the POST doesnt seem to work using this approach. While debugging on the browser through the network tab, I always see:
Request URL:https://test.payu.in/_payment
Request Method:GET
Status Code:200 OK
Also, the test payment page (https://test.payu.in/_payment) shows:
"Error Reason
One or more mandatory parameters are missing in the transaction request."
Any help would be appreciated!!
How did I implement this..
Use Jquery and create a Form
Use sha512 to create hashcode. (bower install js-sha512)
var hashString = this.merchantKey+'|'+ options.uid +'|'+ options.totalPrice + '|'+'options.uid + '|' +
options.recipient_name + '|'+ options.email +'|||||||||||'+ this.merchantSalt ;
var hash = sha512(hashString);
var key1 = $('<input></input>').attr('type', 'hidden').attr('name', "key").val("merchantKey");
var key2 = $('<input></input>').attr('type', 'hidden').attr('name', "txnid").val(options.uid);
var key3 = $('<input></input>').attr('type', 'hidden').attr('name', "amount").val(options.totalPrice);
var key4 = $('<input></input>').attr('type', 'hidden').attr('name', "productinfo").val(options.uid);
var key5 = $('<input></input>').attr('type', 'hidden').attr('name', "firstname").val(options.recipient_name);
var key6 = $('<input></input>').attr('type', 'hidden').attr('name', "email").val(options.email);
var key7 = $('<input></input>').attr('type', 'hidden').attr('name', "phone").val(options.phone);
var key8 = $('<input></input>').attr('type', 'hidden').attr('name', "surl").val("http://192.168.43.121/payment/success");
var key9 = $('<input></input>').attr('type', 'hidden').attr('name', "furl").val("http://192.168.43.121/payment/error");
var key10 = $('<input></input>').attr('type', 'hidden').attr('name', "hash").val(hash);
var key11 = $('<input></input>').attr('type', 'hidden').attr('name', "service_provider").val("payu_paisa");
var form = $('<form/></form>');
form.attr("id", "payuform");
form.attr("action", this.payumoneyLink );
form.attr("method", "POST");
form.attr("style", "display:none;");
form.append(key1, key2, key3, key4, key5, key6, key7, key8, key9,key10, key11);
$("body").append(form);
// submit form
form.submit();
This is my first answer on StacksOverflow. Hope it helps!
As per the browser network tab which you have mentioned,
Request URL:https://test.payu.in/_payment Request Method:GET Status Code:200 OK
This means PayU is getting called with GET request instead of POST request somehow. PayU accepts data as a POST request only.
Also, the test payment page (https://test.payu.in/_payment) shows: "Error Reason One or more mandatory parameters are missing in the transaction request."
This is due to GET request. I have faced similar situation in my JSF based application wherein I was sending all parameters correctly but as a GET request. Later on when I switched to POST, the error got resolved automatically.
For information about sending POST request from angular, check below link.
https://www.devglan.com/angular/payumoney-integration-angular
NOTE: If input type is hidden, angularjs has some issue connecting model and view. So please take a note of that. txnid and hash I am getting from AJAX get call so I had to bind it in seperate variable from scope.
Angular code is staright forward, just populate the variables.
One more thing to remember as of today, if your account is not active then you need to use test salt/key provided by their customer support:
MID : 4934580
Key : rjQUPktU
Salt : e5iIg1jwi8
Authorization : y8tNAC1Ar0Sd8xAHGjZ817UGto5jt37zLJSX/NHK3ok=
Test Card : 5123456789012346
Expiry : 05/20
CVV : 123

Resources