2016年9月27日火曜日

【JavaでPlayFramwork2.4.6】routesファイル

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

ただ今、もうすぐ始まるプロジェクトの実装で使用するPlayFrameworkについて事前勉強を進めています。


今回はURLを制御するroutesファイルについてご紹介します。

伝説のXML地獄


JavaWebシステム業界では長年の間、Struts1が支配的な地位を占めてきました。
そこで常に大問題を起こしてきたのが「struts-config.xml」「web.xml」という巨大XMLです。

コイツラはWebシステムが受け付けるURLを制御したり、そのリクエストを行った際に取得するパラメータを格納するFormや、遷移先のjspなど、WebシステムのWeb部分を管轄する設定ファイル達です。

欠点は、もの凄く煩雑なんですよね!!

基本的にココで躓くのは新人レベルの人なのですが、XMLなんでちょっと壊れただけでも動かなくなりますし、設定が間違っていても動かないし、ログを追うのも難しいし、と不慣れな若手プログラマーの未来の芽を摘むのに多大な役割を果してきました。

更にORMappingにSpringとHibernateを導入すれば完璧。

今やJavaWebシステム業界の金字塔とも言える究極のXML地獄が完成します。

これね、慣れれば分かるんですよ。でも不慣れだと全然分からない。
だから自分が数年の月日を経て手慣れてきても、その頃には会社には後輩が入ってきているわけで、「何か動かないんですけど~」と単体環境で起動も出来ないような始末になっていることは日常茶飯事。

あのXML地獄は最悪だとみんな身に染みて分かっているんですね。
そうして出てきた概念が、あの有名なRubyOnRailsのキャッチフレーズ、

「設定より規約」

です。

一言で言いますと、「ファイル名、クラス名を合わせておけばXMLは省略出来るよ」というものです。

RubyOnRailsの命脈を引き継ぐPlayFramworkもこの思想がありまして、膨大な設定ファイルを多数記述しなくても、ある程度の命名規約に則してソースを作っておくだけでとりあえず動いてくれる。

もう「設定より規約」はRubyOnRailsがどうこうと言うより、Webシステム業界の基本概念と言って良いくらいになってきましたね。

今回はPlayFramworkでURL制御をする為のやり方を検証してみたいと思います。

コントローラ


まず最初にリクエストを叩いた直後に呼び出されるクラス「コントローラ」を作成します。

public class LoginController extends Controller {
 /**
  * @return Result
  */
 public Result index() {

  Form userForm = Form.form(LoginForm.class);

  return ok(views.html.layout.login.render(userForm));
 }

}


命名規約と言っておいてなんですが、実際には「Controllerクラスを継承する」という点だけ守っておけばOKです。

しかし、ここで特徴が一つ。
コントローラを格納するcontrollersパッケージはルート直下に置くのがオススメです。


普通はJavaのパッケージって言うと組織を表現する長~いフルパスを指定するものじゃないですか?
弊社ジェニシスで言えば「jp.co.net.genesis.controllers」というパッケージにするのがJava業界のお約束ですが、PlayFrameworkはいきなり「controllers」だけにするのが普通です。

理由は後述します。

routesファイル


クラスを作ったところで、次にURLの定義に移ります。

上記「LoginController」のメソッド「index」とURLリクエストを結びつけるには、confフォルダ配下のroutesファイルに以下のように記述すればOKです。


GET     /                           controllers.LoginController.index()
GET     /login/                           controllers.LoginController.index()


見た目そのままかと。簡単ですね。

RubyOnRailsと違い「LoginというURLを打ち込めば自動的にLoginクラス」という挙動はありません。
「設定より規約」の思想を受け継ぎつつも、この辺りは「規約より設定の方が便利」という崩しが入っているんですね。

ほら、上記の例だと「URLに何も入力しなかったら自動的にログインを表示」という挙動も簡単に表現できます。
このくらいが自動化するのに丁度良い塩梅だと考えたのでしょう。

また、従来のStruts1のAction方式が「1URL1アクションクラス」だったのに対し、PlayFrameworkのコントローラはメソッド分けにも対応しています。
なのでクラス数が膨大に増えていってしまう問題が解消されている一方、URL設計をちゃんとやらないと1クラスにメソッドが大量終結してしまう欠点があります。
この辺りは設計者の腕の見せ所ですね。

しかし、ここで注意事項。

  • controllers.LoginController.index()

「controllers」という文字がありますね。そう、このroutesファイルの記述はフルパスなんですよ。
これが上記でルート直下をオススメした理由です。

もし「jp.co.net.genesis.controllers」と書いてしまうと、記述がこうなります。

  • jp.co.net.genesis.controllers.LoginController.index()

長いんですよ。
もちろん1システムにURL数は数十~数百まで沢山ありますから、もし会社名まで含めたパッケージにしてしまうと、routesファイルは以下のようになってしまいます。


  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()
  • jp.co.net.genesis.controllers.xxx.xxxx()

これは冗長でしょう!!

気にしなければ良いと言えばそれだけなのですが、PlayFrameworkは軽快にアプリケーションを作っていくという思想がありますから、「フルパスがどれだけ長かろうがコピペするだけなんだから作業効率は変わらん」ということは分かりつつも、
出来るだけ記述する文字数を減らすのがPlayFramework。

伝統的なJavaエンジニアにはちょっと気持ち悪いですが、ここはルートフォルダ直下にcontrollersパッケージを置くのがPlayFrameworkの標準かな、という所感です。

終わりに


これでURL制御は終わりです。
PlayFrameworkの簡単さがよく分かる一例だったと思います。

引き続きPlayFrameworkの検証を進めます。

2016年9月20日火曜日

【JavaでPlayFramwork2.4.6】ログ出力とフィルター

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務多忙により更新が停滞していましたが、再びPlayFrameworkの連載を復活します。

ログ出力

システムを構築する時に最初にどこから作っていくか、というところは個人の趣味があるところかと思いますが、私の場合はまずログ出力から固めていきます。
今回はログ出力についてご紹介します。

出力本体

PlayFrameworkのログ出力と銘打ってこんな記事を書いていますが、PlayFrameworkはJavaを内包していますから、早い話が単なるLog4jなんですよね。


PlayFrameworkの中には最初からLog4jが入っていますので、素直にコレを使えば良いかと。
log4jの標準に従ってlogback.xmlを設置すればその通りに動いてくれるようになります。

この辺りはPlayFrameworkの話ではなくlog4jそのままの話ですので、この記事でわざわざ記述するほどの話ではないかと。

今回はここから一歩踏み込みまして「リクエストの開始と終了のログ」を出力する方法に行ってみたいと思います。

ロギングフィルター


純粋なJavaのフレームワークであれば、リクエストの開始と終了は「doGet」とか「doPost」のメソッドの最初と終了にログを出力するようAbstractの親クラスを作るだけの話ですが、PlayFrameworkはそういう風に出来ていませんのでちょっとしたコツが必要になります。

そのテクニックを「フィルター」と言います。


フィルターとは、前回でご紹介したGrobal.javaに適応するものでして、
全てのリクエストの開始時に呼び出される共通処理を提供する機能です。

使い方はGrobal.javaのメソッド「filters()」にフィルタークラスをセットするだけでOKです。

 /**
  * Get the filters that should be used to handle each request.
  */
 @Override
 public  Class[] filters() {

  Class[] clazz = new Class[1];
  clazz[0] = RequestLogFilter.class;

  return clazz;
 }

これで全てのリクエストの開始時に「RequestLogFilter」が呼び出されますので、そこにログ出力の処理を書けば良いわけですね。
ただし、Filterはscalaで書かなければなりません。

PlayFrameworkでJavaを選択したプロジェクトであってもFilterクラスはscalaのみなのでご注意を。

しかしですので、Filterというのは開始時に呼び出されるものであって、終了時には呼び出されません。
よって「リクエストの終了ログはどうやって出すの?」という問題が発生します。

これにつきましてもPlayFrameworkとscalaならではの機能で実現してくれます。

traitとインターセプター


以下が私が使用しているログフィルターです。

class RequestLogFilter extends EssentialFilter {

  def apply(nextFilter: EssentialAction) = new EssentialAction {

    def apply(requestHeader: RequestHeader) = {

      def isTarget = RequestLogFilterUtils.isLonningTarget(requestHeader.uri);

      val startTime = System.currentTimeMillis

      if (isTarget) {
        Logger.info(RequestLogFilterUtils.getStartLog(requestHeader.method, requestHeader.uri))
      }

      nextFilter(requestHeader).map { result =>

        val requestTime = System.currentTimeMillis - startTime

        if (isTarget) {
          Logger.info(RequestLogFilterUtils.getEndLog(requestHeader.method, requestHeader.uri, result.header.status, requestTime))
        }

        result.withHeaders("Request-Time" -> requestTime.toString)

      }

    }

  }

}


RequestLogFilterUtilsというのは、私はscalaが不見識ですので文字列加工機能部分だけJavaに切り出しているだけなので気にする必要はありません。
今回のポイントはこちら。

