ふるてつのぶろぐ

福岡在住のエンジニアです。

写真提供:福岡市

Angular7 + Bootstrap4 で Web アプリを作ろう - ngx-translate で他言語化の件 。

こんにちはふるてつです。
今日は土曜日、ちょっとくもり。わたしは家でAngularを自習しています。
今回のテーマは他言語です。
勤務先で ngx-translate を使って他言語化した方がいて、話を聞いていると思ったより簡単そうだと感じました。
Angular純正もあったかと思いましたが、ネットでも ngx-translate がよさそうとの評もあり今回試してみました。 https://qiita.com/daikiojm/items/def764b12c8ff2ebbc92

ngx-translate のインストール

まず下記の CLI コマンドでインストールします。
https://github.com/ngx-translate/core (Gitリポジトリ)を参考にして設定します。

ngx-translate の core と http-loader が必要そうです。
両方ともにインストールします。

npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save

なぜ@を ngx-translate/core の前につけるかというと「node_modules」フォルダの中に@付きでライブラリを入れるためです。
言い換えると他のライブラリと区別しやすくするためです。

インストール完了後のターミナル
f:id:tetsufuru:20190323110024p:plain もうひとつ。サクッとうまくいきました。
f:id:tetsufuru:20190323112323p:plain

package.json には ngx-translate/core が追加されました。
f:id:tetsufuru:20190323113917p:plain

package-lock.json も変わりました。 f:id:tetsufuru:20190323113952p:plain

AppModule クラスの修正

まずAppモジュールの中に TranslateModule の import を追加します。
このあたりの設定は Git リポジトリの README.MD の 中段あたり Configuration のところに書いてあります。
TranslateHttpLoaderというクラスを使用して、HTTPで 他言語用の json ファイルを読み込んで変換します。
json ファイルは "/assets/i18n/[lang].json" に置く感じになります。

TranslateModule.forRoot({
    loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
    }
})

あと TranslateHttpLoader を返すメソッドを一つ追加しました。 これも手順通りです。

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

AppModule クラスのコード全体は下記になりました。

// 機能に関するモジュール類
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppRoutingModule } from './app-routing.module';
import { NgbModule } from '@ng-bootstrap/ng-bootstrap';
import { FormsModule } from '@angular/forms';
import { environment } from '../environments/environment';
import { HttpClientModule, HttpClient } from '@angular/common/http';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

// コンポーネント関連
import { AppComponent } from './app.component';
import { HeaderComponent } from './component/common/header/header.component';
import { FooterComponent } from './component/common/footer/footer.component';

import { SignInComponent } from './component/pages/sign-in/sign-in.component';
import { EvaluationResultComponent } from './component/pages/evaluation-result/evaluation-result.component';
import { SearchInfoComponent } from './component/common/search-info/search-info.component';
import { MessagesComponent } from './component/common/message/messages/messages.component';
import { ErrorMessagesComponent } from './component/common/message/error-messages/error-messages.component';

// 他言語化の設定
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

