Taste of Tech Topics

Acroquest Technology株式会社のエンジニアが書く技術ブログ

日経ソフトウエアのJava8連載の第3回は「新しい日付API」です!

みなさん、こんにちは!
インフルエンザやノロウィルスが猛威を振るっていますが、みなさん、いかがお過ごしでしょうか。
周りで感染者が増える中、風邪ひとつ引かない、無駄に丈夫なオカダです。
無事是名馬、いい言葉ですね。

■先取り! Java SE 8

Java8の新機能についてAcroquest社員が紹介する短期集中連載
「先取り! Java SE 8」
の第三回が掲載された、「日経ソフトウエア2014年3月号」が出版されました。

http://itpro.nikkeibp.co.jp/NSW
http://itpro.nikkeibp.co.jp/NSW

■第三回は「新しい日時API

日経ソフトウエア2014年1月号」からスタートした本連載。
1月号は「ラムダ式」2月号は「ストリームAPI」について紹介してきました。

今月は、Java8になって大きく変更が入った「日時APIについて紹介します。
題して、「これまでがいかに面倒だったか・・・「日時API」の改良が喜ばしい」です。

これまでのJavaの日時APIは、処理に制約があったり、直感的でなかったりと、色々と「残念なところ」がありました。
Java8では日時APIが完全に作り直されており、既存の問題を解消した非常に利用しやすいAPIになっています。
既存のコードと対比する形で、新しいAPIを利用した場合の利点を紹介していますので、ぜひ、ご一読下さい!

なお、Acroquestのサイトから最初の1ページ分のPDFを閲覧できますので、こちらも参考にしてくださいね。
http://www.acroquest.co.jp/company/press/2014/0124p1.html

■「先取り! Java SE 8」は今回が最終回

3回に渡って連載してきた「先取り! Java SE 8」は、今回が最終回です。
Java8の正式リリースは3月に予定されており、まもなく手元で動かせるようになるでしょう。
一歩進んだJavaプログラミングを身につけるために、今回の連載が助けになれば幸いです。

それでは!

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Couchbase Tokyo 2014と、Couchbase情報のまとめ

こんちには! ツカノ(@)です。

なんだかんだで1月末。寒い日があるのは良いとしても、忙しい日も多くなってきました。一緒にいろいろな事に取り組む人がもっと多くなって欲しい、との感じる今日この頃です。そんな訳で、当社では人材募集中です!
 →Javaエンジニア緊急募集/キャリア採用


さて、そんな感じの宣伝から入りましたが、本題です。
ここ数年、NoSQLプロダクトは急速に増えましたね。しかも、KVS、ドキュメント指向、グラフ指向など、プロダクトの特徴も様々です。例えばこういう比較ページを見ると、いろんな特徴のNoSQLがあることが分かります。

これらNoSQLプロダクトの中でも、Couchbaseドキュメント指向型(JSON)KVS型(memcached互換)の両方に対応したNoSQLで、インメモリで高速動作するのがウリです(ディスクに永続化できますが、基本はインメモリ)。また、システムを止めないことを重要視しており、障害が発生しても自動でフェイルオーバーしたり、コンパクション時に他のオペレーションが停止しないそうです。

f:id:acro-engineer:20140124151034p:plain

公式ページをチェックしてみると、以下のような特徴が記述されています。

  • 容易なスケーラビリティー
  • 安定したハイパフォーマンス
  • 365日稼動
  • 柔軟なデータモデル

そんなCouchbase入門者の私ですが、Couchbaseを勉強すべくCouchbase Tokyo 2014というイベントに参加してきました。
 →このイベントのEventifierはこちらです。

Couchbase Tokyoは毎年開催されているイベントで、今年で3回目。Couchbase社の方によるCouchbaseの解説と、ユーザによる事例紹介が行われます。朝から夕方まで丸一日のイベントで、最初は製品の概要説明から入り、段々と濃いセッションになっていき、Couchbaseについてよく勉強することができました。ちゃんちゃん♪・・・では面白くないので、中でも気になった「Couchbase Console」「Couchbase Lite」を紹介します。

Couchbase Console

「Couchbase Console」(管理用Webコンソール)は、Couchbase社のMatt Ingenthronさんのセッションで紹介されていた機能で、ノードの設定ができるのはもちろん、秒間のオペレーション数やメモリ・ディスクの利用状況をリアルタイムでグラフ表示できたり、ノード毎のコンパクションの状況を進捗バーで表示することができます。クラスタ化されたシステムを管理する側からすると、素晴らしい機能ですね。こういうところがちゃんとしているNoSQLプロダクトって、なかなか無いと思います。
グラフ表示している画面は、こういう感じです。デザインも良いですね。
f:id:acro-engineer:20140124114108p:plain

Couchbase Lite

要するに、モバイル向けの組み込みCouchbaseです。今のところ、iPhone/Androidに対応しています。Couchbase社のJessica Liuさんのセッションで紹介されていました。
Couchbase Liteを使うと、クラウド上のCouchbaseサーバとデータ同期したり、特定のクエリ結果が更新された際に通知を受信したり(Live Query)Facebook認証するAPIが用意されていたり、モバイル向け機能がいろいろと用意されているようです。また、PhoneGapプラグインも用意されています。
「モバイル向けの機能がいろいろ揃ったNoSQL」といったところでしょうか。多くの人がモバイル端末を持つ時代になってはいますが、OSSのNoSQLプロダクトでモバイル向けの機能があるのはCouchbaseだけ、との事でした。


このイベントで、実際に開発しているCouchbase社の方々に質問できたのは良かったです。また、Couchbase社の方々と話してみると、陽気な方が多く、好印象でした。Matt Ingenthronさんとか、変な質問でも、ちゃんと回答してくれましたし、懇親会も非常に盛り上がっていました。翌日仕事があったため私は二次会までしか参加しませんでしたが、その後、何時まで飲んでたんだろう。。。