nextFilter(requestHeader).map { result =>


nextFilterです。

resultという単語が出ていることから察せられるとおり、この中身がリクエストの終了時に呼び出されることになります。

?????

Javaエンジニアには意味不明な機構ですね。

これはscalaが搭載している「trait」という機能でして、Javaで言うところのインターフェースに近い性質を持つものです。
ただし、インターフェースほどカッチリとはしておらず、より柔軟性を持たせたものである模様。

ともかく、流れたとしては、

  1. リクエストが来る。
  2. リクエストをフィルターでインターセプト(傍受)する。
  3. リクエストにフィルターで定義した機能を挟み込む。

こういうちょっとメタっぽい形でリクエストにフィルター機能を持たせます。

そして開始ログを提供するメイン部分は普通にそのまま実行。
終了ログ部分は「trait」を使って定義しておいて、リクエスト終了時に後から呼び出す(chainするように)ようにフィルターの親クラスである「EssentialFilter」が作られている、とこういう構図なようです。

むむ。
これはPlayFrameworkの中でもかなりscala寄りの部分なようですね。
本格的に理解を深めるにはscalaの勉強を深めなければならなさそうですが、この連載は「JavaでPlayFramwork」なので掘り下げはこの辺り留めたいと思います。

終わりに


引き続きPlayFrameworkの勉強を進めます。

2016年7月25日月曜日

【JavaでPlayFramwork2.4.6】Grobal.java

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近はPlayFrameworkについて勉強を進めています。

前回まででプロジェクトの作成に成功したところで、今回はいよいよ細かい機能の確認に入っていきたいと思います。
今回のテーマは「Grobal.java」です。

Grobal.java


公式の参考ページは以下です。


上記はバージョンPlay2.3の話です。
本ブログで取り扱うのは2.4.6ですが、公式そのものが枯れていないので公式に無い話を取り扱うのもやむなし。
頑張っていきましょう。

役割


まず、Grobalクラスの役割は全てのコントローラクラスの総合継承クラスとでも言いましょうか。
本来コントローラが担当するURLリクエスト活動の親クラスとしての他、システムの初回起動時専用など全体的な共通処理を担当するクラスです。

従って、

  • システム初回起動時に一回だけ行いたい処理
  • 各URLのリクエスト時に毎回実行したい処理

この辺りがGrobalクラスの役割と言えるでしょう。

特徴


Grobalクラスの特徴は、やはりクラス名が「Grobal」であるということです。
「Grobal2」とかちょっとクラス名を変えただけで動きません。
そう、Grobalクラスは、場所がルート直下で、クラス名がGrobal.javaであるというネーミング規約があります。

後は、「GlobalSettingsクラス」を継承しているという点くらいでしょうか。

public class Global extends GlobalSettings {


私が特徴に思うのは、やっぱり「Grobal.java」であることというネーミング規約が敷かれている点でしょうか。
「Grobal2」とかちょっとでも違うネーミングにするともう動きません。

外部ファイル名ではなくJava本体のクラス名にこのような規約を設定するのはJavaプログラミングでは余り見かけない特徴だと思います。
この辺りがscalaベースとしているPlayFramworkの特徴でしょう。

このように、JavaがJavaクラスのクラスやメソッドを「文字列として認識」して振り分けるという機能を「リフレクション」と言います。

メタプログラミングと言い換えても良いでしょうか。

普通にシステム開発者として従事している間は余り需要はありあせんが、ライブラリ開発社の立場からすると偶に裏技として出番がある時があります。
「こういう使い道もある」という程度に覚えておくと良いかもしれませんね。


各メソッド


Global.javaが実現する機能は親クラスであるGlobalSettingsの実装に準拠しています。


public class GlobalSettings {

    /**
     * Executed before any plugin - you can set-up your database schema here, for instance.
     */
    public void beforeStart(Application app) {
    }

    /**
     * Executed after all plugins, including the database set-up with Evolutions and the EBean wrapper.
     * This is a good place to execute some of your application code to create entries, for instance.
     */
    public void onStart(Application app) {
    }

    /**
     * Executed when the application stops.
     */
    public void onStop(Application app) {
    }

    /**
     * Called when an exception occurred.
     *
     * The default is to send the framework's default error page. This is achieved by returning null,
     * so that the Scala engine handles the excepetion and shows an error page.
     *
     * By overriding this method one can provide an alternative error page.
     *
     * @param t is any throwable
     * @return null as the default implementation
     */
    public F.Promise onError(RequestHeader request, Throwable t) {
        return null;
    }

    /**
     * Call to create the root Action of a request for a Java application.
     * The request and actionMethod values are passed for information.
     *
     * @param request The HTTP Request
     * @param actionMethod The action method containing the user code for this Action.
     * @return The default implementation returns a raw Action calling the method.
     */
    @SuppressWarnings("rawtypes")
    public Action onRequest(Request request, Method actionMethod) {
        return new Action.Simple() {
            public F.Promise call(Context ctx) throws Throwable {
                return delegate.call(ctx);
            }
        };
    }

    /**
    *
    * Called when an HTTP request has been received.
    * The default implementation (return null) means to use the application router to find the appropriate action
    *
    * By overriding this method one can provide an alternative routing mechanism.
    * Please note, though, this API is very low level, useful for plugin/module authors only.
    *
    * @param request the HTTP request header as seen by the core framework (the body has not been parsed yet)
    * @return an action to handle this request - if no action is returned, a 404 not found result will be sent to client
    */
    public play.api.mvc.Handler onRouteRequest(RequestHeader request) {
        return null;
    }

    /**
     * Called when no action was found to serve a request.
     *
     * The default behavior is to render the framework's default 404 page. This is achieved by returning null,
     * so that the Scala engine handles onHandlerNotFound.
     *
     * By overriding this method one can provide an alternative 404 page.
     *
     * @param request the HTTP request
     * @return null in the default implementation, you can return your own custom Result in your Global class.
     */
    public F.Promise onHandlerNotFound(RequestHeader request) {
        return null;
    }

    /**
     * Called when an action has been found, but the request parsing has failed.
     *
     * The default behavior is to render the framework's default 400 page. This is achieved by returning null,
     * so that the Scala engine handles onBadRequest.
     *
     * By overriding this method one can provide an alternative 400 page.
     *
     * @param request the HTTP request
     * @return null in the default implementation, you can return your own custom Result in your Global class.
     */
    public F.Promise onBadRequest(RequestHeader request, String error) {
        return null;
    }

    /**
     * Get the filters that should be used to handle each request.
     */
    public  Class[] filters() {
        return new Class[0];
    }

}


メソッドを抜き出すと以下です。

  • beforeStart
  • onStart
  • onStop
  • onError
  • onRequest
  • onRouteRequest
  • onHandlerNotFound
  • onBadRequest
  • filters

色々ありますね……。

このうち、私が現在のシステム開発で必要としているのは以下です。

  • beforeStart:システム初回起動
  • onRequest:各種リクエスト実行時
  • filters:フィルター

beforeStartメソッドというのはシステムで最初にリクエストを受けた時だけ実行されるメソッドです。
シングルトンクラスの初期化などで実行するのが良いでしょう。

onRequestメソッドはリクエスト毎に毎回実行。

filtersメソッドは、onRequestに連動しているものです。

各種リクエストの開始終了ログなど、システムの最初に用意するログ機構についてはこの辺りが活躍するわけですね。

終わりに


次回はログ出力の手法についてご紹介したいと思います。

2016年7月4日月曜日

【JavaでPlayFramwork2.4.6】Eclipseへの取り込み

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近はPlayFrameworkについて勉強を進めています。

前回にて一応、プロジェクトの作成には成功しました。
次はEclipseへの取り込みに行ってみましょう。

開発環境はEclipse


まず大前提ですが、Javaで開発するんだからそりゃEclipse使いたいですよね?
と言いますのも、PlayFrameworkは根っこの思想がScalaなので、根本的には「Eclipseみたいな派手な総合開発環境(IDE)が無くてもテキストエディターだけで実装出来るよ」というものがあります。

いや、確かにそうなのかもしれませんけど、何をするにもやっぱIDEはあった方が良いと思います。

これは他の言語でも同じ。
PHPでもRubyでもその他でも、テキストエディターとかviとかだけで実装する熟練の戦士は確かに一定数いるとは聞きますが、今は文明の利器であるIDEがあるんだから使えばいいしょ。

「最近の若いもんはEclipseが無ければコード一つマトモに書けやしない……」

別にいいだろ! あるんだから使えば!!

と言う訳で、実装パワーをIDEに頼り切るスタイルは今後も継続です。

しかし、問題はどのIDEを使うか、ですね。

  • Eclipse
  • IntelliJ IDEA

ご存じのように、日本ではEclipseがぶっちぎりの一強、事実上のスタンダード。
しかし世界を見渡すとIntelliJ IDEAもなかなかのシェアを誇る。

最近はAndroidアプリ開発専用IDE「AndroidStudio」がIntelliJ IDEAのカスタマイズで作られている辺り、日本人でもIntelliJ IDEAを無視できなくなってきました。

「IntelliJ IDEAの方がEclipseより優れている部分もあるんだぜ!!」

みたいな話も調べると出てきますし、IntelliJ IDEAの習得は将来性を鑑みたJavaエンジニアの課題として一考に値するものだと言えるでしょう。

しかし、今回の所はEclipseでやらせて頂きたいと思います。
私自身がEclipseに慣れっこなのでEclipse以外は気が進まないというのもありますが、何より、私以外の要員も私と同じくEclipse派ばかりですので。
IntelliJ IDEAを導入するには説明出来るだけの合理性と、要員の教育、全員のモチベーションが必要で、そういった体制も考えるとEclipse以外の選択は厳しいのです。

プロジェクトのインポート

では、さっそくEclipseに取り込んでいきましょう。
前回までで「Activator new」で作ったプロジェクトをEclipseのworkspace配下に置いて、プロジェクトを取り込みます。

当然ながら、Eclipseの「プロジェクトの作成」で作るわけでは無いということです。

結果がこちら。


この時点ではプロジェクトにEclipse設定ファイルがありませんので、ご覧のようにJavaプロジェクトではなくファイル一覧のように見えてしまっています。

これをEcipseに対応させるには、Play公式にやり方が掲載されています。


まずプラグイン「sbteclipse」を入れます。project/plugins.sbt に以下の記述を入れるだけでOK。

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")

この『プラグイン』というものに他にどんなものがあるのか、探していくのも面白そうですね。

次に、Activatorで「Eclipse」というコマンドを発行します。


すると、以下のようにプロジェクトにクラスパス等が通ってすっかりJavaプロジェクト風になりました。


特にエラーも起きていませんね……。
おかしいな……。

いえ、実はですね、私が最初に行った時はここまでやってもEclipseにエラーが発生していたのです。
原因はこちら。


赤枠の部分。

  • target/scala-2.11/twirl/main
  • target/scala-2.1.1/routes/main

これが自動的に入ってくれないのでscalaクラスの変数がコンパイルエラーを起こすというものがあったのです。


Application.javaの変数「index」が変数解決不能のエラーを起こしていたら、それはソースフォルダに「scala-2.11/twirl/main」「scala-2.1.1/routes/main」が入っていないことが原因だから手動で追加しろという内容の記事を書こうと思っていたんですが……。

ちくしょー。
私が最初に検証を行っていた4月の頃から今記事を書いている7月の現時点まででこの問題が解消されてやがる。

だからこれからPlayを始める人はこんなことに悩まなくて良いんだ……。

すいませんね。
私は画像キャプチャを取る為に過去に行った作業を一からやり直しながら記事を執筆しており、当時存在していたEclipseコマンドのバグがいつの間にか修正されていることに今気付いたのですよ。

ここまで書いて記事を消すのも悲しいので、本日はこれにて終了……。

PlayFramworkは非常にホットなライブラリなので、過去にあった問題がサラッと直っていることもあるということです。

終わりに


やられましたね、これは!!

しかし過去に存在した問題がアップデートで解決するのは望ましいこと。
Tacyは人柱になったと思って祈りを捧げて下さい。

引き続きPlayの連載を継続します。

2016年6月20日月曜日

【JavaでPlayFramwork2.4.6】ビルド時のネットワーク問題と起動

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近はPlayFrameworkについて勉強を進めています。

プロジェクト起動


前回の荒技で、とにかく2.4.6でのプロジェクトは完成しました。

では、プロジェクトの起動に行ってみましょう。

コマンドプロンプトを起動し、

cd "作成したプロジェクトのフルパス"
activator run

これでプロジェクトが起動します。
が、実際には私はここで躓いたので、その時の経験談も踏まえて今回は雑談ベースです。

Activatorにパスが通っていない


私のような慌て者のエンジニアは上記の通りActivatorコマンドを実行しても「操作可能なプログラムまたはバッチ ファイルとして認識されていません。」とか出てくるかもしれませんね。
これはActivatorにパスが通っていないのでしょう。

PlayFrameworkの管理コマンドであるActivatorはダブルクリックで自動インストールするものではなく、圧縮ファイルを展開して設置し、そこに手動でパスを通さなければいけないものです。
この状況に陥っている人は公式サイトをもう一度ご確認下さい。


ネットワーク問題


PlayFrameworkはActivatorコマンド実行時とrun実行時の二回に分けてインターネット上からファイルをダウンロードしてくる挙動となっています。
従ってネットワーク環境に繋がっていない環境では起動出来ません。

私はここで大変苦労しました。
私の現在の現場環境はセキュリティが大変厳しいので自由にインターネット接続出来ません。
よってsbtのビルドで自動であっちこっちからjarファイル等のライブラリをダウンロードしてくるのは望ましくなかった為、オフラインビルドを試みました。


公式サイトのダウンロードページに「Offline Distribution」というリンクがあり、これがsbt実行ダウンロードするファイルを最初から一塊で取得出来るものです。
これを取得し、USBメモリでオフラインPCに移動させて、いざオフラインPCから起動……とやってみたわけですが……。

結論を言うと、無理!!
初回のオフラインビルドは現実的ではありません。

と言いますのも、どうやら「Offline Distribution」と言えども全部入っているわけではないようです。
インターネット界は日々進化していますので、細かいバージョンの差分とかが発生してしまって「Offline Distribution」には既に古くなってしまったものが混ざっているのです。

また、「Offline Distribution」はあくまで初回セットであり、そこから追加で何かプラグインを入れたりするとなると、当然ながら「Offline Distribution」の中にはありません。

「Offline Distribution」に入っていないものは別途、手動でネットからダウンロードしてオフラインPCに移植し……と頑張ってみましたが、無理でした。
取得しなければならないファイルは一個や二個の話ではないので、手動ダウンロードを繰り返してビルドしようと思ったら一日では終わりません。

二日……三日……どれくらい頑張ったら出来るんだろう???

とにかく、インターネットビルドを使わず手動ビルドで初回起動するのは三途の川のほとりで石を積み上げるようなものです。

頑張ってもゴールに辿り着けませんので、これからビルドする人は絶対にインターネット環境でビルドすることをオススメします。

  • オフラインだけでのビルドは至難。オンライン環境は事実上の必須。
  • どうしてもオフラインでビルドしなければならない場合、最初だけオンラインでビルドし、ダウンロードしたファイルをオフラインPCに移植する。

ただし、あくまでも初回起動時にjarファイルを収集するステップが大変なだけですので、一度ビルド出来てしまえば、後はオフラインでもOKです。
複数人で作業する場合も、最初に一台だけインターネット環境でビルドし、集めたjarファイルをUSBメモリ等で他のオフラインPCに移植すれば、全部オフラインでも起動出来ます。

経験者ならではの体験談ですね。。。

プロキシ


当然ながら社内などプロキシがある環境で実行する場合、プロキシが通っていなければインターネットに接続出来ません。

これは知っている人は当然でしょうが、私は初体験でした。
インターネットオプションのプロキシと、コマンドプロンプトのプロキシは別です。

コマンドプロンプト実行時にプロキシ接続する場合は、例えば以下のようにコマンドラインからプロキシを設定するとか、
システム詳細の環境変数で事前にプロキシ設定を登録するといった対応の必要があります。

set HTTP_PROXY=http://プロキシサーバ:ポート番号/

この辺りはPlayの話というよりネットワークの問題ですので、各環境毎に奮闘願います。
簡単そうで意外に難しかったです。

起動成功

こうして環境の壁を越えて、何とかようやく初回起動出来ました。
「http://localhost:9000/」で以下のような画面が表示出来ます。


私の場合はネットワークの壁があったので大変苦労しましたが、それが無い環境でしたらスルッと簡単に起動まで辿り着けると思います。

やっぱり開発者には快適なインターネット環境は必要不可欠ですね。。。

終わりに


これにてようやく初回起動まで辿り着きました。
引き続き勉強を継続していきます。

2016年6月6日月曜日

【JavaでPlayFramwork2.4.6】プロジェクト作成 後編 ~古いバージョンで作成する~

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務都合によりPlayFramworkを始めました。
ここまでの下勉強により、PlayFramworkのバージョンは2.4.6にすることにしました。

しかし、PlayFramworkは最新バージョンで作成するのは簡単なのですが、古いバージョンで作成するのは面倒なのです。
今回は古いバージョンで作成する手順をご紹介します。

バージョン指定が出来ない


おさらいから行ってみましょう。
PlayFrameworkではプロジェクトを新規作成する場合、コマンドプロンプトでActivatorのnewコマンドを実行すれば一発で作成出来ます。

activator new my-first-app play-java

この時、Activatorはインターネットに接続し、Play本家のサイトから最新バージョンをサーチして取得するという挙動をします。
勝手に最新バージョンを取得してしまい、古いバージョンは取得出来ません。

「-version=2.4.6」のようにオプションを指定することで古いバージョンを取得する機能はありません。

これくらい出来そうな気がするんですけどね。何で無いんだろ……。

しかし、自動で作成出来ないなら手動で作成しましょう。

テンプレートをダウンロード


PlayFrameworkのnewコマンドが最新バージョンになってしまうのは、最新のテンプレートをダウンロードしてくるからです。
そして過去のテンプレートはGitHubに置いてありますので、これを手動でダウンロードすればテンプレートは入手可能です。

以下サイトからお好みのバージョンをダウンロードしてきてください。
私は2.4.6をダウンロードします。


解凍すると、中に「templates」というフォルダが入っています。


その中には2.4.6テンプレート4種が入っています。


これこれ、これが欲しかったんですよ。
私はJavaを使用しますので「play-java」をゲッツします。


その中身は、このように「Activator new」した時とほぼ同じ構成になっています。
PlayFramework初心者はこの状態からスタートするのが最もスムーズに入っていく近道でしょう。

しかし、この状態でアプリを起動しようとするとまだエラーが発生してしまいます。



  • :: org.scala-sbt#sbt;%SBT_VERSION%: java.lang.IllegalArgumentException at sun.net.www.ParseUtil.decode(ParseUtil.java:202)

%SBT_VERSION%!!

バージョン指定。
つまり、本来はnewコマンドが自動で行ってくれる設定ファイルへの最新バージョンセット機能が作動していない。
よってここから先は手動でバージョンを記述することになります。

「手動でセットって、どんな値をセットすればいいの?」という問題につきましては、フォルダを一個遡ってtemplatesフォルダ直下のbuild.sbtに書いてあります。

import play.sbt.activator.Templates._

templateSettings

scalaVersion := {
  // If we're a snapshot build, then default to 2.10.5, since this is what gets built by default for Play
  // If we're a production build, then we want 2.11.6
  sys.props.getOrElse("scala.version", if (isSnapshot.value) {
    "2.10.5"
  } else {
    "2.11.6"
  })
}

crossScalaVersions := Seq("2.10.5", "2.11.6")

templates := {
  val dir = baseDirectory.value
  Seq(
    "play-scala",
    "play-java",
    "play-scala-intro",
    "play-java-intro"
  ).map(template => dir / template)
}

version := sys.props.getOrElse("play.version", version.value)

def playDocsUrl(version: String) = {
  // Use a version like 2.4.x for the documentation
  val docVersion = version.replaceAll("""(\d+)\.(\d+)\D(.*)""", "$1.$2.x")
  s"http://www.playframework.com/documentation/${docVersion}"
}

// Use different names for release and milestone templates
def templateNameAndTitle(version: String) = {
  val officialRelease = version.matches("[0-9.]+") // Match final versions but not *-SNAPSHOT or *-RC1
  if (officialRelease) ("", "") else ("-preview", " (Preview)")
}

templateParameters := Map(
  "PLAY_VERSION" -> version.value,
  "SCALA_VERSION" -> scalaVersion.value,
  "PLAY_DOCS_URL" -> playDocsUrl(version.value),
  "SBT_VERSION" -> "0.13.8",
  "COFFEESCRIPT_VERSION" -> "1.0.0",
  "LESS_VERSION" -> "1.0.6",
  "JSHINT_VERSION" -> "1.0.3",
  "DIGEST_VERSION" -> "1.1.0",
  "RJS_VERSION" -> "1.0.7",
  "MOCHA_VERSION" -> "1.1.0",
  "ENHANCER_VERSION" -> "1.1.0",
  "EBEAN_VERSION" -> "1.0.0",
  "PLAY_SLICK_VERSION" -> "1.1.0",
  "TEMPLATE_NAME_SUFFIX" -> templateNameAndTitle(version.value)._1,
  "TEMPLATE_TITLE_SUFFIX" -> templateNameAndTitle(version.value)._2
)


パッと見て概ね意味は分かるのではないでしょうか?

例えば、「SBT_VERSION" -> "0.13.8"」と書かれていますので、
先ほどのエラーの「%SBT_VERSION%」の所には「0.13.8」を書けば良いという意味になります。

「"PLAY_VERSION" -> version.value」のように直球で書かれていない部分は、
「自分は2.4.6を使いたいんだから2.4.6だな」と判断していくことになります。

これらを元にplay-javaの以下ファイルにガンガン手動記述していってください。

  • play-java/build.sbt
  • play-java/project/build.properties
  • play-java/project/plugins.sbt

ちょっと数が多いので面倒ですが、正常に設定出来ていないと上記画像のようにコマンドプロンプト上にエラーが出来ますから、
地道にやっていけば10分くらいで起動まで到達出来ると思います。

これでPlayFramwork2.4.6の起動に成功しました。
おめでとうございます!!

終わりに


我ながら荒技ですね、このやり方は……。
元々がActivator newコマンド一発で可能な作業なわけですから、
build.sbtによるビルドを熟知している人なら、こんな手動置換作業を行わなくても自動でビルド出来るはずなのですが……。

しかし調べても分からなかったので今回はこのような手動ゴリ押し戦術で対処しました。

何か分かったら追加記事を書きたいと思います。

引き続きPlayFramworkの記事を継続します。

2016年5月30日月曜日

【JavaでPlayFramwork2.4.6】プロジェクト作成 前編

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務都合によりPlayFramworkを始めました。
ここまでの下勉強により、PlayFramworkのバージョンは2.4.6にすることにしました。

では、いよいよプロジェクトの新規作成に行ってみましょう。

Activatorのダウンロード

さて、PlayFrameworkの最初は「Activator」という管理ツールのダウンロードから始まります。
ダウンロードサイトはこちら。


しかしですね~、ここで一つ、驚きの事実が発覚します。


これね、2.2、2.3、2.4、2.5と色々とリンク揃ってるでしょ?
2.3~2.5は全部同じなんですよ。
何でこんなことになっとるんじゃ!!
ともかく、「よっしゃ。俺は2.4.6を使うから2.4.6をダウンロードするぞ!!」なんて指定には何の意味も無いのでどれでもいいから目に入ったヤツを適当にダウンロードしたってください。

しかし、2.2以前は違います。
前回の記事でPlayはバージョン毎の差異が結構あって、特に2.2と2.3の間の隔たりが大きいと書きましたが、その一番の理由がコレです。

「Activatorは2.3以降だけ。2.2以前はActivatorではない」

2.2までは「Playコマンド」っていう旧体系のものなのですね。

なのでコマンドプロンプトで「Play ……」ってやっているサイトが出てきたら、それは古い情報です。
2.3以降はこのActivatorコマンドを使用します。

Activatorのインストール

インストールについて特記事項は無いのでサラリと済ませましょう。
ダウンロードしたファイルを解凍して適当に置き、binフォルダに環境変数でパスを通せばOKです。

公式サイトにあるように済ませて下さい。


プロジェクト作成


Activatorにパスが通ったらプロジェクトの新規作成が可能になっています。
プロジェクトの作成は簡単です。
わざわざこのブログに記述せずとも公式サイトを見てそのままでOKかと思いますが、一応簡単にご紹介を。



プロジェクトを作成したい場所に移動し、コマンドプロンプトで「activator new」とすればプロジェクトの作成が始まります。


  • 1) minimal-akka-java-seed
  • 2) minimal-akka-scala-seed
  • 3) minimal-java
  • 4) minimal-scala
  • 5) play-java
  • 6) play-scala

