2015年7月29日水曜日

Java の Mockito を使ってみた

概要

mockito はJUnit等のユニットテストで使用する Mock オブジェクトを作成するためのライブラリです
例えば外部サービスと接続するアプリでローカルでテストする場合は接続しないでテストしたかったりするケースなんかに使えます

環境

  • Mac OX X 10.10.4
  • Eclipse Luna 4.4
  • Java 1.8.0_31
  • Maven 3.2.1
  • Mockito 1.10.19

使ってみる

サンプルプロジェクトの作成

EclipseでMavenプロジェクトを作成します
maven-archetype-quickstartを ArtifactId に選択してプロジェクトを作成しました
本記事中で扱うパッケージは「com.sample.test」としています

Mockito を使ったテストを書いてみる

maven-archetype-quickstartでプロジェクトを作成すれば「src/main/java/com.sample.test.AppTest.java」があると思うのでそれを使います

pom.xml へライブラリ追加

<dependency>
  <groupId>org.mockito</groupId>
  <artifactId>mockito-core</artifactId>
  <version>1.10.19</version>
</dependency>

上記でOKです
使えるようになったら早速試してみます

verify

verifyは作成した Mock オブジェクトが正確に何回動作したかをチェックするための機能です
とりあえず以下がverifyを使ったサンプルコードです

public void testVerify() {
  List mockedList = mock(List.class);
  mockedList.add("one");
  mockedList.clear();
  verify(mockedList).add("one");
  verify(mockedList).clear();
}

まずはじめに冒頭でimport static org.mockito.Mockito.*;で書いておくといいと思います
Mockitoクラス配下の static なメソッドを使う機会が
多いためです

mockメソッドの引数に Mock オブジェクトとして作成したクラスのオブジェクトを渡します
サンプルのList.classjava.util.Listの List クラスです
作成した Mock オブジェクトは普通にそのクラスに存在しているメソッドをコールすることができます
作成した Mock オブジェクトに対してadd, clearを1回ずつコールします

そしてその後でverifyを使って Mock オブジェクトが正しく動作したかを評価します
verifyの引数に評価したい Mock オブジェクトを指定して、続けて評価したいメソッドをコールします

verify(mockedList).add("one");

こうすることで何が起きているかいうと

mockedList の add メソッドが引数 “one” で1回ちゃんとコールされているか

を評価することができます
なので、例えばverifyする前のadd

mockedList.add("two");

こんな感じでコールし直すように変更するとverifyが失敗することが確認できると思います

verifyは引数をもう一つ持つことができて評価する回数を指定することができます

verify(mockedList, times(2)).add("one");

Mock クラスのtimesというメソッドを使って評価された回数を指定できます

when

whenはある Mock オブジェクトのメソッドがコールされたときにこういう値を返しますという振る舞いを設定することができる機能です
とりあえず以下がwhenを使ったサンプルコードです

public void testWhen() {
  App app = mock(App.class);
  when(app.getAppname()).thenReturn("myapp");
  System.out.println(app.getAppname());
}

Mock オブジェクトを作成してwhenメソッドを呼び出します
引数に作成した Mock オブジェクトのあるメソッドを指定します
指定するメソッドは必ず返り値を保つ必要があるためvoidのメソッドでwhenを利用することはできません
whenで返り値を設定した場合、Setter などで値を上書きしたと思ってもwhenで指定した値が取得されます

when(app.getAppname()).thenReturn("myapp");
app.setAppname("hoge");
System.out.println(app.getAppname());

-> myapp が出力される

要するにあるメソッドの戻り値を意図的に設定することができます
他にも Exception を投げたり引数を元に複雑な返り値を設定できるthenAnswerがあります
※参考 : http://docs.mockito.googlecode.com/hg/org/mockito/stubbing/OngoingStubbing.html

最後に

Java の Mock 系のライブラリは他にもいろいろあります (JMock, EasyMock etc…)
他のライブラリも使って書き方や機能を比較してみるとおもしろいかも
今回

2015年7月28日火曜日

ニフティクラウド RDB で utf8_mb4 が使えるか試してみた

概要

ここの記事を参考にニフティクラウドRDBでも utf8_mb4 が使えるか試してみました
ちなみに utf8_mb4 は 4 バイト長の utf8 文字をサポートする文字コードで emoticon (絵文字) や 第4水準漢字が使えるようになるみたいです

環境

  • Mac OS X 10.10.4
  • MySQL Client 14.14 Distrib 5.6.25
  • MySQL Server 5.6.22 (ニフティクラウド RDB)