Couchbase情報まとめ

Couchbaseの情報が載っているサイトや本について、まとめました。他にもオススメがあれば、ぜひお知らせください。

英語、日本語、韓国語、中国語で情報公開されてます。

couchbase-jp、日本のCouchbaseコミュニティです。meet upなどのイベントも開催されています。

couchbase-jpの方々が作成してくださった日本語版のマニュアルです。バージョンは2.0ですので、利用の際はご注意ください。

Getting Started With Couchbase Server

Getting Started With Couchbase Server

90ページとコンパクトな本で、まずは始めてみましょう、という入門的な内容です。

f:id:acro-engineer:20140124093141g:plain
「Getting Started With Couchbase Server」の日本語訳です。Ebookのみ販売されています。

Developing With Couchbase Server

Developing With Couchbase Server

こちらも88ページとコンパクトな本ですね。Couchbaseは公式のドキュメントが充実してるし、「何百ページもの本を読まないと使えないプロダクトじゃない」と言っている方もいましたし、コンパクトな本が多いですね。

この2つのサイトはCouchbaseに関する記事が豊富です。参考にさせていただきます。

  • 小冊子
    • Couchbase LiteによるiOSアプリケーション開発
    • FluentdとNoSQLデータベースCouchbase Serverで始めるログ解析~それでもやっぱり、SQLが好き~

コミケやCouchbase関係のイベント会場で、couchbase-jpにより販売されているようです。
↓こういう本です。


さて、いかがだったでしょうか?
Couchbaseの良い面ばかり書いた気がするので、「それなりにメモリを使う」「Enterprise Editionが最新版で、Community Editionは1つ前の版」という面があることも書いておきます。それでも、魅力的なプロダクトに見えますが。
Couchbaseに興味を持たれた方は、ぜひ触ってみてはいかがでしょう。

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

RestfuseによるREST API自動試験まとめ(その2)

こんにちは、Web系エンジニアのナカガワです。
皆さん、エンジニアtypeに掲載された私の雄姿(><)は見て頂けましたか?

「技術探求型」で新しい受託開発を実現してきたアクロクエストが有する“組織技術力”とは? - エンジニアtype
まだの人はいますぐチェック!!

さて、前回はRestfuseを使ったテストの手順を説明しました。今回はそのテストをJenkinsで自動化するまでの手順を紹介したいと思います。

f:id:acro-engineer:20140122102519p:plain

Jenkinsを使ってどのような自動試験にするか

まずはEclipseプロジェクトやJenkinsプロジェクトをどのような構成にするかを考えます。
前回の手順では「アプリケーション本体(=テスト対象)」と「結合テスト」を別のEclipseプロジェクトにしました。そのため、Jenkinsプロジェクトでも同様に、この2つに分けて構築しました。
2つのプロジェクトに分けることで、アプリケーション本体側のテストコードと、結合テスト側のテストコードを分けることができます。たとえば実際の業務では、アプリケーション本体側をシンプルなユニットテストにして、結合テスト側をAPサーバやDBサーバを利用した結合テストにしていました。

つまり、Jenkinsで以下のように処理することになります。

  1. アプリケーション本体をビルドしてwarファイルを作成する
  2. warファイルを、テスト用プロジェクトにコピーする
  3. APサーバを起動する
  4. テストを実行する
  5. APサーバを停止する

それでは、実際に設定する手順を説明します。

Jenkinsの自動試験用の設定

1. プロジェクトの作成

まずはJenkinsを起動して、プロジェクト作成します。
※Jenkinsインストールは割愛しますね。

アプリケーション本体も、結合テスト用プロジェクトも、いずれもMavenプロジェクトなので、ビルドは「Maven2/3プロジェクトのビルド」を選択します。
※今回は業務の都合上、Mavenは3系ではなく2.2.1を使いました。

アプリケーション本体用と、結合テスト用プロジェクトのそれぞれについて、Jenkinsプロジェクトを作りました。

f:id:acro-engineer:20140115014614p:plain

どちらもMavenの実行において、clean installを指定しておきます。
結合テスト用のプロジェクトはinstallでなくてもintegration-testが実行されるものであれば構いません。

2. アプリケーション本体のビルドとwarファイルの保存

Jenkinsのパイプライン機能を使って「アプリケーションのビルド」→「テストプロジェクトの実行」の順に実行します。

ここでアプリケーションの「ビルド後の処理」に成果物の保存処理を追加しました。
アプリケーションのビルドの成果物であるwarファイルを保存しておくことで、他のプロジェクトにコピーすることができるようになります。
以下の通りですね。

f:id:acro-engineer:20140115014935p:plain

次は保存した成果物を結合テスト用プロジェクトにコピーします。

3. アプリケーション本体のwarファイルのコピー

結合テスト用プロジェクトに、先ほど作成・保存したwarファイルをコピーします。
今回はJenkinsプラグインの「Copy Artifact Plugin」を使います。当該プラグインは、Jenkinsの管理ページからインストールしました。

f:id:acro-engineer:20140115015134p:plain

上記プラグインを追加すると、Jenkinsプロジェクト内での「前処理」に「他のプロジェクトから成果物をコピー」が追加されます。
これを使えば、warファイルのコピーが可能になります。

ちなみに今回は、「ディレクトリ構造を無視」というチェックボックスにチェックを入れておきます。
このチェックを入れないと、コピー時にディレクトリ構成までコピーされてしまい、想定と違う場所にwarファイルが置かれてしまうからです。

これでworkを指定すればwork直下にwarファイルが配置されます。

f:id:acro-engineer:20140115015332p:plain

後はwarファイルを起動するだけですね。

4. アプリケーションの起動

warファイルを起動する方法はいくつかありますが、今回はMavenで簡単に起動できるjetty pluginを使います。
integration-testフェイズを利用し、pre-integration-testでJettyを起動し、post-integration-testでJettyを停止します。
※integration-testフェイズでテストを実施するのはsurfire-pluginを利用しました。

