Working with Cron Functions

Build a web news application that automatically fetches news from a third-party service periodically using Catalyst Cron, a Cron Function, and an Advanced I/O Function.

Configure the Advanced I/O Function

Let's now configure the Advanced I/O function component. If you initialized the Advanced I/O function in Java, its directory (functions/NewsApp_AIO) will contain:

  • The DatastoreFetch.java main function file
  • The catalyst-config.json configuration file
  • Java library files in the lib folder
  • .classpath and .project dependency files

If you initialized the Advanced I/O function in Node.js, its directory (functions/news_app_function) will contain:

You will be adding code in the DatastoreFetch.java or index.js, based on the stack you initialized.

The Advanced I/O function fetches the news item from its source table in the Data Store and forwards it to the client component as a JSON response.

Copy the Java code and paste it in DatastoreFetch.java in the functions/NewsApp_AIO directory, or the Node.js code and paste it in index.js in the functions/news_app_function directory of your project, and save the file. You can use any IDE to work with the application's files.

Note: Please go through the code in this section to make sure you fully understand it.
  • View code for DatastoreFetch.java, index.js

    Copied 
    import java.util.logging.Logger;
    import java.util.ArrayList;
    import java.util.logging.Level;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import com.catalyst.advanced.CatalystAdvancedIOHandler;
    import com.zc.component.object.ZCRowObject;
    import com.zc.component.zcql.ZCQL;
    
    import org.json.JSONArray;
    import org.json.JSONObject;
    
    public class DatastoreFetch implements CatalystAdvancedIOHandler {
    	private static final Logger LOGGER = Logger.getLogger(DatastoreFetch.class.getName());
    
    	@Override
    	public void runner(HttpServletRequest request, HttpServletResponse response) throws Exception {
    		try {
    			//Fetches the endpoint that the call was made to
    			String url = request.getRequestURI();
    			String method = request.getMethod();
    
    			if (url.equals("/fetchData") && method.equals("GET")) {
    				String tableName = request.getParameter("tablename");
    				//Queries the Data Store to fetch news from a particular table using ZCQL
    				String query = "select title,url from " + tableName;
    				ArrayList<ZCRowObject> rowList = ZCQL.getInstance().executeQuery(query);
    				JSONObject data = new JSONObject();
    				JSONArray content = new JSONArray();
    				
    				//Constructs the data from the Data Store as an JSON response
    				for (int i = 0; i < rowList.size(); i++) {
    					JSONObject rowData = new JSONObject();
    					JSONObject tableData = new JSONObject();
    					String urls = (String) rowList.get(i).get(tableName, "url");
    					Object title = rowList.get(i).get(tableName, "title");
    					rowData.put("title", title);
    					rowData.put("url", urls);
    					tableData.put(tableName, rowData);
    					content.put(tableData);
    				}
    				data.put("content", content);
    
    				//Sends the JSON response back to the client
    				response.setContentType("application/json");
    				response.getWriter().write(data.toString());
    				response.setStatus(200);
    			} else {
    //The errors are logged. You can check them from Catalyst Logs.
    				LOGGER.log(Level.SEVERE, "Error. Invalid Request");
    				response.setStatus(404);
    			}
    		} catch (Exception e) {
    			LOGGER.log(Level.SEVERE, "Exception in DatastoreFetch", e);
    			response.setStatus(500);
    		}
    	}
    }
    
    Copied  
    'use strict';
    var express = require('express');
    var app = express();
    var catalyst = require('zcatalyst-sdk-node');
    app.use(express.json());
    
    //GET API that gets the news from the required table
    app.get('/fetchData', (req, res) => {
    	var tablename = req.query.tablename;
    	console.log("Table Name "+tablename);
    
    	//Initializing Catalyst SDK
    	var catalystApp = catalyst.initialize(req);
    
    	//Queries the Catalyst Data Store table and gets the required news
    	getDataFromCatalystDataStore(catalystApp, tablename).then(newsDetails => {
    			res.send({
    				"content": newsDetails
    			})
    	}).catch(err => {
    		console.log(err);
    		sendErrorResponse(res);
    	})
    });
    /**
     * Executes the Query and fetches the news from the table
     * @param {*} catalystApp 
     * @param {*} tablename 
     */
    function getDataFromCatalystDataStore(catalystApp, tablename) {
    	return new Promise((resolve, reject) => {
    		//Queries the Catalyst Data Store table
    		catalystApp.zcql().executeZCQLQuery("Select title,url from " + tablename).then(queryResponse => {
    			resolve(queryResponse);
    		}).catch(err => {
    			reject(err);
    		})
    	});
    
    }
    
    /**
     * Sends an error response
     * @param {*} res 
     */
    function sendErrorResponse(res) {
    	res.status(500);
    	res.send({
    		"error": "Internal server error occurred. Please try again in some time."
    	});
    }
    module.exports = app;
    

The Advanced I/O function is now configured. We will discuss the application's architecture after you configure the client.