RDBの作成

コントロールパネルから簡単に行えるので詳細は割愛します
流れだけ紹介します

  1. コントロールパネルにログインしDBサーバの一覧から「DBサーバー新規作成」
  2. 入力する内容はとりあえず適当でOK (後で utf8_mb4 を有効にした DB パラメータグループに変更します)

今回はテストなのでスペックは mini として冗長化やディスク拡張はしない最小限のスペックで作成しました
また、DB名やユーザ名も適当に指定しました

30分ほどで作成できるので待ちます

utf8_mb4 用の DB パラメータグループの作成

DBサーバーが作成できたら DB パラメータグループを作成します
今回は utf8_mb4 を設定した専用のパラメータグループを作成します
DBパラメータの一覧から「DBパラメーターグループの新規作成」として作成します
名前は「utf8mb4」とでもしておきましょう
作成できたらパラメータを変更していきます

作成した DB パラメータグループをチェックしてプルダウンから「DB パラメータグループの編集」を選択します
ここで以下4パターンのパラメータを変更します

character 系パラメータの変更

検索ボックスに「character」と入力してください
ここで表示された以下5つの項目を utf8mb4 に変更します

  • character_set_client
  • character_set_connection
  • character_set_database
  • character_set_results
  • character_set_server

変更はプルダウンの一覧から選択してください

set_character.png

collation 系パラメータの変更

次に検索ボックスに「collation」と入力してください
ここで表示された以下2つの項目を utf8mb_general_ci に変更します

  • collation_connection
  • collation_server

変更はプルダウンの一覧から選択してください

set_collation.png

skip-character-set-client-handshake パラメータの変更

3つ目は検索ボックスに「skip-character-set-handshake」と入力してください
このパラメータの値を 1 に変更します

set_handshake.png

init_connect パラメータの変更

最後に検索ボックスに「init_connect」と入力してください
このパラメータは文字列を直接入力する必要があるので「SET NAMES utf8mb4;」と入力してください

set_init_connect.png

上記の作業は一度に変更してもOKですし、1つずつ保存してから実施してもOKです
全項目が設定できたら DB パラメータグループの設定は終わりです

DB サーバの DB パラメータグループを変更する

DB サーバーの一覧に移動します
作成待ちになった DB サーバーができていれば DB パラメーターグループを変更します
DB サーバーをチェックして「設定変更」をクリックします

DB パラメーターグループを変更できる箇所があるのでプルダウンから作成した DB パラメーターグループを選択して変更を適用します

これで DB サーバーに適用されている DB パラメータグループの変更は完了しました
ただ、まだ MySQL 自体にそのパラメータが適用されていないので一度 DB サーバー自体を再起動します
これも DB サーバーをチェックして「DBサーバー再起動」を選択すればOKです
再起動は数分で完了します

MySQL クライアントで接続して動作確認してみる

今回は Mac で動作確認しています
mysqlコマンドがインストールされていない場合はbrew isntall mysqlでインストールしましょう

では接続してみましょう
接続方法は普通の MySQL と同じです

mysql -u usename -p db_name -h grobal_ip_address

username, db_name, grobal_ip_address は作成された DB サーバーの情報を入力してください
パスワードを入力して接続できればOKです

文字コードの設定を確認してみる

statusコマンドで確認してみましょう

mysql> status
--------------
mysql  Ver 14.14 Distrib 5.6.25, for osx10.10 (x86_64) using  EditLine wrapper

Connection id:          41
Current database:       utf8mb4_test
Current user:           username@xxx.xxx.xxx.xxx
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.6.22 MySQL Community Server (GPL)
Protocol version:       10
Connection:             111.171.222.67 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               3306
Uptime:                 1 hour 31 min 41 sec

Threads: 1  Questions: 135  Slow queries: 0  Opens: 73  Flush tables: 1  Open tables: 65  Queries per second avg: 0.024
--------------

utf8mb4 になっていることが確認できます
では実際に絵文字が登録できるか試してみます

絵文字を登録してみる

まず適当にテーブルを作成しましょう

CREATE TABLE test_utf8mb4 (str VARCHAR(50)) CHARACTER SET utf8mb4;

このテーブルにデータを入れてみます
コマンドは以下の通りです
※絵文字を使用しているため画像になります

insert_emoticon.png

完了したらSELECTしてみましょう

select_emoticon.png

絵文字が登録されていることを確認できました
ちなみに utf8mb4 になっていない MySQL に対してもテストしてみたのですが、以下のように絵文字は登録されないことが確認できました