以下がテスト実行用のpom.xmlに追加した内容です。

      <!-- Jettyの設定 -->
      <plugin>
        <groupId>org.mortbay.jetty</groupId>
        <artifactId>jetty-maven-plugin</artifactId>
        <version>8.1.14.v20131031</version>
        <configuration>
          <war>./work/restsample-1.0.0.war</war>
          <webApp>
            <contextPath>/restsample</contextPath>
          </webApp>
        </configuration>
        <executions>
          <!-- integration-test の 事前準備 (Jettyの起動) -->
          <execution>
            <id>start-jetty</id>
            <phase>pre-integration-test</phase>
            <goals>
              <goal>run-war</goal>
            </goals>
            <configuration>
              <scanIntervalSeconds>0</scanIntervalSeconds>
              <daemon>true</daemon>
            </configuration>
          </execution>
          <!-- integration-test の 事後処理 (Jettyの停止) -->
          <execution>
            <id>stop-jetty</id>
            <phase>post-integration-test</phase>
            <goals>
              <goal>stop</goal>
            </goals>
            <configuration>
              <stopKey>stop</stopKey>
              <stopPort>9999</stopPort>
            </configuration>
          </execution>
        </executions>
      </plugin>

      <!-- integration-testの実行 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <!-- integration-test にて実行する -->
        <executions>
          <execution>
            <id>selenium-test</id>
            <phase>integration-test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <includes>
                <include>**/*Test*.java</include>
              </includes>
            </configuration>
          </execution>
        </executions>
      </plugin>

ところで、Jenkinsを8080番ポートで起動している場合は、Jettyを8080番ポートで起動すると、ポートが重複してしまってエラーになります。
というか、私自身、よくやってしまいます orz

JenkinsかJettyの利用するポートを変更する必要があります。
Jetty側のポートを変更するには、Jetty起動時のオプションに-Djetty.port=18080などをつけてください。その場合、結合テスト用のテストコードに記載しているURLも18080に変更する必要がある点に注意してください。

5. テストの実施

改めて実行してみたところ、Jenkinsのビルドには成功するものの、途中でテスト失敗のメッセージが出ていました。

結果ログをよく見ると、JUnitが3回起動していました。
どうやら上に書いた設定のままだと、Jetty起動前に2回JUnitが起動し、それがテスト失敗となっているようです。
Jetty起動前の試験は不要なので、スキップする設定を加えます。

      <!-- integration-testの実行 -->
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <!-- integration-test にて実行する -->
        <executions>
          <execution>
            <id>selenium-test</id>
            <phase>integration-test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <includes>
                <include>**/*Test*.java</include>
              </includes>
            </configuration>
          </execution>
          <!-- ★追加設定 default-test, unit-test をSKIPする -->
          <execution>
            <id>default-test</id>
            <configuration>
              <skip>true</skip>
            </configuration>
          </execution>
          <execution>
            <id>unit-test</id>
            <phase>test</phase>
            <goals>
              <goal>test</goal>
            </goals>
            <configuration>
              <skip>true</skip>
            </configuration>
          <!-- ★追加設定終わり -->
          </execution>
        </executions>
      </plugin>

上記設定でもう一度ビルドすると、無事、JUnitは1回しか実施されず、JUnitのテスト成功のみ残りました。

あとはJenkinsが毎日自動で統合テストを実施してくれるので、安心感があります。

まとめ

2回に分けて紹介してきましたが、最後に簡単にまとめです。

  1. Restfuseを使うと検証に集中してテストケースが書ける!
  2. アプリケーション本体と統合テスト用のJenkinsプロジェクトを分けたほうが管理しやすかった!
  3. みんな大好き、Jenkins + Jettyの組み合わせは、やっぱり鉄板だった!
  4. 8080番ポートを重複させるのは、素人(><)。
  5. Jenkinsで自動試験を常に動かすと安心感ある!

そんなわけで、REST APIの自動試験が必要な時には、Restfuse + Jenkinsも試してみてください!

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Spring4.0で、APサーバに依存しないWebSocketサーバを実現する方法

こんにちは、阪本です。


昨年末に、Springがメジャーバージョンアップして4.0になりましたね。
代表的な変更点を上げてみても、

  1. コールバック関数のJava8ラムダ式対応
  2. Java EE 6 & 7 対応
  3. GroovyによるSpring定義の記述対応
  4. WebSocket、SockJS、STOMP対応
  5. 非同期REST対応等のRESTインタフェース機能拡張

のように、大きな機能追加・変更が行われていますが、その中でも、最近流行りのWebSocketに対応したということで、少し触ってみました。

まずは実装

超シンプルなチャットプログラムを作ってみます。
(エラー処理等は割愛。)

まずはサーバサイドから。
Mavenのpom.xmlのdependenciesに、Springの標準ライブラリに加えて、WebSocket用のライブラリ(spring-websocket)を定義します。

<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-context</artifactId>
  <version>${spring.version}</version>
  <exclusions>
    <exclusion>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
    </exclusion>
  </exclusions>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>${spring.version}</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-websocket</artifactId>
  <version>${spring.version}</version>
</dependency>

もちろん、 ${spring.version} は 4.0.0 です。

次にweb.xml
通常のHTTPリクエストを処理するのと同じく、WebSocketのハンドシェイクを受けるのもDispatcherServletです。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    id="WebApp_ID" version="3.0">
  <display-name>WebSocketServer</display-name>

  <!-- JavaConfigを用いるための設定 -->
  <context-param>
    <param-name>contextClass</param-name>
    <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
  </context-param>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>websocket.config.ApplicationConfig</param-value>
  </context-param>

  <listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

  <servlet>
    <servlet-name>rootServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextClass</param-name>
      <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
    </init-param>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value></param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>rootServlet</servlet-name>
    <url-pattern>/echo</url-pattern>
  </servlet-mapping>

</web-app>


