Javascript receiving Resource object containing chars instead of String - javascript

My Java code should return user login as a String, but on Javascript side I'm receiving a strange Resource object whose numbered attributes each contains one char.
Here is my Java code:
#PostMapping(path = "/account/reset_password/finish", produces = MediaType.TEXT_PLAIN_VALUE)
#Timed
public ResponseEntity<String> finishPasswordReset(#RequestBody KeyAndPasswordVM keyAndPassword) {
if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
return new ResponseEntity<>("Incorrect password", HttpStatus.BAD_REQUEST);
}
return userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey()).map(
user -> new ResponseEntity<String>(user.getLogin(), HttpStatus.OK)).orElse(
new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
}
Javascript controller code:
Auth.resetPasswordFinish({key: $stateParams.key, newPassword: vm.resetAccount.password}).then(function (userLogin) {
vm.success = 'OK';
console.log("userLogin="+userLogin);
}).catch(function () {
vm.success = null;
vm.error = 'ERROR';
});
The console prints:
userLogin=[object Object]
which is not very interesting.
Inspecting the received object gives:
One can see that each char of the String is a numbered attribute of the Resource object.
Javascript Auth code:
function resetPasswordFinish (keyAndPassword, callback) {
var cb = callback || angular.noop;
return PasswordResetFinish.save(keyAndPassword, function (userLogin) {
return cb(userLogin);
}, function (err) {
return cb(err);
}).$promise;
}
This one is just passing the parameter to the callback function.
Do you know how to receive a plain String instead of this Resource object? I apologize if this is a trivial question.
I know that doing this will work in order to retrieve the user login:
var i = 0;
var userLoginToString = "";
while (typeof userLogin[String(i)] !== 'undefined') {
userLoginToString += String(userLogin[String(i)]);
i += 1;
}
however I don't think that this is the intended way to use this Resource object.

Related

Get and check a value from JSON read in NodeJS

