【发布时间】:2013-05-02 17:24:42
【问题描述】:
我正在开发一个 GAE/J 应用,使用 JDO 来管理数据存储区。它提供了许多端点来与数据等进行交互。我还在为这些端点开发一个 Javascript 客户端。
情况:
首先我有一个端点方法Token getSessionToken(User usr),它生成一个会话令牌,将其分配给用户并将用户和会话令牌存储在数据存储中。
然后我有另一个端点方法Info getInfo(Token token) 接收会话令牌,检查该会话令牌是否对应于用户,如果是,则返回一些信息。
问题
从我的 Javascript 客户端,我调用了第一个方法,一切都很好。然后我使用先前检索的会话令牌调用第二种方法,我收到一条错误消息,指出会话令牌不对应于任何用户...
我检查了一下,发现这个错误只是因为新的会话令牌还没有被持久化!
问题
我目前的解决方案是让Javascript客户端调用第二个方法一次,如果收到错误,稍等片刻再调用...有没有更好的解决方案?
编辑:
这是第一个方法调用中涉及的代码,用于了解为什么需要这么长时间...
端点:
@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;
}
控制:
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;
}
道:
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;
}
型号:
@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
}
【问题讨论】:
-
您是否遵循强一致性指南 (developers.google.com/appengine/docs/java/datastore/…)?如果我们可以看到您的实际实体和查询,诊断可能会更容易一些。
-
@adb12 我已经编辑了问题以添加涉及的实体和查询...
标签: java google-app-engine jdo datanucleus google-cloud-endpoints