How to keep App Engine Servlet Listening to Fireba

2019-02-14 15:56发布

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("myEmail@gmail.com", "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) {
            }
        });
    }

}

2条回答
\"骚年 ilove
2楼-- · 2019-02-14 16:17

Simple answer is you can't do that yet. Google cloud endpoints have a timeout of 1 min. Cron jobs also have a timeout.

What you need is triggers. This feature was demoed at Google io 16. Whenever data changes, a rest request is fired from firebase to a server and path of your choice.

Even I am waiting for this to arrive soon.

查看更多
成全新的幸福
3楼-- · 2019-02-14 16:19

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.

查看更多
登录 后发表回答