My problem that I have to consider which firebase project to access depends on the request header value, that came with different values depends on the front end.
What I have now:
FirebaseAppProvider.java:
public class FirebaseAppProvider implements Provider<FirebaseApp> {
private final Logger.ALogger logger;
private final Environment environment;
private final Configuration configuration;
@Inject
public FirebaseAppProvider(Environment environment, Configuration configuration) {
this.logger = Logger.of(this.getClass());
this.environment = environment;
this.configuration = configuration;
}
@Singleton
@Override
public FirebaseApp get() {
HashMap<String, String> firebaseProjects = (HashMap<String, String>) configuration.getObject("firebase");
firebaseProjects.forEach((websiteId, projectId) -> {
FileInputStream serviceAccount = null;
try {
serviceAccount = new FileInputStream(environment.classLoader().getResource(String.format("firebase/%s.json", projectId)).getPath());
} catch (FileNotFoundException e) {
e.printStackTrace();
return;
}
FirebaseOptions options = new FirebaseOptions.Builder().setCredential(FirebaseCredentials.fromCertificate(serviceAccount))
.setDatabaseUrl(String.format("https://%s.firebaseio.com/", projectId))
.build();
FirebaseApp firebaseApp = FirebaseApp.initializeApp(options, projectId);
logger.info("FirebaseApp initialized");
});
return FirebaseApp.getInstance();
}
}
Also for Database:
FirebaseDatabaseProvider.java
public class FirebaseDatabaseProvider implements Provider<FirebaseDatabase> {
private final FirebaseApp firebaseApp;
public static List<TaxItem> TAXES = new ArrayList<>();
@Inject
public FirebaseDatabaseProvider(FirebaseApp firebaseApp) {
this.firebaseApp = firebaseApp;
fetchTaxes();
}
@Singleton
@Override
public FirebaseDatabase get() {
return FirebaseDatabase.getInstance(firebaseApp);
}
@Singleton
public DatabaseReference getUserDataReference() {
return this.get().getReference("/usersData");
}
@Singleton
public DatabaseReference getTaxesConfigurationReference() {
return this.get().getReference("/appData/taxConfiguration");
}
private void fetchTaxes() {
DatabaseReference bundlesRef = getTaxesConfigurationReference().child("taxes");
bundlesRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
TAXES.clear();
dataSnapshot.getChildren().forEach(tax -> TAXES.add(tax.getValue(TaxItem.class)));
Logger.info(String.format("==> %d taxes records loaded", TAXES.size()));
}
@Override
public void onCancelled(DatabaseError databaseError) {
Logger.warn("The read failed: " + databaseError.getCode());
}
});
}
}
So I bind them as well from Module.java:
public class Module extends AbstractModule {
@Override
public void configure() { bind(FirebaseApp.class).toProvider(FirebaseAppProvider.class).asEagerSingleton();
bind(FirebaseAuth.class).toProvider(FirebaseAuthProvider.class).asEagerSingleton();
bind(FirebaseDatabase.class).toProvider(FirebaseDatabaseProvider.class).asEagerSingleton();
}
}
my ActionCreator:
public class ActionCreator implements play.http.ActionCreator {
@Inject
public ActionCreator() {
}
@Override
public Action createAction(Http.Request request, Method actionMethod) {
switchTenancyId(request);
return new Action.Simple() {
@Override
public CompletionStage<Result> call(Http.Context ctx) {
return delegate.call(ctx);
}
};
}
private void switchTenancyId(Http.RequestHeader request) {
// DO something here
}
private Optional<String> getTenancyId(Http.RequestHeader request) {
String websiteId = request.getHeader("Website-ID");
System.out.println(websiteId);
return null;
}
}
What I want is when I use Database service, or auth service, I read the website id and decide which firebase project to access, I really tried the solution like this answer here:
Please note I'm willing to use differents projects, not the same firebase project for each front-end.
But kinda lost, especially the request can be only accessed from controller or ActionCreator, so what I got from the question above is load providers by key into `ThreadLocal` and switch them for each request depends on the annotation, but I was unable to do this because of the lack of knowledge.
----------
Also, I uploaded `taxes-data-export.json` file to import inside firebase project for a test.