「akka」というのはTypesafeが開発している並列分散フレームワークのakkaのことです。
並列分散?
つまり、サーバを1台、2台ではなく、ズラッと沢山並べて大規模処理を分散することを想定したフレームワークです。
今回は取り扱いませんが、こういうのもあるということだけ覚えておきましょう。

「minimal-java」は必要最小限のプロジェトの土台を作るだけのモード。
本当にちょろっとしか無いです。
詳しく知っている人ならともかく、初心者がここから構築していくのは無理じゃないかなぁ。

「play-java」はプロジェクトが一通り構築された状態から始められるコースです。
基本的にこの「play-java」を選ぶのが効率的スタートの起点となるでしょう。

なお、「scala」というのはJavaではなくscalaでプロジェクトを作るという意味です。
PlayFramworkはJavaでもslacaでもどちらでも使えるフレームワークですが、今回の連載はJavaで進行するので割愛。

では、play-javaを選んで次に進みます。

プロジェクト作成済み。しかし……


プロジェクト名は「play-sample」として、無事にプロジェクトが完成しました。


プロジェクト構成は一通り出来上がっており、「Hello World!」が表示可能状態です。
実に簡単ですね!!

しかし、ちょっと待って下さい。
「play-sample/project/plugins.sbt」を見ると以下のような記述があります。

  • addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.5.3")

