読者です 読者をやめる 読者になる 読者になる

Ba.とWEBと梅干し太郎

WEB制作・プログラミング・音楽の学習したこと・つくったもののアウトプットブログです。あとは日記。

文章が好き

INTO THE DAILY

f:id:masayannuu:20170206002646p:plain

突然だが、ふと感じたことを文章にしてみようと思った。

何故かと言うと、日常生活では表に出さない脳内のメタ空間がパンクしそうだとか、なんか文章書けるってかっこいいやんとか。色んなやましい思考があるのだけれど、あえて言うならこう言いたい。

なんとなく書きたいから。

いや、もう少し正当化しよう。
Facebookの友達数である366人+αが自分の知っている世間というやつなら、これはとても狭い。なにせ地球には億単位の人口がいるのだ。
ということは、だ。もしかしたら自分の感性がどこかの誰かを何かしらのアレで救う可能性もあるじゃあないか。
世間は広く、誰もがWEBで簡単にアクセスできるのだから。
そう思うと書かずにはいられない。なんていうのはどうだろう。

こうして無事正当化した私は、執筆欲という変態的衝動のなすがままにキーボードをなぞっている。

この執筆欲というやつはずーっと昔から持っていたが、こうして人目のある場に投稿する気になったきっかけは、実にささいなものだ。

私は見てしまったのだ。

品川駅を歩いている時に。

若者のカバンにイヤホンが引っかかり、そのまま大事なイヤホンを攫われそうになっているスーツの男性を。

帰宅ラッシュで人の溢れた駅の構内で、なるべく若者を刺激しないようにイヤホンの奪還を図る男性。
イヤホンをひっぱるものの外れない。若者の歩幅は大きく、イヤホンはずんずんと離れていく。
自分の背中で起こっている事態を知らない若者。
必死の男性。

こんな話、友達にしゃべったら1秒でしらける。
つまり、顔見知り程度の人との世間話にも使えない。
それでも、私は男性と若者とイヤホンが作り出したその空間を目撃してしまったし、忘れられなくなった。

書くしかないわけだ、これはもう。

もしあの光景を目撃したのが漫画家やデザイナーだったらイラストのネタにしているだろう。
たまたま目撃したのが私で、私は文章が好きだった。たった、それだけ。

自分の感性を形で表現できる人がとても好きだから、私もそっち側にいってみようと思った。たった、それだけの話なのだ。

クリスマス後のカップルの様子をTwitterで分析するクソアプリを作った with @t_yng

どうも!
もっこりMokkoです!

クリスマスもいよいよ終わりを迎えるこのタイミング。 クソアプリアドカレ2016の大トリを投稿させていだきます。

#作ったもの
f:id:masayannuu:20161226001655p:plain
ゲスッター
※予告なく公開停止にする場合があります。

今回はフロントとデプロイ周りを私が、サーバー側を@t_yng氏で分担して作りました。
ありがとう、t_yng氏!

どんなアプリかは多くを語ることなかれ、みてくださいな。
ゲスッターはこちら

クリスマス前後で別れたカップル多すぎてビビりました。

いつまで動かしとくか分からないけど、twitterがある限りゲスッターにもカップルカウントとツイートは溜まり続けますのでたまに覗くと面白いかも?

#何をしているの?
Twitterのエゴサで特定のワードを含んでいるものを取得し、カウントしています。
「何でエゴサすれば目的の情報がとれるか?」を考えるのは面白かったです。
なお、ゲスッターはあくまでクソアプリなので、検索ロジックはゆるめです。

#中はこうなっている
TwitterAPIを定期的に叩いて、fireBaseのDBに入れておき、それをJSから呼び出しています。
フロントはt_yng氏に教えてもらったNetlifyという静的フィアルのホスティングサービスを使って公開しました。めちゃくちゃ便利なので気になる人は一度触って見て欲しい。

というわけで、緩めですがクソアプリ2016締めの投稿でございました! 思いの外良い勉強になりましたし、作るの楽しかったです。

それでは、良いお年を!

(JAVA) Play FrameworkでAkkaのスケジューラーを使わずに処理を定期実行する

どうも!もっこりmokkoです。

これはHamee Advent Calendar 2016の24日目の記事です!