I'm trying to check if a user exists (registered on a json file).
Unfortunately I don't find a valid solution in all Stack Overflow that gives me a simple "true" in a callback.
The version closest to a solution
Experiment V1 :
let userExist;
function check(){
console.log("CHECK!");
return userExist = true;
}
// check(); if this, return true... obvious.
//// check if user exist
server.readFileSync(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if ( userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check(); // return undefined ???
}
}
});
console.log("userExist value : "+userExist);
differently formulated the debugs also appear, but "true" never returns.
note: yes, JSON is read correctly. If everything works inside the readfile, you immediately notice the same emails.
output: "undefined"
Log: total bypassed
Experiment V2 :
In this case (with asynchronous reading) it returns all the debugging (but the "true" remains undefined)
The problem with the asynchronous is that I have to wait for it to check to continue with the other functions.
//// check if user exist
server.readFile(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if (/* json.allusers.hasOwnProperty(key) &&*/ userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check();
}
}
});
var userExist;
function check(userExist){
console.log("CHECK!");
return userExist=true;
}
console.log("userExist value : "+userExist+"");
server listening on: 8080
userExist value : undefined
CHECK!
FINDED EQUAL
Experiment V3 :
after the various suggestions I come to a compromise by using the syntax for the async functions.
This allowed to reach an ordered code, but despite this it is not possible to wait for the results and export them out of the same function (this is because node itself is asynchronous! Therefore it has already gone on!)
using a "message" variable to check if it could return an object I did so:
//simple output tester
var message;
// create a promise
let loopusers = new Promise( (resolve)=>{
server.readFile( filepath, 'utf8',
(err, data) => {
let json = JSON.parse(data),
userlist = json.allusers,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
// loop all items
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : user isn't free");
findedequal=true;
resolve(true); // return the result of promise
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
resolve(false); // return the result of promise
}
}
// call the action
createuser();
});
});
// when promise finished --> start action
async function createuser(message)
{
let userExist = await loopusers;
console.log("userExist: "+userExist);
if(userExist)
{
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
message = { Server: "Registration user -> completed..."};
}
// return values
return message;
};
It is also possible to use the classic syntax via "then". For exemple:
//simple output tester
var message;
// create a promise
let loopusers = new Promise( (resolve)=>{
...
});
loopusers.then( (response)=>{
...
})
Then I realized that it was easy to simplify even more by calling the functions directly from the initial one:
var message;
// create a promise --> check json items
server.readFile( filepath, 'utf8',
(err, data) => {
let json = JSON.parse(data),
userlist = json.allusers,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : user isn't free");
findedequal=true;
createuser(true); // call direct function whit params true
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
createuser(false); // call direct function whit params false
}
}
});
// start action
function createuser(userExist)
{
if(userExist)
{
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
message = { Server: "Registration user -> completed!"};
}
// return values
return message;
};
debugging is taken and written
the message is lost outside the aSync function
Experiment V4 Final! :
Finally, after many attempts the solution! (Yes... But know it's not Async)
If we allocate in a variable the reading becomes synchronous the whole model and we return to the simple one
let message,
file = server.readFileSync(filepath, 'utf8'), // read sync
json = JSON.parse(file), // now parse file
userlist = json.allusers, // get your target container object
userExist,
findedequal;
console.log("CHECK USERS IN DB...for "+userlist.length+" elements");
for (let key in userlist)
{
console.log("Analyzed key ::: "+key);
if ( userlist[key].email == req.body.user_email )
{
console.log("CHECK : finded equal value on key ["+key+"] - user isn't free");
findedequal=true;
userExist = true;
}
else if(key >= userlist.length-1 && !findedequal )
{
console.log("CHECK : User is free ;)");
userExist = false;
}
}
if(userExist)
{
console.log("└ EXIT TO CHECK --> Can't create user, function stop.");
message = { Server: "This user already exists, Try new e-mail..."};
}
else
{
console.log("└ Exit to check --> New user registration ...");
message = { Server: "Registration user -> completed!"};
}
}
return message;
Now:
It's all sync and all log is perfect
all var is checked
all return... return
** Final conclusions: **
Is it possible to retrieve an ASync variable in node?
As far as I understand so far ... no.
Node is async by its nature, therefore recovering information that is not saved and then recovered from a DB is left behind among the things to do, becoming unrecoverable if you use it as in this post.
However ... if the purpose is to make reading a file synchronous, the answer was simpler than expected.
A special thanks to: Barmar; Austin Leehealey; C.Gochev;
The problem is that you are calling console.log("userExist value : "+userExist+"");
too early. At the moment that you call that line, userExist is not defined yet. This is because the server.readFile() function requires a callback and that callback function is executed once it has read the file. However, reading files often take time and so the program keeps going. It executes console.log("userExist value : "+userExist+""); and then goes back to the callback function and defines userExist as true.
If you want more information on what callbacks are look at the link below. Callbacks are a defining feature of Nodejs and understanding them is essential to any Node website.
https://medium.com/better-programming/callbacks-in-node-js-how-why-when-ac293f0403ca
Try something like this.
let userExist;
function check(){
console.log("CHECK!");
return userExist = true;
}
// check(); if this, return true... obvious.
//// check if user exist
server.readFileSync(filepath, 'utf8', (err, data) =>
{
let json = JSON.parse(data),
userlist = json.allusers;
for (let key in userlist)
{
if ( userlist[key].email == req.body.user_email )
{
console.log("FINDED EQUAL");
check(); // return undefined ???
console.log("userExist value : "+userExist);
}
}
});

Getting 400 response error code when running query with apollo/react-hooks [duplicate]

I am using this endpoint:
#PostMapping("graphql")
public ResponseEntity<Object> getResource(#RequestBody Object query) { // String query
ExecutionResult result;
if (query instanceof String) {
result = graphQL.execute(query.toString()); // if plain text
} else{
String queryString = ((HashMap) query).get("query").toString();
Object variables = ((HashMap) query).get("variables");
ExecutionInput input = ExecutionInput.newExecutionInput()
.query(queryString)
.variables((Map<String, Object>) variables) // "var1" -> "test1"
.build();
result = graphQL.execute(input);
}
return new ResponseEntity<Object>(result, HttpStatus.OK);
}
When i don't have variable it works fine:
query {
getItem(dictionaryType: "test1") {
code
name
description
}
}
When i add variable it starts to fail, see here:
query {
getItem(dictionaryType: $var1) {
code
name
description
}
}
In my schema i have defined the query section as followed:
type Query {
getItem(dictionaryType: String): TestEntity
}
In java code:
#Value("classpath:test.graphqls")
private Resource schemaResource;
private GraphQL graphQL;
#PostConstruct
private void loadSchema() throws IOException {
File schemaFile = schemaResource.getFile();
TypeDefinitionRegistry registry = new SchemaParser().parse(schemaFile);
RuntimeWiring wiring = buildWiring();
GraphQLSchema schema = new SchemaGenerator().makeExecutableSchema(registry, wiring);
graphQL = GraphQL.newGraphQL(schema).build();
}
private RuntimeWiring buildWiring() {
initializeFetchers();
return RuntimeWiring.newRuntimeWiring()
.type("Query", typeWriting -> typeWriting
.dataFetcher("getItem", dictionaryItemFetcher)
)
.build();
}
private void initializeFetchers() {
dictionaryItemFetcher = dataFetchingEnvironment ->
dictionaryService.getDictionaryItemsFirstAsString(dataFetchingEnvironment.getArgument("dictionaryType"));
}
Any variables used inside an operation must be declared as part of the operation definition, like this:
query OptionalButRecommendedQueryName ($var1: String) {
getItem(dictionaryType: $var1) {
code
name
description
}
}
This allows GraphQL to validate your variables against the provided type, and also validate that the variables are being used in place of the right inputs.

