Firebase Auth not getting initialized in spring boot

Tags: , , , ,



I am using firebase admin sdk in my spring boot app. (API app)

When I run locally in intelliJ its working fine. But when deployed in tomcat its giving me NPE.

In Springboot application

 public static void main(String[] args) {
    SpringApplication.run(InfanoApplication.class, args);

    try {
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();

        File file = new File(classloader.getResource("firebase2.json").getFile());
        logger.info("FILE PATH : " + file.getAbsolutePath());
        FileInputStream serviceAccount = new FileInputStream(file.getAbsolutePath());

        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .setDatabaseUrl(FB_BASE_URL)
                .build();

        firebaseApp = FirebaseApp.initializeApp(options);
        logger.info("FIREBASE NAME : "+firebaseApp.getName());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

In API code

userRecord = FirebaseAuth.getInstance(InfanoApplication.firebaseApp).getUserByPhoneNumber(mobile);

ERROR:

java.lang.NullPointerException
at com.google.firebase.ImplFirebaseTrampolines.getService(ImplFirebaseTrampolines.java:62)
at com.google.firebase.auth.FirebaseAuth.getInstance(FirebaseAuth.java:101)

Can someone help in fixing this issue. Thank you in advance.

Answer

You shouldn’t create an instance of Firebase like this in the main method. Probably your service account is not being found in the proper classpath. I would create a Spring Configuration which creates a Firebase app on application startup. I have kept my service account in the root of resources folder.

@Configuration
public class FirebaseConfig {

    //TODO: In your case maybe something else
    @Value(value = "classpath:serviceAccount.json")
    private Resource serviceAccountResource;

    @Bean
    public FirebaseApp createFireBaseApp() throws IOException {
        InputStream serviceAccount = serviceAccountResource.getInputStream();

        FirebaseOptions options = new FirebaseOptions.Builder()
                .setCredentials(GoogleCredentials.fromStream(serviceAccount))
                .setDatabaseUrl("<db-url>")
                .setStorageBucket("<storage-url>")
                .build();

        //Add loggers
        System.out.println("Firebase config initialized");

        return FirebaseApp.initializeApp(options);
    }

    
    @Bean
    @DependsOn(value = "createFireBaseApp")
    public StorageClient createFirebaseStorage() {
        return StorageClient.getInstance();
    }

    @Bean
    @DependsOn(value = "createFireBaseApp")
    public FirebaseAuth createFirebaseAuth() {
        return FirebaseAuth.getInstance();
    }

    @Bean
    @DependsOn(value = "createFireBaseApp")
    public FirebaseDatabase createFirebaseDatabase() {
        return FirebaseDatabase.getInstance();
    }

    @Bean
    @DependsOn(value = "createFireBaseApp")
    public FirebaseMessaging createFirebaseMessaging() {
        return FirebaseMessaging.getInstance();
    }
}

Now if I want to use Firebase Auth in any of my service classes I would just do the following:

@Service
class MyService {

    @Autowired
    private FirebaseAuth firebaseAuth;

    //TODO: Probably should have return type
    public void findUser(String mobile) {
        firebaseAuth.getUserByPhoneNumber(mobile);
    }
}


Source: stackoverflow