はじめに
皆さんは『無限の猿定理』というものをご存知だろうか。
無限の猿定理(むげんのさるていり、英語: infinite monkey theorem)とは、十分長い時間をかけてランダムに文字列を作り続ければ、どんな文字列もほとんど確実にできあがるという定理である。比喩的に「猿がタイプライターの鍵盤をいつまでもランダムに叩きつづければ、ウィリアム・シェイクスピアの作品を打ち出す」などと表現されるため、この名がある。
要するに”無限”というものの凄さの例えである。
この定理に着想を得て、以前「頭文字を打つだけで文章ができていくアプリケーション」というものを作成した。
このプログラムはコンソール上だけでの動作だったので,Webアプリに移植して,公開することにした。
URLはこちら。
https://infinite-monkey-theorem.herokuapp.com/
本記事では、公開までに躓いたポイントの備忘録である。
- 環境
- Windows10
- VSCode
- 構成
- Java11
- Spring-Boot
- PostgreSQL
- Heroku
ローカル開発環境の準備
VSCodeに必要な拡張機能をインストールする
- Java Extension Pack
- Spring Boot Extension Pack
- Lombok Annotations Support for VS Code
アプリの雛型を自動生成する
Ctrl+Shift+Pでコマンドパレットを開く
"Spring.Initializr: Create a Maven Project..."を選択
Spring Boot Version 2.5.3を選択
Project Language Javaを選択
Group Idを入力,今回はworks.izumi
Artifact Id を入力,今回はinfinite_monkey_theorem
packaging type Jarを入力
Java Version 11を選択
dependenciesは以下を選択
- Spring Boot Dev Tools
- Lombok
- Spring Web
- Thymeleaf
- Spring Data JPA
- PostgreSQL Driver
プロジェクトを格納するフォルダを選択して終了。
初期動作確認
動作確認のため以下のファイルを追加。
【躓きポイント】利用するDBを指定しないと実行に失敗するので注意
SPRING BOOT DASHBOARDから実行し,localhost:8080にアクセス。
『hello』と表示されたら,成功。
package com.example.demo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class AppController {
@ResponseBody
@RequestMapping("/")
public String init(){
return "hello";
}
}
# 接続情報
spring.datasource.url=jdbc:postgresql://localhost:5432/[データベース名]
spring.datasource.username=[ユーザ名]
spring.datasource.password=[パスワード]
DB作成と接続テスト
さらに,Entity,Repository,serviceを追加し,controllerも追記.
package com.example.demo.model;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import lombok.Data;
@Entity
@Data
@Table(name="test")
public class AppEntity implements Serializable{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int nounId;
@Column(name="initial")
private String initial;
@Column(name="notation")
private String notation;
}
package com.example.demo.repo;
import java.util.List;
import com.example.demo.model.AppEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface NounRepository extends JpaRepository<AppEntity, Integer>{
public List<AppEntity> findByInitial(String initial);
}
package com.example.demo.service;
import java.util.List;
import com.example.demo.model.AppEntity;
import org.springframework.stereotype.Service;
@Service
public interface AppService {
public List<AppEntity> test();
}
package com.example.demo.service.impl;
import java.util.List;
import com.example.demo.model.AppEntity;
import com.example.demo.repo.NounRepository;
import com.example.demo.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class AppServiceImpl implements AppService {
@Autowired
NounRepository repo;
@Override
public List<AppEntity> test(){
return repo.findAll();
}
}
package com.example.demo.controller;
import com.example.demo.service.AppService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class AppController {
@Autowired
AppService service;
@ResponseBody
@RequestMapping("/")
public String init(){
return "hello";
}
@ResponseBody
@RequestMapping("test")
public String test(){
return service.test().toString();
}
}
localhost:8080/testにアクセスし,テーブルの中身が表示されれば成功。
Herokuへデプロイ
こちらの記事が大変参考になる。
とりあえずHeroku + Spring Boot デプロイ
【躓きポイント】Procfileとsystem.propertiesをきちんと追加・設定しよう
これでおそらくデプロイは成功する。
しかしHerokuのURLにアクセスしようとすると、おそらく『Application error』になる。
その場合、Procfileで設定したjarファイルが生成されていない可能性が高い。
こちらの記事が大変参考になる。
Herokuにデプロイしたアプリの更新で「Application error」
【躓きポイント】Mavenビルドとjarファイルをgit addしよう
Sleep対策
Herokuの無料枠では30分アクセスがないとアプリケーションがスリープしてしまう。
スリープ中にアクセスするとSpring Bootの起動から始まるので表示にとても時間がかかる。
そこでNew Relicアドオンを用いて15分毎にアクセスを行うことで、スリープを防止した。
こちらの記事が大変参考になる。
その他忘れがちなこと
- テストクラスに@SpringBootTestをつける
- Ajax(jQuery)の雛型: contentType: "application/json" とすることで、サーバ側@RequestBodyでうまく受け取れるようになる
$.ajax({
type: "POST",
url: "/hoge",
contentType: "application/json",
data: val,
})
.done(function (data) {
// 通信成功時
alert("通信成功");
})
.fail(function (data) {
// 通信失敗時の処理
alert("通信失敗");
})
.always(function (data) {
// 常に実行する処理
console.log(data);
});
おわりに
お盆休みの暇な時間を有効に使おうと思い、セルフサマーキャンプ的なノリで始めた本開発。
実装の中身は既にあったので、今回はクラウドサーバへのアップロードとUIをメインの課題として取り組んだ。
飽き性なのでこれくらいコンパクトに絞って本当に良かった。
今度はツール的なものの開発に取り組んでみようかな。