在 android 客户端和 GAE 端点之间共享 类
Sharing classes between android client and GAE Endpoints
1)我从model模块做了一个依赖,里面有一个UserModel
class。但我无法将其导入客户端,因为我的端点 api getUser
方法 returns com.example.serjsmor.backend.userModelApi.model.UserModel
,而不是 com.serjsmor.digitalpheromone.module.UserModel
。我可以将这个生成的 class 导入我的客户端,但是我的依赖有什么意义呢?
2) 我所做的任何更改 UserModel
都不会影响生成的后端 class(比如添加另一个 Ctor
)。如何让后端在更改后再次重新编译它? (尝试 add/remove、重建、清理等)
我在 Yosemite
上使用 Android Studio 1.02
客户代码:
package com.serjsmor.digitalpheromone;
import com.example.serjsmor.backend.userModelApi.UserModelApi;
import com.example.serjsmor.backend.userModelApi.model.UserModel;
import com.google.android.gms.maps.model.LatLng;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import com.serjsmor.digitalpheromone.module.UserAlreadyExistsException;
import com.serjsmor.digitalpheromone.module.UserNotFoundException;
import com.serjsmor.digitalpheromone.pheromones.Pheromone;
import java.io.IOException;
import java.util.ArrayList;
public class EndpointsServer implements Server {
private static final String TAG = "EndpointsServer";
final UserModelApi userEndpointsApi;
public EndpointsServer() {
UserModelApi.Builder builder = new UserModelApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
@Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
userEndpointsApi = builder.build();
}
@Override
public User getUser(String email) {
User user = null;
try {
Log.d(TAG, "in getUser with email " +email);
// get user from db
UserModel userModel = userEndpointsApi.getUserModel(email).execute();
if (userModel != null) {
Log.d(TAG, "user != null with email " + email);
user = new User(userModel);
}
else { // add user to db
Log.d(TAG, "user == null with email " + email);
user = new User(email);
UserModel afterInsert = userEndpointsApi.storeUserModel(user.getUserModel()).execute();
Log.d(TAG, "after insert user email" + afterInsert.getEmail());
}
} catch (IOException e) {
e.printStackTrace();
}
return user;
}
}
端点:
package com.example.serjsmor.myapplication.backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Transaction;
import com.serjsmor.digitalpheromone.module.UserAlreadyExistsException;
import com.serjsmor.digitalpheromone.module.UserModel;
import com.serjsmor.digitalpheromone.module.UserNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Named;
/**
* An endpoint class we are exposing
*/
@Api(
name = "userModelApi",
version = "v1",
resource = "userModel",
namespace = @ApiNamespace(
ownerDomain = "backend.myapplication.serjsmor.example.com",
ownerName = "backend.myapplication.serjsmor.example.com",
packagePath = ""
)
)
public class UserModelEndpoint {
private static final Logger logger = Logger.getLogger(UserModelEndpoint.class.getName());
/**
* This method gets the <code>UserModel</code> object associated with the specified <code>email</code>.
*
* @param email The id of the object to be returned.
* @return The <code>UserModel</code> associated with <code>id</code>.
*/
@ApiMethod(name = "getUserModel")
public UserModel getUserModel(@Named("email") String email) throws UserNotFoundException {
logger.log(Level.INFO, "serj.pheromone.BeanEndpoint inside getUserModel");
logger.log(Level.INFO, "serj.pheromone.BeanEndpoint email" + email);
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
UserModel user = null;
// throw new UserNotFoundException();
try {
Key k = KeyFactory.createKey(UserModel.class.getSimpleName(), email);
logger.log(Level.INFO, "serj.pheromone.BeanEndpoint key ");
Entity entity = datastoreService.get(k);
user = new UserModel();
user.setEmail(email);
user.setNickname((String) entity.getProperty("nickname"));
} catch (EntityNotFoundException e) {
return null;
}
return user;
}
}
模型依赖:
package com.serjsmor.digitalpheromone.module;
import com.serjsmor.digitalpheromone.module.PheromoneModel;
import java.util.List;
public class UserModel {
protected String email;
protected String nickname;
protected List<PheromoneModel> pheromoneList;
public UserModel() {
}
public UserModel(String email, String nickname) {
this.email = email;
this.nickname = nickname;
}
public UserModel(String email, String firstName, String lastName) {
this.email = email;
this.nickname = firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public List<PheromoneModel> getPheromoneList() {
return pheromoneList;
}
public void setPheromoneList(List<PheromoneModel> pheromoneList) {
this.pheromoneList = pheromoneList;
}
}
忘了回答,我有一个神秘的编译错误,直到我手动启动所有 gradle 任务,尤其是 get ClientLibs 任务后才出现。 More on debugging gradle。
我不确定答案,即使我遇到了同样的问题。但是,您可以通过使用 Google 的 Gson 库从后端摆脱这种模棱两可的 class。例如,如果您的应用中有 Grocery.class,后端有 GroceryBackend.class,并且您确定这两个 class 具有相同的字段,则执行以下操作:
Gson groceryGson = new Gson();
Grocery grocery = groceryGson.fromJson(groceryGson.toJson(groceryBackend), Grocery.class);
1)我从model模块做了一个依赖,里面有一个UserModel
class。但我无法将其导入客户端,因为我的端点 api getUser
方法 returns com.example.serjsmor.backend.userModelApi.model.UserModel
,而不是 com.serjsmor.digitalpheromone.module.UserModel
。我可以将这个生成的 class 导入我的客户端,但是我的依赖有什么意义呢?
2) 我所做的任何更改 UserModel
都不会影响生成的后端 class(比如添加另一个 Ctor
)。如何让后端在更改后再次重新编译它? (尝试 add/remove、重建、清理等)
我在 Yosemite
上使用 Android Studio 1.02客户代码:
package com.serjsmor.digitalpheromone;
import com.example.serjsmor.backend.userModelApi.UserModelApi;
import com.example.serjsmor.backend.userModelApi.model.UserModel;
import com.google.android.gms.maps.model.LatLng;
import com.google.api.client.extensions.android.http.AndroidHttp;
import com.google.api.client.extensions.android.json.AndroidJsonFactory;
import com.google.api.client.googleapis.services.AbstractGoogleClientRequest;
import com.google.api.client.googleapis.services.GoogleClientRequestInitializer;
import com.serjsmor.digitalpheromone.module.UserAlreadyExistsException;
import com.serjsmor.digitalpheromone.module.UserNotFoundException;
import com.serjsmor.digitalpheromone.pheromones.Pheromone;
import java.io.IOException;
import java.util.ArrayList;
public class EndpointsServer implements Server {
private static final String TAG = "EndpointsServer";
final UserModelApi userEndpointsApi;
public EndpointsServer() {
UserModelApi.Builder builder = new UserModelApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null)
.setRootUrl("http://10.0.2.2:8080/_ah/api/")
.setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() {
@Override
public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException {
abstractGoogleClientRequest.setDisableGZipContent(true);
}
});
userEndpointsApi = builder.build();
}
@Override
public User getUser(String email) {
User user = null;
try {
Log.d(TAG, "in getUser with email " +email);
// get user from db
UserModel userModel = userEndpointsApi.getUserModel(email).execute();
if (userModel != null) {
Log.d(TAG, "user != null with email " + email);
user = new User(userModel);
}
else { // add user to db
Log.d(TAG, "user == null with email " + email);
user = new User(email);
UserModel afterInsert = userEndpointsApi.storeUserModel(user.getUserModel()).execute();
Log.d(TAG, "after insert user email" + afterInsert.getEmail());
}
} catch (IOException e) {
e.printStackTrace();
}
return user;
}
}
端点:
package com.example.serjsmor.myapplication.backend;
import com.google.api.server.spi.config.Api;
import com.google.api.server.spi.config.ApiMethod;
import com.google.api.server.spi.config.ApiNamespace;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.EntityNotFoundException;
import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.KeyFactory;
import com.google.appengine.api.datastore.Transaction;
import com.serjsmor.digitalpheromone.module.UserAlreadyExistsException;
import com.serjsmor.digitalpheromone.module.UserModel;
import com.serjsmor.digitalpheromone.module.UserNotFoundException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.inject.Named;
/**
* An endpoint class we are exposing
*/
@Api(
name = "userModelApi",
version = "v1",
resource = "userModel",
namespace = @ApiNamespace(
ownerDomain = "backend.myapplication.serjsmor.example.com",
ownerName = "backend.myapplication.serjsmor.example.com",
packagePath = ""
)
)
public class UserModelEndpoint {
private static final Logger logger = Logger.getLogger(UserModelEndpoint.class.getName());
/**
* This method gets the <code>UserModel</code> object associated with the specified <code>email</code>.
*
* @param email The id of the object to be returned.
* @return The <code>UserModel</code> associated with <code>id</code>.
*/
@ApiMethod(name = "getUserModel")
public UserModel getUserModel(@Named("email") String email) throws UserNotFoundException {
logger.log(Level.INFO, "serj.pheromone.BeanEndpoint inside getUserModel");
logger.log(Level.INFO, "serj.pheromone.BeanEndpoint email" + email);
DatastoreService datastoreService = DatastoreServiceFactory.getDatastoreService();
UserModel user = null;
// throw new UserNotFoundException();
try {
Key k = KeyFactory.createKey(UserModel.class.getSimpleName(), email);
logger.log(Level.INFO, "serj.pheromone.BeanEndpoint key ");
Entity entity = datastoreService.get(k);
user = new UserModel();
user.setEmail(email);
user.setNickname((String) entity.getProperty("nickname"));
} catch (EntityNotFoundException e) {
return null;
}
return user;
}
}
模型依赖:
package com.serjsmor.digitalpheromone.module;
import com.serjsmor.digitalpheromone.module.PheromoneModel;
import java.util.List;
public class UserModel {
protected String email;
protected String nickname;
protected List<PheromoneModel> pheromoneList;
public UserModel() {
}
public UserModel(String email, String nickname) {
this.email = email;
this.nickname = nickname;
}
public UserModel(String email, String firstName, String lastName) {
this.email = email;
this.nickname = firstName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public List<PheromoneModel> getPheromoneList() {
return pheromoneList;
}
public void setPheromoneList(List<PheromoneModel> pheromoneList) {
this.pheromoneList = pheromoneList;
}
}
忘了回答,我有一个神秘的编译错误,直到我手动启动所有 gradle 任务,尤其是 get ClientLibs 任务后才出现。 More on debugging gradle。
我不确定答案,即使我遇到了同样的问题。但是,您可以通过使用 Google 的 Gson 库从后端摆脱这种模棱两可的 class。例如,如果您的应用中有 Grocery.class,后端有 GroceryBackend.class,并且您确定这两个 class 具有相同的字段,则执行以下操作:
Gson groceryGson = new Gson();
Grocery grocery = groceryGson.fromJson(groceryGson.toJson(groceryBackend), Grocery.class);