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) {
}
});
}
}
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.
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.