前回に引き続きPlay FrameWorkネタを一つ。
Play FrameworkではAkkaを使用したスケジューラーが提供&推奨されておりますが、今回はjarファイルを作成しcrontabで定期実行する方法です。
フレームワークの思想からは外れるかもしれないけど、WEBアプリケーションのデプロイ時にバッチの動作を担保したい場合は有用かも。あくまで一つの方法として記事にしておきます。


#この記事から分かること
- PlayFrameWorkでjarファイルを作成して処理を定期実行をする方法
- jarファイルの生成に使用するプラグインの導入方法


#作ったもの
- 10分間に一回、引数に渡した文字列でtwitterでエゴサしてコンソールに出す

#jarファイルを作成するプラグインを導入
sbt assemblyというプラグインを使用します。 Play FarmeworkはScalaで実装されたフレームワークなのでパッケージ管理はsbt(Scala build tool)になります。
というわけで、project/plugins.sbtに下記を追記。

addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.3")

せっかくなので最新バージョン(2016年12月末時点)を使用。
過去のバージョンに比べて設定に必要な記述が減っています。

続いてsbt assemblyの設定をbuild.sbtに記述します。
今回はシンプルに3つの設定だけ書きました。

//jarファイルの名前を決める。  
assemblyJarName in assembly := "twitter-kun.jar"  
//これを書いておくと、テストをスキップしてjarファイルを作成できる。コンパイル時間が長いので今回はスキップしちゃいます。    
test in assembly := {}  
//jarファイルのマニュフェストを設定できます。今回は実行したいmain関数を持つクラスを指定しました。  
mainClass in assembly := Some("batch.GetToTweet")

これでjarファイルを作成する準備は整いました。
プラグインをインストールする時間がかかるので、すぐにassemblyコマンドを叩くとエラーになるかも。

実際に叩くコマンドはこちら。プロジェクト直下で叩くとtarget/scala-x.xx.xx/下にjarファイルができます。

$activator assembly  

後はcrontabに書いてjarを実行してあげればいいわけですが、ここでハマりポイントがあります。
Play Frameworkはサーバー上でアプリケーションが起動している状態じゃないとクラスやORMを使えない場合があります。
Ebeanを使った時はうんともすんとも言いませんでした。

というわけで、jarファイルからでもアプリのソースを使いまわせるよう実行するmain関数内でアプリケーションの起動と停止をやってあげましょう。
Play Framework入門の記事で作ったアプリに定期実行で使えるクラスを追加してみました。

package batch;

import controllers.ApplicationController;
import play.api.Play;
import play.inject.guice.GuiceApplicationLoader;
import play.libs.Json;
import twitter4j.TwitterException;
import utils.TwitterSearch;
import java.io.File;
import java.util.Arrays;

public class GetToTweet {
    public static void main(String[] args) {

        //アプリケーションを起動するソース
        play.Environment env = new play.Environment(
                new File("."),
                ApplicationController.class.getClassLoader(),
                play.Mode.PROD
        );
        play.ApplicationLoader.Context context = play.ApplicationLoader.Context.create(env);
        GuiceApplicationLoader appLoader = new GuiceApplicationLoader();
        play.Application application = appLoader.load(context);

        //javaのライブラリにはstartのメソッドがないため、ここだけScalaのライブラリのPlay.api.play
        Play.start(application.getWrappedApplication());

        //コンソールに取得したツイートをはく。
        Arrays.stream(args).forEach(arg -> {
            try {
                System.out.println(Json.toJson(TwitterSearch.searchTweet(arg).getTweets()));
            } catch (TwitterException e) {
                e.printStackTrace();
            }
        });

        //処理が終わったらアプリケーションを停止してあげることも忘れずに
        Play.stop(application.getWrappedApplication());
    }
}

起動時に使っているクラス達はJavaScalaで同名のクラスがあり、importを間違えると型を解決できなくなるので要注意!
今回書いたソースでは、Play.start()までは全部Javaのクラスを使います。

        //scalaにはplay.api.Environmentがある。play.apiと続くものはscala。
        play.Environment env = new play.Environment(
                new File("."),
                ApplicationController.class.getClassLoader(),
                play.Mode.PROD
        );
        play.ApplicationLoader.Context context = play.ApplicationLoader.Context.create(env);
        GuiceApplicationLoader appLoader = new GuiceApplicationLoader();
        play.Application application = appLoader.load(context);

        //javaのライブラリにはstartのメソッドがないため、ここだけScalaのライブラリのPlay.api.play。Applicationクラスの.getWrappedApplication()でscalaのアプリとしてstart()に渡さなければいけない。
        Play.start(application.getWrappedApplication());

