2014年11月10日月曜日

新しいサイトを立ち上げてみた。

http://recruitpage.herokuapp.com/
採用ページの先輩の声を集めたサイト、「Recpe」

仕事に対する熱が冷めてしまった時などに、このサイトを見て再び熱意を持てますように。

Play FrameworkをHeroku上でデプロイしております。
PostgreSQLのコネクション数が、無料だとかなり制限厳しいですね。

2014年6月21日土曜日

wordpressに取ってきたRSSを独自のフィールドを登録させる

今回はカスタムフィールを拡張するプラグイン「Advanced Custom Fields」を利用します。

インストールすると管理画面に「カスタムフィール」のメニューが増えるので、ここからRSSから取り込みたいフィールドの名前を決めます。

フィールドのセット一覧を登録します。

次にSyndicated Posts & Links からカスタムにセットするRSSの項目を登録します。






wordpressにRSSを取得して記事として投稿するプラグイン「FeedWordPress」をインストールする

Wordpressで外部のRSSを表示するプラグインは結構あるみたいです。
今回は記事としてエントリーさせたいので、投稿まで出来るプラグイン「FeedWordPress」を利用します。

インストールが完了すると左メニューに「Syndication」が表示されるので、このメニューから「Syndicated Sites」を選択します。

画面上の「New Source」に取込を行いたいRSSのURLを入力します。
次の画面でカテゴリの設定をしておきます。






WordpressにURLからスクリーンショットのサムネイルを作ってくれるプラグイン「Browser Shots」をインストールする

URLからそのサイトのスクリーンショットを撮影して、そのサムネイルを作ってくれるプラグイン「Browser Shots」を導入します。

Web APIで似たようなのに、「HeartRails Captureスクリーンキャプチャ」がありますが、これは横幅が最大400pxなので、プラグインの方を使ってみたいと思います。

Wordpressの管理画面のプラグインで「新規追加」から「Browser Shots」と入力をしてインストールします。



2014年6月20日金曜日

さくらのVPSにWordpressをインストールする

自分がやりたいことがもしかしたらWordpressでできてしまうのでは・・・と思ったので、実際に出来るかWordpressをインストールして確かめてみます。

さて、なるべくコマンドで実行してインストールを進めていきます。
まずはダウンロード

cd /usr/local/src/
wget http://ja.wordpress.org/wordpress-3.9.1-ja.zip
unzip wordpress-3.9.1-ja.zip
mv wordpress /var/www/html/
続いてデータベースの準備
mysql> CREATE DATABASE `wordpress` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
mysql> GRANT ALL ON wordpress.* to wordpress@localhost;
mysql> FLUSH PRIVILEGES;
mysql> SET PASSWORD FOR wordpress@localhost=password('パスワード');
後は画面からインストール手順に従ってインストールをします。
設定ファイルは書き込みができなかったので、またまたコマンドで書き込みを行います。

vim /var/www/html/wordpress/wp-config.php
テーマをインストールできるように、パーミッションの変更を行っておきます。

vim /var/www/html/wordpress/wp-config.php

以下を追記します。

define('FS_METHOD', 'direct');
あとはパーミッションの変更

cd /var/www/html/wordpress/
mkdir wp-content/upgrade
chmod 0707 wp-content/upgrade
chmod 0707 wp-content/themes
chmod 0707 wp-content/plugins
以上です





2014年6月3日火曜日

Play Framework for Java 2.3を試してみる:プロジェクトの作成

Play Framework 2.3がリリースされました。
日本語サイトではまだ更新が反映されていませんが、本家のサイトの方では既に2.3.0がリリースされているのでさっそく使ってみましょう。

http://www.playframework.com/download

Java版では2.3系からORMにEBeanをやめてJPAが採用されたという話があるので、そのあたりも順次確認をしていってみたいと思います。

Playは新しいモノ好きなので、きっと動くだろうと確信してJDK 8の環境で構築をしていきます。

ダウンロード


まずは http://www.playframework.com/download からPlay 2.3をダウンロードします。実際はこれPlayをダウンロードしてるわけじゃなく、typesafe-activatorをダウンロードしてその中のテンプレートのPlayプロジェクトを作る感じの位置づけかと思います。
ダウンロードした typesafe-activator-1.2.1-minimal.zip を適当なフォルダに解凍します。

アプリケーション作成

Add activator your PATH to have the command available in your cli.
とりあえずPATH通せと言われていますが、環境を汚したくないので、解凍したフォルダに移動してActivatorを起動してみます。

cd activator-1.2.1-minimal/
./activator new
jarファイルをよしなにダウンロードするのでしばらく待ちます。
しばらくすると以下の様な画面が現れます。

Browse the list of templates: http://typesafe.com/activator/templates
Choose from these featured templates or enter a template name:
  1) minimal-java
  2) minimal-scala
  3) play-java
  4) play-scala
(hit tab to see a list of all templates)
とりあえずJavaのPlayを立ち上げるので、「3」を入力してみます。minimal-javaとの違いがよくわかりませんが、まあきっとこれはsrcフォルダとかを作るだけのJavaプロジェクトなんだろうかと思います。

Enter a name for your application (just press enter for 'play-java')
アプリケーション名を求められました。とりあえず「test-project」としてみましょう