そう、PlayFrameworkのActivatorは「自動的に最新バージョンを取得する」という仕様なのです。
つまり、このプロジェクトは「2.4.6」ではなく「2.5.3」で作られてしまっているわけです。

ここが最初の山場です!!

PlayFrameworkは最新バージョンで作成するのは簡単ですが、古いバージョンを指定して作る機能が見当たりません。

私もネットで散々探したのですが、どうやら「activator new version=2.4.6」みたいに簡単にスパッと作るコマンドは無いみたいなのです。

終わりに


次回後編は本番。

「PlayFrameworkを古いバージョンで始めたい場合にどうすれば良いのか?」


情報がどうしても見つからないので私が体当たりで編み出した荒技をご紹介します。

2016年5月23日月曜日

【JavaでPlayFramwork】バージョン選定⇒2.4.6

お久しぶりです。
株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務都合によりPlayFramworkを始めました。

が、実際にアプリ構築に入っていくまでにはまだSTEPがあります……。

要事前調査

PlayFramworkは慣れてしまえば簡単に開発していける……はずですが、全然枯れていないので猪突猛進に開始出来ないのが厄介な所です。
構築前に予備知識を得てから始めることをオススメします。

バージョン選定

PlayFramworkはバージョンが沢山ある上にバージョン毎の違いも大きいです!!
まず2016年5月時点でのリリース状況を見てみましょう。


.X系のバージョンアップだけ見ても以下のような状況です。

  • Play 2.5.3 (activator) Apr 27 2016
  • Play 2.4.6 (activator) Dec 14 2015
  • Play 2.3.10 (activator) Aug 3 2015
  • play-2.2.6.zip Nov 14 2014
  • play-2.1.5.zip Sep 20 2013
  • play-2.0.8.zip Sep 20 2013

ここ数年で2.0⇒2.5まで上がってしまっていますね。
しかも.X.Y系まで見ていると早い時は2週間でバージョンアップしたりします。

つまるところ、今プロジェクトを開始したところで、完成する頃には古くなってしまっているわけですよ。
そりゃライブラリはいつか古くなるものですけど、リリース前から旧式ってのは余り気分が良いものではありませんね。

しかも.X系の間では互換性が無いっぽい。。。
実際に今、2.4.6と2.5.3では違ってますもん。
これらを考慮しますと、私TacyはPlayFramworkを導入する上では.X系の一個前を選ぶことをオススメします。

つまり、2.5.3が最新である現時点では、一個前の世代の最終版である2.4.6を選ぶという意味です。

2016年5月現在、2.5系は情報が殆どありません。これを採用するのは人柱もいいとこ。
でも2.4.6だとまだいくらか情報がありますからね。

新しさと安定性のバランスを踏まえるとこれくらいが良いバランスでしょう。

2.2系からの卒業

このサイトに流れ着いてくる人の中には現在進行形で困惑している人もいるかもしれませんね。

PlayFrameworkは2.2と2.3以降では大きく違います。
そして、ネット上の情報はどうも2.2系が多いんですよ!!

私も自分のPCに入っているのが2.4.6なのに2.2の解説サイトを見てたので全く無駄な労力を費やしました。

何故こんなことになっているのか……。
恐らく、原因はコレ。


掌田 津耶乃氏による、ほぼ唯一と言って良い日本語のPlay Frameworkの参考図書です。
私も購入しましたが、これが2.2系なんですよ。
この参考書が日本PlayFramework界に支配的な影響を及ぼし、結果として情報サイトが2.2に占拠される結果になったとしか思えません。

でも、この参考書は2013年の古い情報ですからね。
この本のうち8割くらいは今でも通用しますが、2割くらいは別機能に差し替わっています。
そして、詰まる所に限ってこういう場所なんです。

PlayFrameworkはタダでさえバージョン毎の違いが目立ちますので、情報を調べる際は常に「この記事はいつのバージョンの話をしているのか?」「自分のバージョンと差異がある部分か?」を最初にチェックする必要があります。
それには公式サイトと照らし合わせて裏を取るしかありません。


幸い公式サイトのドキュメントは充実しており、部分的ですが日本語化もされています。
Strutsみたいな枯れ果てたライブラリと比較すると不足ですが、現状でも何とかやっていけるんじゃないかと思います。

終わりに

このように、PlayFrameworkはまだまだ過渡期にあるフレームワークであると言えるでしょう。

情報サイトが求められている状況ですので、このブログがその一翼を担えるようになれば幸いです。

2016年5月16日月曜日

【JavaでPlayFramwork】概論2

お久しぶりです。
株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務都合によりPlayFramworkを始めました。

