アプリケーションのコーディング
aliencity/src/main/java/com/catalyst/appsail/aliencity/ ディレクトリに、Javaコードファイルを作成し、AlienCity.java という名前を付けます。このコードファイルには、アプリケーションのバックエンドロジックが含まれます。
aliencity/src/main/resources/static ディレクトリに、以下のファイルを作成します:
- index.html: アプリケーションのフロントエンドのHTMLコードを含むファイルです。
- main.js: フロントエンドとバックエンドを接続するJavaScriptコードを含むファイルです。
aliencity/ Spring Boot - JAR プロジェクトディレクトリの最終的な構造は以下のとおりです:

AlienCity.java、AliencityApplication.java、index.html、および main.js をコーディングします。また、app-config.json と pom.xml ファイルも更新します。
以下のコードをコピーして、IDEを使用してプロジェクトのそれぞれのファイルに貼り付け、ファイルを保存してください:
package 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.apache.commons.logging.Log;
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 java.util.logging.Logger;
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 + "'";
Logger.getLogger(AlienCity.class.getName()).info("Query: " + query);
ArrayList<ZCRowObject> rowList = ZCQL.getInstance().executeQuery(query);
return rowList.size();
}
@GetMapping("/alien")
public ResponseEntity<String> getAlienEncounter(@RequestParam String city_name, HttpServletRequest request,
HttpServletResponse response) throws Exception {
CatalystSDK.init(request);
try {
int length = getAlienCountFromCatalystDataStore(city_name);
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("city_name");
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);
}
}
}
package 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);
}
}
<!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="/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>
function 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("<img src='" + imagesrc + "' />");
hideLoader();
},
error: function (error) {
alert(error.message);
}
});
}
function showLoader()
{
$("#result-container").hide();
$("#loader").show();
}
function hideLoader()
{
$("#loader").hide();
$("#result-container").show();
}
<?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> <!-- この値にバージョンを変更してください -->
<relativePath />
</parent>
<groupId>com.catalyst.appsail</groupId>
<artifactId>aliencity</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>aliencity</name>
<packaging>jar</packaging> <!-- これを含めてください -->
<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> <!-- プロジェクトと互換性のあるバージョンを使用してください -->
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<!-- 必要なリポジトリをインストール -->
<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>
{
"command": "java -jar aliencity-0.0.1-SNAPSHOT.jar",
"buildPath": "./target/",
"stack": "java17",
"env_variables": {},
"memory": 256,
"scripts": {
"preserve": "mvn clean package",
"predeploy": "mvn clean package"
},
"platform": "javase"
}
アプリケーションの動作を簡単に確認しましょう:
-
GET操作
- アプリケーションで都市名を入力して過去のエイリアン遭遇記録を確認すると、index.html の Check ボタンのonClickイベントが、main.js で定義された getAlienEncounter() 関数をトリガーします。
- これにより、AlienCity.java 関数で定義されたURLルートへのAjax呼び出しが実行されます。
- AlienCity.java で定義された GET API は、getAlienCountFromCatalystDataStore() 関数を呼び出し、リクエストクエリを渡します。
- この関数は、ZCQLクエリを実行して Data Store の Alien City テーブル内のデータを検索します。
- テーブル内に都市名と一致するレコードが見つかった場合、positive シグナルがレスポンスとして送信されます。それ以外の場合は、negative シグナルがレスポンスとして送信されます。
- クライアントは、レスポンスに一致するメッセージを表示します。main.js で定義されたレスポンスに一致するGIFも表示されます。
-
POST操作
- クライアントで都市名を入力してエイリアン遭遇を報告すると、index.html の Report ボタンのonClickイベントが、main.js で定義された postAlienEncounter() 関数をトリガーします。
- これにより、AlienCity.java 関数で定義されたURLルートへのAjax呼び出しが実行されます。AlienCity.java で定義されたPOST APIは、getAlienCountFromCatalystDataStore() 関数を呼び出し、同じ都市名のレコードが既に存在するかどうかを確認するためのリクエストクエリを渡します。
- この関数は、ZCQLクエリを実行して Data Store の Alien City テーブル内のデータを検索します。レコードが既に存在する場合、レスポンスが送信され、アプリケーションはその都市名が既に追加されていることを示すメッセージを表示します。
- 都市名のレコードがない場合、ユーザーが入力した都市名で Alien City テーブルに新しい行が作成されます。Data Store へのレコード挿入を確認するポップアップボックスがクライアントに表示されます。適切なメッセージもログに送信され、Logs コンポーネント(Catalyst DevOps サービス内)から確認できます。
最終更新日 2026-03-05 11:43:24 +0530 IST