select_empty_character.png

最後に

ニフティクラウドRDBでも utf8mb4 が動くことを確認できました
サーバ側の設定はコンパネおよびターミナルでできるのですが、動作確認時の絵文字の入力が Mac じゃないとちょっと大変かもしれません
Mac の場合Shift+Cmd+Spaceで絵文字一覧がでるのでそこから選択するだけ絵文字入力できるので楽です

2015年7月27日月曜日

Spring でファイルアップロードを PUT メソッドで処理する方法

概要

Spring で multipart/form-data + MultipartFile を扱う場合は、通常は POST メソッドでなければなりません
どうやら MultipartFile は POST メソッドでないと操作できないようです
実装上そもそも不要なケースが多いですが、PUT メソッドで multipart/form-data を受け取る方法を紹介します

環境

  • Mac OS X 10.10.4
  • Eclipse Luna 4.4.1
  • Spring Framework 4.1.6
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Maven 3.2.1

サンプルプロジェクト作成

過去の記事を参考に作成してください
Spring Framework のバージョンが最新でない場合は pom.xml 「org.springframework-version」のバージョン記載部分を最新のバージョンに変更してください

コーディング

@RequestMapping に PUT で multipart/form-data を受け取る定義を記載する

@RequestMapping(value = "/**", method = {RequestMethod.PUT}, headers = "content-type=multipart/form-data")
@ResponseBody
public void receivePutMulti(@RequestParam(value = "file", required = true) MultipartFile file) {
  ...
}

受け取りたいURLマッピングに上記のようにメソッド名とヘッダーのタイプを指定します
今回はファイルのアップロードを想定しているため MultipartFile を受け取るように指定します
返り値は jsp を返却したい場合は String 型を返り値に指定し@ResponseBodyを削除してください

ちなみにこの状態で以下のように PUT メソッドでファイルのアップロードを実行しようとすると500エラーになります

curl -v -X PUT -H "Content-Type: multipart/form-data" http://localhost:8080/test/put/ -F "file=@pom.xml"
java.lang.IllegalArgumentException: Expected MultipartHttpServletRequest: is a MultipartResolver configured?

このエラーがでないように設定していきます

servlet-context.xml に独自 MultipartResolver を指定する

<beans:bean id="multipartResolver" class="com.sample.test.ExtendedMultipartResolver">
</beans:bean>

Multipart なデータは MultipartResolver というクラスでどう受け取るかのルール付けがされており、このクラスを拡張することで PUT メソッドでも MultipartFile が受信できるようにします

次に指定した独自の MultipartResolver クラスを作成していきます

独自 MultipartResolver クラスの作成

pom.xml に定義を追加する

<!-- FileUpload -->
<dependency>
  <groupId>commons-fileupload</groupId>
  <artifactId>commons-fileupload</artifactId>
  <version>1.3.1</version>
</dependency>

独自の MultipartResolver を作成するのに commons-fileupload が必要になるので pom.xml に追記します
既存の<dependencies>タグ内に追記してください

ExtendedMultipartResolver クラスの作成

今回はcom.sampe.test.ExtendedMultipartResolverとして作成します
とりあえず以下がサンプルになります

package com.sample.test;

import javax.servlet.http.HttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

public class ExtendedMultipartResolver extends CommonsMultipartResolver {

    @Override
    public boolean isMultipart(HttpServletRequest request) {
        if (request != null) {
            String httpMethod = request.getMethod().toLowerCase();
            // test for allowed methods here...
            String contentType = request.getContentType();
            return (contentType != null && contentType.toLowerCase().startsWith("multipart"));
        } else {
            return false;
        }
    }
}

ポイントは@OverrideしているisMultipartメソッドでこの中でHttpServletRequestからアクセスしているメソッド情報を取得して PUT メソッドでもtrueを返却するように実装し直します
サンプルは全メソッドで multipart/form-data を許可する設定になっており特にメソッド名に応じてfalseを返却するような if 分岐は入れていません

動作確認

ここまで実装できたらアプリを再起動してコードを反映しましょう
先ほどの PUT + multipart/form-data の curl のサンプルリクエストを投げてみましょう

すると先ほどのエラーにはならず定義したメソッド内の処理が実行されていることが確認できると思います

最後に

ちょっと調べてみたんですが Spring がデフォルトで実装していないのは RFC 的にそうなっているため(?) みたいな記事があったような気がします
詳細には調べていないので、わかりませんが PUT で multipart/form-data は基本は受け取らないんですかね
そもそもそれは実装が悪いってことになるのか

