【发布时间】:2017-09-28 16:36:29
【问题描述】:
我正在尝试通过管理 SDK 从 Java 端点访问 firebase 实时数据库。认证好像成功了,但是查询没有效果。不会发生错误,也不会调用侦听器。 Firebase 规则设置为可写(通过模拟器保证)。
Firebase 数据库:
mydbid
+---users
+---user0
+---email:default@gmail.com
端点定义:
@Api(
name = "firebaseTestEndpoint",
version = "v1",
description = "Firebase admin test endpoint.")
public class FirebaseTestService {
private static final Logger log =
Logger.getLogger(FirebaseTestService.class.getName());
static {
log.setLevel(Level.INFO);
}
@ApiMethod(httpMethod = HttpMethod.POST)
public void connectToFirebase(@Named("id") String id,
ServletContext servletContext) {
Map<String, Object> authVars = new HashMap<String, Object>();
authVars.put("uid", "admin");
try {
FirebaseOptions options = new FirebaseOptions.Builder()
.setDatabaseUrl("https://mydbid.firebaseio.com")
.setCredential(FirebaseCredentials.fromCertificate(
servletContext.getResourceAsStream(
"/WEB-INF/firebase-credentials.json")))
.setDatabaseAuthVariableOverride(authVars)
.build();
FirebaseApp app = FirebaseApp.initializeApp(options);
DatabaseReference ref =
FirebaseDatabase.getInstance().getReference("/users/user0/email");
ValueEventListener valueEventListener =
ref.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot arg0) {
log.info(arg0.getRef().getPath().toString() +
" changed to " + arg0.getValue(String.class));
}
@Override
public void onCancelled(DatabaseError arg0) {
log.info("cancelled");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
@ApiMethod(httpMethod = HttpMethod.POST)
public void updateEmail(@Named("id") String id) {
Map<String,Object> values = new HashMap<String,Object>();
values.put("email", "updated@gmail.com");
try {
FirebaseDatabase.getInstance().getReference("/users/user0")
.updateChildren(values, new DatabaseReference.CompletionListener() {
public void onComplete(DatabaseError databaseError,
DatabaseReference databaseReference) {
if (databaseError != null) {
throw databaseError.toException();
}
log.info("update completed.");
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
appengine-web.xml(相关部分):
<basic-scaling>
<max-instances>2</max-instances>
</basic-scaling>
web.xml(相关部分;*前插入空格):
<servlet>
<servlet-name>EndpointsServlet</servlet-name>
<servlet-class>com.google.api.server.spi.EndpointsServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value>mypackage.FirebaseTestService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>EndpointsServlet</servlet-name>
<url-pattern>/_ah/api/ *</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>SystemServiceServlet</servlet-name>
<servlet-class>com.google.api.server.spi.SystemServiceServlet</servlet-class>
<init-param>
<param-name>services</param-name>
<param-value>mypackage.FirebaseTestService</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>SystemServiceServlet</servlet-name>
<url-pattern>/_ah/spi/ *</url-pattern>
</servlet-mapping>
在 APIs Explorer 中测试,connectToFirebase() 调用后跟对 _ah/background 的请求,但 updateEmail() 没有。 怎么了?
【问题讨论】:
-
数据库监听器在不同的后台线程上运行。您的请求线程将在侦听器执行之前返回。您可以尝试等待他们,看看是否有什么不同?您可以使用 Tasks API 进行等待:firebase.google.com/docs/reference/admin/java/reference/com/…
-
使用 Tasks.await(task),返回 DEADLINE_EXCEEDED 错误。后台线程似乎无法完成它的工作......
-
您能确认您的 Firebase SDK 版本吗?并且还可以使用 ThreadManager API 来确保您的实例确实具有后台线程支持。您可以自己创建并启动一个后台线程来验证这一点:cloud.google.com/appengine/docs/standard/java/…
-
另外,请尝试删除以下行的代码:authVars.put("uid", "admin")。这将帮助我们排除由 Firebase DB 规则引起的奇怪超时的情况。
-
Firebase 管理员的版本是 4.1.7。删除 .setDatabaseAuthVariableOverride(authVars) 没有效果。ThreadManager#createBackgroundThread(Runnable) 效果很好。
标签: java firebase firebase-realtime-database google-cloud-endpoints firebase-admin