I'm developing a GAE/J app using JDO to manage the Datastore. It offers a number of Endpoints to interact with the data and so on. I'm also developing a Javascript client for those endpoints.
Situation:
First I have an endpoint method Token getSessionToken(User usr)
, which generates a session token, assigns it to the user and stores both user and session token in the Datastore.
Then I have another endpoint method Info getInfo(Token token)
which receives a session token, checks if that session token corresponds to an user and if so, returns some info.
Problem
From my Javascript client, I call the first method and everything is fine. Then I call the second method with the previously retreved session token, and I receive an error saying that the session token doesn't correspond to any user...
I've checked and I realised that this error happens just because the new session token has not been persisted yet!
Question
My current solution is to make the Javascript client call the second method once, and if it receives an error, wait a while and call again... is there a better solution?
EDIT:
This is the code invloved in the first method call to get an idea about why it takes so long...
Endpoint:
@ApiMethod(
name = "getSessionToken",
path = "get_session_token",
httpMethod = HttpMethod.GET
)
public SessionToken getSessionToken (@Named("email") String email, @Named("password") String password)
throws InternalServerErrorException {
SessionToken sessionToken = new UsersController().getSessionToken(email, password);
return sessionToken;
}
Control:
public SessionToken getSessionToken(String email, String password) throws InternalServerErrorException {
SessionToken sessionToken = null;
PersistenceManager pm = PMF.get().getPersistenceManager();
Transaction txn = DatastoreServiceFactory.getDatastoreService().beginTransaction();
try {
DAO dao = new DAO(pm);
User user = dao.getUserByLogin(email, password);
dao.deleteSessionToken(user.getSessionToken());
sessionToken = SessionTokenManager.generateToken(user.getEmail(), user.getPassword());
user.setSessionToken(sessionToken);
user = dao.insertUser(user);
txn.commit();
} catch (Exception e) {
throw new InternalServerErrorException();
} finally {
if (txn.isActive()) {
txn.rollback();
}
pm.close();
}
return sessionToken;
}
DAO:
public User getUserByLogin(String email, String password) throws InternalServerErrorException {
User user = null;
Query query = null;
try {
query = this.pm.newQuery(User.class);
query.setFilter("email == emailParam && password == passwordParam");
query.declareParameters("String emailParam, String passwordParam");
List<User> results = (List<User>) query.execute(email, password);
user = results.get(0);
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException("Error in DAO.getUserByLogin()");
} finally {
query.closeAll();
}
return user;
}
/////
public void deleteSessionToken(SessionToken sessionToken) throws InternalServerErrorException {
try {
this.pm.deletePersistent(sessionToken);
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException("Error in DAO.deleteSessionToken()");
}
}
/////
public User insertUser(User user) throws InternalServerErrorException {
try {
this.pm.makePersistent(user);
} catch (Exception e) {
e.printStackTrace();
throw new InternalServerErrorException("Error in DAO.insertUser()", e);
}
return user;
}
Model:
@PersistenceCapable
public class User {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String name;
@Persistent
private String email;
@Persistent
private String password;
@Persistent
private Folder rootFolder;
@Persistent
private SessionToken sessionToken;
@Persistent(defaultFetchGroup = "true")
private AccountContainer accountContainer;
//getters & setters
}
/////
@PersistenceCapable
public class SessionToken {
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Key key;
@Persistent
private String token;
@Persistent
private Long created;
@Persistent
private String sha1;
//getters & setters
}