Java EE FirebaseApp 名称 [DEFAULT] 已存在
Java EE FirebaseApp name [DEFAULT] already exists
我遇到了与 Firebase 和 Java EE 有关的问题。
我目前正在为我的项目编写一些 Java servlet,我是第一次使用 Firebase,因为我想尝试一些新东西。
我的实际问题如下:
我有一个 servlet,它负责在用户数据库中交换 iOS 设备令牌。这是向设备发送远程推送通知所必需的。
我在 google 教程中这样做了,但我遇到了以下异常:
java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
我访问 Firebase 数据库的方式是通过 Java SDK。
我使用以下代码执行此操作:
连接方式
// gets called by the servlet to configure Firebase
public static void connect() {
try {
// for authentication purpose
Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my-service-account");
// Setting up the FirebaseOptions object
// constant FIREBASE_DATABASE_URL = "url to my database"
// constant FIREBASE_KEY_PATH = "path to my json key"
options = new FirebaseOptions.Builder()
.setDatabaseUrl(FIREBASE_DATABASE_URL)
.setServiceAccount(new FileInputStream(FIREBASE_KEY_PATH))
.setDatabaseAuthVariableOverride(auth)
.build();
FirebaseApp.initializeApp(options);
// calling the method for exchanging the token
exchangeIosDeviceToken("testmail@example.com", "5bf53173c9ef0a37638f3ddaa59cf2c0687c14ca0dcd47ccf57f9f09bd6368ab");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
exchangeIosDeviceToken 方法
public static boolean exchangeIosDeviceToken(String email, String newDeviceToken) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
// getting a reference to my "employee" child
DatabaseReference employeeReference = database.getReference("/employee");
Map<String, Object> employeeUpdates = new HashMap<>();
// updating the device token with child "iosDeviceToken" of "employee"
employeeUpdates.put(email+"/iosDeviceToken", newDeviceToken);
// update the actual children
employeeReference.updateChildren(employeeUpdates);
return true;
}
有趣的是,当我尝试在独立的 main class 中执行此代码(用 main 方法替换 connect 方法)时,代码运行正常。
在你说 "there are tons of questions related to this topic" 之类的话之前......它们几乎都与 Android 相关,而与我的问题相关的问题很少有人回答。
此致
问题解决了。
问题是:
每次收到请求时,我都会调用 connect 方法。
解法:
只调用一次连接方法。 (ServletContextListener)
我解决这个问题的方法是调用 FirebaseApp.getInstance().delete();
对于以后的用户,可以这样检查默认应用是否初始化。
FirebaseApp firebaseApp = null;
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if(firebaseApps!=null && !firebaseApps.isEmpty()){
for(FirebaseApp app : firebaseApps){
if(app.getName().equals(FirebaseApp.DEFAULT_APP_NAME))
firebaseApp = app;
}
}
else
firebaseApp = FirebaseApp.initializeApp(options);
出现此异常是因为您正在尝试再次创建 [DEFAULT]
FirebaseApp,只需在初始化之前添加验证以检查它是否存在,如下所示:
if(FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME) != null) {
return;
}
我的解决方案
package com.zs.configuration;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOpt`enter code here`ions;
import com.google.firebase.auth.FirebaseAuth;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
@WebListener
public class MyAppServletContextListener
implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
//Run this before web application is started
@Override
public void contextInitialized(ServletContextEvent arg0) {
try {
FileInputStream serviceAccount = new FileInputStream(getClass().getClassLoader().getResource("zs.json").getFile());
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://zs.firebaseio.com")
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options);
FirebaseAuth.getInstance(firebaseApp);
}catch (Exception exc){
System.out.println("Firebase exception "+exc);
}
System.out.println("ServletContextListener started");
}
}
在我的申请中class
@ServletComponentScan
@SpringBootApplication
public class ZSApplication {
public static void main(String[] args) {
SpringApplication.run(ZSApplication.class, args);
}
}
总结所有解决方案,顺便说一句,这里提出了非常好的解决方案:Running code after Spring Boot starts请在下面找到适合我的 spring-boot (2.6.3) 实现。
注意:请在下方替换为您的应用和文件名。
将 firebase 初始化方法 (FirebaseApp.initializeApp(options)) 直接放在主要方法上(正如我在本教程中发现的那样:https://www.youtube.com/watch?v=8jK9O0lwem0)它导致了错误,只是因为调试我注意到,由于某种原因,方法 FirebaseApp.initializeApp(options) 的调用;已完成多次。
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SpringBootApplication
public class YourAppNameApplication {
public static void main(String[] args) {
SpringApplication.run(YourAppNameApplication.class, args);
}
/**
* Initialize the firebase SDK to integrate with the firebase application. Used
* for check the clients UIDs authentications.
*
* @throws IOException in case the firebase configuration JSON file is not
* present on the path.
*/
@EventListener(ApplicationReadyEvent.class)
public void initFirebaseSDK() throws IOException {
ClassLoader classLoader = YourAppNameApplication.class.getClassLoader();
File file = new File(
Objects.requireNonNull(classLoader.getResource("your_file_firebase.json")).getFile());
FileInputStream serviceAccount = new FileInputStream(file.getAbsolutePath());
@SuppressWarnings("deprecation")
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://your_firebase_app_name.firebaseio.com").build();
FirebaseApp.initializeApp(options);
if (!(FirebaseApp.getApps().isEmpty())
&& FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName() != null) {
log.info("Firebase SDK has been initialised with the app name: "
+ FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName());
} else {
log.error(
"Firebase SDK has NOT been initialised. This is a serious error. Please contact the administrator of the app.");
}
}
}
我遇到了与 Firebase 和 Java EE 有关的问题。
我目前正在为我的项目编写一些 Java servlet,我是第一次使用 Firebase,因为我想尝试一些新东西。
我的实际问题如下: 我有一个 servlet,它负责在用户数据库中交换 iOS 设备令牌。这是向设备发送远程推送通知所必需的。 我在 google 教程中这样做了,但我遇到了以下异常:
java.lang.IllegalStateException: FirebaseApp name [DEFAULT] already exists!
我访问 Firebase 数据库的方式是通过 Java SDK。
我使用以下代码执行此操作:
连接方式
// gets called by the servlet to configure Firebase
public static void connect() {
try {
// for authentication purpose
Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my-service-account");
// Setting up the FirebaseOptions object
// constant FIREBASE_DATABASE_URL = "url to my database"
// constant FIREBASE_KEY_PATH = "path to my json key"
options = new FirebaseOptions.Builder()
.setDatabaseUrl(FIREBASE_DATABASE_URL)
.setServiceAccount(new FileInputStream(FIREBASE_KEY_PATH))
.setDatabaseAuthVariableOverride(auth)
.build();
FirebaseApp.initializeApp(options);
// calling the method for exchanging the token
exchangeIosDeviceToken("testmail@example.com", "5bf53173c9ef0a37638f3ddaa59cf2c0687c14ca0dcd47ccf57f9f09bd6368ab");
} catch (FileNotFoundException ex) {
ex.printStackTrace();
}
}
exchangeIosDeviceToken 方法
public static boolean exchangeIosDeviceToken(String email, String newDeviceToken) {
FirebaseDatabase database = FirebaseDatabase.getInstance();
// getting a reference to my "employee" child
DatabaseReference employeeReference = database.getReference("/employee");
Map<String, Object> employeeUpdates = new HashMap<>();
// updating the device token with child "iosDeviceToken" of "employee"
employeeUpdates.put(email+"/iosDeviceToken", newDeviceToken);
// update the actual children
employeeReference.updateChildren(employeeUpdates);
return true;
}
有趣的是,当我尝试在独立的 main class 中执行此代码(用 main 方法替换 connect 方法)时,代码运行正常。
在你说 "there are tons of questions related to this topic" 之类的话之前......它们几乎都与 Android 相关,而与我的问题相关的问题很少有人回答。
此致
问题解决了。
问题是: 每次收到请求时,我都会调用 connect 方法。
解法: 只调用一次连接方法。 (ServletContextListener)
我解决这个问题的方法是调用 FirebaseApp.getInstance().delete();
对于以后的用户,可以这样检查默认应用是否初始化。
FirebaseApp firebaseApp = null;
List<FirebaseApp> firebaseApps = FirebaseApp.getApps();
if(firebaseApps!=null && !firebaseApps.isEmpty()){
for(FirebaseApp app : firebaseApps){
if(app.getName().equals(FirebaseApp.DEFAULT_APP_NAME))
firebaseApp = app;
}
}
else
firebaseApp = FirebaseApp.initializeApp(options);
出现此异常是因为您正在尝试再次创建 [DEFAULT]
FirebaseApp,只需在初始化之前添加验证以检查它是否存在,如下所示:
if(FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME) != null) {
return;
}
我的解决方案
package com.zs.configuration;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOpt`enter code here`ions;
import com.google.firebase.auth.FirebaseAuth;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.io.FileInputStream;
@WebListener
public class MyAppServletContextListener
implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent arg0) {
System.out.println("ServletContextListener destroyed");
}
//Run this before web application is started
@Override
public void contextInitialized(ServletContextEvent arg0) {
try {
FileInputStream serviceAccount = new FileInputStream(getClass().getClassLoader().getResource("zs.json").getFile());
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://zs.firebaseio.com")
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options);
FirebaseAuth.getInstance(firebaseApp);
}catch (Exception exc){
System.out.println("Firebase exception "+exc);
}
System.out.println("ServletContextListener started");
}
}
在我的申请中class
@ServletComponentScan
@SpringBootApplication
public class ZSApplication {
public static void main(String[] args) {
SpringApplication.run(ZSApplication.class, args);
}
}
总结所有解决方案,顺便说一句,这里提出了非常好的解决方案:Running code after Spring Boot starts请在下面找到适合我的 spring-boot (2.6.3) 实现。
注意:请在下方替换为您的应用和文件名。
将 firebase 初始化方法 (FirebaseApp.initializeApp(options)) 直接放在主要方法上(正如我在本教程中发现的那样:https://www.youtube.com/watch?v=8jK9O0lwem0)它导致了错误,只是因为调试我注意到,由于某种原因,方法 FirebaseApp.initializeApp(options) 的调用;已完成多次。
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import lombok.extern.slf4j.Slf4j;
@Slf4j
@SpringBootApplication
public class YourAppNameApplication {
public static void main(String[] args) {
SpringApplication.run(YourAppNameApplication.class, args);
}
/**
* Initialize the firebase SDK to integrate with the firebase application. Used
* for check the clients UIDs authentications.
*
* @throws IOException in case the firebase configuration JSON file is not
* present on the path.
*/
@EventListener(ApplicationReadyEvent.class)
public void initFirebaseSDK() throws IOException {
ClassLoader classLoader = YourAppNameApplication.class.getClassLoader();
File file = new File(
Objects.requireNonNull(classLoader.getResource("your_file_firebase.json")).getFile());
FileInputStream serviceAccount = new FileInputStream(file.getAbsolutePath());
@SuppressWarnings("deprecation")
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://your_firebase_app_name.firebaseio.com").build();
FirebaseApp.initializeApp(options);
if (!(FirebaseApp.getApps().isEmpty())
&& FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName() != null) {
log.info("Firebase SDK has been initialised with the app name: "
+ FirebaseApp.getInstance(FirebaseApp.DEFAULT_APP_NAME).getName());
} else {
log.error(
"Firebase SDK has NOT been initialised. This is a serious error. Please contact the administrator of the app.");
}
}
}