そごうソフトウェア研究所

SOA、開発プロセス、ITアーキテクチャなどについて書いています。Twitterやってます@rsogo

Amazon SESを使ってみた

AWSのアカウントはもっている前提で進めます。

メールアドレスの認証

docs.aws.amazon.com

初期の状態。「Verify a New Email Address」をクリックする。 f:id:begirama:20150929144145p:plain

eメールアドレスを追加します。 f:id:begirama:20150929144153p:plain

追加したアドレスに、次のようなタイトルのメールが来ます。 * Amazon SES Address Verification Request in region US West (Oregon)

メール中のリンクをクリックすることで、メールアドレスの検証が完了しました。 f:id:begirama:20150929144115p:plain

追加したアドレスのStatusがVerifiedに変わって居ます。 f:id:begirama:20150929144219p:plain

このEmailの検証依頼を、APIから行うこともできるので、利用者に送信メールアドレスを登録させて、自前のサービスに組み込むこともできそうです。 VerifyEmailIdentity - Amazon Simple Email Service

Consoleからのメールの送信

使用する送信元を選択して、Send a Test Emailを選択します。 f:id:begirama:20150929144242p:plain

この状態ではSandboxなので、認証済みの送信先にしか遅れません。ここでは送信元と同じアドレスにします。 f:id:begirama:20150929144254p:plain

このようなメールを受信しました。amazonses経由と表示されています。DKIMの設定を行うことで、自ドメインから遅れるようなので後から試します。 f:id:begirama:20150929144058p:plain

コンソール側で見ると送信済み1件になってますね! f:id:begirama:20150929144305p:plain

Amazon SES APIを使用したメール送信

次はAPIを使ってメールの送信を行ってみたいと思います。

docs.aws.amazon.com

2015年夏のAndroidのツール関連、個人的に気になるポイント

Android Mの名前はマカロンとか、M&Mとか噂になりましたけど、Marshmallowになりましたね。

Android Studioはバージョン1.3が安定版としてリリースされました。

Get your hands on Android Studio 1.3 | Android Developers Blog

Data Binding

これまではサードパーティのライブラリを使用していましたが、公式でサポートされました。 Data Bindingを使うことで、画面と、エンティティの間をひたすら値をコピーするしょうもない作業をする必要がなくなります。

Data Binding Guide | Android Developers

NDK

お試してきな感じで、Android Studio 1.3でサポートされているようです。 丁度、NDKを使用するプロジェクトが始まっているのですが、Qiitaとかで苦労されている人が多そうだったので、Android Studioでの開発は見送りました。

参考

Android Developers Blog 公式発表もここから発信されることが多いみたいです。

Android Developers マニュアル、サンプル、ガイドライン

Android Tools Project Site

Mule ESB 3.7 GETのQuery Parameterを解析してログに出すサンプル

'http://localhost:8082/4apppot/output_queries?name1=test1&name2=test2' こういうURLでアクセスしたときに、Query Parameterを解析するサンプルです。

"#[message.inboundProperties.'http.query.params'.name1]"というキーを指定して取得することもできますが、動的にQueryを解析したい場合には、固定のキーを書くことができないこともあると思います。

Muleアプリのサンプル

gist.github.com

実行時のログ

'http://localhost:8082/4apppot/output_queries?name1=test1&name2=test2'にアクセスしたときに、次のログが出力されました。1行が長くて見にくいので、大事なところだけ編集しています。

About to echo ParameterMap{[name1=[test1], name2=[test2]]}
payload(1): name2=test2
payload(1).key: name2
payload(1).value: test2
payload(2): name1=test1
payload(2).key: name1
payload(2).value: test1

サンプル解説

foreachでループ

Queryの数分ループします。 '#[counter]'で、ループの回数を取れます。0じゃ無くて、1からスタートするので注意!

entrySet()

このサンプルのポイントは、foreachのcollectionに指定している"#[message.inboundProperties.'http.query.params'.entrySet()]"

25行目で、#[message.inboundProperties.'http.query.params']の値をログに出していますが、その時の値は ParameterMap{[name1=[test1], name2=[test2]]}。つまりMapです。entrySet()を使うことで、payload変数にはKey、Valueのセットが入ります。

後はpayload.keyでQueryのKeyへ、payload.valueでQueryのValueへアクセスできます。

Mule ESB 3.7のエラーハンドリング

Muleではフローの実行中にエラーが発生したときのエラーハンドリングの仕組みを持っています。

いくつかの例外のタイプが用意されています。これらの例外ハンドリングの定義を含んだ親Flowを実行中に発生した例外が対象です。

この中で実案件では、Choice exceptionの理解は必須でかなと思います。 発生したエラーの内容に合わせて、実装するハンドリングを切り替えます。 実際のエラーハンドリングはCatch exception strategyや、Rollback exception strategyで書いていく。

構造を単純に書くとこんな感じ。