参考サイト

2015年7月23日木曜日

Spring の @RequestMapping で OPTIONS メソッドを処理する方法

概要

Spring で OPTIONS メソッドのリクエストを受け取る方法を紹介します
普通に@RequestMappingmethod=RequestMethod.OPTIONSを指定するだけだとダメでした

環境

  • Mac OS X 10.10.3
  • Eclipse Luna 4.4.1
  • Spring Framework 4.1.6
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Maven 3.2.1

サンプルプロジェクト作成

過去の記事を参考に作成してください
Spring Framework のバージョンが最新でない場合は pom.xml 「org.springframework-version」のバージョン記載部分を最新のバージョンに変更してください

コーディング

@RequestMappingにOPTIONSメソッドを追加する

これだけだとダメという話をしましたが、これがないと始まらないので定義します

@RequestMapping(value = "/", method = {RequestMethod.GET, RequestMethod.OPTIONS})

既存のメソッドと同じマッピングで受け取る場合は中括弧を使って定義してください
もちろん上記を追加しただけだと、まだリクエストを受け取ることができません

web.xml に定義を追加する

web.xml<servlet>タグに以下を追記します

<servlet>
  <servlet-name>appServlet</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>dispatchOptionsRequest</param-name>
    <param-value>true</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
</servlet>

おそらくweb.xml内に<servlet>タグはすでにあると思います
<servlet-name><servlet-class>がある場合は新規で追加しなくてOKなので過不足分を既存の<servlet>タグ内に追記すればOKです

web.xmlはSTSで作成していれば、src/main/webapp/WEB-INF/web.xmlにあります

動作確認

書き換えが完了したらアプリを再起動してOPTIONSメソッドのリクエストが処理されるか確認してみましょう
自分はいつもcurlコマンドで確認しますが、curl の場合は以下のようにするとOPTIONSメソッドのリクエストが送信できます

curl -v -X OPTIONS http://localhost:8080/test/

これで@RequestMappingアノテーションが付与されたメソッドが実行されればOKです

Tips

MockMVCを使っている場合に有効にする方法

上記の手順を実行すれば実際のアプリ側でOPTIONSメソッドのリクエストを取得することができます
ただ、テストの場合は有効になっていないようで別途有効にする必要があります
MockMVCを使っているのであればテスト用のMockMVCのオブジェクトを生成する際に.dispatchOptions(true)を指定します

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();

これを実施しないとテスト時にOPTIONSメソッドが受け取れませんでした

最後に

OPTIONSメソッドはリソースがサポートしているメソッドの一覧を返却するために用意されたメソッドです
OPTIONSメソッドのリクエストのときにレスポンスボディを返却することは基本ないと思いますが、やりたい場合は今回紹介した方法で実現できると思います

2015年7月22日水曜日

開発合宿してみたいメモ

概要

  • 非日常的な環境で開発をすることで、おそろしく開発効率が上がるのではないか
  • 「仕事」として行く気はないので気軽に行こう
  • 成果のルールは決めない
  • 南国でやりたい

唯一のルール

  • 必ず最後に何をしたのか、していないのか、作ったのかなど「発表」をすること
  • 昼飯と晩飯はみんなで食べましょう

欲望メモ

  • 仕事はしたくない、とにかく自分がやりたいことをやってみよう
  • オフィスでない非日常的な環境で開発することで効率アップ(するかどうか)を体験してみる
  • あれ、オレリモートでも仕事できるじゃん
  • OSS、クローズドは問わない
  • ホテルとかじゃなくて、Airbnbとかでコテージとか借りてやりたい(ホテルでもいいと思うけど)
  • 食事、睡眠以外の時間は基本的にフリーでコーディング、場所も問わない、飯の時間は決めておくし、みんなで一緒に食う
  • フリー時間はコーディングすらしなくてもOK、遊んでもOK
  • コーディングスタイルは自由、ペアでもチームでも個人でもいい
  • メンバーは一応知人を中心に 3 - 5人、多すぎはダメ
  • コーディング中はみんなバラバラだと思うので連絡は Slack とかのチャットを使おうと思う
  • 1泊2日 or 2泊3日
  • あえて土日返上
  • 集合解散は最悪、現地集合 - 解散でもOK
  • 開発環境(ネットワーク、ディスプレイ)は知らん、自分で何とかする
  • 移動とかも知らん
  • 最後の発表はフリーフォーマット、特にテーマはなし
  • たぶん単発、定期的にやる気はないです
  • ぶっちゃけ自分が開発したいだけ