// モジュール定義
@NgModule({
  declarations: [
    AppComponent,
    HeaderComponent,
    FooterComponent,
    SignInComponent,
    EvaluationResultComponent,
    SearchInfoComponent,
    MessagesComponent,
    ErrorMessagesComponent
  ],
  imports: [
    BrowserModule, NgbModule.forRoot(),
    FormsModule, AppRoutingModule, HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

上のコードが長くなり見にくくスミマセン。

AppModule クラスの修正

次は一旦 AppComponent のコンストラクタで TranslateService をインジェクトして、日本語を使用するよう設定しておきます。
今後どのようにするかまだ決めていませんが、ブラウザの言語設定に合わせて切り替えるか? DBにユーザ毎の言語設定を登録して切り替えるか?どちらかにすると思います。

AppComponent クラスのコードは下記になります。
コンストラクタで TranslateService をインジェクトしてデフォルトの言語と使用する言語を設定しました。

import { Component } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'sanrokumaru';

  constructor(translate: TranslateService) {
    // 言語の初期設定
    translate.setDefaultLang('en');
    translate.use('ja');
  }

}

json ファイルの作成

assets/i18n/に en.json と ja.json 2ファイルを作ります。
f:id:tetsufuru:20190323225040p:plain

json の中身は下記です。
フォーマットを間違えなければ、どういうまとめ方でも構わないと思います。

{
  "welcomeScreen": {
    "title": "ようこそ",
    "systemName": "Sanrokumaruシステムへ",
    "comment": "より良いコミュニケーションを目指して"
  },
  "signInScreen": {
    "signIn": "サインイン",
    "userId": "ユーザID",
    "password": "パスワード",
    "signInBtn": "サインイン",
    "information": "お知らせ"
  }
}

html の書き換え

あとは html の中で直に文言を書き込んでいる個所を書き換えるだけです。

まずは簡単な書き方です。下記のような label の例になります。
タグの中に translate を追記し文言を json のキーに置き換えます。

<label for="loginUserId">ユーザID</label>
↓ 変更後
<label for="loginUserId" translate>signInScreen.userId</label>

次はちょっと難しい分。例はプレースホルダーになります。 {{}}の中に json のキーを追記し、パイプで translate をするように書きます。

<input id="loginUserId" type="text" placeholder="ユーザID">
↓ 変更後
<input id="loginUserId" type="text" placeholder="{{ 'signInScreen.userId' | translate }}">

あとは大体似たような感じで、サインイン画面の文言を他言語化しました。

日本語の時は下記 f:id:tetsufuru:20190323231129p:plain

英語の時は下記のようになります。 f:id:tetsufuru:20190323231024p:plain

今日の感想

今日は ngx-translate を使って他言語化にチャレンジしました。
1画面だけですが思ったより簡単にできました。
コードを書くよりこのブログを書く方に時間がかかったくらいです。
今後の他言語化は全部これで行こうか~と思いました。

では、今日もお疲れ様でした。

Angular7 + Bootstrap4でWebアプリを作ろう - サービスその2 HTTP通信。

こんにちはふるてつです。
今日は Angular です
前回の社内もくもく会でモックサービスを作りました。
そして今回はそれを HTTP 通信で取得するように変えました。
サーバ側は先日環境を作った Spring Boot にしています。
まずは定数を格納するクラスを作る所から始めます。

appConstクラスを追加

まずはサーバのURLなど固定値専用のクラスを作ります。下記の CLI コマンドで作ります。
固定値だけなのであとでテストファイル 「xxx.spec.ts」 は消しました。

ng generate class appConst

① AppConst クラスにローカルで実行するときのサーバURLを追加します。
② HTTP 接続する際に、クロスオリジン制約にかからないようプリフライトリクエストを送る必要があります。
プレフライトリクエスト用の HTTP オプションを一ヶ所に持ち、各サービスで使いまわします。
プレフライトリクエストについてはこちらが分かりやすいかもですhttps://qiita.com/rooooomania/items/4d0f6275372f413765de

○ appConst クラスの内容

import { HttpHeaders } from '@angular/common/http';

export class AppConst {

  // サーバー URL
  static readonly URL_DEV_SERVER = 'http://localhost:8080/api/';
  // HTTP オプション(プレフライトリクエスト)
  static readonly httpOptions = { headers: new HttpHeaders({ 'Content-Type': 'application/json' }) };

}

information サービスの修整

information サービスは下記のように修正しました。
① AppConst クラスからローカルテスト用のサーバURLを取得して private 変数で持つ。
api のエンドポイント名を private 変数で持つ "informations"
③コンストラクタの引数に private http: HttpClient を追加して、HTTP CLIENTをインジェクトする。
④あとは最後の行で Spring Boot に HTTP通信して json データを取得する。
http はコンストラクタでインジェクトしているので、this で呼び出せる。
this.http.get<Information[]>() メソッドの第2引数には
先ほど作ったプリフライトリクエスト用のHTTP オプションを渡す。

○ information サービスクラスの内容

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Information } from 'src/app/entity/domain/information';
import { environment } from '../../../environments/environment';
import { AppConst } from '../../app-const';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})
export class InformationService {

