Get information from Firebase Realtime Database with Firebase Admin SDK - java

I'm trying to get some information from Firebase Real-time database without success. I don't know what I'm doing wrong. I also tried the doc's example and they didn't work. Here's my code and my firebase db structue:
Topics.java:
public class Topics {
private String name;
public Topics() {
}
public Topics(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Main.java
public static void main(String[] args) {
// TODO Auto-generated method stub
FileInputStream serviceAccount;
FirebaseOptions options = null;
try {
serviceAccount = new FileInputStream(".//...");
options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("...")
.build();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
FirebaseApp.initializeApp(options);
String topics = getDatafromFirebase();
System.out.println("Everything right!");
}
private static String getDatafromFirebase() {
CountDownLatch done = new CountDownLatch(1);
StringBuilder b = new StringBuilder();
DatabaseReference dbRef = FirebaseDatabase.getInstance()
.getReference();
dbRef.child("topics").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// TODO Auto-generated method stub
if(snapshot.exists()) {
for(DataSnapshot s:snapshot.getChildren()) {
Topics t = s.getValue(Topics.class);
b.append(t.getName());
b.append(" ");
done.countDown();
}
}
else {
b.append("No existe ");
done.countDown();
}
}
#Override
public void onCancelled(DatabaseError error) {
// TODO Auto-generated method stub
b.append("Error: "+error.getDetails());
done.countDown();
}
});
try {
done.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b.toString();
}
I have wait for the CountDownLatch for 5+ minutes, which I think is enough time for it to trigger. Also, important note: I have successfully sent message through firebase cloud messaging, so I don't think that it is a problem with the credentials.

I ran your code against my database with the same db structure and I can for sure say that I am ableto get information from the database.
onDataChange breakpoint not triggering only happens if I remove the topics subtree entirely. ie. in your case an empty database.
I suspect either your database url or Private Key JSON.
Follow the below Instruction for a new private key
In the console, click the gear icon on the left, and the Service Accounts Tab
Refer
Take a note of databaseUrl and click on Generate New Private Key, save it.
Refer
Here is the working code for example
package fireb;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.concurrent.CountDownLatch;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class Fireb {
public static void main(String[] args) {
// TODO Auto-generated method stub
FileInputStream serviceAccount;
FirebaseOptions options = null;
try {
serviceAccount = new FileInputStream("C:\\key\\testapp-f0fe2-firebase-adminsdk-4po4a-5ce6c60b81.json");
options = new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://testapp-f0fe2.firebaseio.com")
.build();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch(IOException e) {
e.printStackTrace();
}
FirebaseApp.initializeApp(options);
String topics = getDatafromFirebase();
System.out.println(topics);
System.out.println("Everything right!");
}
private static String getDatafromFirebase() {
CountDownLatch done = new CountDownLatch(1);
StringBuilder b = new StringBuilder();
DatabaseReference dbRef = FirebaseDatabase.getInstance()
.getReference();
dbRef.child("topics").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot snapshot) {
// TODO Auto-generated method stub
if(snapshot.exists()) {
for(DataSnapshot s:snapshot.getChildren()) {
Topics t = s.getValue(Topics.class);
b.append(t.getName());
b.append(" ");
}
done.countDown();
}
else {
b.append("No existe ");
done.countDown();
}
}
#Override
public void onCancelled(DatabaseError error) {
// TODO Auto-generated method stub
b.append("Error: "+error.getDetails());
done.countDown();
}
});
try {
done.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return b.toString();
}
}

According to the documentation available here.
Before you can access the Firebase Realtime Database from a server using the Firebase Admin SDK, you must authenticate your server with Firebase. When you authenticate a server, rather than sign in with a user account's credentials as you would in a client app, you authenticate with a service account which identifies your server to Firebase.
If you are not running your code on server, you may authenticate as a client instead as described here.
Hope this helps.

Related

can't save firebase realtime database data in java web application

