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

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

AWS DataPipeline TaskRunnerのJava8での実行エラー

Data Pipelineを検証しています。

Data Pipelineのマニュアルはこちら。 docs.aws.amazon.com

やりたいことはデータ分析用のバッチを夜間に実行したい。

実行するためのEC2インスタンスを指定します。指定の仕方は次の2パターン。

  1. RunOnオプションを指定して、インスタンスを起動させて実行する
  2. WorkGroupオプションを指定して、既存のインスタンス上で実行する

既存インスタンスで実行するためには、TaskRunnerを実行する必要があります。

で、Java8で実行すると下記の問題があります。

$ java -jar TaskRunner-1.0.jar  --workerGroup=ec02_dev --region=ap-northeast-1 --config=./credencials.json 
log4j:WARN No appenders could be found for logger (amazonaws.datapipeline.objects.PluginModule).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Starting log pusher...
Not enabling task runner logging as given log uri null is invalid
Initializing drivers...
Starting task runner...
private.com.amazonaws.services.s3.model.AmazonS3Exception: AWS authentication requires a valid Date or x-amz-date header (Service: Amazon S3; Status Code: 403; Error Code: AccessDenied; Request ID: XXXXXXX), S3 Extended Request ID: XXXXXXX
    at private.com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1182)
    at private.com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:770)
    at private.com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:489)
    at private.com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:310)
    at private.com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:3604)
    at private.com.amazonaws.services.s3.AmazonS3Client.createBucket(AmazonS3Client.java:792)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:497)
    at private.com.amazonaws.services.datapipeline.retrier.RetryProxy.invokeInternal(RetryProxy.java:36)
    at private.com.amazonaws.services.datapipeline.retrier.RetryProxy.invoke(RetryProxy.java:48)
    at com.sun.proxy.$Proxy24.createBucket(Unknown Source)
    at amazonaws.datapipeline.logpusher.Uploader.ensureBucketExists(Uploader.java:86)
    at amazonaws.datapipeline.logpusher.Uploader.compressAndUploadToS3(Uploader.java:49)
    at amazonaws.datapipeline.logpusher.LogPusher.uploadPart(LogPusher.java:404)
    at amazonaws.datapipeline.logpusher.LogPusher.pushFile(LogPusher.java:397)
    at amazonaws.datapipeline.logpusher.LogPusher.pushItem(LogPusher.java:226)
    at amazonaws.datapipeline.logpusher.LogPusher.finishAndRemoveLogItem(LogPusher.java:108)
    at amazonaws.datapipeline.taskrunner.TaskPoller.executeRemoteRunner(TaskPoller.java:144)
    at amazonaws.datapipeline.taskrunner.TaskPoller.executeTask(TaskPoller.java:105)
    at amazonaws.datapipeline.taskrunner.TaskPoller$1.run(TaskPoller.java:81)
    at private.com.amazonaws.services.datapipeline.poller.PollWorker.executeWork(PollWorker.java:76)
    at private.com.amazonaws.services.datapipeline.poller.PollWorker.run(PollWorker.java:53)
    at java.lang.Thread.run(Thread.java:745)

公式のフォーラムでも話題になっていますが、まだ正式には解決していなさそう。 https://forums.aws.amazon.com/thread.jspa?messageID=688746

Jodaの入れ替え

TaskRunner-1.0.jarを解凍して、joda-time-2.9.1.jarのクラスファイルと入れ替えます。 ここにあります。

TaskRunner-1.0/org/joda/time

入れ替えたら、再アーカイブ。実行可能なjarにするために、マニフェストファイルを指定しています。