SpringのBean定義。JavaConfigを用いると、以下のように書きます。
@EnableWebSocket アノテーションを書くことで、WebSocketが有効になります。
合わせて、WebSocketConfigurerインタフェースを実装します。
registerWebSocketHandlersメソッドの中で、実際のWebSocket通信を処理するハンドラ(ここではEchoHandler)を登録します。
なお、コネクションごとにハンドラオブジェクトを分ける場合は、PerConnectionWebSocketHandlerを用います。

package websocket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import websocket.handler.EchoHandler;

@Configuration
@EnableWebSocket
public class ApplicationConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry)
    {
        registry.addHandler(new EchoHandler(), "/echo");
        // セッションごとにオブジェクトを分ける場合は以下のように書く
        // registry.addHandler(new PerConnectionWebSocketHandler(XxxHandler.class), "/echo");
    }

}


ハンドラ(EchoHandler)の中身。受信した文字列(TextMessage)を、各クライアントに転送します。
今回は文字列の送受信を行うので、TextWebSocketHandlerクラスを継承しています。
バイナリデータを送受信する場合はBinaryWebSocketHandlerクラスを継承します。

package websocket.handler;

import static java.util.Map.Entry;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

public class EchoHandler extends TextWebSocketHandler {
    /** セッション一覧 */
    private Map<String, WebSocketSession> sessionMap_ = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        this.sessionMap_.put(session.getId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session,
            CloseStatus status) throws Exception {
        this.sessionMap_.remove(session.getId());
    }

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 接続されているセッション(自分も含め)に転送する
        for (Entry<String, WebSocketSession> entry : this.sessionMap_.entrySet()) {
            entry.getValue().sendMessage(message);
        }
    }

}


最後に、HTMLファイルの内容です。
テキストフィールドに文字列を入力し、「送信」ボタンを押下すると、サーバに文字列を送信します。
サーバからメッセージを受信したら、divの中身に追記します。

<!DOCTYPE html>
<html>

<head>
  <script type="text/javascript" src="./views/lib/jquery.js"></script>
  <script type="text/javascript">
    $(function(){
      var ws = new WebSocket("ws://localhost:8080/WebSocketServer/echo");

      ws.onopen = function(){
      };

      ws.onclose = function(){
      };

      ws.onmessage = function(message){
        $("#log").append(message.data).append("<br/>");
        $("#message").val("")
      };

      ws.onerror = function(event){
        alert("エラー");
      };

      $("#form").submit(function(){
        ws.send($("#message").val());
        return false;
      });
    });
  </script>
</head>

<body>
  <div id="log"></div>
  <form id="form" action="#">
    <input type="text" id="message" /> <input type="submit" id="send" value="送信" />
  </form>
</body>

</html>


ちなみに、こんな画面になります。
f:id:acro-engineer:20140112003431p:plain



なお、上の例では、Springの定義をJavaConfigで記述しましたが、XMLで記述したい場合は以下のように書きます。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:websocket="http://www.springframework.org/schema/websocket"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/websocket
    http://www.springframework.org/schema/websocket/spring-websocket.xsd">

    <websocket:handlers>
        <websocket:mapping path="/echo" handler="echoHandler" />
    </websocket:handlers>

    <bean id="echoHandler" class="websocket.handler.EchoHandler" />

</beans>

IE8/9に対応する(SockJSを使う)

WebSocket自体、IEは10以降でないと対応していません。
業務系ではまだまだIE8/9を使用しているところも多いはず。

そんなIE8/9ユーザには、WebSocketの動作をエミュレートする「SockJS」を使うと、
似たような動きを実現することができます!

WebSocketを用いる場合はWebSocketオブジェクトを生成していましたが、
SockJSを用いる場合はSockJSオブジェクトを生成します(引数のURLのプロトコル部分がhttpとなっていることに注意)。
これだけ。

<head>
  <script src="http://cdn.sockjs.org/sockjs-0.3.min.js"></script>
  <script type="text/javascript">
    $(function(){
      var sock = new SockJS("http://localhost:8080/WebSocketServer/echo");

      sock.onopen = function(){
      };

      sock.onclose = function(){
      };

      sock.onmessage = function(message){
        $("#log").append(message.data).append("<br/>");
        $("#message").val("")
      };

      sock.onerror = function(event){
        alert("エラー");
      };

      $("#form").submit(function(){
        sock.send($("#message").val());
        return false;
      });
    });
  </script>
</head>


SockJSはWebSocketを擬似的に再現しているに過ぎないため、通信の仕組みが異なります。
そのため、サーバサイドもWebSocketと同じ実装では動きません。

・・・

と言いましたが、Spring4.0では、なんと、たった13バイト付け足すことでSockJSに対応できます。
addHandlerメソッドの呼び出しの後ろに「.withSockJS()」を付けるだけ!超簡単!便利!!

package websocket.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
import org.springframework.web.socket.config.annotation.WebSocketConfigurer;
import org.springframework.web.socket.config.annotation.WebSocketHandlerRegistry;

import websocket.handler.EchoHandler;

@Configuration
@EnableWebSocket
public class ApplicationConfig implements WebSocketConfigurer {

    @Override
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry)
    {
        registry.addHandler(new EchoHandler(), "/echo").withSockJS();
        // セッションごとにオブジェクトを分ける場合は以下のように書く
        // registry.addHandler(new PerConnectionWebSocketHandler(XxxHandler.class), "/echo").withSockJS();
    }

}


Springの定義をXMLで記述する場合も、「<websocket:sockjs />」を記述するだけ。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:websocket="http://www.springframework.org/schema/websocket"
  xsi:schemaLocation="
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/websocket
    http://www.springframework.org/schema/websocket/spring-websocket.xsd">

    <websocket:handlers>
        <websocket:mapping path="/echo" handler="echoHandler" />
        <websocket:sockjs />
    </websocket:handlers>

    <bean id="echoHandler" class="websocket.handler.EchoHandler" />