今回も本格的な技術的検証に入る前の概論です。

何でPlayか?

前回でも記述しましたように、今はWebフレームワークは群雄割拠の時代……と言うよりは一通り出揃っているので何でもアリな時代です。

「明らかにコレが最強!!」って時代であれば迷わずそれを使えば良いんですけど、今の時代はWebシステムくらいどうにでもなりまっせ。。。
選択肢が多過ぎるというのは逆に不便でもあります。
採用フレームワーク検討の段階で決め手に欠きますからね。

今回はPlayFramworkを採用する為の根拠についてお話しましょう。

Railsライクである

私が推す一番大きい点はここ、「Ruby on Rails」ライクであるということですね。
「ライク」というのがまた絶妙にいい加減な表現ですが、ともかくRuby on Railsの思想を引き継いでいるんですよ。

Ruby on Railsとは言わずと知れたRubyWebシステムにおける世界標準の最強フレームワークです。
「設定より規約」という設計思想があり、一定のコーディングルールに従って作っていくことで余計な設計作業をしなくて良く、これによって開発効率を高めるものです。
この思想は世界的に大好評の支持を得ておりまして、Ruby on Rails登場以降、Ruby on Railsの思想に影響を受けたフレームワークが多数登場しました。

要するに、


「Ruby on Railsの思想をパクって別言語で同じ事やったろ」


この発想で作られたフレームワークが沢山あるんですよ!!
PlayFramworkもその一種。

つまり、PlayFramwork単品で見ると数あるJavaWebフレームワークの一つでしかありませんが、
Ruby on Railsパクリブラザーズの一員と見ると、「最強フレームワークRuby on Railsファミリーの一角」という後ろ盾を得られます。

それがどういう利点をもたらすかと言いますと、例えばこのTacy。
2016年5月の現時点においてPlayFramwork開発の経験はありません。しかしRubyOnRailsの開発経験はあります。
そのTacyがPlayFramworkの解説サイトを見ると……、内容が分かるんですよ。

RubyOnRailsと同じ思想のフレームワークであるから、RubyOnRailsの知識を流用した着眼点でPlayFramworkを見ることで速やかに技術背景を得ることが出来る。


「PlayFramworkは知らないけどRubyOnRailsなら知ってまーす」


こういう要員を戦力として投入することが可能なんですよ。
今後の開発フェーズで要員を探すことも容易になりますし、その後の長期的保守の観点でも要員調達のハードルが下がる。

これが大きい!!


フレームワークの世界は寄らば大樹の陰であり、使っている人間の数の多さが正義である!!


この意味でPlayFramworkは軌道に乗っています。

ちなみに同じRuby on Railsパクリブラザーズの一角にPHPの「CakePHP」があります。
これも同じく、RubyOnRailsを知っていればスルッと入っていけるフレームワークです。
私はCakePHPも経験ありますが、あの時も勉強期間3日くらいで設計に入って行けました。

今後も同じ感覚で色々な所で使っていけるでしょう。


一度勉強すれば一粒も二粒も美味しい。


技術背景をRubyOnRailsファミリーで固めるのはエンジニアのキャリア戦略として絶大な価値をもたらしてくれるのです。


Grails


ちなみに、JavaVM上で動くRubyOnRailsライクのフレームワークという意味では、PlayにはGrailsという兄貴分がいます。




私は一度だけこの開発の経験があって、確かに革新的で光るものがあるフレームワークでした。
一時期はコイツが注目された時代も過去にあったと噂を聞きますが……、
現時点で見ると特に流行っているようには思えませんね。

何でも、開発者がサボってアップデートを怠っているうちに折角来そうだったブームが過ぎ去ってしまったそうな。(泣)

運命の巡り合わせがあればこの記事もPlayではなくGrailsだったかもしれないと思うと忍びないですね……。
もしまた時代が来たらTacyはGrailsにも参戦しますよ……。

終わりに


以上でPlayFramwork概論は終了です。
次回からは実際にPlayFramworkを使いつつ検証していきたいと思います。

2016年5月10日火曜日

【JavaでPlayFramwork】概論1

お久しぶりです。
株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

業務多忙により更新が止まってしまっていましたが、再び復活して連載します。

前回まではAndroidStudioの検証を行っていましたが、業務都合により今回からテーマを変更。
テーマはWebフレームワークの「PlayFramwork」です。

昔を振り返る

PlayFramworkは、まあ単なるJavaのWebフレームワークですね。
別にそれほど特別なものではなくて、あくまで標準的に使用されるべきフレームワークの一つと言えるでしょう。

  • Struts1
  • Spring
  • Seasar2(SAStruts)

これら有名JavaWebフレームワークの同族です。

私は自分をJavaWebプログラマーとしては極めて平凡な道を歩んできたと思います。
Struts1で社会人入り、Springで炎上し、Seasar2で快適生活……。
上記に挙げたフレームワークはJavaWebフレームワークの首領達であり、これを知らずしてJavaWebの歴史は語れません。

しかし、あの頃から時代も流れ、現在はこんな状況……。

  • Struts1 ⇒ サポート終了
  • Spring ⇒ 炎上プロジェクトの代名詞
  • Seasar2(SAStruts) ⇒ サポート終了

何と、必殺のキラーコンテンツだった「Struts1」「Seasar2」がサポート終了を迎えてしまいました。

Struts1は言わばJava全体のキラーコンテンツのようなものであり、何故今の時代にJavaがこれだけ普及しているかと言うと、それはStruts1があったから。
「スーパーマリオブラザーズが人気だったおかげでファミコンが普及した」と言っていいくらいの勢いでJavaの普及に貢献した伝説的フレームワークでした。
しかしサポートが終了してからセキュリティ脆弱性などが見つかってもう使えるシロモノではありません。(まあ、ごり押しで使ってるトンデモ現場もありま……ゲホゲホ)

Seasar2(SAStruts)は、日本製フレームワーク。
日本を代表するプログラマーひがやすを氏によるフレームワークで、これも日本人なら知らぬ者無し。
しかしSeasar2のWeb部分であるSAStrutsって内部ではStruts1を使っているそうじゃないですか。
Struts1サポート終了してからも随分と延命して下さいましたが、そろそろ限界の模様。
ひがやすを氏ご本人が卒業を勧告しておりますから、全人類はこれに従ってSeasar2の時代を終焉させるべきですね。


そしてSpringは……、申し訳ありませんね。
Spring自体は良く出来たものなはずなのですが、どういうワケか私の人生では100%炎上しているのですよ。
Springは大規模プロジェクトに導入されることが多い為か、フル活用する為には熟練した知識が必要な為か……。
ともかく、何か呪われているような印象がありまして、実際やっぱり色々と難しい部分もあって、小規模プロジェクトに気軽に導入するようなものじゃないと思いますよ。
同じ意見の人も少なくないと思います。なので最近は採用率が下がり気味な印象……。


以上のように、かつて一斉を風靡していたJavaWebフレームワーク達はその役割を終えて新しい時代が到来してきているのが昨今のJavaWeb業界です。

では、これら伝説のフレームワークに続く新時代のフレームワークは……、ありません!!

そう、JavaWebフレームワークは群雄割拠の時代。
問答無用の最強フレームワークが無いご時世なのです。

何で無いんだろう……。
色々あるでしょうが、私としては以下のような持論を持っています。

JavaでWebシステムを作る必要性が無くなった。


そもそもコレ。PHPやRubyなど色々な言語が普及してノウハウも蓄積してきた昨今、Javaに拘る理由が無くなってきているんですね。
現在私が参画しているシステムは業務用でバッチ出力などもあるから全言語をJavaで統一して気合い入れて作る話になっているものの、そうでもないちょっとしたWebサイト開発だったらスクリプト言語ベースの方が小回りが効いて良いですもんね。

実装の必要が無くなった。


最近はパッケージやクラウドサービスも普及してきましたからね~。
「Salesforce」などが代表格ですが、自社用業務アプリを自社開発するより、既に存在するサービスに使用料を払って使った方が機能もコストパフォーマンスも優れていることも多いです。
必然的にJavaで必死に実装するシチュエーションも減ってきました。

悲しいですが、私みたいなプログラマーの出番があるということは、それはその業務が洗練されていないだけであり、本来はパッケージ製品で業務出来るように運用を見直すのが真の理想、というのが真実の姿かと……。

スマホ対応


最近はスマホが普及してきたのでWebシステムの需要もスマホに盗られ……、たわけではありません。
スマホが通信している先はサーバであり、そのサーバでは気合い入れてJavaが動いています。
問題はですね、スマホ、タブレット、PCなど色々な端末に対応する為には「JSONでデータをやりとりするWebAPIである」のがベストってことなんです。

WebAPIとて所詮はHTTP通信するWebシステムってことに代わりはありませんからWebシステムと言えばWebシステムです。
しかし、かつてのようなPC向け画面を作っていた頃のWebシステムと、JSON文字列をストリームで送り返すだけのWebAPIではやっぱり根底が違いますよ。

jspが無いことを始めとして、インターフェース部分が全然違いますからね。

Webフレームワークってのは「画面フォームから受けたパラメータをどうやって受け取るか」ってのがデザインの見せ所なんです。
でもWebAPIって基本、クエリがチョロって来るだけじゃないですか?
気合い入れてWebフレームワークを導入する話じゃないっていうか……。

私だったら自前でそのWebAPIに特化したフレームワークを作るでしょうね。
高機能なWebフレームワークの極一部だけ拝借するよりも、自前で作った方がずっと高速でスリムなシステムを作れるでしょうから。

なのでスマホ用サイト構築の場合は、Webサイトだったら別言語で作り、WebAPIだったらフレームワーク無しでOK、とJavaWebフレームワークの出番が来ない。


まとめますと、最近は技術やノウハウが蓄積されて昔みたいなStruts単細胞野郎が淘汰され、ケースバイケースで色々な言語、製品、フレームワークを選択するようになった結果、「これさえあれば最強!!」みたいな単純な時代では無くなったというのが私の所感です。


何故PlayFramworkか?