  private server = environment.production ? AppConst.URL_PROD_SERVER : AppConst.URL_DEV_SERVER;
  private webApiUrl = 'informations';

  constructor(private http: HttpClient) { }

  getInformations(): Observable<Information[]> {

    console.log(this.server + this.webApiUrl);
    return this.http.get<Information[]>(this.server + this.webApiUrl, AppConst.httpOptions);

  }

}

Spring Boot の設定

Spring Boot のコントローラに対し、クロスオリジンを許すようにします。

○ Spring Boot のコントローラ内容
@CrossOriginアノテーションをコントローラにつけてクロスオリジンを許可します。

@RestController
@RequestMapping("api/informations")
@CrossOrigin
public class InformationRestController {
    @GetMapping
    public List<InformationDto> getInformations(){

        return informationService.searchAll();

    }   
}

Spring Bootの設定を変えてクロスオリジンを許すようにしました。
これで準備完了です。
あとは Angular と Spring Boot を共に起動して HTTP 通信でデータの疎通を確認して終わりました。

今日の感想

今日はモックでなく、HTTPで実際に通信してデータを取得するようにしてみました
これでやっと Angular を動かしている気になってきました。
当面はこれで行こうかと思います。
しかしチュートリアルと比較するとエラー時のハンドリングが足りないようです。
チュートリアルではサービスで http.get メソッドを動かした後、
observable の結果を pipe() で拡張して、それを catchError() オペレーターに渡してますねぇ。
通信に失敗した時など必要そうなので、最終的にはその形にリファクタリングしたいと思いました。

では、お疲れ様でした。

今夜は社内AWSもくもく会 - EC2その2 インスタンスの作成とSSH、HTTPアクセスの許可

こんにちはふるてつです。
今回も社内 AWS もくもく会の内容です。EC2 の利用その2です。
今回のテーマは EC2 の作成と SSH ログイン、HTTP アクセスの許可です。
前回はセキュリティグループの作成などを行いましたが、 これでやっとすこし進んだ気がします。

EC2 作成

まずは EC2 のダッシュボード画面。まだ実行中のインスタンスは何もありません。
画面中段の「インスタンスの作成」ボタンを押してインスタンスを作り始めます。
f:id:tetsufuru:20190320192529p:plain

マシンイメージを選ぶ画面が出てきます。もちろん無料利用枠の中から選びます。
Amazon Linux だと2種類あります。
Amazon Linux 2 AMI (HVM), SSD Volume Type」と「Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type」です。
どちらにするか少し迷ったのですが、今回はわたしが参考にしている本と同じく「Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type」を使用します。
上から2段目です。長く使うのであれば新しい方(Amazon Linux 2 AMI)が良いとは思いますが。
f:id:tetsufuru:20190321111726p:plain

インスタンスタイプを選択する画面が出てきます。
無料枠の「t2.micro」を選びます。
選んだあと「インスタンス詳細の設定」ボタンをクリックします。
f:id:tetsufuru:20190320192730p:plain

インスタンス詳細の設定画面では「ネットワーク」欄と「サブネット」欄、「自動割り当てパブリックIP」を設定します。
「ネットワーク」欄と「サブネット」欄はどちらもこれまでに作ってきたものを選択します。
「自動割り当てパブリックIP」は "有効化" にします。
上記以外はデフォルトのままにしておきます。
f:id:tetsufuru:20190320193052p:plain

ストレージもデフォルトのまま。
f:id:tetsufuru:20190320194036p:plain

タグは「キー」欄に "Name" と入力し、EC2 インスタンスに好きな名前を設定しておきます。
f:id:tetsufuru:20190320194308p:plain

セキュリティグループの設定画面では、前回作成したセキュリティグループを設定します。
そして「確認と作成」ボタンをクリックする。
f:id:tetsufuru:20190320194640p:plain

この画面で「確認」。
f:id:tetsufuru:20190320195951p:plain

次は下の画面のようにキーペアについて聞かれます。
ここは既存のキーペア(前回作成したもの)をもちろん選択します。
インスタンスの作成」ボタンをクリックすると、AWS が EC2 インスタンスを作り始めます。
f:id:tetsufuru:20190320200104p:plain