</beans>

ハンドラ等はWebSocketと同じものをそのまま使えます。

補足:APサーバに依存しない理由

今までは、WebSocketプログラムを作る場合、APサーバが提供するServletクラスを継承して作っていたため、プログラムがAPサーバに依存した作りになっていました。
(例えばJettyの場合は、org.eclipse.jetty.websocket.servlet.WebSocketServletクラスを継承してServletを作ります。)
それに比べて、上のチャットプログラムは、APサーバに依存しない実装となっています。

APサーバ依存脱却!

・・・といいつつも、WebSocketの実現の仕組みは、APサーバによって異なるはず。

では、どこでAPサーバ依存の処理を行っているのでしょうか?

気になってSpringのソースコードを見てみると・・・やはりありました!
Spring WebSocketモジュールのDefaultHandshakeHandlerクラスで、APサーバ依存の処理を切り分けています。

private static final boolean jettyWsPresent = ClassUtils.isPresent(
        "org.eclipse.jetty.websocket.server.WebSocketServerFactory", DefaultHandshakeHandler.class.getClassLoader());

private static final boolean tomcatWsPresent = ClassUtils.isPresent(
        "org.apache.tomcat.websocket.server.WsHttpUpgradeHandler", DefaultHandshakeHandler.class.getClassLoader());

private static final boolean glassFishWsPresent = ClassUtils.isPresent(
        "org.glassfish.tyrus.servlet.TyrusHttpUpgradeHandler", DefaultHandshakeHandler.class.getClassLoader());

(中略)

private static RequestUpgradeStrategy initRequestUpgradeStrategy() {
    String className;
    if (jettyWsPresent) {
        className = "org.springframework.web.socket.server.jetty.JettyRequestUpgradeStrategy";
    }
    else if (tomcatWsPresent) {
        className = "org.springframework.web.socket.server.standard.TomcatRequestUpgradeStrategy";
    }
    else if (glassFishWsPresent) {
        className = "org.springframework.web.socket.server.standard.GlassFishRequestUpgradeStrategy";
    }
    else {
        throw new IllegalStateException("No suitable default RequestUpgradeStrategy found");
    }
    try {
        Class<?> clazz = ClassUtils.forName(className, DefaultHandshakeHandler.class.getClassLoader());
        return (RequestUpgradeStrategy) clazz.newInstance();
    }
    catch (Throwable ex) {
        throw new IllegalStateException("Failed to instantiate RequestUpgradeStrategy: " + className, ex);
    }
}

Jetty、TomcatGlassFish、それぞれのWebSocket用クラスが存在するかチェックして、ハンドシェイク処理クラスを切り替えています。
これにより、私たちはAPサーバの種類を意識せずに実装できます。

・・・もうお分かりのように、Spring4.0のWebSocket対応APサーバは、Jetty、TomcatGlassFishです^^

おわりに

今後、WebSocketを使用したシステムは増えてきます。
APサーバ依存性の排除や実装量の削減に、Springを活用するのは有効な手段と思います。
ぜひ、試してみてください。

では。


Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

RestfuseによるREST API自動試験まとめ(その1)

こんにちは、Web系エンジニアのナカガワです。

皆さん、REST APIのテストはどのようなツールを使っていますか?
私はJUnitでテストが書ける「Restfuse」を使っています。
今回、実プロジェクトでRestfuse + Jenkinsで定期的にREST APIをテストする仕組みを構築したため、このあたりのノウハウをまとめて書きたいと思います。

REST APIテスト自動化のゴール

ゴールは以下の二つです。
(1) APサーバ上で動作しているWebアプリケーションに対し、自動でREST APIテストを実施する。
(2) Jenkinsを用いてCIを実施可能にする。
まず今回は、前者のREST APIテストを実施するところまで紹介します。

Restfuseを使って、REST APIJUnit上でテスト可能に!

先にも書きましたが、私が使ったのはRestfuseというツールです。

Restfuseは、HTTP/REST通信のテストを容易に実行できるようにするためのJUnitExtentionです。
ここが公式サイトです。

http://developer.eclipsesource.com/restfuse
http://developer.eclipsesource.com/restfuse/

なおREST APIのテストとして便利そうなフレームワークとしては、他にREST-assuredなどがあります。
今回は検証を自分でカスタマイズして書きたかったので、電文送信処理をアノテーション記述のみで実現でき、テストコードには検証コードを書くだけに絞れるRestfuseを選択しました。

ちなみに今回は扱わないのですが、Restfuseでは定期ポーリングテストやコールバック処理の記載など、REST APIを使う際にテストが必要なさまざまなパターンに対応しています。

Restfuseを使うための準備

1. 統合テスト自動化用のEclipseプロジェクトを作成。

統合テスト用にMavenを使って新規にEclipseプロジェクトを作りました。

統合テスト用に新規にEclipseプロジェクトは作るか、アプリケーションを実装したEclipseプロジェクトにテストを追加するかは好みが分かれると思います。
私の場合は単体試験相当のJUnitと統合試験相当のJUnitコードが混ざると見にくいと考え、別プロジェクトにしています。
Eclipse上でMavenを用いてプロジェクトを作成する方法は以下のサイトが詳しいです。
archetypemaven-archetype-quickstartを選択して作成しました。
http://d.hatena.ne.jp/kagamihoge/20121228/1356695798

2. Restfuseを使うために必要なMavenのdependencies設定を追加。

以下に定義を記載します。

	<!-- 依存関係 -->
	<dependencies>
		<!-- JUnit Test -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.11</version>
		</dependency>

		<!-- HTTP Test -->
		<dependency>
			<groupId>com.restfuse</groupId>
			<artifactId>com.eclipsesource.restfuse</artifactId>
			<version>1.2.0</version>
		</dependency>
	</dependencies>

これで試験を実施する準備が完了しました。

REST APIテスト(テスト対象API説明)

今回は以下のAPIのテストを実施します。