これで問題なくjarファイルが実行できるようになりました!

java -jar twitter-kun.jar 'メリークリスマス'  

f:id:masayannuu:20161225142002p:plain

Jsonにして出力してみました。
play.libs.Jsonを使えば簡単にListをJsonにして出力できるので便利です。

あとはcrontabをこんな感じで書けば、定期実行できますね。

*/10 * * * * root java -jar hogehoge/twitter-kun.jar 'メリークリスマス'   

といったところで、javaでplay Framework使っている人のお役に立てれば幸いです!

(Java) Play FrameWork入門! Twitter のつぶやき検索アプリを作ってみたよ

Java WEB & プログラミング

どうも!もっこりmokkoです。

日付も変わろうとしていますが、Hamee Advent Calendar 2016の10日目の記事です!
初アドカレにドキがムネムネなわけですが、最初書こうと思っていた内容(スクレイピングと置換)は自分自身納得ができなかったのでまた次回に。

というわけで、今日はScalaフレームワークとして有名な「Play Framework」のJava版入門を1つ。
簡単なTwitterのエゴサアプリを作ってみました。

デモ
※herokuのFreeの使用時間超えて止まっちゃいました。(12月11日追記)


この記事から分かること
- PlayFrameWorkの導入方法
- 簡単なアプリケーションのつくりかた
- 開発環境 & 本番環境での動かし方
(組み込みのNetty と Tomacatの2手法を紹介)


Play FrameWorkとは

The High Velocity Web Framework For Java and Scala

公式ドキュメントより引用
https://www.playframework.com/

Ruby on Rails感覚で扱えるJavaフレームワーク
Scala界ではかなり有名だそう。

導入方法
公式ページよりactivatorというツールをインストール。
▼こちらからどぞ
Typesafe Activator(https://www.lightbend.com/activator/download)

コマンドラインを通して、コマンドを叩けばすぐ使える。

▼ちょっとサボるけど、詳しくはこちらを参照
Installing - 2.4.x

プロジェクトを作成するコマンドはこれ。

$ activator new 

対話式でアプリ名など色々聞かれるので答えると必要なファイルが生成される。

Javaアプリを作成する場合はplay-javaを選択

Browse the list of templates: http://lightbend.com/activator/templates
Choose from these featured templates or enter a template name:
  1) minimal-akka-java-seed
  2) minimal-akka-scala-seed
  3) minimal-java
  4) minimal-scala
  5) play-java
  6) play-scala
(hit tab to see a list of all templates)

簡単なアプリケーションを作ってみた
機能はtwitterでエゴサしてそれを引っ張ってくるだけ。

※Play Frameworkのバージョンは2.4.8を使用。現時点での最新バージョンは2.5.10。

▼画面はこんなの
f:id:masayannuu:20161210234432p:plain

コマンドでプロジェクトを作成すると既に Model 、View、Controllerのクラスが作成されている。
このMVCの仕様はjava初めての私でもとても分かりやすかった。

▼Modelクラスはこんな感じ。

package models;

public class SearchWord {

    public String word;

    public String getWord() {
        return word;
    }

    public void setWord(String word) {
        this.word = word;
    }
}

今回はPOSTされた文字列をtwitterでエゴサするだけなのでシンプルに。
DBに繋がないのでORMも使用しない。
Ebeanを使用した時はebeanのModelクラスを継承して使った。

▼そして、conf/routesにルーティングを書く。

#アプリのルーティングを設定するファイル  
#HTTPリクエスト  URL   呼び出すメソッド名 の順に記載  
GET     /                           controllers.ApplicationController.index()

POST    /search                     controllers.ApplicationController.search()