まだ作成中…
f:id:tetsufuru:20190320200349p:plain

インスタンスの状態が下記の感じ(runnning)になったら出来上がりです。
f:id:tetsufuru:20190321120306p:plain

SSH接続

では次に SSH で先ほどの EC2 にログインします。
本では TeraTerm を使っています、わたしもずっと TeraTerm です。
若い方は RLonin などを使われているかもしれませんね。
今回は TeraTerm を起動します。
ホスト欄にはパブリック DNS を設定しておきます。
パブリック DNS は、上記の EC2 インスタンスの一覧画面の右下に表示されています。
こちらをコピー/ペーストで構いません。
「OK」をクリックすると。
f:id:tetsufuru:20190320201808p:plain:w300

SSH認証の画面がでてきます。
「ユーザー名」は「ec2-user」(EC2 にデフォルトで存在するユーザです)
秘密鍵」の欄は前回作成したキーペアファイルを指定します。
(このキーペアファイルは誰にも渡してはなりません)
これで「OK」を押すとつながるはずです。
f:id:tetsufuru:20190320202103p:plain:w300

繋がりました。コマンドが打てるようになりました。
f:id:tetsufuru:20190320202519p:plain:w300

HTTPサーバーをインストールしてアクセスを試してみる

ここからはただのテストですが、EC2 に Apache をインストールして http でアクセスしてみます。

まずは Apache のインストール。yum です。 chkconfig コマンドは今後自動で Apache を起動するために実行します。

sudo yum install httpd -y
sudo service httpd start
sudo chkconfig httpd on

次はセキュリティグループの再設定
80番ポートを開くよう「ルールの追加」をクリックします。
f:id:tetsufuru:20190320203407p:plain

タイプ "HTTP" を "任意の場所" で追加します。そして「保存」をクリック。
f:id:tetsufuru:20190320203646p:plain

下のように「インバウンド」のルールに "HTTP" が2件ほど追加されました。
上が IPv4 用の設定で、下が IPv6 用の設定です。どちらもすべてを許可する設定です。
(本日一緒に勉強している者から聞きました)
f:id:tetsufuru:20190320204002p:plain

あとはローカルマシンのブラウザから EC2 インスタンスのパブリック DNS にアクセスしてみると TestPage が表示されます。
f:id:tetsufuru:20190320204754p:plain

感想

やっと今回 EC2 のインスタンスを作りました。
一応 SSH も HTTP もつながるようになりました。すこし進んだ気になりちょっぴり嬉しいです。
この先は ELB(ロードバランサ)などが出てくるようです。楽しみですねぇ
ではでは

Angular7 + Bootstrap4でWebアプリを作ろう - 今夜はSpring Bootだけ 環境作りからモックのREST APIを1本作るまで。

こんにちはふるてつです。
Angular でサービスを作るようになり、そろそろサーバが欲しくなってきました。
そこで今日は Spring Boot 環境を作りAPIを1本作るまでを行いたいと思います。
なぜ Spring かというとそれしかできないからですね。選択の余地ありません…

環境の準備(Eclipseのダウンロード)

まずは環境を整えます。何度やっても、わたしはやり方をすぐ忘れちゃいますね。

Eclipseのダウンロード

まずは基本的なところで Eclipse のダウンロードから始めます。
オールインワンを使いたく。下記のURLですね。
http://mergedoc.osdn.jp/

今回は「4.8 Photon」を使います。クリックします。
f:id:tetsufuru:20190315231525p:plain

ダウンロードする Eclipse ですが、わたしは迷わず「Java」の「Full Edition」を選びます。
エディションについて「Standard Edition」を選び必要なプラグインを入れるやり方もありますが、 大雑把な私には向いてませんので。
f:id:tetsufuru:20190315231655p:plain 上記の画面でダウンロードしたZIPファイルを展開すると Eclipse が出てきます。
(ZIPから解凍するときに回答先のフォルダ名が長かったり階層が深すぎると展開時にエラーメッセージが出るので注意しましょう)