<flow>
    <リクエストの受取/>
    <メッセージ変換など/>
    <連携先の呼び出し/>
    <応答メッセージの編集/>
    <choice-exception-strategy>
        <例外Xが起こったときのハンドリング/>
        <例外Yが起こったときのハンドリング/>
    </choice-exception-strategy>
</flow>

実際のサンプルです。

Mule エラーハンドリング・サンプル

例えば、上の定義だと、データベースの接続ができなかった場合は次のエラーが発生しますが、その時、「500 Internal Server Error」をクライアントに返します。

org.mule.module.db.internal.domain.connection.ConnectionCreationException: java.sql.SQLException: Cannot get connection for URL

Select文のWhere句に使用する値をQuery Parameterから取得しています。そこに不正な文字列が使用された場合などにjava.sql.SQLSyntaxErrorExceptionが発生しますが、「400 Bad Request」をクライアントに返します。

これでよく分からないエラーメッセージが返ってくるよりも ぐっと、使い易いWebサービスになりました。

参照情報

マニュアル

Error Handling - Current Mule Documentation

公式サンプル

anypoint-examples/implementing-a-choice-exception-strategy at 3.7 · mulesoft/anypoint-examples · GitHub

JenkinsからWildFlyへのリモートデプロイ(pom.xmlの更新)

前回は、Jenkinsサーバーが乗っているDockerコンテナから、WildFlyが動作しているアプリケーションサーバー用Dockerコンテナへのコンテナ間接続をやりました。 begirama.hatenablog.com

JenkinsからWildFlyへのリモートデプロイはWildFly Maven Pluginというのがあって、MavenからWildFlyへのデプロイ、アンデプロイ、インスタンスの起動停止が行えるようです。

WildFly Maven Plugin - Plugin Documentation

deployに関する詳細なリファレンスは下記。 WildFly Maven Plugin - wildfly:deploy

公式サイトではないですが、リモートサーバーへデプロイする際のpom.xmlの例はこちら。 Configuring Maven WildFly plugin

実際のpom.xmlのデプロイ部分はこんな感じ。

<plugin>
  <groupId>org.wildfly.plugins</groupId>
  <artifactId>wildfly-maven-plugin</artifactId>
  <version>1.1.0.Alpha1</version>
  <executions>
    <execution>
        <id>deploy</id>
        <phase>install</phase>
        <goals>
            <goal>deploy</goal>
        </goals>
        <configuration>
            <hostname>apppot_runtime1.7</hostname>
            <port>9990</port>
            <name>apppot-1.7-ci-jenkins.war</name>
            <username>{username}</username>
            <password>{password}</password>
            <filename>apppot-1.7-ci-jenkins.war</filename>
        </configuration>
    </execution>
  </executions>
</plugin>

deployタスクのconfigurationとして、次を指定しています。

  • hostname: Docker Linkした結果、hostsに定義されたホスト名を指定します。apppot_runtime1.7
  • port: WildFlyの管理ポートを指定。アプリケーションサーバーコンテナで、管理ポートをexposeしています
  • name: デプロイする名前。warの拡張子を付けてないとだめ。付けてない場合、デプロイタスク自体は成功するけど、WildFly側でいろいろ認識されていなくて動かなかった。特にエラーもでないから調査に時間かかった。
  • username: WildFlyにログインするためのアカウント
  • password: WildFlyにログインするためのパスワード
  • filename: デプロイするwarファイルを指定しています

すごくはまったのは、[ERROR] JBREM000200: Remote connection failed: javax.security.sasl.SaslException: Authentication failed: the server presented no authentication mechanismsのエラー。 いろなサイトを参考にして、nameだけ指定して、usernameは使っていませんでした。この時に、上のエラーが発生していました。逆にusernameのみを指定しても同じエラーが発生しました。結局、usernameとnameの両方を指定することで、解消しました。参考にしたサイトの人たちはなんで成功していたんだろう・・・。 認証で、こけると何でもこのエラーになるみたいです。

2015/08/21追記

WildFlyの古いバージョンだと、ネイティブ用のポートを使ってデプロイしていて、それだとusernameが不要のようです。 最新のWildFlyだと管理ポートのプロトコルはHTTPで、その場合、usernameが必要なようです。 それで古い記事を参考にしていると駄目だったんだな。

JenkinsからWildFlyへのリモートデプロイ(DockerコンテナのLink)

自社製品のAppPotの開発、運用環境は次のような構成になっています。

  1. 自社クラウド本番環境:クラウド運用しているバージョンのみ
  2. 自社クラウドテスト環境:クラウド運用しているバージョンのみ
  3. 自社クラウド開発環境:クラウド運用しているバージョンのみ
  4. 自社CI環境:製品バージョンごとに存在
  5. 受託プロジェクト開発開発:プロジェクトごとに存在

