Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to keep App Engine Servlet Listening to Firebase

I am following the tutorial at: https://cloud.google.com/solutions/mobile/firebase-app-engine-android-studio

I have everything working and the email is sending every 2 minutes as it should. However, I now wish to extend this to trigger sending an email only upon data change on the Firebase node, not sending a message every 2 minutes.

To test I replaced the cron.xml file from:

<?xml version="1.0" encoding="UTF-8"?>
<cronentries>
   <cron>
       <url>/hello</url>
       <description>Send me an email of outstanding items in the morning</description>
       <schedule>every 2 minutes</schedule>
   </cron>
</cronentries>

to:

<?xml version="1.0" encoding="UTF-8"?>
<cronentries/>

To clear out the scheduled tasks.

But now upon making a change in the Firebase db, the email is never sent....

How can I keep my app engine server "listening" to the firebase node and subsequently produce an action given onDataChanged in real-time?

MyServlet class:

public class MyServlet extends HttpServlet {
    static Logger Log = Logger.getLogger("com.example.username.myapplication.backend.MyServlet");

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        Log.info("Got cron message, constructing email.");

        //Create a new Firebase instance and subscribe on child events.
        Firebase firebase = new Firebase("[firebase ref]");
        firebase.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                // Build the email message contents using every field from Firebase.
                final StringBuilder newItemMessage = new StringBuilder();
                newItemMessage.append("This should arrive very closely after changing the data");


                //Now Send the email
                Properties props = new Properties();
                Session session = Session.getDefaultInstance(props, null);
                try {
                    Message msg = new MimeMessage(session);
                    //Make sure you substitute your project-id in the email From field
                    msg.setFrom(new InternetAddress("anything@[app-engine].appspotmail.com",
                            "Todo Nagger"));
                    msg.addRecipient(Message.RecipientType.TO,
                            new InternetAddress("[email protected]", "Recipient"));
                    msg.setSubject("Feast Email Test");
                    msg.setText(newItemMessage.toString());
                    Transport.send(msg);
                } catch (MessagingException | UnsupportedEncodingException e) {
                    Log.warning(e.getMessage());
                }
            }

            public void onCancelled(FirebaseError firebaseError) {
            }
        });
    }

}
like image 214
Sauron Avatar asked Sep 25 '22 06:09

Sauron


1 Answers

Your question is actually a question about AppEngine and how to create a Servlet that starts automatically and automatically performs some initialization.

You will want to keep manual scaling on, but follow the steps here: https://cloud.google.com/appengine/docs/java/config/appconfig#using_a_load-on-startup_servlet

for setting up your listeners on init() instead of an http request. What you are trying is definitely possible and have seen it run elsewhere.

like image 148
Benjamin Wulfe Avatar answered Nov 15 '22 10:11

Benjamin Wulfe