あと日本語化もしておきましょう。職場では Eclipse は英語版と決まっているのですが、個人的には日本語が落ち着きます。
同じサイトからダウンロードしてきた下記のツールを起動します。
「日本語化するアプリケーション」欄に 日本語化したいEclipse の exe ファイルを選択して実行するのみです。
f:id:tetsufuru:20190315233333p:plain:w300

②Spring Boot プラグインと DBeaver プラグインの追加

次はSpring Boot プラグインEclipse に追加します。
「メニュー」→「ウィンドウ」→「マーケットプレイス」から「sts」を検索するとプラグインが出てきます。
下のような画面になります。
そもそも Spring Tool Suite (STS) を使う方法もありますが、オールインワンに Spring Boot プラグインを入れる方が Eclipse のバージョンを選べ、こちらのほうがわたしは良いとか思っています。
f:id:tetsufuru:20190315234629p:plain

あと開発時は H2 DB を使いたいので、DBeaver プラグインをいれておきます。これはH2 DB の中身を見るためのツールです。
H2 を使わなければ不要です(本番は PostgreSQL の RDS にする予定ですが)
f:id:tetsufuru:20190315235616p:plain

Lombokのインストール

Lombok を使用したいのでインストールします(例の getter/setter などを勝手につくってくれるプラグインです)

下記のURLからダウンロードします。 https://projectlombok.org/

このサイトのメニューからダウンロードを選びます。
f:id:tetsufuru:20190317113307p:plain

下の画面にて最新バージョンらしき「1.18.6」をダウンロードします。
f:id:tetsufuru:20190317113356p:plain

中にインストーラーが入っていますので、起動します。
起動してすぐに自分のマシン中の Eclipse を捜しだそうとするようですが、時間がかかり待っていられないので、わたしはいつも手動で Eclipse の場所を指定します。
中段の「Specify location…」ボタンがそれです。Eclipse の exeファイルを選択して「Install / Update」を押します。
f:id:tetsufuru:20190317113645p:plain:w300

終わるとこの画面が出てきます。
f:id:tetsufuru:20190317114514p:plain:w300

ここまでで Eclipse の環境準備は終わりです。

Rest APIの作成

次はプロジェクトを作成し、Restコントローラとモックサービスを作ります。

①プロジェクトの作成

Eclipse のメニューから「新規」→「その他」を選びます。
f:id:tetsufuru:20190317115309p:plain

「Spring スタータープロジェクト」を作成します。
f:id:tetsufuru:20190317115405p:plain:w300

サービスURLはデフォルトのまま、あとは全部自分の好きに設定します。
わたしは、Maven と Gradle 両方の経験がありますが、Gradle の方が便利だと感じそちらを使います。
Javaは 8 のままでしばらくは開発しようとは思います。
どこかのタイミングで 12に変更するかもしれません。
f:id:tetsufuru:20190317115638p:plain:w300

次へをクリックすると下の画面になります。ここで選択したライブラリが Gradle の設定ファイルに登録されます。
まずSpring Bootのバージョンは最新「2.2.0」にして
Web、Lombok、H2、JDBC、MyBatis、Flywayを選択しました。
職場では jOOQ や JPA が使われてますが、 MyBatis にしました。いまだにこれが一番いい気がして…
Spring Securityも含めたいところですが、きちんと時間をとってやりたいので、別途あとから手動で入れようと思います。
f:id:tetsufuru:20190317124312p:plain:w300

作成した後、xxxApplication.java が最初の起動ファイルになります。
(このファイルを右クリックして実行するとサーバが起動します)
f:id:tetsufuru:20190317122920p:plain

②コントローラ / モックサービスの作成

いま私が考えているシステムではログイン画面下に管理者からのお知らせを表示します。
そのお知らせを取得するAPIを作ります。
そこで今回は下記 3ファイルを Eclipse に追加します。

DTO
entiry/InformationDto.java

○モックサービス
mockService/MockInformationService.java

○コントローラ
controller/InformationRestController.java

Eclipse 画面の左端パッケージエクスプローラーではこのような構成になります。
f:id:tetsufuru:20190317130952p:plain