バージョンごとに環境を立てるのは大変なので、自社CI環境と受託プロジェクト開発環境はDockerコンテナ上で運用しています。常にすごい負荷がかかっているわけではないので、小規模なさくらインターネットのサーバーで3〜5つくらいのコンテナが動作しています。

このうち、CI環境の一部だけはJenkinsを使ったビルド、デプロイ、テストのプロセスが自動で回っています。この一部というのは、Jenkinsと同居しているアプリケーションサーバーのみ。 なぜかというと、コンテナ間の連携をちゃんとやる時間が無かったから・・。

というわけで、コンテナ間の連携、JenkinsからのWildFlyへのリモートデプロイをできるようにするのが、本エントリの目標です。

Dockerコンテナ間連携

まだしばらく同一サーバー内でのコンテナ間連携で行けそうなので、--linkを使います。

https://docs.docker.com/docker/userguide/dockerlinks/#communication-across-links

今回の場合はJenkinsサーバーコンテナから、アプリケーションサーバーコンテナへリンクします。

アプリケーションサーバーの起動

--nameオプションで、apppot_runtime1.7という名前でコンテナを起動させています。

docker run -it --expose 9181 -p 9181:8080 -p 9991:9990 --name apppot_runtime1.7 rsogo/wildfly8:v1 /bin/bash

Jenkinsサーバーコンテナの起動

--linkオプションで、apppot_runtime1.7という名前のコンテナをリンクさせています。

docker run -it --expose 8081 -p 8081:8080 --name jenkins --link apppot_runtime1.7:apppot_runtime1.7 rsogo/jenkins:v5 /bin/bash

コンテナIDでもリンクで指定することはできますが、コンテナIDはコンテナの起動の度に変わります。 上のような起動スクリプトはシェルとして用意しておきたいと思いますので、コンテナIDより、コンテナ名を定義しておいた方が便利です。

Jenkinsサーバーコンテナでのhostsファイル、環境変数の確認

apppot_runtime1.7がhostsファイルに追加されていることが分かります。

# cat /etc/hosts
172.17.0.71 cfc8c054ccf8
127.0.0.1   localhost
172.17.0.69 apppot_runtime1.7 9b5ee14ff469

envコマンドを実行した結果、環境変数アプリケーションサーバーコンテナが公開しているポートごとに次のような環境変数が定義されています。

APPPOT_RUNTIME1.7_PORT_8080_TCP_ADDR=172.17.0.69
APPPOT_RUNTIME1.7_PORT=tcp://172.17.0.69:22
APPPOT_RUNTIME1.7_PORT_22_TCP_PORT=22
APPPOT_RUNTIME1.7_PORT_22_TCP_ADDR=172.17.0.69
APPPOT_RUNTIME1.7_PORT_22_TCP=tcp://172.17.0.69:22
APPPOT_RUNTIME1.7_PORT_9181_TCP_PORT=9181
APPPOT_RUNTIME1.7_PORT_22_TCP_PROTO=tcp
APPPOT_RUNTIME1.7_PORT_8080_TCP_PORT=8080
APPPOT_RUNTIME1.7_PORT_9990_TCP=tcp://172.17.0.69:9990
APPPOT_RUNTIME1.7_PORT_9080_TCP_PORT=9080
APPPOT_RUNTIME1.7_PORT_9181_TCP_PROTO=tcp
APPPOT_RUNTIME1.7_PORT_8080_TCP=tcp://172.17.0.69:8080
APPPOT_RUNTIME1.7_PORT_8080_TCP_PROTO=tcp
APPPOT_RUNTIME1.7_PORT_9080_TCP_PROTO=tcp
APPPOT_RUNTIME1.7_PORT_9990_TCP_ADDR=172.17.0.69
APPPOT_RUNTIME1.7_PORT_9080_TCP_ADDR=172.17.0.69

この状態で、Jenkinsサーバーコンテナから以下のコマンドを実行することで、JenkinsサーバーからWildFlyのポートにアクセスできることを確認できます。

# curl http://apppot_runtime1.7:8080
<!--
  ~ JBoss, Home of Professional Open Source.
  ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
略

次は、JenkinsサーバーからWildFlyへリモートデプロイします。

Mule ESBまとめ

本ブログ内のMule ESBについてのまとめです。

Mule ESBはオープンソースのESB製品です。 オープンソースのCommunity Editionでも、基本的な機能やプロトコルに対応しています。

コネクタの一覧は下記のサイトから調べることができます。 Anypoint Exchange

パッケージ製品用のアダプターを使いたい、GUIで開発したいという場合にはEnterprise Editionが用意されています。

起動

begirama.hatenablog.com

Groovyスクリプト

begirama.hatenablog.com

Database Connector

begirama.hatenablog.com

begirama.hatenablog.com

begirama.hatenablog.com

フロー定義

begirama.hatenablog.com

begirama.hatenablog.com

サンプル

begirama.hatenablog.com

古い記事

有償版についている、Anypoint Studioを使ったエントリ。

begirama.hatenablog.com