$ jar cfm ../TaskRunner-1.0.sogo.jar META-INF/MANIFEST.MF ./*

TaskRunnerの実行

$ java -jar TaskRunner-1.0.sogo.jar  --workerGroup=ec02_dev --region=ap-northeast-1 --config=./credencials.json

これで作ったjarはサポートされる訳は無いと思うので、公式な解決を待ちたいところです。 古いJavaを入れて、TaskRunnerは古いJavaで動かしてもいいんだけど、TaskRunnerだけのために余計なもの入れたくなかったんだよなー。

インスタントWebミーティングツール「speak」試してみたよ

Sqwiggleの人から最近、Speakっていうサービスをやってるから試してみてねという案内が来ました。

f:id:begirama:20151127153607p:plain

使い方

  1. https://go.speak.io にアクセスする
  2. ユニークなIDを含むURLが生成されるので、参加者とシェアする

以上。

f:id:begirama:20151127152420p:plain

主な機能

  • 音声チャット
  • ビデオチャット
  • テキストチャット
  • 画面共有
  • 録音(有償プランに要アップグレード)

f:id:begirama:20151127153622p:plain

画面共有には専用のGoogle Extensionが必要だった。入れた後、ブラウザの再起動が必要だったので、この機能が必要な場合には大事なミーティングの前に入れときたい。

特徴

とにかく簡単。 ブラウザで使えば、専用のアプリを立ち上げる必要もないし、ログインが不要なので、誰でもすぐに使える。

テキストチャットは消えるし、ファイルをアップしたりもできないし、がっつりミーティングというのには向かないけど、 社外の人とちょっと話せる?みたいな使い方にはいいかも。

Jekyllを使って極力デザインに手をかけずに製品サイトを作りたい

自分が製品マネージャをやっているAppPotという製品のWebサイトを再整備する取り組みをやっています。

  • 今のWebサイト

AppPot〜企業向けスマートデバイスアプリ開発のためのプラットフォーム

このサイトとは別にGithub上にマークダウンで記載した製品マニュアルを公開しています。今回の再整備で、Github上のマニュアルを静的HTMLに変換して、製品サイトと一緒に公開したいと思っています。

今回は、Jekyllを使って、且つ、なるべく既存のThemeを使ってやりたいと思っています。

今日は技術検証なので、このテーマを使て試してみたいと思います。

swcool/landing-page-theme · GitHub f:id:begirama:20151126162004p:plain

  • jekyllのインストール
$ gem install jekyll
$ git clone https://github.com/swcool/landing-page-theme.git
  • serveオプションでローカルで試せる
$ jekyll serve
Configuration file: /Users/rsogo/work/jekyllsample/landing-page-theme/_config.yml
            Source: /Users/rsogo/work/jekyllsample/landing-page-theme
       Destination: /Users/rsogo/work/jekyllsample/landing-page-theme/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
                    done in 0.206 seconds.
 Auto-regeneration: enabled for '/Users/rsogo/work/jekyllsample/landing-page-theme'
Configuration file: /Users/rsogo/work/jekyllsample/landing-page-theme/_config.yml
    Server address: http://127.0.0.1:4000/
  Server running... press ctrl-c to stop.

4000番ポートにアクセスするとこんな感じ。ここまでは簡単。

f:id:begirama:20151126162004p:plain

ここからテーマをカスタマイズしていきます。 このテーマは_postsの内容をServicesとして表示してくれるみたいです。 この辺はテーマによって違うようなので、テーマのお作法に沿ってやる必要があります。

以下の様な感じでファイルを作成すると、 _posts/2014-09-20-services-0.markdown

---
layout: default
img: only_use_detail01.jpg
category: Services
title: 開発コストが2分の1になります
description: |
---
AppPotを使えばサーバーの開発が不要です。そのため、セットアップ後、すぐにフロントエンドの開発を行うことができ、開発期間の短縮と、開発コストの削減に効果があります。

こんな感じに表示してくれます。 f:id:begirama:20151126170414p:plain

  • _config.ymlの基本の設定を変更します。 titile、twitterアカウント、githubの情報を更新して、LinkedInの情報を消しました。 変更した場合はjekyll servを再起動しないと変更されないです。
# ----------------------- #
#      Main Configs       #
# ----------------------- #

url: http://yoursite.com
title: AppPot
email: your-email@domain.com
author: Your Name
description: > # "Write an awesome description for your new site here.
  You can edit this line in _config.yml. It will appear in your document
  head meta (for Google search results) and in your feed.xml site
  description.
copyright: 'Copyright © 2015 Your Name. All Rights Reserved.'
credits: 'Credits: Landing Page is a free to use, open source Bootstrap theme created by <a href="http://startbootstrap.com/">Start Bootstrap</a>.'

# ----------------------- #
#    Jekyll & Plugins     #
# ----------------------- #

# Build settings
markdown: kramdown
permalink: pretty

# ----------------------- #
#   3rd Party Settings    #
# ----------------------- #

social:
  - title: twitter
    url: https://twitter.com/app_pot
  - title: github
    url: https://github.com/NCDCHub/apppot-docs
    

後、一番上の画像を元の製品サイトのものに変えました。 ここまで変えるとレイアウトの崩れなどはありますが、それっぽくなりました。

f:id:begirama:20151126172315p:plain

このテーマを実際使うわけではないので、微調整はやりませんが、テーマに合わせて画像などを用意すれば良さそうです。

実際やってみて感じたのは、ブログ・サイト用のテーマはたくさん有るのですが、それ以外の場合、自分の求めているサイトに「デザイン」「サイト構成」の点で近いものを探すのがポイントかなと思います。

いいところ

  • デザイナーさんに画像などを用意してもらう必要がありますが、だいたいイメージにあったサイトをすごい速さで作ることができる
  • コンテンツをマークダウンで書けるので楽
  • デザインを変えたかったらテーマを変えればいい。コンテンツと、テーマが強制的に明確に分離されているので、やりたいサイトにフィットしたテーマがあれば楽

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