まずDTOについてですが、
@DataLombok 用のアノテーションです。
このアノテーションを書くと getter / setter が自動的に作られます。
@AllArgsConstructorLombok 用のアノテーションです。
このアノテーションを書くと その名前の通り、すべての引数を渡すコンストラクタが自動的に作られます。

package com.weekenditlaboratory.entity.dto;
import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class InformationDto {
    private String date;
    private String information;
    private String detail;
}

次にモックサービスです。
@Service は Spring のアノテーションです。
これは Spring でいうところのいわゆるサービス(ビジネスロジック)につけるアノテーションです。
今回はモックを作りたくDBに接続せずに固定値を返すようにします。
List<InformationDto> を返す、#searchAll() メソッドを追加しました。

package com.weekenditlaboratory.mockService;
import java.util.ArrayList;
import java.util.List;
import org.springframework.stereotype.Service;
import com.weekenditlaboratory.entity.dto.InformationDto;

@Service
public class MockInformationService {
    public List<InformationDto> searchAll(){
        InformationDto informationDto1 = new InformationDto("2019/3/1","運用停止のお知らせ","メンテナンスのため月末の0:00~2:00まで運用を停止します。");
        InformationDto informationDto2 = new InformationDto("2018/2/1","運用停止のお知らせ","メンテナンスのため月末の0:00~2:00まで運用を停止します。");
        InformationDto informationDto3 = new InformationDto("2018/1/1","運用開始","運用を開始します。");
        List<InformationDto> res = new ArrayList<InformationDto>();
        res.add(informationDto1);
        res.add(informationDto2);
        res.add(informationDto3);
        return res;
    }
}

最後にコントローラ
@RequiredArgsConstructorlombokアノテーションで、クラス中で「static final」宣言したオブジェクトのコンストラクタを自動的に作ります。
この場合、Spring が Lombok で作ったコンストラクタに合わせて mockInformationService を DI してくれます。
そして他は Spring のアノテーションです。

@RestController は Rest 用のアノテーションです。もちろん他の形式のコントローラもあります。例えば Thymeleaf だと @Controller
@RequestMapping アノテーションは http リクエストの URL を指定します。
@CrossOrigin はクロスドメイン接続を許す設定です。
Angular をng serve で動かした場合クロスドメイン制約にかかり接続できず一時的にクロスドメインを許しました。
※本来はコントローラに書くべきではなく Spring Security の設定ファイルなど1ケ所に書き、さらにローカル環境のみでの設定にすべきですが、今回はまだお試し中なので、アノテーションを直接書き込みました。

@GetMapping は Rest でいうところの http メソッド の GET が呼ばれた場合に動くコントローラのメソッドを指定しています。
つまり http://example/api/informations が GET で呼ばれた場合には InformationRestController の #getInformations() が動きます。
そしてそのメソッド内でモックサービスが呼ばれ InformationDto のリストが Spring の中で Json に変換されてhttp のレスポンスとして返されます。

package com.weekenditlaboratory.controller;
import java.util.List;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.weekenditlaboratory.entity.dto.InformationDto;
import com.weekenditlaboratory.mockService.MockInformationService;
import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@RestController
@RequestMapping("api/informations")
@CrossOrigin
public class InformationRestController {
    private final MockInformationService mockInformationService;
    @GetMapping
    public List<InformationDto> getInformations(){
        return mockInformationService.searchAll();
    }
}

ここまで来たら Spring を起動して Angular とつないでみます。
下記のログイン画面の下、お知らせが今日のAPIを使っている場所です。
とりいそぎ無事繋がりました。

f:id:tetsufuru:20190317142922p:plain しばらくは Spring側 はモックサービスのみを作り Angular の製造がある程度落ち着いてから、 DBを使った本物のサービスに変えていきたいと思っています。

今日の感想

今日は Spring の記事を書きました。何度も繰り返した手順ですが、こうやってブログに書くとまた新鮮に思えます。
Angular 以外のところに時間をかけてしまいましたが、次回こそは Angular で http 通信をおこなうところを書きたいと思います。
では、お疲れ様でした。