OK, application "test-project" is being created using the "play-java" template.
To run "test-project" from the command-line, run:
***/activator-1.2.1-minimal/test-project/activator run
To run the test for "test-project" from the command-line, run:
***/activator-1.2.1-minimal/test-project/activator test
To run the Activator UI for "test-project" from the command-line, run:
***/activator-1.2.1-minimal/test-project/activator ui
え、そのフォルダの中にできちゃうの?という感じでどうやらプロジェクトが作られたようです。

アプリケーション起動


色々な思いをぐっとこらえ、とりあえず起動してみます。
activator-1.2.1-minimal/test-project/activator run ッてコメントで書いてあるので、まあ起動してみましょう。

cd test-project/
activator run
今度はプロジェクトに依存するjarファイルがよしなにダウンロードされるので、しばし待ちます。

結構待ちます。
時間としてカップ麺3個くらい作れてしまうのではないかと思います。

まだ終わりません・・・。明日の朝までかかるのではないでしょうか。。。

30分位待ってようやく起動しました。

http://localhost:9000/

にアクセスしてみます。

デザイン特に代わり映えしないこの画面が出たら起動完了です。



2014年4月22日火曜日

http://www.caspli.com/ について

結婚式の余興動画を収集するサイト、http://www.caspli.com/ http://www.caspli.com/
ですが、27日でドメインの有効期限が切れるのを持って、GAEデフォルトのURL
http://casplication.appspot.com/
にドメインを切り替えます。
振り返ってみると、サイトリリースがちょうど1年前でした。

  1. YouTubeから結婚式に関連する動画を取得
  2. Yahooの構文解析を使ってキーワードを抽出
  3. 結婚式の余興でどんなキーワードが多いのかランキング

というのを行ってみたサイトでしたが、マネタイズの方法が思いつきませんでした!(リアルな業者と手を結ぶとかの方法は模索すればあったかもしれませんが・・・)
14172の動画を集めたコンテンツはほぼ100%YouTube。
Google AdSenseを貼るわけにもいかず、結局そのへんは放置。
クローラーは毎日稼働するようにしていたので、セコセコと動画を集めてきていましたが、GoogleのDataStoreはI/Oが遅いので、バッチのように集中して書き込み処理が発生するものには向いていないことがわかりました。

ももクロ、AKB、カンナムスタイルあたりが余興の定番
最近だとフラッシュモブが流行りなのはなんとなく感じていましたが、アルゴリズム的にそこを抽出するところまでブラッシュアップできず。。。

それでもまあいい経験は出来たと思うので、次に進みたいと思います。
とりあえずGAE単体では動いているので、appspotのドメインではゆるりと動かしておきたいと思います。

ちなみにアクセスは1日平均40ユニークユーザーくらいでございました。

あと、Slim3はやはり楽でした。




2014年3月5日水曜日

PlayFrameworkで会員制ギャラリーサイトを作る習作:一般的なフォームの作成

さて一般的なフォームをPlay Frameworkで作っていきます。
入力画面→確認画面→完了画面の表示にします。

まずは事前準備として幾つかヘルパー等の用意をしておきます。

URLバリデータ


Play Frameworkでは基本的なバリデータはほとんど種類がありません。
URLの入力形式をチェックするバリデータを用意します。
正規表現を使って悩むのも面倒なので、org.apache.commons.validator.routines.UrlValidatorを使ってURLのバリデートをします。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/commit/3ed201aea99c0ed525467a69b7bd7f3d1b889753

Bootstrap Helper


PlayにはもともとBootstrapのHelperが用意されていますが、出力されるhtmlタグがあんまり良くなかったりするので、調整したものを用意しました。
エラー時の入力欄の枠の色を変える処理、「必須」ボタンの表示処理などを調整しています。

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/a238b208f2009861e28e28d76aa4d8e36d171d5f/modules/base/app/views/base/helper/bootstrapField.scala.html

確認画面用にテキストの表示とhiddenタグを出力するヘルパーを用意します。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/a238b208f2009861e28e28d76aa4d8e36d171d5f/modules/base/app/views/base/helper/bootstrapStaticControlField.scala.html

フォームの作成

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/commit/44e08da367faa07d8599216af9387c4e08fa6e76
でコミットをしています。

SiteFormController.java

がControllerになります


  • 入力画面:register()
  • 確認画面:confirm()
  • 登録:submit()
  • 完了画面:success()


のようになっています。
登録処理と完了画面表示処理を分けているのは、ブラウザのリロードにより2重投稿されるのを防ぐためです。

リダイレクトは
redirect(controllers.site.routes.SiteFormController.success());
のように書きます。

また、FormにセットするModelはEBeanのEntityを拡張したXXXBeanをセットするようにしてみました。


register.scala.html

入力画面のテンプレートになります。
bootstrapFieldを使ってhtmlを生成しています。
各入力欄にエラー表示をする処理をしつつ、画面上部にエラーを表示させる処理を行っています。
action指定は

controllers.site.routes.SiteFormController.confirm()
のようにして指定します。




confirm.scala.html

確認画面のテンプレートになります。
bootstrapStaticControlFieldを使って入力画面で入力したテキストの表示・hiddenタグへのデータ渡しを行っています。
Helperを使うとこんなに短く書くことが出来ます。




success.scala.html


確認画面のテンプレートになります。



messages

ヘルパーを使う関係で用意しました。がイマイチなんでこんなに短い定義でテキストが割り当てられるのかよくわかりません。。。


routes

