SPA + REST API構成のサービス開発リファレンスが提供するコンテンツの1つです。 小さなチャットサービスを実装したコード例です。
SPAやREST APIを開発するときに参考にして頂いたり、必要に応じてソースコードを流用して再利用して頂くことを目的としています。
GitHub上でソースコードを見て頂いたり、git cloneをしてローカルにソースコードを取得してテキストエディターやJavaのIDEで見て頂くことを想定しています。
トップレベルのファイル・ディレクトリの説明をします。
| ファイル・ディレクトリ | 説明 |
|---|---|
.ci |
CI用のスクリプトを格納しています |
.gitlab |
GitLab上でマージリクエストを作成するときのテンプレートです |
.gitlab-ci.yml |
GitLabでCI/CDするためのビルドパイプラインの設定ファイルです |
README.md |
このファイルです |
api-document |
REST APIのインターフェースを記述したOpenAPIドキュメントです |
backend |
REST APIのソースコードです |
docker |
Dockerを使用してローカルで動かすミドルウェアのための設定ファイルを格納しています |
docker-compose.yml |
ローカルで必要なミドルウェアを動かすためのDocker Compose設定ファイルです |
frontend |
SPAのソースコードです |
notifier |
WebSocketで通知を行うアプリケーションのソースコードです(※SPAでもなくREST APIでもありませんが、WebSocketによる通知の例として参考にして頂けます) |
本コンテンツはソースコードを参考にして頂くことは勿論ですが、GitLabでCI/CDを行う際に必要となるビルドパイプラインの設定なども参考にして頂くことも想定しています。
※本コンテンツはGitHubで公開していますが、開発自体はGitLabを用いて行っています
本アプリケーションの開発には次のソフトウェアを使用しています。
ローカルで本アプリケーションを動かす場合はこれらソフトウェアのインストールをしてください。
また、必要に応じてテキストエディタやJavaのIDEをインストールしてください。
本アプリケーションはGoogle Chromeを対象としています。 他の環境では動作しない可能性があります。
ローカルで本アプリケーションを動かすには大きくわけて次の4つを起動する必要があります(括弧内はソースコードのディレクトリです)。
- データベースや外部サービスのモックなどのミドルウェア
- REST API(
backend) - WebSocketで通知を行うアプリケーション(
notifier) - SPA(
frontend)
本アプリケーションでは次のような外部サービスを利用しています。 ※実際にサービスとして運用を行なっているわけではないので、AWSのマネージドサービスに関しては「実際にサービス運用をすると仮定した場合に利用するもの」と捉えてください
- Amazon RDS for PostgreSQL
- 永続化データの保持
- ローカルではPostgreSQLで代替
- Amazon ElastiCache for Redis
- 認証前の一時的なユーザー情報の保持
- 通知のためのキュー
- ローカルではRedisで代替
- Amazon S3
- アップロードされた画像ファイルの保持
- ダウンロードさせるためのチャットログの保持
- ローカルではMinIOで代替
- Amazon SES
- ユーザーへ連絡するためのメール送信
- ローカルではMailHogで代替
ローカル環境ではDockerおよびDocker Composeを利用することで、動作できるようにしています。
次のコマンドで起動してください。
$ docker-compose up -d
次のようにdocker-compose psコマンドを実行してStateがUpになっていれば起動成功です。
$ docker-compose ps
Name Command State Ports
-----------------------------------------------------------------------------------------------------------------
example-chat_mail_1 MailHog Up 0.0.0.0:1025->1025/tcp, 0.0.0.0:8025->8025/tcp
example-chat_minio_1 /usr/bin/docker-entrypoint ... Up 0.0.0.0:9000->9000/tcp
example-chat_postgres_1 docker-entrypoint.sh postgres Up 0.0.0.0:5432->5432/tcp
example-chat_redis_1 docker-entrypoint.sh redis ... Up 0.0.0.0:6379->6379/tcp
停止する場合は次のコマンドを実行してください。
$ docker-compose down
REST APIをローカルで動かす場合、アプリケーションサーバとしてJettyを利用しています。
Mavenプラグインを利用しており、以下のようなコマンドを実行することで起動できます。
$ # backendディレクトリで実行してください
$ mvn jetty:run
初回の実行時はMavenリポジトリから依存するJARファイルをダウンロードするため、多少時間がかかります。
例外が発生することなく次のようなログが出力されると起動成功です。
[INFO] Started ServerConnector@114a18d6{HTTP/1.1,[http/1.1]}{0.0.0.0:9080}
[INFO] Started Server@75689d9c{STARTING}[10.0.0.alpha1] @6271ms
Hit <enter> to redeploy:
停止する場合はCtrl + Cを押してください。
REST APIをローカルで動かす場合、Dockerコンテナで起動することもできます。
そのままDockerイメージを作成するとSameSite属性がNoneに設定されるようになっていますので、Cookieを送信するにはSecure属性をつける必要があり、HTTPS通信でなければCookieを送信することができなくなります。
ローカルでHTTP通信を使用して動作させたい場合は、Dockerイメージの作成前に、SameSite属性がLaxになるように設定を変更しておきます。
backend/src/main/jib/usr/local/tomcat/conf/context.xmlファイルを開き、CookieProcessorのsameSiteCookies属性の値をlaxに変更します。
<Context>
...
<CookieProcessor className="org.apache.tomcat.util.http.Rfc6265CookieProcessor" sameSiteCookies="lax"/>
</Context>Dockerイメージは次のコマンドで作成します。Dockerイメージの名前はexample-chat-backendになります。
$ # backendディレクトリで実行してください
$ mvn package jib:dockerBuild -DskipTests
Dockerイメージが作成されているかどうかは、次のコマンドで確認することができます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example-chat-backend 1.0.0 662b55a12169 50 years ago 466MB
example-chat-backend latest 662b55a12169 50 years ago 466MB
Dockerイメージが作成されたら、次のコマンドでDockerコンテナを起動します。Dockerコンテナ内から他のミドルウェアへはlocalhostでアクセスできないため、環境変数でミドルウェアの接続先を設定します。
docker run -it --rm -p 9080:8080 --network example-chat-network -e NABLARCH_DB_URL="jdbc:postgresql://postgres:5432/postgres" -e NABLARCH_LETTUCE_SIMPLE_URI="redis://password@redis:6379" -e MAIL_SMTP_HOST="mail" -e AWS_S3_ENDPOINTOVERRIDE="http://minio:9000" example-chat-backend:latest
例外が発生することなく次のようなログが出力されると起動成功です。
04-Sep-2020 07:55:36.952 情報 [main] org.apache.catalina.startup.Catalina.start サーバーの起動 [5,184]ms
停止する場合はCtrl + Cを押してください。
WebSocketで通知を行うアプリケーションはREST APIと同様にローカルで動かす場合、アプリケーションサーバとしてJettyを利用しています。
次のコマンドで起動ができます。
$ # notifierディレクトリで実行してください
$ mvn jetty:run
例外が発生することなく次のようなログが出力されると起動成功です。
[INFO] Started ServerConnector@38eafdab{HTTP/1.1,[http/1.1]}{0.0.0.0:9081}
[INFO] Started Server@491cc0eb{STARTING}[10.0.0.alpha1] @4770ms
Hit <enter> to redeploy:
停止する場合はCtrl + Cを押してください。
まれにアプリケーション起動後、通知を行うと次のようなエラーになる場合があります。
java.lang.NoClassDefFoundError: Could not initialize class com.example.presentation.websocket.WebSocketNotifier
このエラーが発生し、解消されない場合は後述するDockerコンテナでの起動を試してください。
WebSocketで通知を行うアプリケーションをローカルで動かす場合、Dockerコンテナで起動することもできます。
まず、次のコマンドでDockerイメージを作成します。Dockerイメージの名前はexample-chat-notiferになります。
$ # notifierディレクトリで実行してください
$ mvn package jib:dockerBuild -DskipTests
Dockerイメージが作成されているかどうかは、次のコマンドで確認することができます。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
example-chat-notifier 1.0.0 d3d0a0844ffb 50 years ago 454MB
example-chat-notifier latest d3d0a0844ffb 50 years ago 454MB
Dockerイメージが作成されたら、次のコマンドでDockerコンテナを起動します。Dockerコンテナ内から他のミドルウェアへアクセスするため、環境変数でミドルウェアの接続先を設定します。次のコマンドでは、ホスト端末(実行端末)を表すhost.docker.internalを使用して、localhostと同等の接続先に設定しています。
docker run -it --rm -p 9081:8080 --network example-chat-network -e NABLARCH_LETTUCE_SIMPLE_URI="redis://password@redis:6379" example-chat-notifier:latest
例外が発生することなく次のようなログが出力されると起動成功です。
04-Sep-2020 07:58:41.380 情報 [main] org.apache.catalina.startup.Catalina.start サーバーの起動 [3,314]ms
停止する場合はCtrl + Cを押してください。
SPAはcreate-react-appを使用して開発しており、create-react-appの利用方法に則っています。
依存するライブラリをダウンロードするため、初回のみ次のコマンドを実行してください。
$ # frontendディレクトリで実行してください
$ npm ci
起動するには以下のようにnpm startを実行します。
$ # frontendディレクトリで実行してください
$ npm start
次のように出力されると起動成功です。
Compiled successfully!
You can now view example-chat-frontend in the browser.
Local: http://localhost:3000
On Your Network: http://192.168.0.19:3000
Note that the development build is not optimized.
To create a production build, use npm run build.
更にnpm startは自動でブラウザを起動して http://localhost:3000 を開きます。
停止する場合はCtrl + Cを押してください。
アプリケーションを触ってみてください。
本アプリケーションにはログイン認証機能があります。 あらかじめ用意しているユーザーの情報は次の通りです。
| ユーザー名 | メールアドレス | パスワード |
|---|---|---|
user1 |
user1@example.com |
pass123- |
user2 |
user2@example.com |
pass123- |
新しくユーザーを登録することも可能です。 ユーザー登録にはメールを使いますが、本アプリケーションをローカルで動かしている場合はメールサーバーのモックを使用します。 本アプリケーション内で送信されたメールを読む場合は、ブラウザで http://localhost:8025 を開いてください。
Docker Composeで起動しているミドルウェアへ接続するための情報はdocker-compose.ymlおよびdockerディレクトリ内のファイルに記載してあります。
PostgreSQLとRedisはDockerコンテナ内にCUIのクライアントツールが同梱されています。
PostgreSQLは次のコマンドで接続できます。
$ docker-compose exec postgres psql -U postgres
Redisは次のコマンドで接続した後にAUTHコマンドでパスワードを入力して認証を行なってください。
$ docker-compose exec redis redis-cli
MinIOとMailHogはDockerコンテナ内にGUIのクライアントツールが同梱されています。 いずれもウェブアプリケーションです。
MinIOのクライアントツールを使うにはブラウザで http://localhost:9000 を開いてください。
MailHogのクライアントツールを使うにはブラウザで http://localhost:8025 を開いてください。
REST APIとWebSocketで通知を行うアプリケーションはNablarchが提供しているJavaスタイルガイドを参考にして静的解析を組み込んでいます。
SpotBugsによる静的解析をMavenで実行できます。 次のコマンドでチェックできます。
$ # backendディレクトリ、またはnotifierディレクトリで実行してください
$ mvn spotbugs:check
SPAはESLintによる静的チェックが行えるようにしています。
次のコマンドでチェックできます。
$ # frontendディレクトリで実行してください
$ npm run lint
内容によっては機械的に修正が可能なものもあります。 そういったものは、次のコマンドで修正することが可能です。
$ # frontendディレクトリで実行してください
$ npm run lint:fix
JUnitを使ったテストコードを用意しています。
次のコマンドでテストを実行できます。
$ # backendディレクトリ、またはnotifierディレクトリで実行してください
$ mvn test
mvn testで実行されるものはミドルウェアを使用しない箇所に対するテストになります。
ミドルウェアを使用する箇所に対するテストは次のコマンドで実行できます。なお、ミドルウェアを使用するため、事前にDocker Composeでミドルウェアを起動しておく必要があります。
$ # backendディレクトリ、またはnotifierディレクトリで実行してください
$ mvn verify
次のコマンドでテストを実行できます。
$ # frontendディレクトリで実行してください
$ npm test
※ このリポジトリはApache License Version 2.0の下に提供されています。
※ このドキュメントに記載されている会社名、製品名は、各社の登録商標または商標です。
※ AWS、Amazon RDS for PostgreSQL、Amazon ElastiCache for Redis、Amazon S3、Amazon SESは、米国および/またはその他の諸国における、Amazon.com, Inc.またはその関連会社の商標です。