undefined value return from node.js javascript class [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 6 years ago.
I have declared class which generates the records and simply return it but it is returning undefined.
var classObj = new User();
var user = classObj.generateUserResponse(val1,mode);
console.log(user) //undefined
User.prototype.generateUserResponse = function (userid, mode) {
conn.query('select * from users where user_id = ?', [userid], function (err, user) {
if(mode == 'true') {
var genObj = new CustomerJSON();
userObj = genObj.generateUserCustomer(user);
console.log(userObj) // displays the value
return userObj;
} else {
// do something else
}
})
What I am doing above is creating a new class and passing a user object in a new class for further processing. I can console log and can see the data but when I return userObj it displays undefine.
It is right, because the invoked asynchronous function calls the callback (which returns the object to noone) after you log the object to console.
The function generateUserResponse returns no value.
Solution: make the required actions in the callback function.
Pavel is correct. Your function is asynchronous. You need a callback. Try something like this:
var classObj = new User();
classObj.generateUserResponse(val1, mode, function(userObj) {
console.log(userObj);
});
User.prototype.generateUserResponse = function(userid, mode, callback) {
//you could decide to return conn.query here and handle it differently above
conn.query('select * from users where user_id = ?', [userid], function(err, user) {
if (mode == 'true') {
var genObj = new CustomerJSON();
userObj = genObj.generateUserCustomer(user);
console.log(userObj) // displays the value
return callback(userObj);
} else {
// do something else
//THEN
return callback(userObj);
}
})
});
Or you could return conn.query(... and handle the promise it returns based on whatever library you're using.

JavaScript function response and chained promises

I have a Parse CloudCode beforeSave function, which roughly does the following:
Runs a query to check if there's a duplicate user to the one being saved;
If there is NO duplicate, I call a response.success(), which means the code can go ahead and allow saving the new user;
If, however, there is a duplicate, I want to take the existing user, fetch a group object and add the existing user to the group.
For this purpose, I am using chained promises to make the code cleaner. The code is below:
Parse.Cloud.beforeSave("Contact", function(request, response) {
var facebookID = request.object.get("facebookID");
var email = request.object.get("email");
var queryFb;
if (facebookID) {
queryFb = new Parse.Query(Parse.User);
queryFb.equalTo("facebookID", facebookID);
}
var queryEmail;
if (email) {
queryEmail = new Parse.Query(Parse.User);
queryEmail.equalTo("email", email);
}
var query;
if (facebookID && email) {
query = new Parse.Query.or(queryFb, queryEmail);
} else if (facebookID) {
query = queryFb;
} else {
query = queryEmail;
}
var user;
query.first().then(function(user) {
if (!user) {
response.success();
} else {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("title", "ssAll");
groupQuery.equalTo("owner", request.user);
return groupQuery.first();
}
}).then(function(group) {
group.addUnique("contacts", user);
return group.save();
}).then(function(success) {
response.error("NOT ERROR - new object was NOT created");
}, function(error) {
response.error(error);
});
});
In my test case, the query returns !user, so the response.success() message is called - all good. However, this response seems to then travel down the promise chain, which is intended for the case when the query returns a user object. And so, my function terminates with an error on line group.addUnique("contacts", user); because, obviously, the group object is undefined.
How do I work around this issue?
The code needed a few improvements. The key improvement was to provide consistent starting conditions to the second promise's resolution (the second then block). The OP code called response.success() in the case where there was no existing user. This is fine, except the execution still falls through to the next resolution, in one case with an undefined group parameter.
The new code fixes that by returning either the existingUser (after the group has been updated) or null. Null tells the next promise resolution to call success() and allow the save to proceed, otherwise, block the save.
Also note, it is a mistake for the first block's user parameter to conflict with the var user in the enclosing scope. I tried to use variable naming below to highlight the two different types of users the code considers...
Parse.Cloud.beforeSave("Contact", function(request, response) {
var facebookID = request.object.get("facebookID");
var email = request.object.get("email");
// moved into a function so we can test and deal with it tersely
findUserByEmailOrFB(email, facebookID).then(function(existingUser) {
return (existingUser)? addContactToGroupOwnedBy(request.user, existingUser) : null;
}).then(function(existingUser) {
if (existingUser) {
response.error("NOT ERROR - new object was NOT created");
} else {
response.success();
}
}, function(error) {
response.error(error);
});
});
// find the group owned by ownerUser, add contactUser to its contacts return a promise fulfilled as contactUser
function addContactToGroupOwnedBy(ownerUser, contactUser) {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("title", "ssAll");
groupQuery.equalTo("owner", ownerUser);
return groupQuery.first().then(function(group) {
group.addUnique("contacts", contactUser);
return group.save().then(function() { return contactUser; });
});
}
function findUserByEmailOrFB(email, facebookID) {
var queryFb;
if (facebookID) {
queryFb = new Parse.Query(Parse.User);
queryFb.equalTo("facebookID", facebookID);
}
var queryEmail;
if (email) {
queryEmail = new Parse.Query(Parse.User);
queryEmail.equalTo("email", email);
}
var query;
if (facebookID && email) {
query = new Parse.Query.or(queryFb, queryEmail);
} else if (facebookID) {
query = queryFb;
} else {
query = queryEmail;
}
return query.first();
}
The problem is that you are always resolving the first promise regardless of whether checking for the user was successful (no such user yet) or not. However, actually you don't ever have to resolve the promise. I suggest you separate the error case like this:
query.first().then(function(user) {
if (!user) {
response.success();
} else {
addUserToGroup(request.user).then(function() {
response.error("NOT ERROR - new object was NOT created");
}, function(error) {
response.error(error);
});
}
});
function addUserToGroup(user) {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("title", "ssAll");
groupQuery.equalTo("owner", user);
return groupQuery.first().then(function(group) {
group.addUnique("contacts", user);
return group.save();
});
}
As you can see, the first promise doesn't ever have to be resolved because the result is not used anyway.

Parse Cloud Code: Logic Branching in Promises

I'm trying to write a Parse.com Cloud Code function to accomplish the following workflow:
User submits a value.
Cloud code function checks to see if that value matches any objects of type code.
If not, the function returns a "not found" value.
If so, the object of type code is assumed to have a pointer to an object of type item.
Then, code.item is checked to see whether it has a pointer to an object of type alert.
If not, the function returns a "not found" value.
If code.item.alert does exist, then I want to fetch the full alert object, including pointers which may or may not exist, up to 2 layers deep.
As I begin writing the code for this function, I can get it working to the point of checking to see whether the code exists and, if so, whether code.item.alert also exists.
This is where the problem arises. As it currently stands, in the working version of my function, the alert item that is returned is only the class type and objectId. I understand why that is happening, and I am trying to write code to populate the object before returning it, but I am failing in that attempt.
Here's the code that is working so far (but only returning the alert object's shell):
Parse.Cloud.define("alertLookup", function (request, response) {
Parse.Cloud.useMasterKey();
var codeQuery = new Parse.Query("code");
codeQuery.equalTo("value", request.params.code);
codeQuery.include("item");
codeQuery.find().then(function (codes) {
if (codes.length === 0) {
response.success("no item");
} else {
var code = codes[0];
var item = code.get("item");
var alert = item.get("alert");
if (alert === null || alert === undefined) {
response.success("no item");
} else {
response.success(alert);
}
}
}, function (error) {
response.error(error);
});
});
Here's what I have tried that is failing with an error code of 141:
Parse.Cloud.define("alertLookup", function (request, response) {
Parse.Cloud.useMasterKey();
var codeQuery = new Parse.Query("code");
codeQuery.equalTo("value", request.params.code);
codeQuery.include("item");
codeQuery.find().then(function (codes) {
if (codes.length === 0) {
response.success("no item");
} else {
var code = codes[0];
var item = code.get("item");
var alert = item.get("alert");
if (alert === null || alert === undefined) {
response.success("no item");
} else {
return alert.fetch();
}
}
}).then(function (a) {
response.success(a);
}, function (error) {
response.error(error);
});
});
Why won't the fetch() call work properly? When I insert console.log() statements, although alert is non-null, return alert.fetch(); does not ever seem to be called. At least, the response.success(a); line is never called. Why not?
Try this instead while chaining Promises:
codeQuery.find().then(function (codes) {
if (codes.length != 0) {
var code = codes[0];
var item = code.get("item");
var alert = item.get("alert");
if (alert != null && alert != undefined) {
var alertObj = new Parse.Object("alert"); // alert class ???
alertObj.id = alert.id;
return alertObj.fetch();
}
}
// return a Promise for no items
return Parse.Promise.as("no item");
}).then(function (a) {
response.success(a);
}, function (error) {
response.error(error);
});

Categories