I am trying to save data on Firebase realetime database from Java class with a main method. But it doesn't works.I followed the instructions in firebase website, but the data of realtime database didn't update one time. And there is no error messages. I don't know why.
The rules has been set already.
{
"rules": {
".read": true,
".write": true
}
}
The following is my code, please give some suggestions, thanks a lot!
public class Firebasetest {
private static DatabaseReference database;
public static void main(String[] args) throws InterruptedException {
// Initialize Firebase
final Semaphore semaphore = new Semaphore(0);
FirebaseApp defaultApp = null;
try {
// [START initialize]
FileInputStream serviceAccount = new FileInputStream("test-firebase.json");
FirebaseOptions options =
new FirebaseOptions.Builder()
.setCredentials(GoogleCredentials.fromStream(serviceAccount))
.setDatabaseUrl("https://test.firebaseio.com")
.build();
FirebaseApp.initializeApp(options);
System.out.println("init");
// [END initialize]
} catch (IOException e) {
System.out.println(e.getMessage());
System.out.println("ERROR: invalid service account credentials. See README.");
System.out.println(e.getMessage());
}
try {
database = FirebaseDatabase.getInstance().getReference();
ApiFuture<Void> future = database.setValueAsync("1234");
try {
// future.get();
future.get(20, TimeUnit.SECONDS);
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
final CountDownLatch latch = new CountDownLatch(1);
database.setValue(
"234343",
new DatabaseReference.CompletionListener() {
#Override
public void onComplete(
DatabaseError databaseError, DatabaseReference databaseReference) {
latch.countDown();
}
});
System.out.println("done");
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

Firebase Java Admin SDK don't work

I am following the documentation on Firebase website on setting up an Java Admin SDK. So I add the dependency to the build.gradle, and added the following code:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.Map;
import com.google.firebase.FirebaseApp;
import com.google.firebase.FirebaseOptions;
import com.google.firebase.auth.FirebaseCredentials;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
public class Main {
public static void main(String[] args) throws FileNotFoundException{
FileInputStream serviceAccount = new FileInputStream("/Users/idanaviv10/Desktop/mapit-33290-firebase-adminsdk-fdy24-a1d0505493.json");
FirebaseOptions options = new FirebaseOptions.Builder()
.setCredential(FirebaseCredentials.fromCertificate(serviceAccount))
.setDatabaseUrl("https://mapit-33290.firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
final FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference ref = database.getReference("server/saving-data/fireblog");
DatabaseReference usersRef = ref.child("users");
Map<String, User> users = new HashMap<String, User>();
users.put("alanisawesome", new User("June 23, 1912", "Alan Turing"));
users.put("gracehop", new User("December 9, 1906", "Grace Hopper"));
usersRef.setValue(users);
}
public static class User {
public String date_of_birth;
public String full_name;
public String nickname;
public User(String date_of_birth, String full_name) {
// ...
}
public User(String date_of_birth, String full_name, String nickname) {
// ...
}
}
}
The problem is when I am trying to get data (adding a listener) or trying to save data (like in the example) nothing happened. I am running the code in eclipse, I can see in the console that it print "Done", but when I check the database (on the firebase console on the browser) nothing change.
I found the problem, the problem was that the program will terminate before connecting to the Firebase server. What you need to do is to delay the termination of the program, by either calling Thread.sleep(20000);, or like I did it
Scanner scanner = new Scanner(System.in);
while(!scanner.nextLine().equals("Quit")){}
System.exit(0);
One other thing you can try is to explicitly wait until the setValue() task is complete using the Tasks API:
Task<Void> task = usersRef.setValue(users);
try {
Tasks.await(task);
} catch (ExecutionException | InterruptedException e) {
// Handle error if necessary
}
below code is pushing data into firebase database using java async call api from firebase sdk but listeners code is not executing . I am running below code in server side backend.
public enum Firebase {
INSTANCE;
FirebaseApp firebaseApp;
public void initilizeFirebaseApp(ConfigLoader configReader) {
CountDownLatch done = new CountDownLatch(1);
final AtomicInteger message1 = new AtomicInteger(0);
InputStream firebaseSecret = getClass().getClassLoader().getResourceAsStream("ServiceAccount.json");
final GoogleCredentials credentials;
try {
credentials = GoogleCredentials.fromStream(firebaseSecret);
} catch (IOException e) {
e.printStackTrace();
System.out.println("Error while reading Firebase config file." + e.toString());
throw new IllegalStateException(e);
}
Map<String, Object> auth = new HashMap<>();
auth.put("uid", "my_resources");
FirebaseOptions options = new Builder()
.setConnectTimeout(1000)
.setCredentials(credentials)
.setDatabaseAuthVariableOverride(auth)
.setDatabaseUrl(configReader.getFirebaseDatabaseURL())
.setStorageBucket(configReader.getFirebaseStorageBucket())
.setProjectId(configReader.getFirebseProjectId())
.build();
firebaseApp = FirebaseApp.initializeApp(options);
System.out.println(firebaseApp.getName());
//System.out.println(firebaseApp.getName());
// Use the shorthand notation to retrieve the default app's service
FirebaseAuth defaultAuth = FirebaseAuth.getInstance();
FirebaseDatabase defaultDatabase = FirebaseDatabase.getInstance();
// The app only has access as defined in the Security Rules
DatabaseReference ref = FirebaseDatabase
.getInstance()
.getReference("/analyst_profiles");
DateTime dt = new DateTime(java.util.Date.from(Instant.now()), java.util.TimeZone.getDefault());
System.out.println(dt.getValue());
//test data push
// https://firebase.google.com/docs/database/admin/save-data
AnalystProfiles analystProfilesObjTemp = new AnalystProfiles("test2", Long.toString(dt.getValue()), "dsds", "ds", "ds",
"dsa2323", "32ddss232");
ref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
AnalystProfiles post = dataSnapshot.getValue(AnalystProfiles.class);
System.out.println(post);
//done.countDown();
}
#Override
public void onCancelled(DatabaseError databaseError) {
System.out.println("The read failed: " + databaseError.getCode());
}
});
CompletableFuture<String> welcomeText = CompletableFuture.supplyAsync(() -> {
try {
ref.push().setValueAsync(analystProfilesObjTemp).get();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException("Error while waiting for future", e);
}
return "ok";
}).thenApply(x -> {
System.out.println(x);
System.out.println("Listeners code is not executing");
return x;
});
done.countDown();
try {
System.out.println(welcomeText.get());
done.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
public void testdataLoad() {
// The app only has access as defined in the Security Rules
DatabaseReference ref = FirebaseDatabase
.getInstance()
.getReference("/analyst_profiles");
DateTime dt = new DateTime(java.util.Date.from(Instant.now()), java.util.TimeZone.getDefault());
System.out.println(dt.getValue());
//test data push
// https://firebase.google.com/docs/database/admin/save-data
AnalystProfiles analystProfilesObjTemp = new AnalystProfiles("test2", Long.toString(dt.getValue()), "dsds", "ds", "ashutsh",
"dsa2323", "32ddss232");
CompletableFuture<String> welcomeText = CompletableFuture.supplyAsync(() -> {
try {
ref.push().setValueAsync(analystProfilesObjTemp).get();
} catch (ExecutionException | InterruptedException e) {
throw new RuntimeException("Error while waiting for future", e);
}
return "ok";
}).thenApply(x -> {
System.out.println(x);
return x;
});
try {
System.out.println(welcomeText.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
Add this code:
ApiFuture api=/*your reference to database*/usersRef.setValueAsync(users/*the data*/);
Object o = api.get(/*time out*/8,TimeUnit.SECONDS/*unite for time out her is seconds*/);
And at last you can check with
api.isDone();

Trying to acquire token with adal4j

I don't know how to acquire token without username and password using the adal4j library. I have this code:
public class GetToken implements AuthenticationCallback {
public static void main(String[] args) {
// TODO Auto-generated method stub
String resource = "resource";
String redirectUrl = "redirecturl";
String authority = "https://login.microsoftonline.com/common/";
ExecutorService executor = null;
ClientAssertion clientId = new ClientAssertion("my-client-id");
AuthenticationCallback callback;
// Authenticate the registered application with Azure Active Directory.
AuthenticationContext authContext;
try {
authContext = new AuthenticationContext(authority, false,executor);
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Future <AuthenticationResult> result = authContext.acquireToken(resource, clientId, callback);
}
#Override
public void onSuccess(AuthenticationResult result) {
// TODO Auto-generated method stub
}
#Override
public void onFailure(Throwable exc) {
// TODO Auto-generated method stub
}
}
And I don't know how to acquire token ....
Check this link: https://learn.microsoft.com/en-us/azure/active-directory/develop/active-directory-devquickstarts-webapp-java#step-8-create-the-basicfilter-file-for-basicfilter-mvc
Look into the getAccessToke() method.This is what you're looking for:
ExecutorService executor = Executors.newFixedThreadPool(1);
Hope this helps!
You will get an IllegalArgumentException as the Executor service passed to AuthenticationContext is null.

synchronization with executorService

i wrote tthe below method to insert records using threads, but at run time i receive "[SQLITE_BUSY] The database file is locked (database is locked)" error,and i think could be due to conflict
of sqlite statement.
i just want to know i am wusing the executorservice correctly in the "insertRecord" method? is there any other variables shoule have been synchronizedß
code:
public void insertRecord(String nodeID, String lat, String lng, String xmlpath) throws SQLException, ClassNotFoundException {
if (this.isTableExists(this.TABLE_NAME)) {
InsertRun insRun = new InsertRun(this.psInsert, nodeID, lat, lng, xmlpath);
this.executor.execute(insRun);
} else {
Log.e(TAG, "insertRecord", "table: ["+this.TABLE_NAME+"] does not exist");
}
}
public void flush() throws SQLException {
this.psInsert.executeBatch();
this.psInsert.close();
this.connInsert.close();
Log.d(TAG, "insertRecord", "the rest of the records flushed into data base table.");
}
private class InsertRun implements Runnable {
private PreparedStatement psInsert = null;
private String nodeID;
private String lat;
private String lng;
private String xmlPath;
public InsertRun(PreparedStatement psInsert, String nodeID, String lat, String lng, String xmlpath) {
// TODO Auto-generated constructor stub
this.psInsert = psInsert;
this.nodeID = nodeID;
this.lat = lat;
this.lng = lng;
this.xmlPath = xmlpath;
}
#Override
public void run() {
// TODO Auto-generated method stub
try {
this.psInsert.setString(1, this.nodeID);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
this.psInsert.setString(2, this.lat);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
this.psInsert.setString(3, this.lng);
} catch (SQLException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
try {
this.psInsert.setString(4, this.xmlPath);
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
try {
this.psInsert.addBatch();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized(this) {
if (++batchCnt == SysConsts.BATCH_SIZE) {
try {
this.psInsert.executeBatch();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
batchCnt = 0;
Log.d(TAG, "InsertRun", SysConsts.BATCH_SIZE+" records inserted.");
}
}
}
}
SQLite is not a database suitable for concurrent access. You cannot modify your database concurrently:
Multiple processes can have the same database open at the same time. Multiple processes can be doing a SELECT at the same time. But only one process can be making changes to the database at any moment in time, however.
.
When SQLite tries to access a file that is locked by another process, the default behavior is to return SQLITE_BUSY
Read this for details (and simply give up multithreading in your app...)
Additionally, good concurrency design considerations can be difficult to offer without know alot more about the program. Suggest perusing through Java Concurrency in Practice if you plan on writing more multi-threaded applications.

Doing networkprocesses on the Main UI

My Android App needs some basic data to run. This data is downloaded from a server using JSON. In Xcode I simply used the sendsynchronous request but I noticed that Eclipse gives me a error when i do networking on the main ui.
Found a lot of stuff on asynctask but i want my app to wait till the required data is downloaded (synchronous?).
I tried using asynctask .execute().get() and setting the variables in onPostExecute but when I return the variable I get a NullPointerException. Does someone know how to make this work? I really need this data before the app can run so I want my app to wait till the data is downloaded.
MainActivity calls this:
SingletonClass appIDSingleton = SingletonClass.getInstance();
this.ID = appIDSingleton.getAppID();
Singleton Class:
public String getAppID() {
try {
new DownloadAppID().execute(APP_ID_URL).get(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return AppID; //AppID is still NULL (because the download isnt finished yet?)
}
private class DownloadAppID extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... urls) {
String response = "";
for (String url : urls) {
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
try {
HttpResponse execute = client.execute(httpGet);
InputStream content = execute.getEntity().getContent();
BufferedReader buffer = new BufferedReader(new InputStreamReader(content));
String s = "";
while ((s = buffer.readLine()) != null) {
response += s;
}
} catch (Exception e) {
e.printStackTrace();
}
}
return response;
}
#Override
protected void onPostExecute(String result) {
System.out.println(result);
AppID = result;
}
}
You need to understand that your getAppID method can't return a result that is going to be computed asynchronously.
You could for instance provide a listener to your async task in order to notify when app ID is available:
SingletonClass appIDSingleton = SingletonClass.getInstance();
appIDSingleton.getAppID(new AppIdDownloadListener() {
#Override
public void appIDAvailable(String appId) {
this.ID = appId;
}
});
public void getAppID(AppIdDownloadListener listener) {
try {
new DownloadAppID(listener).execute(APP_ID_URL).get(5000, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ExecutionException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (TimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public interface AppIdDownloadListener {
public void appIDAvailable(String appId);
}
private class DownloadAppID extends AsyncTask<String, Void, String> {
private AppIdDownloadListener listener;
public DownloadAppID(AppIdDownloadListener listener) {
this.listener = listener;
}
#Override
protected String doInBackground(String... params) {
/* Your stuff here */
}
#Override
protected void onPostExecute(String result) {
System.out.println(result);
listener.appIDAvailable(result);
}
}

Categories

Resources