1. リクエスト

HTTPヘッダ 設定値
URL http://localhost:8080/restsample/getJson
METHOD POST
ContentType application/json

HTTPボディ

{
  "id" : "String値",
  "number" : "String値",
  "name" : "String値",
  "message" : "String値"
}

2. レスポンス

HTTPヘッダ 期待値
ContentType application/json

期待するHTTPボディ

{
  "result" : "success",
  "message" : ""
}

REST APIテスト(テスト作成)

以下に作成したテストコードを掲載します。

RestSampleTest.java

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;

import org.junit.Rule;
import org.junit.runner.RunWith;

import com.eclipsesource.restfuse.Destination;
import com.eclipsesource.restfuse.HttpJUnitRunner;
import com.eclipsesource.restfuse.MediaType;
import com.eclipsesource.restfuse.Method;
import com.eclipsesource.restfuse.Response;
import com.eclipsesource.restfuse.annotation.Context;
import com.eclipsesource.restfuse.annotation.HttpTest;

/**
 * @author nakagawa
 *
 */
@RunWith(HttpJUnitRunner.class)
public class RestSampleTest {

	/**
	 *  REST APIの設定としてURLを記載します。
	 */
	@Rule
	public Destination restfuse = new Destination(this,
			"http://localhost:8080/restsample");
	/**
	 * レスポンスオブジェクトが格納されるフィールドを用意します。
	 */
	@Context
	private Response response;

	/**
	 * JSON取得APIに接続する。
	 * HttpTestにテストを実施するメソッドの設定を行います。以下の通り
	 * 1. method : リクエストのメソッドを設定
	 * 2. path   : リクエスト送信先のパスを設定。今回であれば、http://localhost:8080/restsample/getJsonにアクセスする。
	 * 3. type   : リクエストのContent-Typeを設定する。
	 * 4. file   : リクエストのbodyに設定する内容を記載する。
	 * 
	 * @throws Exception
	 *             エラー
	 */
	@HttpTest(method = Method.POST, path = "/getJson", type = MediaType.APPLICATION_JSON, file = "sampleData.txt")
	public void testGetJson_Status200() throws Exception {
		assertThat(response.getStatus(), is(200));
	}
}

sampleData.txtとexpectedValue.txtはそれぞれ以下の値としました。

sampleData.txt

{
  "id" : "12345",
  "number" : "1",
  "name" : "nakagawa",
  "message" : "first step of automation test"
}

expectedValue.txt

{
  "result" : "success",
  "message" : ""
}

以下ポイントを解説します。

1. Runnerの設定

RestfuseはJUnitExtentionです。
@RunWith(HttpJUnitRunner.class)をクラスの先頭につけることでRestfuseが動きます。

2. RootURLの設定

テスト対象のルートURLを設定したDestinationを生成します。
@RuleをつけることでRestfuseが設定を読み込み、URLを解決してくれます。

	/**
	 *  REST APIの設定としてURLを記載します。
	 */
	@Rule
	public Destination restfuse = new Destination(this,
			"http://localhost:8080/restsample");

3. レスポンスオブジェクトの格納先の追加

以下のように@Contextを付けたフィールドを用意すると
Restfuseが通信後にレスポンスを自動で格納してくれます。

	/**
	 * レスポンスオブジェクトが格納されるフィールドを用意します。
	 */
	@Context
	private Response response;

4. テスト条件の指定

テスト条件を指定します。
指定方法はテストメソッドにHttpTestアノテーションを付けます。

それぞれ以下の値を設定します。

フィールド名 設定内容
method リクエストのメソッドを指定。
path RootURLから先のパスを指定します。以下の記述だと、http://localhost:8080/restsample/getJsonにつながります。
type Content-typeを指定します。
file リクエストのbody要素に値を入れる場合には、ファイル名を記載することで対象のファイルを読みbodyに設定してくれます。
	@HttpTest(method = Method.POST, path = "/getJson", type = MediaType.APPLICATION_JSON, file = "sampleData.txt")

REST APIテストを実施する。

Jenkinsで試験をする前に、まずは自分でWebアプリケーションを動かして、テストが実施できているか確認しておきます。
※テスト対象のWebアプリケーション(APサーバ)は事前に起動しておく必要があります

f:id:acro-engineer:20131201221029p:plain

テストが実施されました。
無事レスポンスも返りチェックできています。

f:id:acro-engineer:20131201221034p:plain

Restfuseを使うことで、通信処理はすべてFrameworkでやってもらい、検証処理の記載に絞ることができました。
通信を伴うテストだと、電文を送信するまでの事前条件だけでテストコードの半分が埋まってしまうことが多々ありました。
Restfuseによって、テストコードが検証処理だけになるのは見通しがよくなるのはうれしいですね。

Restfuseで通信を行う前の初期化をどうするか

ところで、Restfuseを使っていると、「事前のデータの初期化とかはどうやっているの?」という質問を受けることがよくあります。
Restfuseはアノテーションベースでテストを行うため、テストケース内で事前に初期化を行うためのコードを書く事ができません。

私はシンプルに、以下のようにしています。
1. BeforeClassアノテーションで初期化を行い、電文送信前にDBの初期化を実施。
2. AfterClassアノテーションで処理で、DBの値を削除。
この方法ではメソッドごとの柔軟な初期化こそできませんが、複雑になり過ぎることがありません。

より柔軟な初期化が必要な場合には、以下のような初期化を行ないます。
1. テストメソッド名と同名の初期化処理用ファイルを用意する。
2. @Ruleアノテーションを付けたTestNameをフィールドに設定する。
3. Beforeアノテーションで、TestNameを利用してテストメソッド名を取り出して、1を実行してDB初期化を行なう。
4. Afterアノテーションで、DBの値を削除する。
この方法では管理や見通しが少し複雑になるものの、柔軟な初期化ができるので、必要に応じて利用しています。