このような選択肢の多い群雄割拠のこの時代、では何故、今回私がPlayFramworkを採用することを思い立ったのか……。
もちろんこれには理由がありますが、一番のポイントは、


  • Ruby On Railsのフォロアーであること


これですね。
この辺り、フレームワーク採用の評価ポイントについては、次回に続きます。

終わりに


フレームワークはただ効率良く使えれば良いというものではなく、何故それが他と比べて優れているかを他者に説明出来る必要があるのだ。

PlayFramwork編は長期連載になると思いますが、末永く宜しくお願いします。

2016年2月29日月曜日

【AndroidStudio】FindBugs導入

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近はAndroidStudioの検証を進めています。

現在は快適な環境構築を目指してプラグイン探しをしています。
本日はFindBugsに行ってみましょう。

FindBugsとは

FindBugsとは、一言で言えばプログラムの静的解析ツールとでも言いましょうか。
Java業界では結構有名なツールで、ソース中のバグらしき箇所を発見してくれる機能を提供してくれます。

結構有名なツールですので、調べれば色々出てくるでしょう。

前回紹介したCheckStyleと静的解析という意味では似ていますが、
CheckStyleは変数のネーミング規約とかそういう『可読性』に関するチェック機能に対し、
FindBugsは処理に問題無いかどうかという『ロジック』についてチェックしてくれるものです。

まあ正直言いますと、FindBugsで検出出来るバグって「自分で気付けよ!!」っていう程度の低レベルバグですので、
これに依存しているようではプロジェクトの品質はボロボロに決まっておる。。。
実装を根本から見直した方が良いでしょう。

とは言え、導入しても別に損はありませんから、入れるだけ入れるに越したことはありません。

では、入れてみましょう。

インストール

インストール手順は、前回のCheckStyleとほとんど同じ。

設定画面から「QAPlug」で検索するとCheckStyleと一緒に出てきます。


どうなってんだ???

CheckStyleとFindBugsは用途としては似たものですが、本来別物なんですけどね。
親切な人が便宜上一纏めにしてくれているのかもしれませんね。

上記画像に出ている「Hammurapi」と「PMD」とは?

どうやら全部静的解析ツールのようです。
今回のテーマはFindBugsですが、もういっそ全部インストールしてみましょう。


全部纏まって入りましたね。

設定とカスタマイズ


後は設定するだけですが、実はこれも前回と同じ。。。
「設定 ⇒ Other Setting ⇒ QAPlug」にある「Coding Rules」から設定をカスタマイズしていけばOKです。


ようやく分かってきました。
「CheckStyle」「FindBugs」「Hammurapi」「PMD」を全部一纏めにしてくれているのが「QAPlug」なわけですよ。

どこからどこまでがCheckStyleで、どこからがFindBugsで……。
Eclipseのプラグインだとこれらはそれぞれ別々にインストールして別々に設定する必要がありますが、
こちらQAPlugを使用すればそんな境界線を気にする必要はありません。

スパッと全部入れて、スッキリ品質の良いコードを書いていけばOKです。

終わりに


引き続きAndroidStudio関連の調査を継続していきます。

2016年2月7日日曜日

【AndroidStudio】CheckStyle導入

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

最近はAndroidStudioの検証を進めています。

現在は快適な環境構築を目指してプラグイン探しをしています。
本日はCheckStyleに行ってみましょう。

CheckStyleとは

かなり有名なツールなのでCheckStyleの存在をご存じな方も多いかと思いますが、手短に噛み砕いてご説明しましょう。
代表的なコードの静的解析ツールで、つまりJava実装のコーディング規約をリアルタイムでチェックしてくれます。

例えば、実装における一般的な規約として「ローカル変数の頭は小文字で始める」というのがあります。

  • String name = "遠藤 太志郎";

しかし、実装に慣れていない人が実装すると、こういった規約まで配慮が行き届かなくてガタガタになってしまうケースがあります。

  • String NaMe = "遠藤 太志郎";

こういう時、先輩格のSEが目視でレビューするのは大変ですよね?
そんな時がCheckStyleの出番です。
こういう規約に沿っていない箇所に警告を出し、目視し易いようエディター上に黄色く表示してくれます。

これで作業が随分と楽になります。
効率的な実装作業には欠かせないツールと言えるでしょう。

AndroidStudioにもこのプラグインを入れてみたいと思います。

インストール……失敗

では、インストールしていきましょう。
設定画面からCheckStyleを検索します。



え……。沢山出てきたのですが。。。

意味分かりませんが、とりあえずインストールしてみました。

まず、一番上の「CheckStyle-IDEA」って、これ罠だろう!!


プロジェクトを読み込めません : com.intellij.ide.plugins.PluginManager$StartupAbortedException: com.intellij.diagnostic.PluginException: org/infernus/idea/checkstyle/CheckStylePlugin : Unsupported major.minor version 52.0 [Plugin: CheckStyle-IDEA] [Plugin: CheckStyle-IDEA]

起動しなくなりましたわ。

起動しなくなったのでアンインストール画面も起動出来ねえし……。

こうなったら強制削除しかありませんね。
うっかり入れてしまった人は以下フォルダの該当フォルダを手動削除してください。

  • ユーザホーム\.AndroidStudio1.5\config\plugins

よく見ると画面に「INSPECTION(評価版)」って書いてありますね。

ログの「Unsupported major.minor version 52.0」ってのは、実行JREのバージョンが古かったりする時に見るエラーログなんですが、環境変数見直したりJREを再インストールしなおしても結局直りませんでした。

もしかしたらAndroidStudioの本家である「IntelliJ IDEA」なら普通に動くのかも。だとしれば、もしかしたらプラグインも最新版ではなく少し古いバージョンなら動く……。
など考えましたが、結論としてはもう一つのプラグインを使うことにしましたので調査打ち切り。

デバッガーの人なら何か手があるのかもしれませんが、初心者は寄りつかない方が賢明でしょう。

インストール

仕切り直していきましょう。

QAPlugというプラグインの方が正解です。

QAPlugとは、日本語情報が全くありませんが、どうやらIntellij IDEAのプラグインのうち、コード解析を中心に活動しているプロジェクトのようです。


CheckStyle以外にもプラグインを提供しています。
他のプラグインは後日記事にしますので、今回はCheckStyleのみ。

QAPlugは

  • 本体プラグイン:QAPlug
  • 拡張プラグイン:QAPlug - CheckStyle

この二段構えになっていますので、両方インストールして下さい。

設定とカスタマイズ

インストールすると、「設定 ⇒ Other Setting ⇒ QAPlug」が出現しています。
デフォルトでもある程度設定されていますが、Coding Rulesから設定をカスタマイズしていきましょう。


この画面の「+」ボタンを押すとこのような画面が出てきます。


このようにEclipseで作成した設定ファイルをこちらにインポートすることも出来るわけですね。
Eclipseで使っていた設定ファイルをこっちに持ってこれるので楽チンです。

実行

では、登録したCheckStyleの設定でソースを走査してみましょう。

これがまた分かり辛いんですが、右クリックなどで「分析」などを探して、そこから「Analyze Code」を実行すれば良いです。
AndroidStudioにはCheckStyle以外の分析機能も備わっていますから「CheckStyleで分析」とか書いていてくれないとどれがどれやら分からねえ……。


次の画面ではどの設定でチェックするか選択出来ますので、先ほど自分で作成した設定でチェック実行。


コンソール画面にチェック結果が出てきました。


後は警告が無くなるまでこれを繰り返して綺麗なソースを作るだけですね。

終わりに

やっぱりEclipseとは相当使い勝手が違いますね。
慣れるまでは時間をかけて使っていく必要がありそうです。

引き続きプラグイン探しを行います。

2016年2月1日月曜日

【AndroidStudio】フォーマッター設定(Eclipse Code Formatter)

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

ただ今、業務都合によりAndroidStudioの検証を進めています。

今週からは色々とプラグインを探しつつ、快適な実装環境を模索していきたいと思います。

フォーマッターを使おう!!

新しく開発環境を導入した時に最初に着眼するべき所は必ずコレ。フォーマッターです。
ご存じの方も多いかと思いますが、話の前振りとしてフォーマッターの意義をご説明しましょう。

まず、言うまでもありませんがソースというのは可読性が非常に重要になります。
偶に「え? 動けばいいんじゃね?(=何もしなければコストダウンに繋がる)」みたいな事を言う人もいますが、
いやいや、可読性が低いソースを残すことはいずれ大きな弊害を招きます。
バグの見落とし然り。開発効率の低下然り。

とは言え、既に本番稼働に入ってしまったソースを修正するのは新しいバグを生み出す可能性も高く、
上記の通り「動いてるんだから何もするんじゃねえよ」という話に繋がってしまい、未来永劫に修正する機会を得られないケースも少なくありません。

このような事態を未然に防ぐ最善完璧ベストの手段は、もちろんコレです。


  • 最初から綺麗なソースを書く。


コレですよ。最初が肝心。
綺麗に実装出来る環境を最初に整えることが一番肝心なのです。

しかし、綺麗な実装というのはある程度の実力者ならば可能ですが、
チームメンバーは全員が実力者揃いばかりとは限らず、実力者同士の組み合わせであっても個人の癖があります。

キチッと統制を取ってやらなきゃソースの可読性なんてあっという間にガッタガタ。
開発効率は日を追うにつれてどんどん下がっていきます。

そんな時、フォーマッターを導入することである程度まではソースの癖を統一して可読性を向上させることが出来ます。

開発リーダーが最初にやるべきことは、メンバー全員の開発環境を洗練して統一することなのです。
その第一歩がフォーマッターの導入というわけですね。

「戦争のプロは兵站を語り、戦争の素人は戦略を語る」(アントワーヌ=アンリ・ジョミニ)という格言がありますが、
開発で言うとこんな感じですかね。

  • 「開発のプロは環境を語り、開発の素人は技術を語る」(Tacy)

OK?

フォーマッター実行

