Welcome all!
I am currently working to pass a token generated by Stripes API from an Android app to a ParseServer. Below is my code, please be advised that I commented out previous failed attempts to let you know what I have tried and to also spark your imagination. Please note that with trial and error the issue presents to be with saving the data to the server. I have double checked that the class User has write permissions and it has an Object attribute titled token.
// Test the data.
if (userCard.validateCard()) {
Stripe stripe = new Stripe(CardActivity.this, "correct data is here I removed it, for StackOverflow");
stripe.createToken(
userCard,
new TokenCallback() {
public void onSuccess(final Token token) {
// Send token to your server
// Query the users, and get the username.
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
ParseUser user = ParseUser.getCurrentUser();
String objectId = user.getObjectId();
// Query the current user.
//query.whereEqualTo("objectId", username);
ParseObject object;
try {
object = query.get(objectId);
object.put("token", token);
object.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(CardActivity.this, "Success", Toast.LENGTH_SHORT).show();
}
}
});
} catch (ParseException e) {
Toast.makeText(CardActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
// Attempt to update... Currently not working.
/*query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null && objects != null) {
for (ParseObject object : objects) {
object.put("token", token);
object.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(CardActivity.this, "Success", Toast.LENGTH_SHORT).show();
}
}
});
}
} else {
Toast.makeText(CardActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
});*/
}
public void onError(Exception error) {
// Show error message
Toast.makeText(CardActivity.this,
error.getMessage(),
Toast.LENGTH_LONG
).show();
}
}
);
} else {
Toast.makeText(CardActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
A few things here:
1) Parse allows you to add/overwrite information to objects from their "shell". This is a ParseObject instance, set to a specified class, assigned an objectId, and then whatever values you want to add/change, and then saved. Any field you did not assign a value to will be ignored, so say you only set field3, field2 and field1 will not be overwritten to nothing.
2) ParseUser user = ParseUser.getCurrentUser() already returns a user object. You don't even need to create a shell from the id, this is a fully functioning parse object. You can then set the value you want and save it!
3) Queries and fetches (and cloud function calls) are asynchronous. This means that the code executes over time on a background thread, and your main thread will go on. So, things that require the results of these methods need to be called within the completion handler. You're doing object = query.get(objectId), but query.get() takes a bit to run so you're probably running through the rest of the code block before object has a proper value.
4) To my knowledge (not an Android developer, but I've used the JS and iOS SDKs) the Parse SDKs have a specific query for the User class that is a bit easier and safer to use than creating a ParseQuery set to the "User" class. Should be something like ParseUser.query()
So, not being an Android developer, I think what you want is more like this:
// Test the data.
if (userCard.validateCard()) {
Stripe stripe = new Stripe(CardActivity.this, "correct data is here I removed it, for StackOverflow");
stripe.createToken(
userCard,
new TokenCallback() {
public void onSuccess(final Token token) {
// Send token to your server
// Query the users, and get the username.
ParseQuery<ParseObject> query = ParseQuery.getQuery("User");
ParseUser user = ParseUser.getCurrentUser();
try {
user.put("token", token);
user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Toast.makeText(CardActivity.this, "Success", Toast.LENGTH_SHORT).show();
}
}
});
} catch (ParseException e) {
Toast.makeText(CardActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
public void onError(Exception error) {
// Show error message
Toast.makeText(CardActivity.this,
error.getMessage(),
Toast.LENGTH_LONG
).show();
}
}
);
} else {
Toast.makeText(CardActivity.this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
Related
The Parse android SDK does not allow updating of a column in the user table
while I am using getCurrentUser() method to mark it as authenticated. When I call saveInBackground() on it I get the following error in the log file:
Uncaught internal server error. { [MongoError: exception: Mod on _id not allowed]
name: 'MongoError'
Below is the code I am using for saving:
byte[] data = "Working at Parse is great!".getBytes();
final ParseFile file = new ParseFile("abcdef.txt", data);
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser != null) {
// do stuff with the user
currentUser.put("column_name", file);
currentUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("KQ", "update successfully");
} else {
Log.i("KQ", "update error e = " + e);
}
}
});
} else {
// show the signup or login screen
Log.i("KQ", "else");
}
You have to save the ParseFile before attaching it to the User object.
Your code should be like this
byte[] data = "Working at Parse is great!".getBytes();
final ParseFile file = new ParseFile("abcdef.txt", data);
file.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if(e==null)
{
ParseUser currentUser = ParseUser.getCurrentUser();
if (currentUser != null) {
// do stuff with the user
currentUser.put("column_name", file);
currentUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
Log.i("KQ", "update successfully");
} else {
Log.i("KQ", "update error e = " + e);
}
}
});
} else {
// show the signup or login screen
Log.i("KQ", "else");
}
}
}
});
Till I get a good answer.I am currently using my cloud code beforeSave trigger in parse to remove the id field to get rid of the exception and unblock my work.
any good answer will still be appreciated.
code I am using right now is as follows in the cloud code.
Parse.Cloud.beforeSave(Parse.User, function(request, response) {
// For Android SDK remove id field while updating a user becasue it was creating MongoDB Exception in android.
if (request.object.get("updatedFrom") == 'android') {
request.object.unset("updatedFrom");
request.object.unset("id");
}
response.success();
});
thanks.
I'm trying to add a relation on the table users with the bars on the table bar. The bars already exist on my database but I'm always getting the error "unable to encode an association with an unsaved ParseObject".
ParseUser user = ParseUser.getCurrentUser();
ParseObject barParseObject = ParseObject.createWithoutData(TABLE_BAR, bar.getBarId());
ParseRelation<ParseObject> relation = user.getRelation(ApiUserMapper.FIELD_LIKES);
if (bar.isFavourite()) {
relation.add(barParseObject);
} else {
relation.remove(barParseObject);
}
user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
resultCallback.processResults(bar);
} else {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error: updateFav " + e.getMessage());
}
resultCallback.processError(e);
}
}
});
bar.getBarId() contains a valid ObjectId already stored in the database, but I also tried querying for that bar before with the same result.
ParseQuery<ParseObject> query = ParseQuery.getQuery(TABLE_BAR);
query.getInBackground(bar.getBarId(), new GetCallback<ParseObject>() {
public void done(ParseObject object, ParseException e) {
if (e == null) {
ParseRelation<ParseObject> relation = user.getRelation(ApiUserMapper.FIELD_LIKES);
if (bar.isFavourite()) {
relation.add(object);
} else {
relation.remove(object);
}
user.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
resultCallback.processResults(bar);
} else {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error: updateFav " + e.getMessage());
}
resultCallback.processError(e);
}
}
});
}
}
});
If I try to add the relation the other way around, it works fine. But I want the relation to be added on the table User.
ParseObject barParseObject = ParseObject.createWithoutData(TABLE_BAR, bar.getBarId());
ParseRelation<ParseObject> relation = barParseObject.getRelation(ApiUserMapper.FIELD_LIKES);
relation.add(user);
barParseObject.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (e == null) {
resultCallback.processResults(bar);
} else {
if (BuildConfig.DEBUG) {
Log.e(TAG, "Error: updateFav " + e.getMessage());
} else {
Crashlytics.log(LOG_PRIORITY, TAG, "Error: updateFav " + e.getMessage());
}
resultCallback.processError(e);
}
}
});
Any hints? Something related to permissions? I'm assuming that the current user is able to write his own data but I don't have any specific setting anywhere in my code.
Thanks!
Are you sure the user is logged in? It looks like the user.getCurrentUser() may be returning null, which would explain the sticky error.
I don't know what was going on but I deleted my user on the Parse console. I created a new one and now everything it's working fine!
I can't comment or upvote yet but I wanted to let it be known that deleting and readding the user also fixed my problem, in case someone else has the same issue.
I use Parse to build user profile.
Is there anyone know why there is no update on server ROW in Parse?
Code:
String parseSessionToken = ParseUser.getCurrentUser().getSessionToken();
Log.d("ParseUser.getSessionToken", parseSessionToken);
ParseUser.becomeInBackground(parseSessionToken, new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
// The current user is now set to user.
Log.d("ParseUser before getUsername", user.getUsername());
user.setUsername(stringUserName);
Log.d("ParseUser after getUsername", user.getUsername());
} else {
// The token could not be validated.
Log.d("ParseUser after fail", e.toString());
}
}
});
Log:
04-27 02:30:21.730 677-677/com.di D/ParseUser.getCurrentUser objectID﹕ cUCPqKIV4HQe892eamTP0Ocyv
04-27 02:30:23.450 677-677/com.di D/ParseUser before getUsername﹕ h3#msn.com
04-27 02:30:39.100 677-677/com.di D/ParseUser after getUsername﹕ h3
Parse.com still keep String in old data. (I have reloading)
Please help, thanks.
After setting the username you need to call the save method. You can use the below method;
ParseUser parseUser = ParseUser.getCurrentUser();
parseUser.setUsername(stringUserName);
parseUser.saveInBackground(new SaveCallback() {
#Override
public void done(ParseException e) {
if (null == e) {
// report about success
} else {
// report about error
}
}
})
Hope this helps;
Regards.
If a user is registered by calling the following call once:
private void signup() {
ParseUser user = new ParseUser();
user.setUsername("ola");
user.setPassword("kari4ever");
user.setEmail("ola#nordmann.no");
user.put("phone", "650-253-0000");
user.signUpInBackground(new SignUpCallback() {
public void done(ParseException e) {
if (e == null) {
toast("Hooray! The user is signed up");
} else {
toast("signup failed \n" + e.toString());
}
}
});
}
If the user already exists, the parse library repeats the HTTP request many times before the SingupCallback.done() method is called.
Is this a bug?
I am writing a Parse Android application which uses anonymous users by enabling automatic user creation. I can successfully signup this user (to convert the anonymous user into a regular user) and after that, logging in. Both calls return successfully. When I then set data on the user object and trying to save the user, I get a stackoverflow in the ParseObject class.
My code looks like this (simplified example code):
user.setUsername("MyUserName");
final String password = new PasswordGenerator().nextSessionId();
user.setPassword(password);
try {
user.signUp();
ParseUser.logInInBackground(verification.getPhoneNumber(), password, new LogInCallback() {
#Override
public void done(final ParseUser parseUser, final ParseException e) {
if (parseUser == null) {
requestListener.onError(e);
} else {
parseUser.put("phone_no", "123");
parseUser.saveInBackground(new SaveCallback() { // This generates a stackoverflow
#Override
public void done(final ParseException e) {
int i = 0;
System.out.println("i = " + i);
}
});
// requestListener.onSuccess(null);
}
}
});
} catch (ParseException e) {
e.printStackTrace();
}
The stack overflow is generated when calling saveInBackground on the ParseUser. The stackoverflow looks like this:
java.lang.StackOverflowError
at com.parse.ParseObject.isDataAvailable(ParseObject.java:3212)
at com.parse.ParseObject.checkGetAccess(ParseObject.java:3284)
at com.parse.ParseObject.getString(ParseObject.java:2867)
at com.parse.ParseUser.getUsername(ParseUser.java:401)
at com.parse.ParseUser.signUpAsync(ParseUser.java:665)
at com.parse.ParseUser.resolveLazinessAsync(ParseUser.java:1397)
at com.parse.ParseUser.saveAsync(ParseUser.java:502)
at com.parse.ParseUser.signUpAsync(ParseUser.java:681)
at com.parse.ParseUser.resolveLazinessAsync(ParseUser.java:1397)
at com.parse.ParseUser.saveAsync(ParseUser.java:502)
at com.parse.ParseUser.signUpAsync(ParseUser.java:681)
The Parse version I use is 1.8.0.
Any ideas?
I found the solution! Turns out you have to save the anonymous user first before converting the user into a registered one. If you save the user first, convert the user into a registered one and then do a saveInBackground, you won't get a stackoverflow. So the full code to convert an anonymous user is:
final String accountUsername = username.getText().toString();
final String accountPassword = password.getText().toString();
final ParseUser user = ParseUser.getCurrentUser();
user.setUsername(accountUsername);
user.setPassword(accountPassword);
user.signUpInBackground(new SignUpCallback() {
#Override
public void done(final ParseException e) {
if (e != null) {
Toast.makeText(MainActivity.this, "Signup Fail", Toast.LENGTH_SHORT).show();
e.printStackTrace();
} else {
Toast.makeText(MainActivity.this, "Signup success", Toast.LENGTH_SHORT).show();
final ParseUser user = ParseUser.getCurrentUser();
user.put("phone_no", "31743379507");
user.saveInBackground(new SaveCallback() {
#Override
public void done(final ParseException e) {
if (e != null) {
Toast.makeText(MainActivity.this, "Save data Fail", Toast.LENGTH_SHORT).show();
e.printStackTrace();
} else {
Toast.makeText(MainActivity.this, "Save data success", Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
Please note that the saveInBackground in the SignupCallback is optional. You could also set this data on the user before the signUpInBackground is called and save an extra roundtrip. This is pure for demonstration purposes.
Also, it is assumed the following code is placed in the Application class to allow anonymous users:
ParseUser.enableAutomaticUser();
ParseUser.getCurrentUser().saveInBackground();
Here you see the user is saved as soon it is created.
findViewById(R.id.createUser).setOnClickListener(newView.OnClickListener() {
#Override
public void onClick(final View v) {
final String accountUsername = username.getText().toString();
final String accountPassword = password.getText().toString();
final ParseUser user = ParseUser.getCurrentUser();
user.setUsername(accountUsername);
user.setPassword(accountPassword);
user.signUpInBackground(new SignUpCallback() {
#Override
public void done(final ParseException e) {
if (e != null) {
Toast.makeText(MainActivity.this, "Signup Fail",
Toast.LENGTH_SHORT).show();
Log.e(TAG, "Signup fail", e);
} else
{ Toast.makeText(MainActivity.this,"Signupsuccess",Toast.LENGTH_SHORT).show();
final ParseUser user = ParseUser.getCurrentUser();
user.put("phone_no", "31612345678");
user.saveInBackground(new SaveCallback() {
#Override
public void done(final ParseException e) {
if (e != null) {
Toast.makeText(MainActivity.this, "Save data Fail", Toast.LENGTH_SHORT).show();
Log.e(TAG, "Signup fail", e);
} else {
Toast.makeText(MainActivity.this, "Save
data success", Toast.LENGTH_SHORT).show();
}
}
});
}
}
});
}
})