さて、次は今回作ったテストをJenkinsを用いてCI実施してみます。
ではでは!

 

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

Storm関連本とオススメ電子書籍

新年あけましておめでとうございます。ツカノ(@)です。
今年最初のT3ブログですね。よろしくお願いします。

私はリアルタイム分散処理の仕事に携わっているため、昨年、こんな話題に興味を惹かれました。

  • CDHによるSparkのサポート
  • AmazonからKinesisが登場
  • ImpalaPrestoといった分散クエリの盛り上がり

こういった傾向から、リアルタイム分散処理に関する機運の高まりを感じます。この調子だと、2014年はリアルタイム分散処理でアドベントカレンダーを立ち上げられるくらいの年になるのではと、期待しています。

さて、リアルタイム分散処理を行うプロダクトはSparkSplunkStorm等、様々あります。中でもStormは、このブログで特に取り上げてきました。そこで、今回はStorm関連本についてまとめてみました。
あっ、私が知らないだけで、他にもオススメの本があれば是非教えてください^^

Getting Started With Storm

Getting Started With Storm

  • 作者: Jonathan Leibiusky,Gabriel Eisbruch,Dario Simonassi
  • 出版社/メーカー: Oreilly & Associates Inc
  • 発売日: 2012/09/17
  • メディア: ペーパーバック
  • クリック: 1回
  • この商品を含むブログを見る
92ページとコンパクトですが、Topology、Spout、Boltといった概念を図やコード付きで一通り説明しています。また、後半では、Node.jsやRedisと連携してECサイトを構築する例が載っています。ただし、Stormは0.7.1を使っていて、現在ではAPIが変更されている箇所があるため注意が必要です。

f:id:acro-engineer:20140109230121g:plain
「Getting Started with Storm」の日本語訳です。Ebookのみ販売されています。

Storm Real-time Processing Cookbook

Storm Real-time Processing Cookbook

ログファイルを集めてStormで処理した結果をElasticsearch+Kibanaで処理したり、機械学習したり、AWSに載せたり、様々なことにチャレンジしています。
この本を出版しているPackt Publishingは新しい技術の電子書籍を素早く、積極的に出版しています。また、年末に電子書籍の一律$5セールを行ったり、随分お世話になっています。書籍の種類も多いため、気になる方はPackt Publishingのサイトをチェックしてみてはいかがでしょうか。

f:id:acro-engineer:20131212194541j:plain
Manning PublicationsMEAP(Manning Early Access Program)です。正式出版は先ですが、書いたところから公開されています。2014年夏に正式出版予定です。まだ書かれていませんが、目次を見るとチューニングトラブルシュートの章があるので、期待しています。
Manning Publicationsは「~~ in Action」シリーズを出版している会社で、中でもMEAPは新しい技術についてすぐに読むことができるので、素敵な企画だと思います。また、一年中、日替わりで電子書籍の半額セールを行っているので、欲しい本がある人は半額になるタイミングを待つのがオススメです!

f:id:acro-engineer:20140110001915j:plain
これもMEAPです。Stormの作者であるNathan Marzさんが著者のひとりです。2014年3月に正式出版予定です。twitterハッシュタグをリアリタイム分析するために生まれた「ラムダ・アーキテクチャ」(このアーキテクチャにStormが組み込まれています)の説明などがあり、Stormに限らず、ビッグデータ周りのアーキテクチャおさえる上でも良いと思います。以下のページでは、ラムダ・アーキテクチャの日本語での解説が読めます。非常にありがたいですね。
  ハッシュタグのリアルタイム分析のためのラムダ・アーキテクチャー

The Storm Book

The Storm Book

書名を見て思わず買ってしまった、その名も「The Storm book」。32ページと手軽なサイズ。また、本全体の半分は絵だけのページとなっており、
小学生でも読めるStorm関連本(^^)となっています。
Amazonのカスタマーレビューでは★★★★★のコメントがいくつも寄せられているので、小さなお子さんがいる方は、Stormの英才教育をすべく、寝る前に読み聞かせてみましょう!

……はい、どう見てもただの絵本です。本当にありがとうございました^^


さて、いかがだったでしょうか?
最後の本はともかく、今年は一層盛り上がる(と思っています!)リアルタイム分散処理、中でもStormを学ぶ際に参考になればと思います。

ちなみに、Stormの入門には以下のSlideShareがオススメです^^


Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ

本ブログの2013年を振り返る!

レコード大賞をAKBではなくEXILEが取るというニュースが届く年末の候、皆様いかがお過ごしでしょうか、推しメンはまゆゆの@です。

さて、アベノミクスが駆け巡り、株価の大幅上昇と円安が続く中、オリンピックが決まり、さらには流行語大賞が4つもあった2013年ですが、何か1年間のうちに4年間ぐらいがギュッと詰め込まれたようでもありました。

そんな慌ただしかった2013年の、このTaste of Tech Topics、通称T3blogを振り返ってみたいと思います。

■実はかなり飛躍した2013年

2013年には、全部で62の投稿がありました。平均すると週に1本以上の投稿があった事になります。
実は昨年、一昨年もほぼ同じぐらいの投稿数があって、同じペースでの投稿が続いています。これはもう「ほぼ週T3blog」と言って差し支えないでしょう。

そんな中、大きな変化があったのは、実はブックマーク数。
はてなブックマークはてブ)でブックマークされた数が、昨年まで合計200弱だったところが、今年は一気に1600弱まで増えました。80倍だぞ、80倍(違う)
これまでは、ブクマもツイートもほぼほぼ0だったのですが、今年の後半から伸び始め、最近では、はてブ人気エントリーGunosyに取り上げられることも増えてきました。

興味をひく記事を提供できた部分もあるかも知れませんが、その一方で、RSSの終焉とキュレーションの台頭を感じさせます。
Google ReaderがクローズしたことがきっかけでRSS自体を使うのをやめ、Gunosyのようなキュレーションツールを使ったり、あるいは情報ソースを、はてブ人気エントリーTwitterに切り替える人も増えているように思います。そのような動向が、このブックマーク数(やツイート数)の飛躍に繋がる一因になったのではないでしょうかね?

