Getting Started With Cron Functions: NPM Install G Zcatalyst Cli
Getting Started With Cron Functions: NPM Install G Zcatalyst Cli
Started with Cron Functions
1.Introduction
Here you will be building a simple online news application which fetches
the current news for every one hour using the cron function in Catalyst.
Step 1 : Project Creation
Initially, let's create a project and set up the required tools in your local machine. Login
to catalyst.zoho.com and create a project named 'NewsApp'. To learn more about "how
to create a project?", please refer to the help documentation.
Execute the following command in your machine's terminal to install the Catalyst CLI,
npm install -g zcatalyst-cli
To learn more about CLI installation, please refer to the CLI installation document.
It is mandatory to authenticate the Catalyst CLI with your catalyst account to use
the CLI further. Execute the following command from your root directory,
catalyst login
A page opens in the browser asking for the CLI access permission. Click accept
and return to your terminal window so that you are successfully authenticated. The
following image depicts this authentication process.
Initialize a project by executing the following command, from the root directory of your
terminal.
catalyst init
Select the options, client and functions by pressing the space bar and click Enter. The list of
existing catalyst projects and an option to create a new project will be displayed. You can even
create a new project from CLI itself and associate it with the application. Since we have already
created a project NewsApp via catalyst web console let us select the same.
In the function, select the stack as java8. Then you will be asked for a folder name, class
name and author of your Cron Function. Give the values as NewsFetch, FetchNews
respectively. Next, you will be asked to install the required dependencies. Just click Enter which
will install the required dependencies. Now, you will be asked for the Client (static content)
name. Please enter 'NewsAppClient' (You can enter any name).
Local Debugging Steps
Once the initialization process is complete, one can notice some directories and files
that are automatically created by the Catalyst CLI. This is a boiler-plate code of your
Catalyst project which helps you kick start your development and coding process.
You can use any IDE of your choice. In this tutorial, we are using the Microsoft
Visual Studio code editor. Open the visual studio code editor and open the project by
navigating to the root directory, where you initialized the project. Now, you can view the
boilerplate code structure that is auto generated by CLI in the IDE.
Step 6: Code the Cron Function
Next, let us get into the editor where we have opened the catalyst project to code the
cron function.
We are now going to code the cron function which will be triggered every one hour
when associated with a Cron.
NewsFetch.java
1 import java.util.ArrayList;
2 import java.util.List;
3 import java.util.logging.Level;
4 import java.util.logging.Logger;
5
6 import com.catalyst.Context;
7 import com.catalyst.cron.CRON_STATUS;
8 import com.catalyst.cron.CronRequest;
9 import com.catalyst.cron.CatalystCronHandler;
10
11 import com.zc.common.ZCProject;
12 import com.zc.component.object.ZCObject;
13 import com.zc.component.object.ZCRowObject;
14 import com.zc.component.object.ZCTable;
15 import com.zc.component.zcql.ZCQL;
16
17 import org.json.JSONArray;
18 import org.json.JSONObject;
19
20 import okhttp3.HttpUrl;
21 import okhttp3.OkHttpClient;
22 import okhttp3.Request;
23 import okhttp3.Response;
24
25 public class NewsFetch implements CatalystCronHandler {
26
27 private static final Logger LOGGER =
Logger.getLogger(NewsFetch.class.getName());
28 static String[] TABLENAME = { "HEADLINES", "BUSINESS",
"ENTERTAINMENT", "HEALTH", "SCIENCE", "SPORTS", "TECHNOLOGY" };
29 static String COUNTRY = "IN";
30 static String APIKEY = "f415a97085614b6c92184317e436cd66";
31
32 @Override
33 public CRON_STATUS handleCronExecute(CronRequest request, Context
arg1) throws Exception {
34 try {
35 ZCProject.initProject();
36
37 OkHttpClient client = new OkHttpClient();
38
39 for (int i = 0; i < TABLENAME.length; i++) {
40
41 HttpUrl.Builder urlBuilder =
HttpUrl.parse("http://newsapi.org/v2/top-headlines").newBuilder();
42
43 urlBuilder.addQueryParameter("country", COUNTRY);
44 urlBuilder.addQueryParameter("apiKey", APIKEY);
45
46 if (i != 0) {
47 urlBuilder.addQueryParameter("category",
TABLENAME[i]);
48 }
49 String url = urlBuilder.build().toString();
50
51 Request requests = new
Request.Builder().url(url).build();
52
53 Response response =
client.newCall(requests).execute();
54
55 if (response.code() == 200) {
56
57 JSONObject responseObject = new
JSONObject(response.body().string());
58
59 JSONArray responseArray = (JSONArray)
responseObject.getJSONArray("articles");
60
61 pushNewstoDatastore(responseArray, i);
62
63 } else {
64 LOGGER.log(Level.SEVERE, "Error fetching
data from News API");
65 }
66 LOGGER.log(Level.SEVERE," News Updated");
67
68 }
69 } catch (Exception e) {
70
71 LOGGER.log(Level.SEVERE, "Exception in Cron Function",
e);
72 return CRON_STATUS.FAILURE;
73 }
74 return CRON_STATUS.SUCCESS;
75 }
76
77 private void pushNewstoDatastore(JSONArray responseArray, int
length) throws Exception {
78
79 String action = null;
80 String query = "select ROWID from " + TABLENAME[length];
81 ArrayList<ZCRowObject> rowList =
ZCQL.getInstance().executeQuery(query);
82
83 ZCRowObject row = ZCRowObject.getInstance();
84 List<ZCRowObject> rows = new ArrayList<>();
85 ZCObject object = ZCObject.getInstance();
86 ZCTable table = object.getTable(TABLENAME[length]);
87
88 for (int i = 0; i < 15; i++) {
89
90 JSONObject response = responseArray.getJSONObject(i);
91
92 Object author = response.get("author");
93 Object title = response.get("title");
94 Object url = response.get("url");
95 row.set("author", author);
96 row.set("title", title);
97 row.set("url", url);
98
99 if (rowList.size() > 0) {
100 Object RowID =
rowList.get(i).get(TABLENAME[length], "ROWID");
101 String rowid = RowID.toString();
102 Long ID = Long.parseLong(rowid);
103
104 row.set("ROWID", ID);
105 rows.add(row);
106 action = "Update";
107
108 } else {
109 action = "Insert";
110 rows.add(row);
111 }
112
113 }
114 if (action.equals("Update")) {
115 table.updateRows(rows);
116 LOGGER.log(Level.SEVERE, TABLENAME[length] + " Table
updated with current News");
117 } else if (action.equals("Insert")) {
118 table.insertRows(rows);
119 LOGGER.log(Level.SEVERE, TABLENAME[length] + " Table
inserted with current News");
120 }
121 }
122}
123
Step 7: Code the Advanced IO function :
The advanced IO function will help you to query the Catalyst datastore and fetch the
latest news and render it in the UI.
Now use the command catalyst functions:add. In the function, select the type as Advanced IO
and select the stack as java8. Then you will be asked for a folder name, class name and
author of your Advanced IO Function. Give the values as NewsApp_AIO, DatastoreFetch
respectively. Next, you will be asked to install the required dependencies. Just click Enter which
will install the required dependencies.
DatastoreFetch.java
1 import java.util.logging.Logger;
2 import java.util.ArrayList;
3 import java.util.logging.Level;
4
5 import javax.servlet.http.HttpServletRequest;
6 import javax.servlet.http.HttpServletResponse;
7
8 import com.catalyst.advanced.CatalystAdvancedIOHandler;
9 import com.zc.component.object.ZCRowObject;
10 import com.zc.component.zcql.ZCQL;
11
12 import org.json.JSONArray;
13 import org.json.JSONObject;
14
15 public class FetchDatastore implements
CatalystAdvancedIOHandler {
16 private static final Logger LOGGER =
Logger.getLogger(FetchDatastore.class.getName());
17
18 @Override
19 public void runner(HttpServletRequest request, HttpServletResponse
response) throws Exception {
20 try {
21 String url = request.getRequestURI();
22 if (url.equals("/fetchData")) {
23 String tableName = request.getParameter("tablename");
24 String query = "select title,url from " + tableName;
25 ArrayList<ZCRowObject> rowList =
ZCQL.getInstance().executeQuery(query);
26 JSONObject data = new JSONObject();
27 JSONArray content = new JSONArray();
28
29
30 for (int i = 0; i < rowList.size(); i++) {
31 JSONObject rowData = new JSONObject();
32 JSONObject tableData = new JSONObject();
33 String urls = (String)
rowList.get(i).get(tableName, "url");
34 Object title = rowList.get(i).get(tableName,
"title");
35 rowData.put("title", title);
36 rowData.put("url", urls);
37 tableData.put(tableName, rowData);
38 content.put(tableData);
39 }
40 data.put("content", content);
41 response.getWriter().write(data.toString());
42 response.setStatus(200);
43 } else {
44 LOGGER.log(Level.SEVERE, "Error. Invalid Request");
45 response.setStatus(404);
46 }
47 } catch (Exception e) {
48 LOGGER.log(Level.SEVERE, "Exception in FetchDatastore", e);
49 response.setStatus(500);
50 }
51 }
52 }
Step 8 : Code the Client
Catalyst supports Web Client Hosting through which you can deploy the client files
required for your application.
1 <!DOCTYPE html>
2 <html>
3 <script src="main.js"></script>
4 <script
src="https://js.zohostatic.com/catalystclient/1.0.0/catalys
tWebSDK.js"></script>
5 <script
src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jqu
ery.min.js"></script>
6 <script>
7 var cred = new catalystCredential();
8 cred.loadFromJSON({
9 project_Id: 6479000000181084,
10 zaid: 10020137659
11 });
12 catalyst.initApp(cred, {});
13 </script>
14
15 <head>
16 <meta name="viewport" content="width=device-width,
initial-scale=1">
17 <style>
18 .sidenav {
19 height: 100%;
20 width: 220px;
21 position: fixed;
22 z-index: 1;
23 top: 0;
24 left: 0;
25 background-color: #111;
26 overflow-x: hidden;
27 }
28
29 .login {
30 height: 100%;
31 }
32
33 .sidenav a {
34 padding: 6px 8px 6px 16px;
35 text-decoration: none;
36 font-size: 25px;
37 font-family: "Verdana", sans-serif;
38 color: #818181;
39 display: block;
40 }
41
42 .sidenav a:hover {
43 color: #f1f1f1;
44 }
45
46 .main {
47 margin-left: 200px;
48 /* Same as the width of the sidenav */
49 font-size: 20px;
50 /* Increased text to enable scrolling
/*onload="myFunction()"*/
51 padding: 0px 10px;
52 font-family: "Poynter", sans-serif;
53 }
54
55 @media screen and (max-height: 450px) {
56 .sidenav {
57 padding-top: 15px;
58 }
59
60 .sidenav a {
61 font-size: 18px;
62 }
63 }
64 </style>
65 </head>
66
67 <body onload="myFunction('HEADLINES')">
68
69 <center>
70 <h1>Welcome to the Daily Bugle</h1>
71 <h3>Today's News</h3><br>
72 </center>
73 <div class="sidenav">
74 <img src=news.jpg width="220"
height="200"></img><br>
75 <a href="#Business" onclick="return
myFunction('BUSINESS');">Business</a><br>
76 <a href="#Entertainment" onclick="return
myFunction('ENTERTAINMENT');">Entertainment</a><br>
77 <a href="#Health" onclick="return
myFunction('HEALTH');">Health</a><br>
78 <a href="#Science" onclick="return
myFunction('SCIENCE');">Science</a><br>
79 <a href="#Sports" onclick="return
myFunction('SPORTS');">Sports</a><br>
80 <a href="#Technology" onclick="return
myFunction('TECHNOLOGY');">Technology</a><br>
81 </div>
82
83 <div class="main">
84 <ul id="myList"></ul>
85 </div>
86
87 </body>
88
89 </html>
main.js
1 function myFunction(name) {
2 debugger;
3 var count =
document.getElementById("myList").childElementCount;
4 d = count / 2;
5 var j, k;
6 for (k = 0; k < count; k++) {
7 for (j = 0; j < d; j++) {
8 var list = document.getElementById("myList");
9 list.removeChild(list.childNodes[j]);
10 }
11 d = Math.floor(d / 2);
12 }
13 var tablename = name;
14 console.log(tablename);
15 $.ajax({
16 url: "/server/NewsApp_AIO/fetchData?tablename=" +
tablename,
17 type: "get",
18 success: function (response) {
19 debugger;
20 var data = JSON.parse(response);
21 var i;
22 for (i = (data.content.length) - 1; i >= 0;
i--) {
23 var list =
document.getElementById('myList');
24 var anchor = document.createElement('a');
25 var li = document.createElement('li');
26 var linebreak =
document.createElement("br");
27 anchor.href =
data.content[i][tablename].url;
28 anchor.innerText =
data.content[i][tablename].title;
29 anchor.setAttribute('target', '_blank');
30 li.appendChild(anchor);
31 list.appendChild(li);
32 list.appendChild(linebreak);
33 }
34 }, error: function (error) {
35 alert(error.data);
36 }
37 });
38 }
After copying the above code Go to catalyst home directory in CLI and execute the
command
catalyst deploy
On successful deployment you will see the Client Invoke URL.
Test your Cron function using function shell :
In your Catalyst CLI, execute the command catalyst functions:shell. Now your function
shell will open up. Try executing the function by giving NewsFetch(). If there is no
problem, the function would run successfully.
Create a Cron that runs every one hour in the Catalyst console.
The above FetchNews function has to be associated with a Cron so that it can run every
one hour and fetch the breaking news.
Go to catalyst.zoho.com, Select NewsApp Project and Click on the Cron tab in
the left pane. In that select create Cron. You will be asked to enter the Cron name. Give a
name of your wish and select the schedule point as Function. Now in the Target
Function tab, select the Cron function which we configured (here NewsFetch). Select the
schedule type as Recursive, Repeat type as "Every" and give 01 hour, 0 minutes, 0
seconds for the time. Now save the Cron. Your cron is good to go and will begin
fetching the latest news every one hour and update it in the datastore.