Call Firebase Database from Google App Engine

I followed this tutorial to configure my instance of the Google App Engine application, and I also use Firebase. My goal is to put all the β€œcalculations” into the Google App Engine. I want to call a function like the one below:

MyEndpoint:

package productions.widowmaker110.backend; /** An endpoint class we are exposing */ @Api( name = "myApi", version = "v1", namespace = @ApiNamespace( ownerDomain = "backend.widowmaker110.productions", ownerName = "backend.widowmaker110.productions", packagePath="" ) ) public class MyEndpoint { /** A simple endpoint method that takes a name and says Hi back */ @ApiMethod(name = "sayHi") public MyBean sayHi(@Named("name") String name) { // Write a message to the database FirebaseDatabase database = FirebaseDatabase.getInstance(); DatabaseReference myRef = database.getReference("message"); // Read from the database myRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // This method is called once with the initial value and again // whenever data at this location is updated. String value = dataSnapshot.getValue(String.class); Log.d(TAG, "Value is: " + value); } @Override public void onCancelled(DatabaseError error) { // Failed to read value Log.w(TAG, "Failed to read value.", error.toException()); } }); MyBean response = new MyBean(); response.setData("Hi, " + name); return response; } } 

MainActivity:

 package productions.widowmaker110.gpsweather; // imports... public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); new EndpointsAsyncTask().execute(new Pair<Context, String>(this, "Manfred")); } class EndpointsAsyncTask extends AsyncTask<Pair<Context, String>, Void, String> { private MyApi myApiService = null; private Context context; @Override protected String doInBackground(Pair<Context, String>... params) { if(myApiService == null) { // Only do this once MyApi.Builder builder = new MyApi.Builder(AndroidHttp.newCompatibleTransport(), new AndroidJsonFactory(), null) // options for running against local devappserver // - 10.0.2.2 is localhost IP address in Android emulator // - turn off compression when running against local devappserver .setRootUrl("http://10.0.2.2:8080/_ah/api/") .setGoogleClientRequestInitializer(new GoogleClientRequestInitializer() { @Override public void initialize(AbstractGoogleClientRequest<?> abstractGoogleClientRequest) throws IOException { abstractGoogleClientRequest.setDisableGZipContent(true); } }); // end options for devappserver myApiService = builder.build(); } context = params[0].first; String name = params[0].second; try { return myApiService.sayHi(name).execute().getData(); } catch (IOException e) { return e.getMessage(); } } @Override protected void onPostExecute(String result) { Toast.makeText(context, result, Toast.LENGTH_LONG).show(); } } } 

I understand that the above code for Firebase is Android specific, so working in an instance of Google App Engine does not work. I was wondering if anyone knows how to perform CRUD operations on a firebase database from the Google App Engine backend. Any help is appreciated.

+8
java android google-app-engine firebase
source share
1 answer

To make server-side calls, you need to use the Firebase Server SDK. You can find installation and usage information here:

Add Firebase to your server

Install and configure the Firebase Server SDK

When using Firebase with Google Cloud Endpoints, be aware that you will need to use Firebase methods in conjunction with the task APIs . Since Firebase methods are not blocked, unless you use Tasks, your endpoint will return before the call you made in Firebase has the ability to return its result. For a brief introduction to using tasks, check out the link below. This is a conversation defined in Google I / O 2016. The speaker talks about tasks and Firebase on Android, but the concepts are the same when using Tasks and Firebase on the server. Note that they have enabled the task API with the Firebase Server SDK. I missed the part of the conversation that directly relates to tasks.

Firebase SDK for Android: a deep dive in technology

The following are examples if you need to process the result from your Firebase read / write operation before your endpoint returns a value or if other code depends on the result of the Firebase read / write operation. These are server side examples. I'm going to assume that you care about whether the write operation was successful. There may be more efficient ways to do these server side operations, but this is what I have done so far.

An example of a write operation using setValue ():

 DatabaseReference ref = FirebaseDatabase.getInstance().getReference(); YourModelClass obj = new YourModelClass(); 
  • When calling the setValue() method, it returns a Task object, keep a reference to it.

     Task<Void> setValueTask = ref.setValue(obj); 
  • Create a TaskCompletionSource object. This object must be parameterized according to the type of result of your choice. I will use Boolean as the result type for this example.

     final TaskCompletionSource<Boolean> tcs = new TaskCompletionSource<>(); 
  • Create a Task from the TaskCompletionSource created in step 2. Again, the generated Task should use the same parameter type as the TaskCompletionSource object.

     Task<Boolean> tcsTask = tcs.getTask(); 
  • Add a completion listener to the Task that was called by the setValue() call. In the completion listener, set the corresponding result to the Task created in step 3. Calling setResult() on your TaskCompletionSouce object will mark the Task created from it as completed. This is important for step 5.

     setValueTask.addOnCompleteListener(new OnCompleteListener<Void>() { @Override public void onComplete(@NonNull Task<Void> task) { if(task.isSuccessful()){ tcs.setResult(true); }else{ tcs.setResult(false); } } }); 
  • Call Task.await() to block the current thread until the Task you are interested in finishes. We expect the Task generated by the TaskCompletionSource to be marked as completed. This Task will be considered complete when we call setResult() on the TaskCompletionSource used to generate the Task , as it was in step 4. After completion, it will return the result.

     try { Boolean result = Tasks.await(tcsTask); }catch(ExecutionException e){ //handle exception }catch (InterruptedException e){ //handle exception } 

That is, the current thread will block until Tasks.await() returns a value. You can also (and should) set the timeout value in the Tasks.await() method if you want the current thread to block indefinitely.

If you were only interested in whether or not the Task generated by setValue() was completed and did not care whether it was successful or not, you can skip creating TaskCompletionSource and just use Tasks.await() directly on that Task . The same thing works for updateChildren() . And if you like, you can simply use the method calls for updateChilden() or setValue() , which use the DatabaseReference.CompletionListener along with the TaskCompletionListener.

Waiting for the read to complete is similar.

Example read operation using addListenerForSingleValueEvent ()

 DatabaseReference ref = FirebaseDatabase.getInstance().getReference(); YourModelClass mModelClassObject; 
  • Create a TaskCompletionSource object parameterized with the result that you expect from the Task to be generated from it.

     final TaskCompletionSource<YourModelClass> tcs = new TaskCompletionSource<>(); 
  • Generate a Task from the TaskCompletionSource object

     Task<YourModelClass> tcsTask = tcs.getTask(); 
  • Call addListenerForSingleValueEvent() on our DatabaseReference and call setResult() on the Task generated in step 2.

     ref.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { YourModelClass result = dataSnapshot.getValue(YourModelClass.class); if(result != null){ tcs.setResult(result); } } @Override public void onCancelled(DatabaseError databaseError){ //handle error } }); 
  • Call Tasks.await() to block the current thread until the Task you are interested in finishes. Task will be considered complete when we call setResult() , as it was in step 3, and return the result.

     try { mModelClassObject = Tasks.await(tcsTask); }catch(ExecutionException e){ //handle exception }catch (InterruptedException e){ //handle exception } 

As mentioned above, you can use the Tasks.await() method along with a timeout value to prevent the current thread from being blocked.

As in the heads, I found that Firebase does not kill the background thread, which is used for its operations. This means that the GAE instance never works. Check out this topic for more information:

Firebase, Background Threads and App Engine

+11
source share

All Articles