細かいカスタマイズは後述しますが、まずはAndroidStudioでフォーマッターを実行するコマンドはこれです。
さあ、やってごらんなさい。

  • Ctrl+Alt+L

ガシャツっとソースが動いたら、それはあなたが今までフォーマッターを使っていない危険環境で実装していたことを意味しますのでご注意を。

なお、「ソース保存時に自動的にフォーマッターを実行する」ということも出来るようです。
しかしこちらはマクロを組んだりする必要があり、ちょっと大変なのでまた後日。

フォーマッターのカスタマイズ

フォーマットするだけなら上記のコマンド一発で完了です。
しかし、やっぱりソースに拘りを持つ者としてはフォーマッターの設定をカスタマイズしたいところですよね。

AndroidStudioはデフォルトでフォーマッターが入っており、カスタマイズする場所は以下です。

  • 設定 ⇒ Editor ⇒ Code Style


設定は細かい所まで出来ますのでそれぞれの現場で最もマッチする設定を模索してみると良いでしょう。

問題は、作った設定の共有。。。
自分で構築した設定をチーム内に共有するにはどうすれば良いのだろう?

調査すると「androidstudioホーム/config/codestyles」に設定ファイルがあるという情報を見つけたのですが、そんなフォルダ無えよ。。。

真相不明ですが、この設定って古いAndroidStudioの話なんじゃないの?
今のAndroidStudioだと「設定のエクスポート」を使う以外に手段は見つかってないです。

しかしこれはフォーマッター以外にも色々と一緒になってエクスポートしてしまったりして、
ちょっとチーム共有という観点だと柔軟性に欠けるという印象。。。

そんな時は次、Eclipseのフォーマッターを使っていきましょう。

Eclipse Code Formatter

EclipseをメインとするJavaエンジニアのTacyとしては、やっぱEclipseの資産を使っていきたいなぁ。。。

そう思っていたら、ありました。やっぱみんな想いは同じなのですね。
Eclipseのフォーマッター設定をAndroidStudioに移植する人気プラグインが存在しています。

その名は、Eclipse Code Formatter。

公式プラグイン置き場にありますので、さっそくインストールしてみましょう。


インストールして再起動すると、設定にEclipse Code Formatterが増えています。


後はEclipseからエクスポートしてきたフォーマッターをセットすれば良いという寸法です。

注意点は「Eclipseで設定してからAndroidStudioに持ち込む」という二段構えの設定である所ですね。

AndroidStudioだけで全て完結している現場だったらシンプルにデフォルトのフォーマッターでやりくりすれば良いかと。
しかしEclipseと二刀流をやっている現場ではEclipse Code Formatterの方が馴染み易い印象。

まあ、この辺りは絶対的な決まりは無くて、開発者の好みな部分の気がしますね。
実際に現場に導入してみて、評判を見てどちらか一本の統一するのが良いでしょう。

終わりに

引き続き環境構築向けのプラグイン調査を行っていきます。

2016年1月25日月曜日

【AndroidStudio】プラグイン探し 始めに

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

ただ今、業務都合により急ぎAndroidStudioの検証を進めています。
まだまだ理解不足ですが、ブログを書きながら理解を深めていきます。

まだまだ不便過ぎるんだが。。。

AndroidStudioを使い始めて数ヶ月。うち実際に触ったのは二週間程度の現在ですが、ダメだ。全然ダメだ。

基本的に私はEclipseを長年使っており、「Eclipsでは出来たのにAndroidStudioでは出来ない」という不便を強いられている自分自身に気付いてしまいます。
元々Eclipseを知らなきゃ何とも思わないのかもしれませんが、何とかならんか……。

プラグインを探してみよう


しかし考察を次に進めてみると、「AndroidStudioで出来ないのでは無く、プラグインが入っていないだけでは?」という発想に至ります。

私の言う「Eclipse」とは「Pleades」を意味していますが、Pleadesは親切な有識者が最初から便利なプラグインを色々と入れた状態で配布されていますからね。
対して、AndroidStudioの方がそういった親切設計が不十分。
最初から入っているプラグインも少々ありますが、これは最低限。
ここから自分でバンバンプラグインを追加しないとAndroidStudioは真価を発揮しないのですよ。

と言うわけで、ここからは便利そうなプラグインを探していきましょう。

現状理解

本格的にプラグイン探しを始めるのは次回以降としまして、今回は初期状態について理解を深めます。

AndroidStudioのプラグイン設定はこちら。

  • ファイル ⇒ 設定 ⇒ Plugins

どうやら配布段階で最初からそこそこ入っているようです。
これは配布元であるGoogleが選定したものですね。

「Android Support」とか「SDK Updater」とか、Android開発に必要不可欠となりそうなものが見えています。

「Git Integration」や「Subversion Integration」と言った項目がありますね。GitやSVNに繋げるのもこれのお陰です。

「AndroidStudioにはGitやSVNからソースをダウンロードする機能があるものだ」ということは誰でもご存じかと思いますが、
正確にはAndroidStudioにその機能があるのではなく、そういうプラグインが最初からインストール済みで配布してくれているというだけです。
その違いを認識しないと、「そうだ、プラグインを探そう!!」という着想に辿り着きませんので日頃からご注意下さい。

インストール方法

インストール手順も見ていきましょう。
上記画像の下の方にボタンが3つありますよね。何だこりゃ。

Install JetBrains plugin...

AndroidStudioの正体は「IntelliJ IDEA」でして、そのIntelliJ IDEAの開発元がJetBrains社です。
このボタンは「JetBrainsが提供しているプラグインを表示する」という、言わば開発元特権ボタン。。。

まあ、JetBrains社純正品なので変なのは混ざっていないでしょう。
基本として抑えておくことをオススメします。

Browse repositories...

プラグインサイトに載っているプラグインの一覧が出てきます。
基本的にここからプラグインをダウンロードすることになります。

山のように大量のプラグインがあります。

手当たり次第に全部入れていたらAndroidStudioがクラッシュするのは確実ですので、ここから必要なプラグインを探していくのが今後の私の活動です。

Install plugin from disk...

上記サイトの場合はインストールボタンを押すことで手軽にネットから自動ダウンロード&インストールしてくれますが、
こっちは手動モードです。

ネット上からプラグインファイルを手動でダウンロードしてくるわけです。
大抵のプラグインは上記の「Browse repositories」で出来るはずですし、こっちの方がミスも無いはず。

手動モードを使うのは特殊な事情がある時のみと考えておけば良さそうです。

終わりに

次回以降は実際にプラグインをインストールしていきます。
欲しいプラグインは沢山ありますので楽しみです。

2016年1月14日木曜日

【Slack】botでも作ってみるか 後編

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。

前回に引き続き、ちょっと緩急話題としてSlackのbotを作成中です。

前半:Slackbot

ネットでSlackのbotを調べると最初に出てくるのはコレですね。Slackbot。

詳細は省きますが、簡単に言えば「特定の文字列をSlackに投稿すると特定文字列を返却する」というもの。

testとして作ってみたところ、書くと以下のようになりました。
「test」と書き込むと反応して特定文字列が戻ってくる。


馬鹿馬鹿しいわ!!

とは正にこのことですが、これがSlack関連のbotの半分を端的に表していると言えるでしょう。
つまり、「Slackに投稿した文字列をトリガーに特定の処理を行う」というものです。

これと外部システムを組み合わせるとそれなりの機能が実現出来ますね。

  1. Slackに秘密コマンドを投稿する。
  2. 投稿された秘密コマンド文字列を検知して自作のSlackbotが起動。
  3. Slackbotの処理にて、外部にHTTPリクエストを投げる。
  4. HTTPリクエストを以てサーバ処理のトリガーとなり、本格的な処理が開始。

こんなことが出来るわけですよ。
「本格的な処理」については、現場毎の需要にてご自由にどうぞ。

例えば、お店の売上がいつも気になる社長さんとかいるとしますよね。
そういう時に「本日の売上情報を送信しろ」というコマンドをSlackに投げると、
上記のフローで業務サーバで集計処理が走り、結果を社長さんのスマホに送るとか。

その気になれば「自爆スイッチ」とかもSlackでチョイチョイっと作れるわけですよ。
こりゃ危険だ!!

後半:WebAPI処理

上記は「Slackへの投稿をキーにSlack内で処理が起動する」というものでしたね。
これが半分。

では残り半分はと言うと、「外部システムからSlackに文字列を投入する」というものです。
今回の話はこっちがメイン。

Slackは人がログインして手で入力しなくても、WebAPI経由でシステムで投稿することが出来るのです。
ですから、常駐バッチが常にデータを集計して定期的にSlackに上げる、というやり方が出来ます。

上記の売上が気になる社長さんの例で作りますと、


  1. 業務サーバで1時間おきにバッチが起動し、その日の売上を集計する。
  2. 集計結果はSlackのWebAPIを経由してSlackに投稿する。
  3. 社長さんはSlackに投稿された報告を読む。


こっちの方が合理的ですよね。

前述の「前半:Slackbot」の利用方法もそれなりに使い方があるとは思いますが、私の業務界隈を考えると、
どちらかと言うと「後半:外部処理」みたいに一方的な定期報告の方が需要が多い気がします。

ところでこのやり方、実はSlackを使わなくてもメール送信すれば済む話ですよね。
でも、一日に何十何百もメールを受信したく無いという需要もあると思います。

つまり、

  • 定期報告は一応欲しいけど、だからってメールを大量に送り付けられても困る。
  • 常に確認必須の重要な情報じゃない。ただ、偶に観たい時に観れる程度にデータが届いていればいいんだ。

このくらいのゆる~い情報収集にSlackは便利です。

WebAPIの実現方法


では、そのWebAPIとはどういうものかをご説明しましょう。

まず、公式サイトはこちらです。


そこから辿ると「API Methods」というのがあって、それがこちら。


どうやらWebAPIベースで「チャット投稿」「履歴参照」「プロフィール変更」とか殆ど全部出来てしまうようです。

Slackスマホアプリを自分で作ろうと思っても出来るようになっている。

こうやってWebAPIを幅広く提供したのが今日のSlackの反映なのですね。