今夜は社内AWSもくもく会 - EC2その1 キーペアとセキュリティグループ

こんにちはふるてつです。
今回も社内AWSもくもく会の内容です。EC2の利用その1になります。
今回のテーマはキーペア(公開鍵・秘密鍵)の作成と、
セキュリティグループの作成です。
わたしの超苦手なところですね~

キーペア(公開鍵・秘密鍵)作成

EC2のインスタンスを作る前に、まずはキーペアを作ります。
まずはEC2のダッシュボードのメニューから「キーペア」をクリックします。
下の画面が表示されます。
f:id:tetsufuru:20190313202236p:plain

そこで「キーペアの作成」ボタンをクリックします。
f:id:tetsufuru:20190313202619p:plain

作成完了と同時にpem形式のファイルをダウンロードします。
このタイミングでしかキーペアのファイルはダウンロードできないので、 無くさないよう気をつけて管理してください。
f:id:tetsufuru:20190313202758p:plain うーん、なんだかあっけなく作れました。

セキュリティグループの作成

次はセキュリティグループ。
同じくEC2のダッシュボードメニューから「セキュリティグループ」をクリックすると下記の画面が表示されます。
そこで「セキュリティグループの作成」ボタンをクリックする。
f:id:tetsufuru:20190313203748p:plain

下記の画面が表示されるので以下のように入力します。名前と説明は良い感じで書くだけです。
VPCは以前作ったものを選び、「作成」ボタンをクリックする。
f:id:tetsufuru:20190313204057p:plain

セキュリティグループが追加されました。
その後はルールの設定を行います。
インバウンドのタブを開いてSSHの許可を追加します。
f:id:tetsufuru:20190313204342p:plain

これでSSHが通るようになったはずですねぇ。
しかしまだ肝心の EC2 を作っていませんので、いまは試せません。
次回こそは EC2 のインスタンスを作りたいと思います。

感想

今日勉強した内容はもう少し先まであったのですが、キリが悪くてここでいったん区切りました。
EC2 の続きはまた今度書きたいと思います。
まだまだ本の半分も行ってません。先は長いかも。
ではでは

Angular7 + Bootstrap4でWebアプリを作ろう - サービス追加 その1

こんにちはふるてつです。
3月から後輩と二人で社内 Angular もくもく会もはじめました。
これからは AWS と同様に Angular についても、もくもく勉強した内容を書いていきたいと思います。
基本的にはこれまで作ってきたアプリの続きになりますが、作業時間が限られるので若干内容が少なくなるかとは思います。
今回は復習もかねてチュートリアルを参考にサービスを追加しました。

サービス追加

私が個人的に作っているアプリケーションは、下記のようにログイン画面の下にお知らせを表示したいと思っています。
f:id:tetsufuru:20190309193139p:plain

これまではとりあえず Component 内で直接データを作って表示していましたが、今回から Service を追加して Service からデータを取得するように書き換えます。

わたしの環境は app の下に service/information フォルダを作っているので、そこに information(お知らせ)サービスをつくります。
CLIコマンドは下記です。

ng generate service service/information/information

app/service/information 配下にファイルが2つできました。

information.service.spec.ts
information.service.ys

VSCodeでみると下記のようになります。
最近「Material Icon Theme」というプラグインVSCodeに入れました。
画面左側エクスプローラーのフォルダやファイルアイコンが良い感じになっているでしょう。

f:id:tetsufuru:20190309192707p:plain

その他、モック追加

Angularのチュートリアルを見るとヒーローサービスを作るときにモックヒーローを作ってますね。https://angular.jp/tutorial/toh-pt4

同じように インフォメーションのモック mockInformation を作ってみます。

ng generate class mock/mockInformation

固定値を返すだけなので "class" を作成します。

mock-information.spec.ts
mock-information.ts

これは固定値を返すだけなのでテスト不要。
そのため mock-information.spec.ts はいったん削除しました。
mock-information.ts の中身はこのような内容です。モックなので固定値です。

import { Information } from '../entity/domain/information';