もちろん、これほどの飛躍があったのは、日頃、記事を見てくださっている読者の皆さんのおかげです。
ありがとうございます&これからもよろしくお願いします!

それでは各記事にフォーカスして振り返ってみましょう。

1. キーワードランキング

まずは今年のエントリーで使われたキーワードのランキングを見てみましょう。2013年は、どのようなキーワードのエントリーが多かったのでしょうか。

1位 : Java (28エントリー)
2位 : Storm (13エントリー)
3位 : Java8 / vert.x / Netty (8エントリー)

やっぱりJavaのAcroquest、トップのキーワードはやっぱりJavaでした。
2位以下のキーワードもJava絡みのもので、いずれも何らかの形で連載していたエントリーが続いています。

まぁさしづめJavaのT3blog」と言うところでしょうね。

2. 最もブックマークされた記事は「Backbone.js 入門まとめ」

はてなブログで提供している本ブログ、やはり、はてなブックマークの数は気になるところです。
2013年、最もブックマークされたエントリーは、これでした。

試して学ぶ Backbone.js 入門のまとめ by @

近年話題のJavaScript MVCですが、その中でも軽量で他と組み合わせやすいという点で注目しているのが「Backbone.js」です。
Knowledge Noteにて連載していた記事をまとめたエントリーが、ブックマーク数454で堂々の第一位でした。

3. 最もツイートされた記事は「ラムダ禁止」

先ほど、情報ソースをTwitterに頼っている人も増えているようだと書いたとおり、やはりツイート数も見逃せません。
2013年、最もツイートされたエントリーは、こちらです。

ラムダ禁止について本気出して考えてみた - 9つのパターンで見るStream API by @

Java8から導入されるラムダ式について、特にStream APIについて可読性や安全性の観点から論じたエントリーが、ツイート数212で首位になりました。
微妙なテーマを扱い、賛否両論あるところが話題になりやすかったということでしょうか。

http://blog.exoego.net/2013/12/control-collector-to-rule-stream-api.html
このようなトラックバックを頂くなどの広がりもあってとても嬉しいですね。2014年はこの辺りの議論がまだまだ広がると思っています。

4. 今年最初のホッテントリーは「Vert.x」

ブックマーク数やツイート数が飛躍的に伸びたT3blogですが、今年最初のホッテントリーは、こちらでした。

Vert.x がいいね!(第1回:入門する) by @

Javaのイベントドリブンプラットフォーム、平たく言うとにJava版node.jsである「Vert.x」の入門エントリーです。
ブックマーク数89、ツイート数67のスマッシュヒットになりました。
Vert.xと言えば、先頃にもハンズオン形式の勉強会などが行なわれたことが記憶に新しいですが、2014年、もうひと伸びありますかね!?

5. その他の人気エントリー、「JMH」と「Storm」

今年は他にもいくつか人気エントリーがあったので紹介しておきます。

Javaのマイクロベンチマークツール「JMH」 by @

Javaのマイクロベンチマークツールである「JMH」のエントリーが、ブックマーク数88、ツイート数70でした。
Java8のリリースもある2014年には、パフォーマンスを語るためにもマイクロベンチマークが利用される機会がもう少し増えるのではないかと予想しています。

Kafka+Storm+Elasticsearch+Kibanaでストリームデータ処理の可視化を行ってみた by @

Acroの「ストリームデータ処理」の急先鋒、ペンギンのアイコンでおなじみkimukimuのエントリーです。ブックマーク数55、ツイート数53でした。

これらの人気エントリーを振り返ってみると、T3blogでは出たばかりの新プロダクトや、あまり知られていないながらも良質なプロダクトを、積極的に使って紹介するようなエントリーが人気を獲得しているようですね。

要するに「好奇心溢れるT3blog」ということですね。

■今年のアクセス数トップのエントリーは、なんと・・・

どれだけブクマされようが、どれだけツイートされようが、結局のところ、エントリーは読まれてナンボです。
今年最もアクセスされた記事は何だったのでしょうか。

Excel関数 SUMPRODUCTを使いこなす by 阪本

えっ・・・?
圧倒的1位は、なんと、昨年、阪本さんが書いた「SUMPRODUCT」のエントリーでした。詳しい数字は出せないのですが、今年だけでも10万PV以上を稼ぎだし、2位以下に5倍以上の差をつけています (^^;
どうやらYahooやGoogleで「SUMPRODUCT」を検索すると、このエントリーが1位に来るようですね。

要するに、@とか@とかは、単にbuzzるだけで、結局は阪本さんのような真面目な(?)エントリーこそがアクセスされるんだと、そういう事実を突きつけられた感じの結果になりました。(><)

ちなみにこのエントリーへのアクセス元は、ほとんどYahooからでした。
なんとなく、事務のお姉さんとかが、いっぱい見に来てくれているという感じがします。正直、うらやましいです。

■まとめ

世の中、結局、Excelで動いている。

えーっ、そんな結論やだー!(ジタバタ)

いやはや、来年はこの結果を覆せるような良質エントリーを書けるよう、もっと邁進しましょう!



それでは皆さん、良いお年を!!
 

Acroquest Technologyでは、キャリア採用を行っています。


  • 日頃勉強している成果を、Hadoop、Storm、NoSQL、HTML5/CSS3/JavaScriptといった最新の技術を使ったプロジェクトで発揮したい。
  • 社会貢献性の高いプロジェクトに提案からリリースまで携わりたい。
  • 書籍・雑誌等の執筆や対外的な勉強会の開催を通した技術の発信や、社内勉強会での技術情報共有により、技術的に成長したい。
  • OSSの開発に携わりたい。

 
少しでも上記に興味を持たれた方は、是非以下のページをご覧ください。
 キャリア採用ページ