「Slackを使いたければ俺達の作った公式アプリを使え!!」ではなく、「全部公開しています。どうぞどうぞ、ご自由に」とオープンにした結果、世界中のエンジニアがこぞってSlackbotを作り、一大勢力を築き上げたわけです。
こういう開放的な姿勢は素晴らしいですね!!

さて、今回は基本中の基本である「チャット投稿」を実行します。

まず、上記「Slack Web API」のサイトから、自分用のbot用の識別トークンを取得します。
ページの下の方にあるので、軽くササッと発行して下さい。


くれぐれも漏洩させないようにご注意を。

次に、チャット投稿のメソッドである「chat.postMessage」の仕様を参考にHTTPリクエスト送信ロジックを構築。




まあ、早い話が単なるHTML送信ですから、極論を言えばJavaとかRubyとかでロジックを組まずともブラウザのURLに文字列を打ち込めば投稿完了するくらい簡単なものです。
リクエスト文字列としては以下のような例となります。


  • https://<あなたのドメイン>.slack.com/api/chat.postMessage?token=<あなたのトークン>&channel=%23general&text=Hello&username=tacybot


本当にこれだけ。これで「hello」というメッセージが#generlに届きます。
リクエストの形式は正式にはPostですが実はgetでも普通に動いちゃう。単純です。

注意点はURLEncodeすることくらいですね。
エンコードを忘れると文字化けして投稿してしまうので注意です。

以上です。

このように特にサンプルを示す必要があるような特段の技術は存在しないのですが、一応、私が作ったJavaソースを張っておきます。


/**
 * Slack送信
 *
 * @author Tacy
 */
public class RequestSlack {

 /** logger */
 private Logger logger = Logger.getLogger(RequestSlack.class.getName());

 /** BASE_URL */
 private static String BASE_URL =
   "https://tacy.slack.com/api/chat.postMessage?token=%s&channel=%s&username=tacy";

 /** トークン */
 private static String TOKEN = "tacy_token";

 /** 送信先の部屋 */
 private static String CHANNEL = "%23genera";

 /**
  * メッセージを送信する。
  * 
  * @param message 送信メッセージ
  * @throws IOException
  */
 public void sendMessage(String message) throws IOException {

  logger.fine("Slack送信:開始");

  String url = String.format(BASE_URL, TOKEN, CHANNEL);

  requestPost(url, URLEncoder.encode(String.format("text=%s", message)));

  logger.fine("Slack送信:開始");

 }

 /**
  * メッセージをPost送信する。
  * 
  * @param urlStr 送信先URL
  * @param postMessage 送信メッセージ(URLエンコード済み)
  * @throws IOException
  */
 public void requestPost(String urlStr, String postMessage) throws IOException {

  logger.fine("requestPost:開始");

  logger.info("リクエストを送信します。:" + urlStr);

  // サーバへ接続する
  HttpURLConnection connection = null;
  DataOutputStream os = null;
  BufferedReader br = null;

  try {

   URL url = new URL(urlStr);

   connection = (HttpURLConnection) url.openConnection();

   connection.setDoInput(true);
   connection.setDoOutput(true);

   // キャッシュを使用しない
   connection.setUseCaches(false);

   // HTTPストリーミングを有効にする
   connection.setChunkedStreamingMode(0);

   connection.setRequestMethod("POST");

   PrintStream ps = null;

   try {

    ps = new PrintStream(connection.getOutputStream());
    ps.print(postMessage);

   } finally {

    if (ps != null) {
     ps.close();
    }
   }

   // レスポンスを受信する
   int responseCode = connection.getResponseCode();

   if (responseCode != HttpURLConnection.HTTP_OK) {

    throw new IOException("post送信に失敗しました。responseCode=" + responseCode);

   }

  } finally {

   if (br != null) {
    br.close();
   }
   if (os != null) {
    os.flush();
    os.close();
   }
   if (connection != null) {
    connection.disconnect();
   }

   logger.fine("requestPost:終了");
  }

 }
}

支援ライブラリ:Hubot


上記は既に存在しているJavaシステムからSlackにデータを投入するソースの一部なのでJavaになっていますが、
単品で動かすbotを作るなら、もっと軽量なスクリプト言語で作った方がSlackっぽくてお洒落かもしれませんね。

その為のSlack向けBot開発用ライブラリとして有名なのはHubotでしょう。



HubotとNode.jsを使って簡単にbotをリリースしていくのも楽しいかもしれませんね。
逆に「既に違う言語でシステムが動いているんだけど……」「Androidアプリから送りたい」みたいな人は、上記のとおり単にHTTPリクエストを送るだけの話ですのでササッと作ればOK。

実に柔軟な対応が可能となっています。

終わりに


Slackはシンプルではありますが高い拡張性を持っています。
上手く使いこなせればとても会社の役に立ちそうですね。

では、本年度もブログ更新頑張ります。
今後とも宜しくお願い致します。

2016年1月4日月曜日

【Slack】botでも作ってみるか 前編

あけましておめでとうございます。

株式会社ジェニシス 技術開発事業部の遠藤 太志郎(Tacy)です。
2016年もこのブログ更新を始め、色々と張り切っていきたいです。

本日は年末年始休暇明けなので頭の復活を兼ねて小ネタを。
テーマはSlackです。

Slack

Slackとは一言で言うとチャットツールです。

調べたところによると、公開は2013年8月なので2016年正月の現時点においてはまだ3年経ってないわけですか。
例えばLineやSkypeとかと比較すると誰でも知っているツールの域には到達していませんが最近は急速に普及が広がっており、そのうち業界スタンダードになる可能性も十分にあります。

我が社でも最近、このSlackが便利だという話題を聞きつけ、メインで使っていこうという方向に動き出しつつあります。

今回はアカウントを発行して貰ってから一週間も経っていない私がSlackについて少々調べ、簡単なbotを作るところまでを実現したいと思います。

何が便利なのか?

比較対象として上記に「Line」「Skype」を出しましたが、果たしてこれらはライバル関係と言ってしまって良いのか……。
それぞれ違う機能があるので一概には言えませんが、
敢えてこれらと比較すると、Slackは『企業向け』にスコープが照らされているのが特徴でしょう。

「Line」「Skype」の場合、基本的に1人1アカウントあり、それぞれ各自で『部屋』にドーンと集合して使いますよね。
基本的に『個人重視』なわけですよ。
特にLineなんてセキュリティ的にヤベェ。あれで業務連絡とかやる気にならないですよ。


  • 小学校時代の友達の部屋
  • 中学の友達の部屋
  • 部活の友達の部屋
  • 家族用の部屋
  • 誰にも言えない秘密の部屋


こんな感じに、各自好き勝手に部屋を立てて来て集まるイメージです。

対して、Slackは管理人による統括管理が存在しています。
まず「ジェニシス」という大規模集団があり、その配下にチーム部屋(チャンネルと言いますが)がある。

株式会社ジェニシス
LチームTacyの部屋
LチームXXXの部屋
Lリーダーの部屋
L飲み会開催相談所

とまあ、こんな感じに企業という大組織の中に多数の小型グループが存在しているという状況への対応力がSlackは高い。
この辺りが人気の理由の一つと言えるでしょう。

使い道

というわけで、Slackは企業向けという方向で進化を遂げてきました。
結果、今では他の業務ツールと連携するAPIが豊富に取り揃えられるに至っています。

例えば、Subversion。
SVNにコミットすると「コミットしました!!」というメッセージがSlackに飛んでくるようになるとか。
もちろんGitでも同じ事が可能。

連携アプリケーションはこちらに沢山あるようです。


ちょっと数が多過ぎるので追い切れていませんが、なるほど、『概念』というものは分かってきます。
Slackを情報の集積場として使用するわけです。

現時点だとメールで通知を果たしている所が多いと思います。

例えばRedmineでチケットを更新すると「更新しました!!」のメールが自動的に飛びます。
これは最初の頃は便利だと思っていましたが、長年使っているうちに「メールが多過ぎる」という問題に気付いてしまいました。

1日何十通も更新通知が飛んでくるんですよ。

もちろんフィルタリングとかして自動整理はしていますけど、基本的にメール乱射は悪ですからね。

「別に困っちゃいないけど、もうちょっとクールなやり方は無いの?」

とはずっと思ってました。

そもそもですね、メールのフィルタリングを活用しているのは私が自分でフィルタリングしているからであって、自分でフィルタリングを作るスキルの無い人だったらゴチャゴチャになりますよ。
「とりあえずメールを送っときゃいいでしょ?」って発想はやっぱ配慮に欠けるんですよ。

その点、更新通知をSlackに飛ばすというやり方はSlackそのものが整理機能を果たしますので、幾分スムーズになります。


津波のような大量情報はSlackへ寄せる。


これでIT起業らしいクールなコミュニケーションが取れるかな、と楽しみなところです。

自分でもちょっと作ってみるか

と言うわけで、私はSlackの各種機能のうち「外部から情報を送り込む」というところに活用点を感じています。

既製ツールだと「Redmine」とか「Git」とか、既製ツールの連携機能しかありません。
しかし会社活動をやっていると自社特有の情報発信も存在しますよね。

どんな?
そんなのいくらでもあるじゃないですか。


  • システムがダウンしたらボタン一発で同報を発信して欲しい。
  • 朝一でその日のスケジュールを流して欲しい。
  • 今日がメンバーの誕生日であることをピロッ。
  • ログファイルに[FATAL]の文字列を発見したらSlackに流し込むようになってれば便利だな。
  • 知らんうちに自社サーバがダウンしとる。ping通知を流してくれんか?


細々とした用途はいくらでもありますからね。

「こういうのがあれば便利だなぁ」⇒「じゃあ作ろう」

これをパパッと実現出来れば快適な業務環境が待っています。

とにかく、どんな情報を送り込むかは都度センスが問われるとして、
まずは「どうやったら情報を送り込めるのか?」というアーキテクト部分は把握しておきたいと思います。

終わりに

では、次回は実際にメッセージ投入機能をJavaで作っていきたいと思います。