2015年7月16日木曜日

yum で Redis をインストール

概要

yum で Redis の最新版をインストール
バイナリをダウンロードしてインストールする方法はこちら

環境

  • CentOS 6.6 64bit

インストール方法

rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
yum clean all
yum install redis --enablerepo=remi
chkconfig redis on

20150715 時点では3.0.2-1というバージョンがインストールできました

2015年7月15日水曜日

NewRelic にサーバのメトリックを送信してみた

概要

NewRelic で Server のメトリック (CPU, Memory, I/O, Network) を送信する方法を紹介します
過去に紹介したものはアプリ単位で監視する方法を紹介しました
NewRelic ではサーバのメトリック情報だけを送信することもできるのでその方法を紹介します

環境

  • CentOS 6.3 64bit
  • newrelic-sysmond 2.1.0
  • NewRelic 2015/07/14時点

メトリック送信用エージェントのインストール

今回は CentOS のサーバなので yumコマンドでインストール可能です

rpm -Uvh http://yum.newrelic.com/pub/newrelic/el5/x86_64/newrelic-repo-5-3.noarch.rpm
yum install newrelic-sysmond

License Key の設定

License Key は RewRelic の WebUI 上で確認することができます
Account settings に License Key の記載があるのでそれを設定ファイルに記載します

vim /etc/newrelic/nrsysmond.cfg

license_key=xxxxxxxx

エージェントの起動

service newrelic-sysmond start

で起動してしばらくすると NewRelic の Servers に対象のサーバのメトリックが表示されると思います

Tips

上手く監視できなかった場合は、NewRelic とサーバ間の Outgoing の ACL を確認してみましょう
通信するべきIPとポートの情報は以下を参考にしてみたください
wget できなければいけないドメインやIPが記載されています
https://docs.newrelic.com/docs/apm/new-relic-apm/getting-started/networks#availability

動作確認

NewRelic の UI で確認してみましょう
左上のメニュー一覧から「Servers」を選択します
newrelic_choice_servers.png

サーバの一覧が選択されます
newrelic_list_servers.png

メトリックの詳細を見たい場合は対象のサーバをクリックすると見れます
newrelic_detail_metric.png

最後に

前に試した記憶ではnewrelic-sysmondも自動でインストールされて起動されていた記憶があったのですが、今回新規のサーバを追加したらnewrelic-sysmondがインストールされていなかったので別途インストールしてみました
メトリックを見るためだけならNewRelicはめっちゃ簡単です

2015年7月8日水曜日

Java で kill のシグナルを受け取ってみた

概要

Javaで kill の -HUP のシグナルを受け取れるみたいなので検証してみました

環境

Mac OS X 10.10.4
Eclipse Luna 4.4
Java 1.8.0_31

シグナルを受け付けるコードを作成

package test;

import java.util.Scanner;

public class Test {

    @SuppressWarnings("resource")
    public static void main(String[] args) throws InterruptedException {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Run Shutdown Hook.")));
        System.out.println("Please send HUP signal.");
        while (true) {
            System.out.println("looping ...");
            Thread.sleep(5000);
        }
        // 以下のような入力を受け付ける処理でもOK
//      System.out.println("Please input.");
//      Scanner in = new Scanner(System.in);
//      String s = in.nextLine();
//      System.out.println(s);
    }
}

ポイントは1行で

Runtime.getRuntime().addShutdownHook(new Thread(() -> System.out.println("Run Shutdown Hook.")));

になります
上記の場合は HUP を受け取って終了する前にSystem.outを出力しています

動作を確認してみる

Eclipse 上で実行すると Eclipse の子プロセスとして実行されpidがわからないので java コマンドでターミナルから実行します
プロジェクトは普通の Java プロジェクトを想定しています

cd /path/to/project/bin
java test/Test

とすると無限ループがはじまります
この状態でpgrep javaでプロセス番号を調べてその番号を kill してみましょう

kill -HUP [process_number]

でこうすると無限ループが終了してSystem.outの内容が出力されます

$ java test/Test
Please send HUP signal.
looping ...
looping ...
Run Shutdown Hook.

とりあえずこれで Java 側でシグナルを受け取ることができました
addShutdownHookはメソッドもコールすることができるので別のメソッドをコールしてそっちの処理が終了するまでまた処理を続けることも可能です

最後に

