--- title: "アプリケーションのコーディング" url: https://docs.catalyst.zoho.com/ja/tutorials/alien-city-appsail/springboot/code-app/ description: "都市でのエイリアン遭遇を報告または検索できるアプリケーションを作成し、Catalyst AppSailサービスとCatalyst Data Storeを使用してCatalyst上にホストします。" last_updated: 2026-08-17T12:16:04Z service: All Services type: tutorial related_links: - name: "AppSail用Catalyst SDK" url: /ja/cli/v1/initialize-resources/introduction/ --- # アプリケーションのコーディング `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** プロジェクトディレクトリの最終的な構造は以下のとおりです: ![catalyst_alcity_appsail_spring_complete](https://catalyst-docs-development.zohostratus.in/images/tutorials/alien-city-appsail-express/catalyst_alcity_appsail_spring_complete.webp) `AlienCity.java`、`AliencityApplication.java`、`index.html`、および `main.js` をコーディングします。また、`app-config.json` と `pom.xml` ファイルも更新します。 > **注意:** このセクションのコードを十分に理解するために、必ず内容を確認してください。 以下のコードをコピーして、IDEを使用してプロジェクトのそれぞれのファイルに貼り付け、ファイルを保存してください: **AlienCity.java** ```java 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); } } } ``` **AliencityApplication.java** ```java 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); } } ``` **index.html** ```xml <!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> ``` **main.js** ```javascript 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(); } ``` **pom.xml** ```xml <?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> ``` > **注意:** **14** 行目のバージョンは変更しないでください。バージョンが `2.7.10` 以下でなければ、AppSailでアプリケーションをホストすることはできません。 **app-config.json** ```json { "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" } ``` > **注意:** `buildpath` キーに正しい値を指定していることを確認してください。 アプリケーションの動作を簡単に確認しましょう: 1. **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も表示されます。 2. **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*](https://docs.catalyst.zoho.com/ja/devops/help/logs/introduction/) コンポーネント([Catalyst DevOps](https://docs.catalyst.zoho.com/ja/devops/) サービス内)から確認できます。