URLとコントローラをひも付けています。とりあえずこのようなエンドポイントに設定しています。。。ちなみにリダイレクトのURLやFormのPOST先のURLをcontrollers・・・にしておくことで、実際のURLを変更した時にroutesだけの変更で抑えることが出来ます。



Site.java

EBeanのモデルです。
バリデートルールを追加しました。
@Column(nullable = false, unique = true, columnDefinition = "varchar(191)")
でデータベースの定義をします。他のアノテーションはバリデートルールです。
MaxLengthにエラーメッセージを定義する場合には以下のように書きます。

@MaxLength(value=191, message="URLは191文字以下でご入力ください。")

ちなみに@Lobにすると、一覧で取得するときにそのカラムはバイナリデータででかいから取ってこない、という判断をするケースもあるっぽいので注意が必要です。



SiteBean.java

save()メソッドはイケてないので目をつむって下さい。
validate()メソッドですが、正式な書き方はこのようになります。
今回は同じURLの2重登録を防ぐために自前validate()しています。
DBカラムをキーにエラーメッセージの配列をセットすると、入力項目ごとにエラーメッセージを関連付けることが出来ます。

ここで何か全体的なエラー(例えばアプリケーション内での権限的にデータの登録ができない処理とかで入力項目に関係なくエラーを出す場合にはreturnでエラーメッセージのテキストだけを返すようにしておけばOKです。)



SiteService.java


URL重複登録防止用のメソッドを追加しました。

今回のケースではあえて一般的な入力フォームの流れを作成しました。
URLを入力したら自動的でtitleタグを取ってきたかったりするのでそこはまた次回実装します。





2014年3月1日土曜日

PlayFrameworkで会員制ギャラリーサイトを作る習作:Play2.2.xで@NotNullアノテーションについて調べたこと

Play Framework 2.2.1がリリースされましたね。

さて、PlayFramework 2.1で使えていた@NotNullアノテーションが2.2で開発をした時にエラーを吐くようになりました。
その解決方法についていろいろ調べて詰まったので、備忘録として控えておきます。

まず結論から言うと、
Play! 2.1 アプリを Play! 2.2 に移行した作業の覚え書き

@NotNullアノテーション がなくなった
の節にある以下の様な書き換えで対応するのが良いようです。

2.1
import com.avaje.ebean.validation.NotNull;
2.2
import javax.validation.constraints.NotNull;
ここに至るまでに試行錯誤した結果を書いておきます。

2.1で使えていた@NotNullアノテーションをそのまま移植

そのまま使おうとすると、ビルドの際にエラーが出るようになりました。

build.sbtにavaje-ebeanorm-apiを追記してみる

調べてみると、どうやら
avaje-ebeanorm-api is not in the list of SBT dependencies
ということだそうで、EBeanの依存関係のバグでMaven Repositoryで自動取得してくれないようなので、build.sbtに以下を追記するようなので追記してみることにしました。

  "org.avaje.ebeanorm" % "avaje-ebeanorm-api" % "3.1.1"

https://groups.google.com/forum/#!topic/play-framework/aEglzIVCnH8
https://groups.google.com/forum/#!msg/play-framework/azlPQ14XJ2I/tdOKUkYVAxAJ

build.sbtの追記をやっぱり辞める

再度ビルドすると今度は新たなエラーが

Exception in thread "main" java.lang.NoSuchMethodError: com.avaje.ebean.config.AutofetchConfig.isGarbageCollectionOnShutdown()Z

http://stackoverflow.com/questions/20520456/java-lang-nosuchmethoderror-is-chasing-me-at-cloudbees 
を見ると、
isGarbageCollectionOnShutdown
メソッドはEBean の2.6.0系には存在しないメソッドで、3.2.2で存在しているメソッドだそうです。
また、

Looks like conflicting version of same jar in classpath
とあるように、そもそもPlay Framework 2.2系で使用しているEBeanのバージョンと
avaje-ebeanorm-apiのバージョンが混在しているのがいけないっぽい。

改めて
http://cs.hatenablog.jp/entry/2013/12/15/234618
を見てみると、

2.2ではEBeanが3.2.2になっています。
とあるので、できればavaje-ebeanorm-apiも3.2.2系にできればいいんだが、
http://mvnrepository.com/artifact/org.avaje.ebeanorm/avaje-ebeanorm-api
だと、3.1.1しかリリースされてない。。。

さらにGithubを見ると、
https://github.com/ebean-orm
のリポジトリ、
deprecated-avaje-ebeanorm-api
になってる・・・。

ということで、
2.2系では

import javax.validation.constraints.NotNull;
にするという結論になりました。以上。



2014年2月26日水曜日

PlayFrameworkで会員制ギャラリーサイトを作る習作:2ページ目以降をAjaxで取得する

それでだ、
Play Frameworkで会員制ギャラリーサイトを作っている途中。
前回のところでデータを取ってきて表示するところまで行きました。
app/views/ajax/listAjax.scala.html今回は画面をスクロールしたら2ページ目、3ページ目が読み込まれるところの処理を作っていきます。

なお、今回からTypesafe Activatorでアプリケーションを起動させるのはやめました。だって、play cleanがされなくて改修前の実装コードが残ってしまうのだもの・・・・。
すなおに play debug runするようにしました。

さて、2ページ目以降を取得する処理です。

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/commit/5756fc962c1ef328e3020beb0b92d5e20c3a3b51

のコミットが全てなのですが、処理の流れを見て行きましょう。

まずはCntroller