これが何に使えるのかなというのを考えると

  • 無限ループに突入してしまった場合にHUP信号を外から送信して次の処理に進める
  • HUPしたタイミングで特定の処理(例えばロギング)を実行しその時の状況を把握する

とかとか
外部からシグナルを受け付けられる便利な機能なのでいろいろ考えられると思います

あと「java シグナル」とかで検索すると出てくる記事にsun.misc.Signalを使う方法が紹介されていますがどうやらsun.misc.Signalは非推奨もしくはなくなる可能性のあるクラスなので使わないほうがいいと思います

http://docs.oracle.com/javase/jp/6/api/java/lang/Runtime.html#addShutdownHook%28java.lang.Thread%29

2015年7月7日火曜日

Emacs で Mew を使って Gmail を受信してみた

概要

Emacs の mew というメールパッケージを使って Gmail を受信してみました
最新のMac (OS X) で試しています

環境

  • Mac OS X 10.10.4
  • stunnel 5.17
  • Emacs 24.4.1
  • Mew 6.6
  • Gmail 20150707時点

Mew のインストール

package.elを使ってインストールしました
package-list-packagesを起動して melpa の「mew 20150607.2316」を選択してインストールします
※20150707時点での最新の mew をインストールしているのでそれ以上のバージョンがあればそちらをインストールしてください

stunnel のインストール

stunnel は簡単に言えばSSL通信をするためのツールです
Homebrewを使ってインストールしました

brew install stunnel
/usr/local/bin/stunnel -version

証明書の設置

stunnel を使って Gmail と SSL 通信するのに利用します
stunnel のサイトで公開されている証明書をダウンロードして配置すればOKです

