尽管抛出BadRequestException,App Engine仍继续执行程序

时间:2016-04-09 23:25:30

标签: java android google-app-engine objectify

我有2台Android设备连接的App Engine应用程序(Java)。 App Engine后端提供了一个“setUsername”函数,允许客户端设置用户名。

public void setUsername(@Named("username") String username, User oauthUser) throws OAuthRequestException, BadRequestException {
    UserRecord user = OAuthTools.getUser(oauthUser);
    updateUsername(user, username);
    ofy().save().entity(user);
}

private void updateUsername(UserRecord user, String username) throws BadRequestException {
    user.name = username;
//Search for a user that already has the desired username. Note that the entity is NOT being saved in this method.
    UserRecord existingUser = ofy().load().type(UserRecord.class).filter("normalizedName", user.normalizedName).first().now();
    if(existingUser != null && existingUser.id != user.id) throw new BadRequestException("username taken");
}

问题如下: 在我通过调用setUsername(例如,'aaaa')为第一个Android客户端设置了一些用户名后,我尝试使用第二个Android客户端设置相同的用户名(不同时,在两次调用之间至少间隔10秒)。后端然后正确地抛出BadRequestException并显示消息“username taken”,但它仍然将相同的用户名写入数据库中的第二个用户,即两个用户在第二个客户端的此调用之后设置了用户名'aaaa'。

为什么会这样?我的理解是,在抛出Exception时代码执行应该已经停止,因此永远不应该调用ofy()。save()调用。

本地应用引擎开发服务器以及后端应用程序部署到Google服务器时都会出现问题。

编辑:问题似乎是objectify将updateUsername中创建的UserRecord保存到数据库,尽管ofy()。save()永远不会被调用。为什么?

1 个答案:

答案 0 :(得分:0)

您可能还有其他几个问题,但根本问题是:

  1. 您需要使用交易
  2. 您无法在交易中使用常规查询
  3. 如果要强制实施用户名的唯一性,则需要创建一个单独的用户名实体,其id为用户名本身,并加载/创建用户名以及用户记录。因为您的用户名加载是主键,所以您可以在事务上保证其唯一性。