# 静的ファイルのルーティング viewの呼び出しに使用する
GET     /assets/*file               controllers.Assets.at(path="/public", file)

こんな感じで、アクセスしたURLに応じて呼び出すControllerを指定する。
分かりやすい。

▼Controllerクラス

package controllers;

import models.SearchWord;
import play.data.Form;
import play.mvc.Controller;
import play.mvc.Result;
import twitter4j.TwitterException;
import utils.TwitterSearch;

import java.util.List;
import java.util.Map;
public class ApplicationController extends Controller {

    /** POSTされた文字を元にtwitterでエゴサをかけるよ*/
    public Result search() throws TwitterException {
        Map<String, String> postData = new Form(SearchWord.class).bindFromRequest().data();
        List<twitter4j.Status> searchResult =  TwitterSearch.searchTweet(
                postData.get("searchWord"))
                .getTweets();

        return ok(views.html.listTweet.render(searchResult));
    }

    /** viewを表示するだけだよ */
    public Result index() {
        return ok(views.html.index.render());
    }

}

Resultクラスで受け取ってviewへレンダリング
POSTされた値を受け取る時はFormクラスを使えばMAP型で受け取れる。

twitterAPIを叩くライブラリはTwitter4Jを使わせて頂きます。

package utils;

import play.Play;
import twitter4j.*;
import twitter4j.conf.ConfigurationBuilder;

public class TwitterSearch {

    public static QueryResult searchTweet(String searchWord) throws TwitterException {

        ConfigurationBuilder configInfo = new ConfigurationBuilder();
        //application.confからTwitterの設定を読み込むよ
        configInfo.setDebugEnabled(true)
                .setOAuthConsumerKey(Play.application().configuration().getString("twitter.authKey"))
                .setOAuthConsumerSecret(Play.application().configuration().getString("twitter.authSecret"))
                .setOAuthAccessToken(Play.application().configuration().getString("twitter.authToken"))
                .setOAuthAccessTokenSecret(Play.application().configuration().getString("twitter.authSecretToken"));
        TwitterFactory tf = new TwitterFactory(configInfo.build());

        Twitter twitter = tf.getInstance();
        Query query = new Query();
        query.setQuery(searchWord);
        QueryResult result = twitter.search(query);

        return result;

    }

}

twitterの認証に使う情報はconf/application.confという設定ファイルに外出し。
このapplication.confという設定ファイルは環境変数から読み込めるのでおすすめ。

#twitterの認証情報を環境変数から取得  
twitter.authKey=${?AUTH_KEY}
twitter.authSecret=${?AUTH_SECRET}
twitter.authToken=${?AUTH_AUTHTOKEN}
twitter.authSecretToken=${?AUTH_SECRET_TOKEN}

#アプリの言語
play.i18n.langs = [ "ja" ]
 

▼他クラスでapplication.confの変数を呼ぶ時はこれ
(※Playのバージョンによって使うクラスが絶妙に違う。2.4はこれでいける)

Play.application().configuration().getString("twitter.authKey")

▼Viewクラス

@import b3.vertical.fieldConstructor