cd /var/tmp
wget http://www.mew.org/Release/certs-20110624.tar.gz
tar zvxf certs-20110624.tar.gz
mkdir ~/.certs
mv certs-20110624/* ~/.certs

GmailのIMAP設定

デフォルトではONになっています
ここの手順で確認することが可能です

Mewの設定を記載

.emacsでOKです
他の設定ファイルをloadしている場合はそのファイルでもOKです

; for configuration of mew
; Load stunnel
(setq mew-prog-ssl "/usr/local/bin/stunnel")
; User IMAP with Gmail for receiving a mail
(setq mew-proto "%")
(setq mew-imap-server "imap.gmail.com")
(setq mew-imap-ssl-port "993")
(setq mew-imap-user "your.account.name@gmail.com")
(setq mew-imap-auth  t)
(setq mew-imap-ssl t)
; User SMTP with Gmail for sending a mail
(setq mew-smtp-server "smtp.gmail.com")
(setq mew-smtp-ssl-port "465")
(setq mew-smtp-user "your.account.name@gmail.com")
(setq mew-smtp-auth t)
(setq mew-smtp-ssl t)

(setq mew-fcc "%Sent")
(setq mew-imap-trash-folder "%[Gmail]/ゴミ箱")
(setq mew-use-cached-passwd t)

変更する箇所は Gmail のアカウントを記載する部分です
「your.account.name」の部分を変更してください
その他が基本そのままでOKです
(setq mew-proto "%")とすることで mew を起動した際に受信フォルダに移動します
その他の値に関してここを検索するとどんな値なのかわかると思います

起動確認

emacs -e mew
とすると mew が立ち上がります
emacs を起動したあとでM-x mewでもOKです
立ち上がるとアカウントに対する認証が聞かれるのでGmailで使っているパスワードを入力します

問題なく認証が完了するとGmail上のメールデータが古い順に受信されます
初回起動時は全メールを取得するのでGmail上の受信メールが多い場合はダウンロードに時間がかかるかもしれません

デフォルトだと古い順に表示されるので新しい順に表示したい場合はバッファの最下部に移動してください

操作Tips

  • 終了方法
    Inbox内で「Q」とすることで終了させることができます
    メールの受信中に終了した場合は、mew 起動時に再度メールを受信してくれます

最後に

特にハマることなくできました
バージョンもだいぶ新しいのを使っているからでしょうか
ブラウザが使えない環境だと便利ですね
操作方法がわからなくなったら公式のマニュアルを読めばだいたいは解決すると思います

参考サイト

2015年7月6日月曜日

Heroku で Sinatra + Rack アプリを動かしてみた

概要

Sinatra で作成したアプリを Rack で動くようにして Heroku 上でも動作するようにしてみました
簡単にできたので紹介します
サンプルとして紹介するアプリはこちらです

環境

  • CentOS 6.6 64bit
  • Ruby 2.2.0p61
  • Sinatra 1.4.6
  • Rack 1.6.1
  • Heroku Toolbelt 3.39.1

Sinatra アプリの作成

何でもOKです
この辺を参考にすればあっさり作成できると思います
ruby app.rbで起動してポート4567でLISTENするアプリを作成できればOKです

Sinatra アプリを Rack で動作させる

config.ru の作成

config.rurackupという Rack のコマンドでアプリを起動させるために必要な起動ファイルです
以下のような感じで記載してください

require 'bundler'
Bundler.require

require './app'
run Sinatra::Application

requireしている./appの部分は作成した Sinatra アプリのファイル名を指定してください
これを作成したらrackupコマンドでアプリを起動できるようになります

rackup config.ru で起動できるはずです
またサンプルはbundlerでも動作するようになっています
bundler で動作させる場合はbundle exec rackup config.ruで起動できます

heroku へのデプロイ

herokuへのサービス登録は済ませておいてください
heroku-toolbeltのインストールがまだの場合は https://toolbelt.heroku.com/ を参考にインストールしてください
heroku-toolbeltがインストールできたらデプロイしていきます

デプロイは簡単です
作成した Rack アプリのディレクトリに移動して heroku にログインして push すればOKです

heroku login
heroku create
git push -u heroku master

とするだけでOKです
ログインは済んでいる場合は実行不要です

すでに登録済みのアプリに対してデプロイしたい場合はheroku createの代わりにgit remote add heroku https://git.heroku.com/APPNAME.gitとして heroku 上の git リポジトリを remote として追加します
APPNAMEの部分は既存のアプリ名を指定してください
heroku listで既存アプリ一覧を確認することができます

これで push に成功すれば rack アプリがデプロイされます

動作確認

push するとURLがターミナルに表示されると思うのでそこにアクセスしましょう
Mac等の環境でブラウザが使えるのであればheroku openでもOKです

サンプルを使っているのならばリクエスト情報をJsonでダンプしてくれるはずです

最後に

ポイントは config.ru で動作させるようにすることでした
Sinatra アプリとして動作する状況で push してもうまく動作しませんでした
heroku はどういうアプリなのかを自動で判断してアプリを起動します
Sinatra アプリの場合はそのままだと動作せず Rack アプリにすると動作するという話でした

2015年7月2日木曜日

Spring で MockMVC を使ったテストで Filter を使用する方法

概要

MockMvc のテストで Servlet の Filter を使用する方法を紹介します
MockMvc を使ったテスト環境の構築はこちらの記事を参考にして準備してください
また、Spring + Filter の使い方に関してはこちらを御覧ください

環境

  • Mac OS X 10.10.3
  • Eclipse Luna 4.4.1
  • Spring Framework 4.1.6
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Maven 3.2.1

Filter オブジェクトの作成

テスト用のクラスファイルに以下を追記します
@Autowiredを使ってクラスの作成と同時に Filter オブジェクトを生成します

@Autowired
private TestFilter testFilter;

フィルタの名前は自身の環境に合わせて適宜変更してください
また必要に合わせてimport文も定義してください

Beans として登録する

src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xmlに以下を追記します
@Autowiredで定義したフィルタオブジェクトをBeansの仕組みを使って生成するためです

<!-- for Filter -->
<beans:bean id="testFilter" class="com.sample.TestFilter">
</beans:bean>

MockMvc にフィルタを登録する

作成したフィルタをMockMvcのテスト時に使用するようにフィルタを追加します
MockMvc を WebApplicationContext から生成しているところで以下のようにフィルタを追加してください

this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).addFilter(this.testFilter, "/").build();

addFilterメソッドを呼び出します
第一引数でフィルタを指定して第二引数でフィルタを適用するURLマッピングを指定します

動作確認

mvn package等でテストを実行してフィルタの動作が実行されているか確認してください

最後に

web.xmlでアプリ的にフィルタを使うように定義していてもMockMvcでテストした際に有効にならないことに気が付き今回の対応を実施しました
web.xmlで定義していればテストでも通るようにしていいと思うんだけど、こうなっているのは MockMvc が Servlet の世界とは別世界のクラスだからなのだろうか
それとも親切心からなのだろうか

2015年7月1日水曜日

Spring で MockMVC を使ってテストしてみる

概要

Spring Framework には End to End の のテストを実現するためにMockMvcという仕組みが存在しています
簡単にいうとAPIをコールしてその結果を評価するという一連の流れをテストすることができます

環境

  • Mac OS X 10.10.3
  • Eclipse Luna 4.4.1
  • Spring Framework 4.1.6
  • Spring Tool Suite 3.6.4
  • Java 1.8.0_31
  • Maven 3.2.1

サンプルプロジェクト作成

過去の記事を参考に作成してください
Spring Framework のバージョンが最新でない場合は pom.xml 「org.springframework-version」のバージョン記載部分を最新のバージョンに変更してください

Spring-Test のライブラリを追加する

pom.xmlspring-testのライブラリを追加します

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-test</artifactId>
   <version>${org.springframework-version}</version>
</dependency>
<dependency>
  <groupId>javax.servlet</groupId>
  <artifactId>javax.servlet-api</artifactId>
  <version>3.1.0</version>
</dependency>

junitを定義するところが既にある場合でもバージョンが4.9未満である場合は4.9以上にしてください
javax.servletを読み込んでいますが、デフォルトだと読み込んでいるサーブレットのバージョンが2.5でこれだとCaused by: java.lang.ClassNotFoundException: javax.servlet.SessionCookieConfigと言われてテストが失敗するので 3.0 系のバージョンを読み込みます

テストコードの作成

src/test/java/test/sample/MockMvcSampleTest.javaにテストコードを作成していきます
STSでプロジェクトを作成するとテスト用のコードは何も作成されないので、適当にテスト用のクラスファイルを作成しましょう
作成したらMockMVCを使うための定義を記載します

package com.sample;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@WebAppConfiguration
public class MockMvcSampleTest {

    @Autowired
    private WebApplicationContext wac;

    protected MockMvc mockMvc;

    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
    }

    @Test
    public void sampleTest() throws Exception {
        this.mockMvc.perform(get("/")).andExpect(status().isOk());
    }
}

いろいろ書いているので簡単にポイント説明します

クラスの定義の冒頭で3つのアノテーションを宣言しています

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"file:src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml"})
@WebAppConfiguration

JUnit + MockMvc を使ってテストするために必要な記述です
詳細は正直自分もよくわかっていませんが

  • RunWithでランナーを選択して
  • ContextConfigurationでサーブレットの設定が記述されたコンテキストファイルを読み込んで
  • WebAppConfigurationでWebアプリをテストするための必要なコンテストに触れるようにしています

とにかく1つでも定義がかけるとエラーになるので必ず定義します

次にMockMvcのオブジェクトを定義する部分です

@Autowired
private WebApplicationContext wac;

protected MockMvc mockMvc;

MockMvcのオブジェクトを作成するのにWebApplicationContextが必要で、このオブジェクトは先程のアノテーション+@Autowiredすることで勝手に設定されるオブジェクトです
この2つのオブジェクトを使って、サンプルのsetupメソッドにあるようにbuildするとMockMvcのオブジェクトが生成されます

最後にテストの方法です

this.mockMvc.perform(get("/")).andExpect(status().isOk());

ポイントはgetstatusというメソッドをimport文でstaticに読み込んでいる部分です
こうすることでテストを書く際にメソッドの呼び出しを直感的に行えます
performでコールするAPIのパスとHTTPメソッドを指定して、その結果をandExpectで評価する感じです
今回のテストの場合はレスポンスコードが20X系であることを確認するテストになっています

Tips

他のHTTPメソッドでコールしたい場合は

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;

こんな感じでimportして

this.mockMvc.perform(post("/")).andExpect(status().isMethodNotAllowed());

こんな感じでテストできます

リクエストヘッダを指定したい場合はperformの後に.header("key", "value")で指定できます

リクエストパラメータを指定したい場合はperformの後に.param("key", "value")で指定できます

(POSTやPUTの場合に)リクエストボディを設定したい場合はperformの後に.content("body_value")で指定できます

実行

STSで作成していれば自動的にMavenプロジェクトになっているのでmvn packageなどで実行すればライフサイクルの中にテストが含まれるので自動でテストされます
テストだけ個別で実行したい場合はmvn test-compile testなどとすれば実行されます

最後に

Spring Framework にはデフォルトで end to end のテスト方法が含まれているのでAPIサーバを作る場合には割りと簡単にテストが書けそうです
MockMvc を使わないテストも記述することもできるので、メソッド個別でテストしたい場合には別のテストメソッドを作成してテストするといいと思います
JUnitが使えるのでJUnitAssert等も使うことができます

次回はテスト時に Filter を通してテストする方法を紹介したいと思います