export const INFORMATIONS: Information[] = [
  { date: '2019/3/1', information: '運用停止のお知らせ', detail: 'メンテナンスのため月末の0:00~2:00まで運用を停止します。' },
  { date: '2018/2/1', information: '運用停止のお知らせ', detail: 'メンテナンスのため月末の0:00~2:00まで運用を停止します。' },
  { date: '2018/1/1', information: '運用開始', detail: '運用を開始します。' }
];

インフォメーションサービスの書き換え

最初にCLIコマンドで作った informationService の内容を書き換えます。
下のように。
Observable でモックインフォメーションを返すようにします。

import { Injectable } from '@angular/core';
// ↓追加
import { Observable, of } from 'rxjs';
import { Information } from 'src/app/entity/domain/information';
import { INFORMATIONS } from 'src/app/mock/mock-information';
// ↑追加

@Injectable({
  providedIn: 'root'
})
export class InformationService {

  constructor() { }

  // ↓追加
  getInformations(): Observable { 
    return of(INFORMATIONS);
  } 
  // ↑追加

}

ログインコンポーネントの書き換え

ログインのコンポーネントも書き換えます。
コンストラクターで informationService をインジェクトして、初期化時に informationService の #getInformations() メソッドを呼び出します。
これもチュートリアル通りです。


import { Component, OnInit } from '@angular/core';
import { Information } from '../../../entity/domain/information';
// ↓追加
import { InformationService } from '../../../service/information/information.service';
// ↑追加

@Component({
  selector: 'app-if1001-login',
  templateUrl: './if1001-login.component.html',
  styleUrls: ['./if1001-login.component.css']
})
export class If1001LoginComponent implements OnInit {

  // ↓コンストラクタは書き換え(infomationServiceを DI するように)
  constructor(private infomationService: InformationService) { }
  // ↑書き換え

  // ↓追加
  // お知らせ
  informations: Information[];
  // ↑追加

  ngOnInit() {
    // ↓追加
    this.getInformations();
    // ↑追加
  }

  // ↓追加
  getInformations(): void {
    this.infomationService.getInformations().subscribe(Informations => this.informations = Informations);
  }
  // ↑追加
}

これでコンポーネントにサービスを追加できました。

今日の感想

今日は Angular のサービス追加について書きました。
ほぼチュートリアルをまねただけに終わってしまいましたが、しばらくはなれていたので思い出すのにはちょうどよかったと思います。
次回はモックでなく、HTTPで実際に通信してデータを取得するようにサービスを変える予定です。

では、お疲れ様でした。

今夜は社内AWSもくもく会 - CloudFormer(ベータ版)の後日談、初の課金

こんにちはふるてつです。
今回も社内AWSもくもく会の内容です。

前回 CloudFormer をご紹介しましたが、その後 CloudFormer が元でさっそく課金されました。
$4ほどなので大して気にしていませんが、びっくりしました。
まだ12か月の無料期間のはずなので注意して使えば大丈夫と思っていたのですが。
今日はそのお話です。

その1 請求のアラートメールが届く

週末にAWSから請求のアラートメールが届きました。
こんな感じのメールが...
f:id:tetsufuru:20190306200616p:plain

その2 AWSで請求額確認!

AWSにログインして請求額を見る。
あら~$4くらいかかっとる。もっとかな
f:id:tetsufuru:20190306200936p:plain

EC2のインスタンスを確認! EC2がたしかに上がっとる。
だけど、でも作った覚えがないんだけど…
f:id:tetsufuru:20190306201643p:plain

その3 ああ思い出した。 CloudFormer だ。

思い出しましたよ。 CloudFormer を動かそうとしたときに CloudFormation でEC2インスタンスを作ったのでした。
すっかり忘れてました。うーむ、無料枠(micro)ではない small でEC2が作られていました。

その4 CloudFormationごと削除!

というわけで、スタックごと削除しました。
f:id:tetsufuru:20190306202750p:plain

感想

今日は思わぬ出費をしてしまったお話になってしまいました。
そもそも CloudFormer を試した後にすぐスタックを消せばよかったですねぇ。
自分が設定したアラートメールが見れたことだけは良かったですが…

今日は小ネタでした。ではでは