app/controllers/ajax/ListAjaxController.java
にしました。なおパッケージ名はcontrollers/ajax/***とかcontrollers/api/*** とかのように、共通するレスポンス形式とかでまとめておいたほうが後々フィルタをかけて処理させるときとかに楽になります。

1Action1Controllerファイルくらいにしておくと大規模開発にも耐えられるようになります。(コンフリクトが起きにくくなるという意味で)

1Controllerに入れていいのはせいぜいフォームの入力・確認・完了処理くらいまでかと思います。あとは分けましょう。
デメリットとしてはコンパイルが遅くなります。
ちなみにajax/ListAjaxController.javaの名前の付け方はイケてないです。

中身の処理は引数をページ番号としてまあ結果一覧を取得して返すだけの処理です。
 
public static Result index(int page) {
   List<SiteBean> resultList = SiteBeanService.getSiteBeanResultList(page);
   return resultList.size() == 0 ? ok("") : ok(views.html.ajax.listAjax
     .render(page, resultList));
  }

テンプレートでは面倒なのでhtmlを返しています。
JSONで返して、Javascript側でゴニョゴニョしてもいいかと思います。

conf/routes
にルーティングの設定を追加しておきましょう。
 
GET     /listAjax/:page                           controllers.ajax.ListAjaxController.index(page:Integer)

次にテンプレートから呼び出す方法


さて、最初の画面を表示して2ページ目以降を取得する処理ですが、
jquery_bottom
を利用してアクションを呼び出すようにします。

ページのフッターに次に呼ぶページ番号と更に読み込むページがあるかのフラグ用の値をセットしておきます。
 
<input type="hidden" id="hasNext" value="0" />
<input type="hidden" id="page" value="1" />


あとは呼び出す処理が呼ばれた際の中身を書いていきます。

 
 $(window).on('bottom', function() {
  var obj = $(this);
  // since this ajax call might take a while
  if (!obj.data("loading") && $("#hasNext").val() == 0) {
   obj.data("loading", true);
   $("#loading").show();
   $.ajax({
    url : "/listAjax/" + $("#page").val(),
    dataType : "html",
    success : function(data) {
     if (data == "") {
      $("#hasNext").val(1);
     } else {
      $("#listContainer").append(data);
     }
     var page = parseInt( $("#page").val() );
     $("#page").val(page + 1);
     // remove the loading text
     $("#loading").hide();
     // now that the ajax call is done, we can re-enable this
     obj.data("loading", false);
     $("#list"+page).preloader();
    },

    error : function(data) {
     console.log(data);
    }
   });
  }
 });


  1. 次に呼び出すページがあるようであればページ番号を渡してAjaxリクエスト
  2. レスポンスが空だったら処理終わりのフラグを立てて終了
  3. レスポンスがあったら帰ってきたレスポンスのhtmlをappendして表示
  4. ページ番号を1追加する
  5. ローディングを隠す
  6. 画像をかっこ良く表示させるpreloaderを呼ぶ

みたいなことをやっています。

2014年2月23日日曜日

PlayFrameworkで会員制ギャラリーサイトを作る習作:EBeanを使ってデータの取得を行う

さて、それではさっそくデータを取得してトップ画面に一覧を表示する機能を作っていきます。

プロジェクトの概要はこちら

今回の機能に関するIssueはこちらになります。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/issues/9

ロジック層

まずはデータを取得していく、MVCで言えばMのあたりから作っていきます。

modules/core/app/services/bases/SiteService.java
を作ります。

データの件数取得、データの一覧取得の条件は
getSiteCriteria
のメソッドにして共通の処理を呼ぶようにしています。

 public static PagingList<Site> getSiteCriteria() {
  return find.where().orderBy().desc("createDate")
    .findPagingList(ApplicationConfigUtils.MAX_PER_PAGE);
 }

 public static List<Site> getSiteResultList(Integer page) {
  PagingList<Site> pagingList = getSiteCriteria();
  Page<Site> currentPage = pagingList.getPage(page);
  return currentPage.getList();
 }

 public static Integer getSiteResultCount(Integer page) {
  PagingList<Site> pagingList = getSiteCriteria();
  return pagingList.getTotalPageCount();
 }


なかなかPlayFrameworkでページャーを使ってるサンプルがないのですが、このようにして呼ぶみたいです。

つぎにSiteServiceをextendsしたクラス
を作ります。
 
 public static List<SiteBean> getSiteBeanResultList(Integer page) {
  ArrayList<SiteBean> list = new ArrayList<SiteBean>();
  List<Site> resultList = getSiteResultList(page);
  for (Site site : resultList) {
   list.add(setSiteBean(site));
  }
  return list;
 }

SiteServiceはDBに直接操作を行うクラスという位置づけにしていて、
Controller側ではそのラッパーのSiteBeanServiceを呼ぶようにしています。
このクラスではDBからデータを取得する処理をSiteServiceから呼び出して、SiteBeanにセットする処理をしています。

こうすることで今後例えばキャッシュ機構を組み込む、などのようになった場合にDBアクセス層のSiteServiceはそのままで、SiteBeanServiceにキャッシュ機構を組み込めばいいようになります。

今の段階ではSiteBeanはSiteクラスをextendsしていますが、これはEBeanのModelではないため、多分extendsはやめると思います。。

JavaだとこういったModel,Bean系はsetter,getterを使うのが常ですが、Playはpublicにするのが流儀っぽいので、そういう感じにしています。

1ページに表示する件数については
modules/base/app/utils/base/ApplicationConfigUtils.java
に記述しています。こういうのは1つのサービス上統一するケースが多いと思うので、baseモジュールに書いてあります。
 
public static final int MAX_PER_PAGE = 10;

コントローラ層

 app/controllers/Application.java
のコントローラ側では
 
List resultList = SiteBeanService.getSiteBeanResultList(0);

のようにSiteBeanServiceを呼びます。
テンプレート側では
@(message: String, description: String, beanList: List[models.beans.SiteBean])

のようにしてリストを渡します。

 
<div class="container">
<div class="row">
 @if(beanList != null && beanList.size() > 0){
     @for(bean <- beanList){
    <div class="col-sm-6 col-md-4">
      <div class="thumbnail">
      <a href="@{bean.url}"><img title="@{bean.title}" src="@{bean.thumbUrl}" alt="@{bean.url}" /></a>
      </div>
    </div>
     }
 }
</div>
</div>

 でSiteBeanの一覧を表示します。
出来上がったのがこんなかんじになっています。


2014年2月21日金曜日

PlayFrameworkで会員制ギャラリーサイトを作る習作:EBeanを使用してModelの作成を行う

さてEBeanを使ってModelを作っていきます。
作成するModelの定義はこちらのIssueのとおり。


まずはModelを作成していきます。作るのはcoreのサブプロジェクト内。

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/f2f8ff770ea3b3ca15a04137a0d56fe269f6c962/modules/core/app/models/bases/Site.java

@Entity
public class Site extends Model {

 private static final long serialVersionUID = 3890695880010099962L;

 @Id
 public Long siteId;

 @Required
 @NotNull
 public String title;

 @Required
 @NotNull
 @Lob
 public String url;

 @CreatedTimestamp
 public Date createDate;

 @Version
 public Date updateDate;
}

個人的にはLazyLoadとかを信頼してないので、Model同士のひも付けは自前でする派です。

urlは255文字を超える場合もあるので(企業の採用ページだったら超えることもほぼ無いはずですが)、@Lobにしています。

ちなみに、NotNullのアノテーションですが、
libraryDependencies ++= Seq(
  // Select Play modules
  javaJdbc,  // Java database API
  javaEbean, // Java Ebean plugin
  //javaJpa,   // Java JPA plugin
  javaCore,  // The core Java API
  cache,
 "org.webjars" %% "webjars-play" % "2.2.0",
 "org.webjars" % "bootstrap" % "3.1.1",
   "org.webjars" % "font-awesome" % "4.0.3",
  "mysql" % "mysql-connector-java" % "5.1.29",
  "org.avaje.ebeanorm" % "avaje-ebeanorm-api" % "3.1.1")

のようにして呼ぶ必要があります。



2014年2月19日水曜日

PlayFrameworkで会員制ギャラリーサイトを作る習作:アプリケーションの雛形を準備する

さて、アプリケーションの作成に先立って、PlayFrameworkのアプリケーションの準備をしておきます。

  • Typesafe Activatorを元にプロジェクトを作成する
  • Bootstrapの3系を組み込む
  • Ebeanを組み込む
  • 各種設定ファイルを管理がしやすいように分割しておく
ところまでやったのがこのリビジョンです。(料理番組的・・・)

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/cbd6850947c7d31fc3d4cb9899a4ee197aeaf57f

今回のアプリケーションではユーザー側と管理者側とを同じ1台のサーバで処理する想定です。
この場合、データベースは一緒になりますが、ルーティング及びコントローラは別になるため、サブプロジェクトとして予め準備をしておきます。

このエントリーはこのチケットの解説です。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/issues/7

サブプロジェクトの作り方はこちらのエントリーを参照して下さい。
Play Frameworkでサブプロジェクトを使い倒す

このエントリーと同じ設計思想で

  • common:自作ライブラリ系
  • base:Controller共通処理系・Filter系
  • core:ORM・DB操作系
  • admin:管理画面

のサブプロジェクトを用意します。

common

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/master/modules/common

どうやらコンパイルをすると自動的に

  • .classpath
  • .project

ファイルが生成される模様。多分あとで消す。
src/main/javaなどのフォルダも自動的に生成されていました。とりあえずGitで管理したいので、 .gitkeep を置いておきます。

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/master/modules/common/src/main/java/components

にあるような、Javaで使いまわせるようなUtilityを配置します。

base

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/master/modules/base

これはPlayのサブプロジェクトになります。
各ディレクトリの形式もPlayの形式に従っています。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/master/modules/base/app/cache/base

にあるような、Playのapiを使用する共通処理を配置します。
わざわざcacheフォルダの中にサブプロジェクト名と同じサブフォルダを掘っているのは、後述のadminプロジェクトの構成と合わせるためこのようにしています。

  • Cache処理
  • Filter処理

などのように、Playのプロジェクトで共通して使えるような処理系を配置します。
これはPlay形式のサブプロジェクトになるので、build.sbtを配置しておきます。

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/master/modules/base/build.sbt

とりあえずnameをサブプロジェクト用に書き換えたものを置いてみました。

ちなみにPlay Framework2.2.xでcacheを使うときには
libraryDependencies ++= Seq(
  // Select Play modules
  javaJdbc,  // Java database API
  javaEbean, // Java Ebean plugin
  //javaJpa,   // Java JPA plugin
  javaCore,  // The core Java API
  cache,
 "org.webjars" %% "webjars-play" % "2.2.0",
 "org.webjars" % "bootstrap" % "3.1.1",
   "org.webjars" % "font-awesome" % "4.0.3",
  "mysql" % "mysql-connector-java" % "5.1.29")

のようにlibraryDependenciesにcacheを追加しておきます。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/master/build.sbt

core

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/master/modules/core

ここにはフロントエンド側、管理画面側で共通で使えるDB操作系の処理を配置します。
model周りやmodelを操作するservice周り、modelのラッパー的に使用するbeansを置くことになると思います。

admin

お待たせしました、やっとそれっぽいサブプロジェクトの登場です。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/tree/master/modules/admin

ここでは管理画面の処理を起きます。
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/master/modules/admin/app/controllers/admin/ApplicationController.java

のような感じですね。個人的にControllerのクラス名にはXXXControllerとしたいのは僕だけでしょうか?
さて、ちょっとControllerのパッケージがフロントエンド側とかぶると、ルーティングとかがめんどくさくなるので、controllers/admin/ApplicationController.java みたいな感じの場所においています。viewも同様です。

ルーティングですが、
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/master/conf/routes

->  /admin admin.Routes

みたいな感じでサブプロジェクトのルーティングルールを呼びます。

https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/blob/master/modules/admin/conf/admin.routes

# Routes
# This file defines all application routes (Higher priority routes first)
# ~~~~

GET /index                  controllers.admin.ApplicationController.index()

# Map static resources from the /public folder to the /assets URL path
GET     /assets/*file               controllers.Assets.at(path="/public", file)
GET     /webjars/*file              controllers.WebJarAssets.at(file)

assets,webjarsについてはadminとフロントエンドと分ける方法が未だによくわかりません・・・・。

Play Framework 2.2.x では以前ブログに書いた2.1.x系とサブプロジェクトの作り方が変わっていたので大変でした。以上。


PlayFrameworkで会員制ギャラリーサイトを作る習作:アプリケーションの概要を決める

PlayFrameworkに付属のサンプルではあまり実際の業務レベルのものが無いため、実際の業務レベルに耐えうる会員制ギャラリーサイトを作っていきたいと思います。

プロジェクトの要件を決める(PTF)

まずはプロジェクトの要件を決めます。

企業の採用ページデザインを集めたギャラリーサイトの作成

CSSのギャラリーサイト、フラットデザインのギャラリーサイトなどの採用ページ版を作成する。


  • ユーザーはログインしてサイトを登録することが出来る。
  • 外部APIを利用してサイトのキャプチャを表示する。
  • 他のユーザーが投稿したサイトに対してコメントをつけたり、評価をしたりすることが出来る。
  • ログインしなくてもギャラリーの表示はできる。
  • 今どきっぽいデザインにする。
  • 同じサーバ上で管理画面を用意して不適切な投稿・コメントの削除、ユーザーの管理ができるようにする。

開発要件

実際の開発にあたっての要件です。


  • フレームワーク:Play Framework 2.2.1 for Java
  • サーバ:さくらのVPSを想定(協賛者募集中です。@aimluck_iwasaki まで)
  • ソースコード管理・チケット管理:Github
  • デザイン:Bootstrap
  • Jenkinsを使ってビルド・デプロイを自動化する
  • テストコードを書く!
  • メンテナンスをしやすいように可読性の高いコードにしておく










2014年2月18日火曜日

Play FrameworkにBootstrap3系を組み込む

Typesafe Activatorで作ったPlayFrameworkのアプリケーションでは初期の状態でBootstrapが組み込まれていました。 この設定はbuild.sbt
に記述されています。
libraryDependencies ++= Seq(
  // Select Play modules
  //jdbc,      // The JDBC connection pool and the play.api.db API
  //anorm,     // Scala RDBMS Library
  //javaJdbc,  // Java database API
  //javaEbean, // Java Ebean plugin
  //javaJpa,   // Java JPA plugin
  //filters,   // A set of built-in filters
  javaCore,  // The core Java API
  // WebJars pull in client-side web libraries
  "org.webjars" %% "webjars-play" % "2.2.0",
  "org.webjars" % "bootstrap" % "3.1.1"
  // Add your own project dependencies in the form:
  // "group" % "artifact" % "version"
)

ここのところのバージョンを変えることで、読み込むBootstrapのバージョンを変更することが可能です。
"org.webjars" % "bootstrap" % "3.1.1"
対応しているバージョンやライブラリは http://www.webjars.org/ から探します。






Play FrameworkにBootstrapのSassを組み込む

Play Frameworkの場合、バージョンによって手順がもろもろ異なるので注意が必要です。 

事前準備


まず事前準備としてsassをコンパイルできるように不本意ながらsassをインストールします。
sudo gem install sass sass -v Sass 3.2.14 (Media Mark)

Play Frameworkの設定


さて次にPlayFrameworkにSass組み込みの設定をします。 PlayFramework 2.2.x系の場合です。

  https://github.com/jlitola/play-sass

project/plugins.sbt

resolvers += "Sonatype OSS Releases" at "https://oss.sonatype.org/content/repositories/releases"
addSbtPlugin("net.litola" % "play-sass" % "0.3.0")

build.sbt

import net.litola.SassPlugin
play.Project.playScalaSettings ++ SassPlugin.sassSettings

Play 2.0,2.1系は他にも設定が必要なようです。詳しくは
https://github.com/jlitola/play-sass をご確認下さい。

なお
http://qiita.com/Liberty/items/51dd4c6113ffc52efd3b
も参考にさせていただきました。

Bootstrap Saasの読み込み


 最後にBootstrapのSassを組み込みます。
http://getbootstrap.com/getting-started/#download
からSassのファイルをダウンロードして解答します。
解答するとvendorフォルダが出来上がるので、vendor内のassetsフォルダをPlay Frameworkのassetsフォルダにコピーします。

最終的には
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole/commit/84150e65946ef30e0840867eccb67cdbeb111bcc
のようになります。





Typesafe Activatorで作ったapplicationをgithubにpushする方法

普段はGithub上でリポジトリを作ってpullしてローカルでもろもろのファイルを作るのですが、Typesafe Activatorはapplicationを作成する際にディレクトリの中にファイルが在ると、アプリケーションが作れないので先にローカルでアプリケーションを作成し、github上にpushする必要があります。

Github上でリポジトリを作る際には、全く空の状態にしたいので、「Initialize this repository with a README」にチェックを入れないようにします。

Githubで空の状態でリポジトリを作ると、実行すべきコマンドが表示されるので、それをベースにコマンドを実行します。
全部のファイルをaddしてコミットします。

cd /Users/myname/Documents/workspace/PlayFrameworkRecruitConsole
git init
git add .
git commit -m "first commit"
git remote add origin https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole.git
git push -u origin master
GithubにPushします。
git remote add origin https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole.git
git push -u origin master
https://github.com/YoshiteruIwasaki/PlayFrameworkRecruitConsole
プロジェクトの準備が出来ました。
EclipseからGitのひも付けが出来るよう「チーム」→「プロジェクトの共用」を選んで「Git」→「プロジェクトの親フォルダー内のリポジトリーを使用または作成」にチェックを入れることでEclipseからGitのヒストリーなどが確認できるようになります。

2014年2月17日月曜日

Typesafe Activatorでapplicationを削除する方法


Typesafe Activatorでアプリケーションを作ってる時に、サンプルで作ったアプリケーションなどを削除したい場合があります。
アプリケーションを作成したディレクトリを削除しますが、なぜか一覧に残ってしまいます。


設定ファイルにアプリケーションの情報が残っているのでそれを削除します。
vim ~/.activator/1.0/config.json
{"applications":[]} 

のようにします。
http://stackoverflow.com/questions/19464093/remove-application-from-typesafe-activator

Typesafe Activator から Play Frameworkのプロジェクトを作成する

Play Frameworkのバージョンが挙がっているので、動作を試してみます。
どうやら2.2系からTypesafe Activator によるアプリケーションのセットアップが出来るようになったようです。
この辺よくわかってないので実際に手を動かして確認してみます。

http://www.playframework-ja.org/downloadから
Typesafe Activator1.0.13をダウンロードします。 

ダウンロードしたファイルを解凍して
/Users/myname/Documents/lib/activator-1.0.13
に展開をしてみました。(Macのパス)

ターミナルから以下を実行してみます。
/Users/myname/Documents/lib/activator-1.0.13/activator ui 
初回は依存関係のあるjarファイルがダウンロードされます。
しばらくするとブラウザが立ち上がります。

ベースとなるTemplateと
プロジェクトのName、Locationを選択してプロジェクトを作成します。



正直Templateはどれを選択していいかよくわからないので、「Hello Play Framework」を選んでおきました。他にも色いろあるようですが、これってユーザーが自由に作ったものもリストアップされてるんでしょうか?

上記のTemplateを選択するとScala版をベースに作成されるようです。
Javaベースで開発したい場合は以下を選びます。注意!

[basics] Hello Play Framework (Java Only)
Play Framework is the High Velocity Web Framework for Java and Scala. Play is based on a lightweight, stateless, web-friendly architecture. Built on Akka, Play provides predictable and minimal resource comsumption (CPU, memory, threads) for highly-scalable applications. This app will teach you how to start building Play 2.1 apps with Java.

完了すると格好いいコンパネっぽい画面が表示されました。


出来上がったProjectをEclipseにインポートする方法ですがこのコンパネから「Open project in Eclipse」を選択すると、Eclipseのプロジェクトファイルを生成してくれます。

その上で以下の手順でEclipseにインポートすることが可能です。

Now that you've generated your project files:
  1. Launch Eclipse and select Import... from the File menu.
  2. In the import dialog, choose Existing Projects Into Workspace and click Next.
  3. In the import dialog, browse to /Users/myname/Documents/workspace/PlayFrameworkAdminConsole. You should see your app's project(s) there.
  4. Select your project and click Finish.
If you need to (re)generate your project files, start over.
Hello Play Framework (Java Only)だとScalaプロジェクトだと判定されているのか、.classpathが正常に生成されないみたいです。。。

2014年2月10日月曜日

東京都知事選に見るツイートとの相関関係

今回の東京都知事選挙に向け、「2014年東京都知事選挙東京都知事選挙に関するツイートから本当の人気をランキング!」というサイトを立ち上げました。
http://tokyo.negaposia.com/
http://tokyo.negaposia.com/
このサイトでは

  • 各候補者名でTwitterを検索
  • 形態素解析を使ってつぶやきの内容を単語に分解
  • 単語ごとにネガポジ判定
  • ネガポジ判定を元に1日1回集計

を行って各候補者の人気をランキングしています。


こちらのランキングのソースは
https://github.com/YoshiteruIwasaki/NegativePositieAnalyzerForJa
で公開しています。

また、ネガポジ判定のロジックはrikyuを使用しています。
https://github.com/YoshiteruIwasaki/rikyu

ネガポジ判定ロジックとしてはyonagaもありますが、こちらはネガティブの割合のほうが重くなる傾向があるため今回は使用していません。


さて、今回当選をしたのは舛添要一氏でした。
舛添氏のランキングを見てみると最終日のランキングは最下位になっています。


また公示後のランキングについても見てみると、2月4−6日にかけては上位に食い込んできましたが、それ以外の期間はランキング下位が続いています。

舛添氏に関するツイートはネガティブな内容ポジティブな内容もどちらも多い、支持する人も多いけれど、反対する人も多い、といった傾向にあるようです。


途中まで、隠れた支持率の高い人を見出すため、その人に対するツイートに対するポジティブの割合をランキング上位に来るようにしていましたが、選挙は民主主義、数の理論のため、途中から純粋にポジティブなツイートからネガティブなツイートを引いた数、でランキングを出すようにしました。

今回の結果としては実際の結果とは外れた形になるので、精度を上げていきたいところです。やはりネットでつぶやく層と投票に行く層とは違うのでしょうか?
このロジックの今後の改善点として以下が挙げられます。


期間途中、ツイート数増加に耐えられず解析が間に合わない期間がありました。1候補者につき、1日3000から4000件ほどはつぶやかれているようです。

ツイート検索ロジックのリファクタリングが必要そうです(例えば今回「家入一真」氏は「家入 一真」で検索をかけましたが、「家入 かずま」と言った形でつぶやかれるケースも想定されます。)


形態素解析以外の重み付け手法の検討。今回は形態素解析でネガティブ・ポジティブを解析しましたが、あくまで単語ベースでの重み付けとなり、「この候補者マジでクソ。だが応援する」などの文章から判断することはできていないので、文章でその単語が出てくる場所(後半の方に重みをもたせる)、逆説のあとは重み付けを強くするなどの処理が必要かもしれません。(この辺りになってくると研究的側面が出てくるので、どなたか良いjarファイルをご存知であれば教えて下さい。)


最後に皆さん、投票には行きましょう!
以上。







2014年1月16日木曜日

Twitter4JでSSLを有効にする

twitterのAPIではSSLが必須になったので、twitter4jもSSL対応の設定をします。

ConfigurationBuilder conf = new ConfigurationBuilder().setUseSSL(true);
Twitter twitter = new TwitterFactory(conf.build()).getInstance();

のようにして対応します。
https://github.com/YoshiteruIwasaki/NegativePositieAnalyzerForJa/commit/f33a8f89033d8c2dd2c3e3bbfb6f421445cfffc2

設定ファイルから読み込みを行っている場合は、

twitter4j.properties


http.useSSL=true
を追加すればいけるかと思います。
http://twitter4j.org/ja/configuration.html


ちなみに動かなくなったのは、2014年1月15日4:15 AM以降でした。



2014年1月10日金曜日

さくらのVPSでPlay Frameworkを動かす:MySQL5.5の文字コードをよろしくする

UTF-8 エンコードされた絵文字を MySQL / JDBC で取り扱うには?


にあるように、ちょっとTwitterと連携する関係でutf8mb4を使いたくなりました。
以下の対応を行って様子を見てみます。

設定ファイルの変更


/etc/my.conf の以下を変更してMySQLを再起動します。

[mysqld]
#character-set-server = utf8
character-set-server = utf8mb4

既存テーブルの変更


とりあえず対応が必要なデータベースは1つでテーブルの数も5個位だったので、全部のテーブルに以下のSQLを実行

ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4;

Play Frameworkの接続設定の変更


application.confを以下のように書き換え

db.default.url="jdbc:mysql://localhost:3306/dbname?useUnicode=yes&characterEncoding=utf8&connectionCollation=utf8mb4_general_ci"

2014年1月9日木曜日

さくらのVPSでPlay Frameworkを動かす:MySQLを5.1から5.5にアップデートする

utf8mb4_general_ciが使いたいので、
CentOSのMySQLを5.1から5.5にアップデートします。

方法はもちろんお手軽なyum updateで行います。

事前準備


バックアップをとっておきましょう
mysqldump  -u root -p --all-database > all.sql
設定ファイルも念のためバックアップをとっておきます。
cp /etc/my.cnf /etc/my.cnf.backup

remiリポジトリの追加

epelの追加
rpm --import http://dl.fedoraproject.org/pub/epel/RPM-GPG-KEY-EPEL-6
rpm -ivh http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
remiの追加
rpm --import http://rpms.famillecollet.com/RPM-GPG-KEY-remi
rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

アップデート

service mysqld stop
yum --enablerepo=remi update mysql mysql-server

設定ファイルの変更

/etc/my.conf
の以下の場所を書き換えます。

[mysqld]
#default-character-set = utf8
character-set-server = utf8

#key_buffer = 128M
key_buffer_size = 128M

#log-slow-queries = /var/log/mysql-slow.log
slow-query-log = ON
slow-query-log-file = /var/log/mysql-slow.log

MySQLを起動します

service mysqld start
アップデートバッチを実行します
mysql_upgrade -u root -p