Code Your Application
In the aliencity/src/main/java/com/catalyst/appsail/aliencity/ directory, create a Java code file and name it AlienCity.java. This code file will contain the backend logic of your application.
In the aliencity/src/main/resources/static directory, create the following files:
- index.html: The file that contains the HTML code for the front-end of the application.
- main.js: The file that contains the JavaScript code that connects the front-end and backend.
The final structure of the aliencity/ Spring Boot - JAR project directory is shown below:
You will be coding the AlienCity.java, AliencityApplication.java, index.html, and main.js. You will also be updating the app-config.json, and the pom.xml file.
Copy the code below and paste it into the respective files of your project using an IDE and save the files:
AlienCity.javacopypackage com.catalyst.appsail.aliencity; import org.springframework.web.bind.annotation.*; import com.fasterxml.jackson.databind.ObjectMapper; import com.zc.auth.CatalystSDK; import com.zc.component.object.ZCObject; import com.zc.component.object.ZCRowObject; import com.zc.component.zcql.ZCQL; import org.springframework.http.ResponseEntity; import org.json.simple.JSONObject; import org.json.simple.parser.JSONParser; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @RestController public class AlienCity { Map<String, String> responseMap = new HashMap<>(); private int getAlienCountFromCatalystDataStore(String cityName) throws Exception { String query = "Select * from AlienCity where CityName = " + cityName; ArrayList<ZCRowObject> rowList = ZCQL.getInstance().executeQuery(query); return rowList.size(); } @GetMapping("/alien") public ResponseEntity<String> getAlienEncounter(@RequestParam String cityname, HttpServletRequest request, HttpServletResponse response) throws Exception { CatalystSDK.init(request); try { int length = getAlienCountFromCatalystDataStore(cityname); if (length == 0) { responseMap.put("message", "Hurray! No alien encounters in this city yet!"); responseMap.put("signal", "negative"); String jsonResponse = new ObjectMapper().writeValueAsString(responseMap); return ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .body(jsonResponse); } else { responseMap.put("message", "Uh oh! Looks like there are aliens in this city!"); responseMap.put("signal", "positive"); String jsonResponse = new ObjectMapper().writeValueAsString(responseMap); return ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .body(jsonResponse); } } catch (Exception e) { e.printStackTrace(); responseMap.put("message", "Internal Server Error"); responseMap.put("signal", "error"); String jsonResponse = new ObjectMapper().writeValueAsString(responseMap); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .contentType(MediaType.APPLICATION_JSON) .body(jsonResponse); } } @PostMapping("/alien") public ResponseEntity<String> postAlienEncounter(HttpServletRequest request, HttpServletResponse response, @RequestBody String requestBody) throws Exception { CatalystSDK.init(request); JSONParser jsonParser = new JSONParser(); JSONObject jsonObject = (JSONObject) jsonParser.parse(requestBody); String cityname = (String) jsonObject.get("cityname"); try { int length = getAlienCountFromCatalystDataStore(cityname); if (length > 0) { responseMap.put("message", "Looks like you are not the first person to encounter aliens in this city! Someone has already reported an alien encounter here!"); String jsonResponse = new ObjectMapper().writeValueAsString(responseMap); return ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .body(jsonResponse); } else { ZCRowObject row = ZCRowObject.getInstance(); row.set("CityName", cityname); ZCObject.getInstance().getTableInstance("AlienCity").insertRow(row); responseMap.put("message", "Thanks for reporting!"); String jsonResponse = new ObjectMapper().writeValueAsString(responseMap); return ResponseEntity.ok() .contentType(MediaType.APPLICATION_JSON) .body(jsonResponse); } } catch (Exception e) { e.printStackTrace(); responseMap.put("message", "Internal Server Error"); String jsonResponse = new ObjectMapper().writeValueAsString(responseMap); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .contentType(MediaType.APPLICATION_JSON) .body(jsonResponse); } } }
AliencityApplication.javacopypackage com.catalyst.appsail.aliencity; import java.util.Collections; import javax.servlet.http.HttpServlet; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class AliencityApplication extends HttpServlet { public static void main(String[] args) { String port = System.getenv().getOrDefault("X_ZOHO_CATALYST_LISTEN_PORT","3000"); SpringApplication app = new SpringApplication(AliencityApplication.class); app.setDefaultProperties(Collections.singletonMap("server.port",port)); app.run(args); } }
index.htmlcopy<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <title>AlientCityAppClient</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" type="text/css" media="screen" href="main.css" /> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> <script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"> </script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"> </script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"> </script> <script src="static/main.js"> </script> </head> <body> <br> <br> <center> <h1>ALIEN CITY</h1> </center> <div class="container"> <ul class="nav nav-tabs" id="myTab" role="tablist"> <li class="nav-item"> <a class="nav-link active" id="check-tab" data-toggle="tab" href="#check" role="tab" aria-controls="check" aria-selected="true">Check My City</a> </li> <li class="nav-item"> <a class="nav-link" id="report-tab" data-toggle="tab" href="#report" role="tab" aria-controls="report" aria-selected="false">Report Alien Encounter</a> </li> </ul> <div class="tab-content" id="myTabContent"> <div class="tab-pane fade show active" id="check" role="tabpanel" aria-labelledby="check-tab"> <br> <br> <form> <div class="form-group"> <label for="city-get-input"> <b>Check if your city has aliens:</b> </label> <input type="text" class="form-control" id="city-get-input" aria-describedby="checkCity" placeholder="Enter City Name"> </div> <button type="submit" class="btn btn-primary" onclick="getAlienEncounter();return false;">Check</button> </form> <br> <br> <div id="result-container"> <div id="result-text"> </div> <br> <div id="result-image"> </div> </div> <div id="loader" style="display: none;"> <div class="spinner-border" role="status"> <span class="sr-only">Loading...</span> </div> </div> </div> <div class="tab-pane fade" id="report" role="tabpanel" aria-labelledby="report-tab"> <br> <br> <form> <div class="form-group"> <div class="city-post-input"> <label for="exampleInputEmail1"> <b>Enter the name of the city where you encountered an alien:</b> </label> <input type="text" class="form-control" id="city-post-input" aria-describedby="cityPost" placeholder="Enter City Name"> </div> </div> <button type="submit" class="btn btn-primary" onclick="postAlienEncounter();return false;">Report</button> </form> </div> </div> </div> </body> </html>
main.jscopyfunction postAlienEncounter() { debugger; var city = $("#city-post-input").val(); $.ajax({ url: "/alien", type: "post", contentType: "application/json", data: JSON.stringify({ "city_name": city }), success: function (data) { alert(data.message); }, error: function (error) { alert(error.message); } }); } function getAlienEncounter() { debugger showLoader(); var positive = "https://media.giphy.com/media/Y1GYiLui9NHcxVKhdo/giphy.gif"; var negative = "https://media.giphy.com/media/fsPcMdeXPxSP6zKxCA/giphy.gif"; var city = $("#city-get-input").val(); $.ajax({ url: "/alien?city_name=" + city, type: "get", success: function (data) { console.log(data); $("#result-text").text(""); $("#result-text").text(data.message); var imagesrc = negative; if (data.signal == 'positive') { imagesrc = positive; } $("#result-image").html(""); $("#result-image").html("
"); hideLoader(); }, error: function (error) { alert(error.message); } }); } function showLoader() { $("#result-container").hide(); $("#loader").show(); } function hideLoader() { $("#loader").hide(); $("#result-container").show(); }
pom.xmlcopy<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.10</version> <!-- Change version to this value --> <relativePath /> </parent> <groupId>com.catalyst.appsail</groupId> <artifactId>aliencity</artifactId> <version>0.0.1-SNAPSHOT</version> <name>aliencity</name> <packaging>jar</packaging> <!-- Include this --> <description>learning Catalyst AppSail~</description> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.zoho.catalyst</groupId> <artifactId>java-sdk</artifactId> <version>0.0.1</version> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>3.9.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpmime</artifactId> <version>4.5.3</version> <scope>compile</scope> </dependency> <!-- Servlet API for HttpServlet --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>2.6.1</version> <!-- Use the version compatible with your project --> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> <!--Insall required Repositories--> <repositories> <repository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> </repository> <repository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> </repository> <repository> <id>java-sdk</id> <url>https://maven.zohodl.com</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>spring-milestones</id> <name>Spring Milestones</name> <url>https://repo.spring.io/milestone</url> <snapshots> <enabled>false</enabled> </snapshots> </pluginRepository> <pluginRepository> <id>spring-snapshots</id> <name>Spring Snapshots</name> <url>https://repo.spring.io/snapshot</url> <releases> <enabled>false</enabled> </releases> </pluginRepository> </pluginRepositories> </project>
Note: Do not change the version in line 14. You can host your application on AppSail only if the version is 2.7.10 or less.app-config.jsoncopy{ "command": "java -jar aliencity-0.0.1-SNAPSHOT.jar", "buildPath": "/Users/emma-2212/Downloads/aliencity/target/", "stack": "java17", "env_variables": {}, "memory": 256, "scripts": { "preserve": "mvn clean package", "predeploy": "mvn clean package" }, "platform": "javase" }
Note: Ensure you provide the right value for the buildpath key.Let’s quickly go through the working of the application:
GET Operation
- When you enter a city name in the application to check for a record of previous alien encounters, the onClick event for the Check button in index.html triggers the getAlienEncounter() function defined in main.js.
- This fires an Ajax call to the URL route defined in the AlienCity.java function.
- The GET API defined in AlienCity.java then invokes the getAlienCountFromCatalystDataStore() function and passes the request query.
- This function searches for the data in the Alien City table in the Data Store by executing a ZCQL query.
- If a record matching the city name is found in the table, a positive signal is sent as the response. Otherwise, a negative signal is sent as the response.
- The client then displays the message that matches the response. A GIF matching the response defined in main.js is also displayed.
POST Operation
- When you enter a city name in the client to report an alien encounter, the onClick event for the Report button in index.html triggers the postAlienEncounter() function defined in main.js.
- This fires an Ajax call to the URL route defined in the AlienCity.java function. The POST API defined in AlienCity.java then invokes the getAlienCountFromCatalystDataStore() function and passes a request query to check if a record with the same city name already exists.
- This function searches for the data in the Alien City table in the Data Store by executing a ZCQL query. If the record already exists, a response is sent, which enables the application to display a message that the city name is already added.
- If there are no records for the city name, a new row is created in the Alien City table for the city name entered by the user. A pop-up box is displayed in the client confirming the insertion of the record in the Data Store. An appropriate message is also pushed to the logs which can be checked from the Logs component present in the Catalyst DevOps service.
Last Updated 2024-05-13 17:20:31 +0530 +0530