@main("ツイッターくん") {
    @b3.form(routes.ApplicationController.search, 'class -> "form-group") {
           <div class="col-sm-offset-0 col-sm-6">
                <label for="searchWord">#つぶやき検索</label>
                <input type="text" name="searchWord">
                @b3.submit('class -> "btn btn-default"){ <span class="glyphicon glyphicon-globe"></span> 検索}
           </div>
    }
}

Play Framewokのviewテンプレート。
ヘルパーでhtml生成はもちろん、素書きでもOKなので扱いやすい。
bootstrapにも対応しており、公式のPlay Bootstrapがあるのであまり手をかけず整ったページを作れる。

viewテンプレートの記法はScalaを使う。
@以降がScalaとして認識されてるのでせ、ループ処理もこのように書ける。

@(searchResult: List[twitter4j.Status])

@main("ツイッターくん") {
    @for(tweet <- searchResult) {
        <li>@tweet.getText()</li>
    }
}

分かりづらいのが、@main()なるもの。
これは要するに変数で、viewの共通ファイルになっているmain.scala.htmlというファイルに渡すhtml要素を定義している。

▼main.scala.htmlはこんな感じ
最上部に@()で定義されているのが、このファイルに渡ってくる引数。
他のviewの@main("ツイッターくん"){ hogehoge }の"ツイッターくん"がmain.scala.htmlのtitleとして、そして{hogehoge}がhtmlとして渡されている。

@(title: String)(content: Html)

<!DOCTYPE html>
<html>
    <head>
        <title>@title</title>
        <link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet">
        <link rel="stylesheet" media="screen" href="@routes.Assets.at("stylesheets/main.css")">
        <link rel="shortcut icon" type="image/png" href="@routes.Assets.at("images/favicon.png")">
        <script src="@routes.Assets.at("javascripts/jquery-1.9.0.min.js")" type="text/javascript"></script>
    </head>
    <body>
        <div class="page-header">
            <a class="navbar-brand logo" href="/">
                <img src="@routes.Assets.at("images/medjed.png")" />
            </a>
            <h1>Play Frameworkのテストだよ
                <br>
                <small>つぶやきを検索するよ</small>
            </h1>
        </div>

        @content

    </body>
</html>

ささ、これだけでつぶやき取得アプリが完成!
テストと入力すると... f:id:masayannuu:20161211002329p:plain

つぶやきを取得する。
f:id:masayannuu:20161211002426p:plain

デプロイしてみる
組み込みサーバーで動かすのはactivatorのコマンドで

$ activator start

application.confでsecret key(クライアントセッションの暗号化に使う)を指定していない場合はstartの引数に

$activator start -Dapplication.secret=abcdefghijk

だけでOK。

▼組み込みサーバーでデプロイ時のコマンドについて。こちら参照
Production - 2.4.x

Tomcatでデプロイする場合はwarファイルを作成する必要があるので、 play2warというプラグインを入れてコマンド1つでサクッと。

project/plugin.sbtに

addSbtPlugin("com.github.play2war" % "play2-war-plugin" % "1.4-beta1")

と build.sbtに

import com.github.play2war.plugin._  

libraryDependencies ++= Seq(
  cache,
  jdbc,
  "mysql" % "mysql-connector-java" % "5.1.40",
  "com.adrianhurt" %% "play-bootstrap" % "1.1-P24-B3",
  "org.twitter4j" % "twitter4j-core" % "4.0.5"
)

このように依存関係を追加すればコマンドからwarファイルを作成できる。

コマンドは

$activator war

使っているplay frameworkのバージョンによってバージョンの指定が異なるので注意! 2016年12月時点で2.5以降は非対応。

後はこのwarファイルをTomcat直下のwebapps内に置いてTomcatを立ち上げればデプロイ完了。


使ってみた感想
java初心者にとってとっつきやすかった。
ハマりどころも多いが嫌いじゃないし、むしろ好きかも。

PS.
▼ライブラリ探しはmaven repositoryでどうぞ。
https://mvnrepository.com/

米国大統領選の週ごとの投票率をいい感じのデザインで見れる「Count Yourself In」

サービスチェック

グラフィックインフォを見かけることが多くなった。
そんな中でも、特に面白いな、優れているな、と思ったのが米国大統領選のグラフィックインフォだ。
というか、単純にこのサイトの各所で使われれいるイラストやフォント、色感が個人的にとても好きだ。
大統領選を追っている人には、ぜひ訪れて欲しいサイトだ。

www.countyourself.in

このサイトのコンセプトは名前からも分かる通り、自分の州での支持率がパッと見で分かる工夫が散りばめられている。
私が気づいたのはこれくらい。
* 州のアイコンの色やグラフの配色を党で決めていて、共和党優勢か民主党優勢かで具合を変えている。(赤い州青い州ってやつ)
* 州のアイコンが州の形(文字だけより分かりやすいと思う)
* 候補者の顔イラストと、ステータスバーで双方の支持率の具合がパっと見で分かる
* 世論調査を円グラフと着色で見えやすく
* 数字の表示を大きめに。強調している
* アクセス元の地域の情報をランディングページとして表示している(日本はnon-usだよ)

f:id:masayannuu:20161020002213p:plain

ものの見せ方の良い勉強になった。
デザインやアプローチの仕方を変えてみると、小難しい話でもとっつきやすかったり、参加意欲を変えることができたりするものだろうなあ。

参考兼チェック用として、メモ。

【今日のひとこと】
やればできる
https://i.guggy.com/g7s3hfAlz6.gif