Jasper Reports で PDF ファイル出力

ちょっと必要がありまして、Jasper Reports というオープンソースの帳票出力ライブラリで PDF の出力を行いました。 使い方を忘れてしまいそうなのでメモがてら。 初めて使うライブラリは勝手が分からずなかなか大変です。 🙂

Jasper Reports とその帳票設計を行う iReport というアプリです。

jasperforge JasperReports Project Home

JasperReports is the world’s most popular open source reporting engine. It is entierly written in Java and it is able to use data coming from any kind of data source and produce pixel-perfect documents that can be viewed, printed or exported in a variety of document formats including HTML, PDF, Excel, OpenOffice and Word.

jasperforge iReport Project Home

iReport is the free, open source report designer for JasperReports. Create very sophisticated layouts containing charts, images, subreports, crosstabs and much more. Access your data through JDBC, TableModels, JavaBeans, XML, Hibernate, CSV, and custom sources. Then publish your reports as PDF, RTF, XML, XLS, CSV, HTML, XHTML, text, DOCX, or OpenOffice.

Jasper Report は LGPL、iReport は AGPL です。 iReport のほうは NetBeans ベースでつくられているよう。 前者がライブラリで、後者がそのライブラリで読み込む GUI 帳票設計アプリケーションとなります。

とりあえず、ファイルをダウンロード。 以下二つを利用しました。 iReport のほうは、Linux、Mac OS X 版もあります。 Jasper Reports は pure java です。

jasperreports-3.7.1-project.tar.gz

iReport-3.7.1-windows-installer.exe

また、Jasper Reports の PDF 出力は iText PDF ライブラリに依存しています。 iText 自体は上記 project.tar.gz (のlib)に同梱されいますが、日本語の出力の際に必要な iTextAsian.jar が含まれていませんので以下からダウンロードします。(下の方です)

Browse iText, a JAVA-PDF library Files on SourceForge.net

extrajars  – ExtraJars1.0  – iTextAsian.jar

これでファイルの準備は完了。 iReport のほうは適当にセットアップしておきます。

Jasper Reports はいろいろなデータソースから帳票を出力できますが、今回は Java の Bean 経由で出力してみます。 DB に直つなぎとかもできるみたいですね。

最終的に Java からだすので、先にプログラムソースの準備を。

以下のようなモジュール構成にしておきます。 Jasper Reports の依存ライブラリがよく分かりませんでしたが、今回のプログラムで class not found がでなくなった最小構成としています。 また、先の iTextAsian.jar もいっしょに入れておきます。

Jasper01

templates フォルダには Jasper Repost の定義体を入れることにしましょう。

SampleReportBean.java が帳票に出力したいレコードを表現した Bean です。 Bean の内容は以下の通り。 getter、setter は省略。

   1: package net.maple4ever.jasper;
   2:  
   3: public class SampleReportBean {
   4:  
   5:     // メーカ
   6:     private String maker;
   7:     // 機種名
   8:     private String name;
   9:     // OS
  10:     private String os;
  11:     // CPU
  12:     private String cpu;
  13:     // メモリ容量
  14:     private String memory;
  15:     // ハードディスク容量
  16:     private String hdd;
  17:  
  18:     // 以下 getter/setter (省略)
  19: }

さてさて、ここから iReport の世界に入っていきます。 iReport 起動。

とりあえずオプション設定。 iTextAsian.jar と今ほどつくった Java プロジェクトに class path を通します。

 Jasper02

Eclipse で Java プロジェクトつくった場合は、プロジェクトロケーション/bin にします。(class ファイルできるところね) で、上のスクリーンショットでは忘れてしまっていますが、Relodable にチェックを入れます。 iTextAsian.jar にはチェックいらないでしょう。(Java プログラムを修正すると読み直してくれます)

了解おして、ここで iReport を一回再起動。(しないと iTextAsian が反映されませんでした)

でもってファイル –> NEW あたりから帳票新規作成。 ファイルの置き場所を先ほどの templates フォルダにします。 種類、ここでは A4 のブランクにしました。

Jasper03

Open this Template おして、

Jasper04 

みたいな感じです。

できたら、まずは帳票プロパティの Language を Java に変更します。 Groovy が標準のようですね。 これやらないと、後で Java から呼ぶときに groovy の class ないぞってエラーになります。

Jasper04-02

帳票設計画面はこんな感じです。

Jasper05

上から Title、Page Header、Column Header、Detail 1、Column Footer、Page Footer、Summary となっています。 この中で Detail の部分が繰り返しのデータをおくところになります。 ここが重要。

でもって、Title、Summary 部分が1ページと最終ページ。 Page/Column  Header、Footer が表ごとページごととなるようです。

ふまえて、レコードとなるさきほどの Bean を Detail 1 に配置していきます。 まずはデザイナ上部、Preview の横のデータベース矢印みたいなアイコンをクリックします。

Jasper05-02

さきほどつくった Bean のパッケージを入力して Read attributes を押下します。 さすると、Bean のプロパティがでてきます。 うまく読めないときは class path の設定を確認。

Jasper06

選択して Add Selected field(s) ボタンを押下します。 するとこのフィールドがデザイナ上で配置できるようになります。

画面左ツリーの Fields 木にいま追加したフィールド出現するので、ドラッグアンドドロップで Detail 1 に置いていきます。 罫線とか必要ならパレット開いて描画していきます。 static text とかでテーブルヘッダとかタイトルとかもつける。

日本語フォントは PDF Font name を「HeiseiKakuGo-W5」に、PDF Encording を「UniJIS-UCS2-H (Japanese)」にします。 こうしないと PDF になったときに日本語が出力されません。(Adobe Reader のフォント。ちょっと詳しくないですが、iTextAsian.jar の設定値なのかもしれません。 MSP ゴシックとかは設定できない模様)

まぁまぁこんな感じです。

 Jasper09

また繰り返しリストではなく、帳票全体でひとつの埋め込み項目は「パラメータ」として配置することができます。 左ツリーのparameter で追加して名前をつけて置いていきます。

Jasper08

でもって、なんとなくできたらデータを埋め込んでみます。 iReport には任意の Java を呼び出してその帰り値の Collection を埋め込んでくれる便利な機能がありました。(Biz Stream はこれできないよね?)

とりあえずさきほどの Java のプロジェクトに SampleReportFactory.java というソースを追加しました。 createBeanCollection という static なメソッドが標準で使われるようなのでこれも用意しておきます。 こんな感じです。

   1: public class SampleReportFactory {
   2:     
   3:     public static List<SampleReportBean> createBeanCollection() {
   4:         
   5:         List<SampleReportBean> lines =
   6:             new ArrayList<SampleReportBean>();
   7:         
   8:         for(int i=1; i<100;i++) {
   9:             SampleReportBean line = new SampleReportBean();
  10:             line.setName("自作機2号");
  11:             line.setMaker("ひろまさ");
  12:             line.setOs("Ubuntu 9.10");
  13:             line.setCpu("PhenomII X4");
  14:             line.setHdd("320GByte");
  15:             line.setMemory("4GByte");
  16:             line.setColor(String.valueOf(i % 2));
  17:             lines.add(line);
  18:         }
  19:         return lines;
  20:     }
  21: }

iReport に戻って画面上部のデータソースのアイコンを押下します。

Jasper05-01

JavaBeans set datasource を選択。

 Jasper10

でもっていまつくった SampleReportFactory を指定します。

Jasper11

Test おして OK もらったら Save します。

で、デザイナの Preview を押してみると帳票につくったデータソースがバインドされた結果が表示されます。 🙂

Jasper13

ソースコードから入力をつくれるので桁数試験とか結構便利です。

さてさて、ちゃんとした帳票だと罫線の制御とかしたくなることがあります。

ちょっとマニュアル調べて簡単そうだったのが各描画オブジェクトがもつ、Print When Express というプロパティ。 フィールドとかの値を判定して表示の可否をきめることができます。

たとえば、行をしましまにしたかったら Bean にそれっぽいフラグ項目をつくって、

Jasper14

こんな感じで Print When Expression を設定してあげると true のときだけ表示になります。(Jasper への戻値は、boolean じゃなくて Boolean のようなので注意してください)

というわけで灰色ざぶとんを行の下に敷いて、しましま。 とか。

Jasper15

他にも良い方法があるとは思うですが、これさえあればあとは組み合わせ、、知恵と勇気でなんでもいけるかと。。(笑)

では最後に Java から作った帳票をだしてみます。 iReport 終了。 iReport で保存・コンパイルされたものが templates フォルダに入っているはずです。

Jasper16 

.jasper がコンパイルされた結果です。 プログラムからはこちらを使います。(動的コンパイルもできるみたいですがここでは割愛)

面倒なので先ほどの SampleReportFactory クラスに main を追加する感じで。 List はさきほどつくったもの。 また、HashMap にパラメータを設定して Jasper に渡すと PDF ができる感じです。

   1: public class SampleReportFactory {
   2:  
   3:     // さきほどの createBeanCollection メソッド省略
   4:  
   5:     public static void main(String args[]) throws JRException {
   6:         
   7:         // 出力するBean のつまった List を DataSource に設定
   8:         JRBeanCollectionDataSource ds =
   9:             new JRBeanCollectionDataSource(
  10:                 SampleReportFactory.createBeanCollection());
  11:         // パラメータの Map 作成
  12:         Map<String,String> param = new HashMap<String,String>();
  13:         param.put("now", "2010/03/11");
  14:         // これらのデータを元に PDF 作成
  15:         JasperPrint pdf = JasperFillManager.fillReport(
  16:                 "./templates/sample-report.jasper", param, ds);
  17:         // PDF をファイルとして出力
  18:         JasperExportManager.exportReportToPdfFile(pdf,
  19:                 "./templates/sample-report.pdf");
  20:         
  21:         // pdf.addPage((JRPrintPage)pdf.getPages().get(0));
  22:         
  23:     }
  24:  
  25: }

実行~。

Jasper17

おめでとうございます(笑)

最後のサンプルソースの一番下にコメントでかいてありますが、複数のテンプレートをつなげて一つの PDF にすることもできそうです。

   1: // pdf.addPage((JRPrintPage)pdf.getPages().get(0));

addPage の引数に index ありもあったので、交互差し込みとかもできるかもですね。

ここまできたら、本家のマニュアルの xml タグを調べていけばあとはなんとか。。(笑)

JasperReports 3.7.1 – Schema Reference

This document describes the structure of the JRXML report template files for the JasperReports library.

Expression 系でいろいろできそうです。

以上、参考になりましたら。

Twitter のボットと Platform as a Service

明けましておめでとうございます。 2010 年、ぼくも hiromasa.another もいつもどおりのまったり感かと思いますが、今年もよろしくお願いいたします。 🙂

さて去年あたりから、Windows Azure などいわゆるクラウド的なサービスがいろいろでてきて、なんだかちょっとわくわく。 今年の興味はこの辺から・・・。

クラウドというと、ラップするレイアがサービスによっていろいろ違ってなんだかよく分からないですが、ぼくはその中の PaaS というサービスが遊ぶに面白そうかなと思っています。

クラウドと呼ばれているものにはいくつか種類があると思いますが、たとえば Amazon EC2 はサーバの物理存在を隠します。 サーバが 2台ほしければ、2 って画面にいれて起動させれば 2台できる。 増やしたければすぐ増やせる。 サーバの手配とかデータセンターの置き場所とか電源とか考えなくていいわけですね。

たとえば Google Apps。 これはサーバとさらにアプリケーションの運用を隠します。 言うならばメールサーバ落ちた!などと会社の情報システム部門がてんやわんやしなくてよくなるというサービス(笑)

で、PaaS というのはその中間。 物理サーバとアプリケーション動作に無関係な運用部分を請け負ってくれます。 で、のせるアプリケーションは各自つくってすぐデプロイできるように環境が整っている感じです。

今で言うところの、レンタルサーバに PHP のアプリケーションを各自入れて動かすの発展系のイメージ。

たとえば現状のレンタルサーバでは WordPress の MySQL のバックアップとか自分でやらなくてはならなくて結構大変ですが、PaaS の場合はスケジュールで勝手にバックアップをとってくれたり簡単にリストアできたり、各種リソースの使用量が管理画面から見えたり、よりアプリケーションよりのサービスが付随します。

PaaS のひとつである、Windows Azure では、既に WordPress も稼働しているとのことです。

「PDC09」リポート:Microsoftはハイブリッドな戦略で古い殻を脱ぎ捨てる (2/3) – ITmedia +D PC USER

欧米を中心に世界中で広く利用されているブログシステム「WordPress」の開発者であるマット・マレンウェッグ氏が登場し、Windows Azure上でWordPressを動作させるデモを紹介した。

さて、この PaaS ですがもう一つの特徴が、様々なアプリケーションを動かすための環境が整っていること。 簡単に言えば、C# とか Java とかそのへんの言語と、そのアプリケーションサーバ環境周りも使うことができます。

PHP では少し無理があったことも簡単にできるようになる・・・。 実はここがぼくの最大の関心事。 大昔 CGI が無料で使える海外サーバがでてきたようなどきどきが(笑)

PaaS のサービスは Google App Engine とか Stax Networks とかありますが、ここでは後者を使ってみました。 Stax のほうがサンドボックスの制限が緩いので遊びやすいのです。

とりあえずつくってみたのは、twitter ボット。

stax02

PHP でももちろんボットはつくれますが、一般的な PHP の環境はプログラムから動き出すことができないという制約があります。 人のアクセスとか別系の cron とか外的要因からプログラムをキックする必要がありますが、ここでは Java のスレッドスケジューラを使って自分から定期起動するようにしています。

いろんなライブラリが簡単に使えるのもいいところで、このボットは twitter クライアントに twitter4j、また スケジューラ に Quartz というライブラリを使っています。

Twitter4J – A Java library for the Twitter API

Twitter4J は TwitterAPI の Java ラッパです。 Twitter4J を使うと XML や HTTP に詳しくなくても容易に Twitter とインタラクトするアプリケーションを書くことが出来ます。

Quartz Scheduler – Home

Quartz is a full-featured, open source job scheduling service that can be integrated with, or used along side virtually any Java EE or Java SE application – from the smallest stand-alone application to the largest e-commerce system.

ちなみに、Google App Engine はスレッド禁止っぽいので、Quatz は残念ながら動作しないと思われます。 http の通信もなにか特別なことをしなくてはいけなそうでした。(たぶん)

で、とりあえずライブラリや web.xml を配置します。 Stax Networks は Tomcat を使っているようで、また一般的な WAR も配置できるので基本的になにも考えずにいつも通りにつくれます。

stax04

web.xml を以下のように。

<?xml version="1.0" encoding="UTF-8"?>
<web-app>
  <display-name>Desyura</display-name>
  <servlet>
    <servlet-name>QuartzInitializer</servlet-name>
    <servlet-class>
    org.quartz.ee.servlet.QuartzInitializerServlet</servlet-class>
    <init-param>
      <param-name>shutdown-on-unload</param-name>
      <param-value>true</param-value>
    </init-param>
    <init-param>
      <param-name>start-scheduler-on-load</param-name>
      <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet>
    <display-name>RobotInitializer</display-name>
    <servlet-name>RobotInitializer</servlet-name>
    <servlet-class>
    net.maple4ever.desyura.RobotInitializer</servlet-class>
    <load-on-startup>2</load-on-startup>
  </servlet>
</web-app>

QuartzInitializerServlet と、スケジューラの起動の Servlet を順番に登録。

あとはソースを書くだけです。 動作できるかどうかのサンプルでかいただけなので、いんちきをたくさん含んでいることをあらかじめご了承ください。

RobotInitializer.java。 スケジュールのインスタンスをもらって、Job を行うクラスを登録する感じです。 CronTriger を使うと cron みたいな形式で時間を指定できます。

package net.maple4ever.desyura;

import java.text.ParseException;
import java.util.Calendar;
import java.util.Locale;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;

public class RobotInitializer extends HttpServlet {

    public static final String START_TIME = "START_TIME";
    private static final long serialVersionUID = 1L;

    public RobotInitializer() {
        super();
    }

    @Override
    public void init() throws ServletException {
        // QuartzInitializerServlet で作成したスケジューラを取得
        Scheduler sched = null;
        try {
            sched = (new StdSchedulerFactory()).getScheduler();
        } catch (SchedulerException e) {
            throw new ServletException(e);
        }
        // Cron 形式のトリガー作成(とりあえず 5分)
        Trigger trigger = new CronTrigger("trigger1", "group1");
        try {
            ((CronTrigger) trigger).setCronExpression("0 0/5 * * * ?");
        } catch (ParseException e) {
            throw new ServletException(e);
        }
        // JobDetail にコールバッククラス登録
        JobDetail jobDetail = new JobDetail(
                "Twitter Bot"
                , "Twitter Bot"
                , TwitterBotService.class
                , true
                , true
                , true);
        // 起動時間を JobDataMap に格納(twitter のロケールも日本にすること)
        jobDetail.getJobDataMap().put(START_TIME,
                Calendar.getInstance(Locale.JAPAN));
        // スケジュール開始
        try {
            sched.scheduleJob(jobDetail, trigger);
            sched.start();
        } catch (SchedulerException e) {
            throw new ServletException(e);
        }
    }

}

TwitterBotService.java。 時間がきたら twitter をみてつぶやく Job クラスです。 スケジュールごとに new されるので手を抜いて static で値を保持しています。(本当は context にシリアライズできる形で値をいれるのが良いと思われます)

package net.maple4ever.desyura;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Date;

import org.quartz.JobExecutionContext;
import org.quartz.StatefulJob;

import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;

public class TwitterBotService implements StatefulJob {

    // StatefulJob は同時実行されないが手抜き synchronized しておく
    static private List<Long> read = (List<Long>) Collections
            .synchronizedList(new ArrayList<Long>());
    static private final int PAGE_COUNT = 20;

    public void execute(JobExecutionContext context) {
        // スケジュールイベント
        System.out.println("Fire! " + context.getScheduledFireTime());
        // 初回起動時間取得
        Date fistTime = ((Calendar) context.getMergedJobDataMap().get(
                RobotInitializer.START_TIME)).getTime();
        // twitter 接続
        Twitter tw = new Twitter("ユーザ名", "パスワード");

        String tweet;
        try {
            // twitter から Mentions をもらう
            List<Status> status = tw.getMentions();
            for(Status stat : status) {
                // 起動時より前の返信は答えない
                if(fistTime.after(stat.getCreatedAt())) continue;
                // すでに返信していたら答えない
                if(read.contains(stat.getId())) continue;
                // 自分のスクリーンネームを相手に置換してつぶやく
                tweet = stat.getText().replaceAll(
                        stat.getInReplyToScreenName(),
                        stat.getUser().getScreenName());
                tw.updateStatus(tweet, stat.getId());
                System.out.println(tweet);
                // 読んだリストに入れておく
                read.add(stat.getId());
            }
            // getMentions() は 20件取得なのでそれを超えたら忘れる
            if(read.size() > PAGE_COUNT) {
                read.remove(0);
            }
        } catch (TwitterException e) {
            // 投稿失敗しても次に期待する
            System.out.println(e.getStackTrace());
        }
    }

}

(あ!!、if の位置間違っていることをブログかきながら発見。。(笑))

ひとつしかスケジュールもアカウントも制御できないエコーなボットですが、100 ステップくらいでできちゃうのはお手軽すぎです。

これは実験なのであれですが、スケジュールも twitter も意識させずに文字列操作部分だけ外だしにできるようにプログラムをかえていけばいいかなという感じですね。 Jython とか JRuby とか Groovy とかの Java の上で動くスクリプト言語にその部分をプラグインのように渡すのも面白いかもしれません。

できた WAR は Stax Networks にそのままデプロイできます。 ant タスクがあるのでコマンド一発。 FTP クライアントとかいりませぬ。

hiromasa.another :o) » Blog Archive » Stax Networks への JavaEE アプリのデプロイ

あとは、ドキュメントにかいてあるとおり build.xml にユーザ名とかパスワード、war の stax-application.xml パスをかきます。

stax-application.xml はとりあえず適当に Stax Networks の管理画面で BASIC Servlet and JSP なアプリを作成しておいて、それをダウンロードしてきてそのまんま使うのが楽かもしれません。

さて、twitter は昔 Jabber をサポートしていたので、たとえば Stax Networks とソケットつなぎっぱなしにして、リアルタイムに反応するボットとかもつくれたと思うのですが、もうできなくて残念。

でも、最近は websocket とかそれっぽい技術もできてきていますので、こういったアプリケーションサーバがあると、いままで http な Web ではできなかったようなことも実現できそうです。

いろいろこのへんの技術で遊んでみたいな、と思った1年の始まりでした。 🙂

Stax Networks への JavaEE アプリのデプロイ

慣れの問題もあるかもですが、ぼくはちょっとした自分でしか使わないような Web アプリをつくるのに PHP とかより Java を使った方が早い場合があります。 言語的な問題というより環境、、便利なライブラリがたくさんあって、いれるのも lib に jar 入れるだけだし~、みたいな(笑)

問題はインターネット上にデプロイする先があまりないことですが、クラウドがでてきてくれたので最近はいくつか無料で使わせてくれるところがでてきています。

昔 Morph AppSpace を使って遊んでいましたが、Stax Networks というのも良さそうなので実験してみました〜 Google App Engine なんてのもありますね。:-P

stax01

Stax Networks – Home

The fastest way for Java EE developers to build, manage and scale applications in the Cloud.

というわけで、早速適当なものをつくってデプロイ。

以前から iアプリ用の Java の twitter クライアントがほしいなぁとおもっていて、この場合サーバサイドのプロキシがないと実装できないので、それをつくるのを見据えて、とりあえず REST すると public タイムラインとってくるのをやってみようと思いました。

Java EE に JAX-RS という REST の仕様がありますが、その実装である JBoss の RESTEasy と、twitter にアクセスするために twitter4j を使ってみます。

JBoss、JAX-RS実装「RESTEasy 1.0」正式版リリース – SourceForge.JP Magazine

JAX-RS(JSR 311)は、JavaでRESTアーキテクチャを利用してWebアプリケーションを作成するためのJCP仕様。RESTEasyはJBossのJAX- RS実装で、開発者に容易に開発できるフレームワークを提供する。Tomcatなど、JDK 5以上をベースとしたサーブレットコンテナで動作するが、「JBoss Application Server」と蜜に統合することで、ユーザーエクスペリエンスを改善できるという。

Twitter4J – A Java library for the Twitter API

Twitter4J は TwitterAPI の Java ラッパです。 Twitter4J を使うと XML や HTTP に詳しくなくても容易に Twitter とインタラクトするアプリケーションを書くことが出来ます。

Eclipse で動的 Web プロジェクトを新規作成して、WebContent/WEB-INF/lib に各ライブラリ jar を放り込みます。

WebCOntent/WEB-INF/web.xml で RESTEasy をサーブレット登録して URL にマッピングします。

<?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_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" id="WebApp_ID" version="2.5">
    <display-name>DJOdekoServer</display-name>
    <context-param>
        <param-name>resteasy.scan</param-name>
        <param-value>true</param-value>
    </context-param>
    <context-param>
       <param-name>resteasy.servlet.mapping.prefix</param-name>
       <param-value>/api</param-value>
    </context-param>
    <servlet>
        <servlet-name>Resteasy</servlet-name>
        <servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>Resteasy</servlet-name>
        <url-pattern>/*</url-pattern>
    </servlet-mapping>
</web-app>

これでアプリをかく準備完了です。 ソースを適当にかきます。 🙂

RESTEasy は resteasy.scan を true にしておくと、@Path のアノテーションをもつクラス(?)を勝手にスキャンしてくれてクラスロードしてくれるようです。

ということで、@Path で URI を指定しておけばエントリポイントが勝手にできます。 便利ですね。

package net.maple4ever.djodeko.server.rest;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.ws.rs.Path;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

import org.jboss.resteasy.annotations.providers.jaxb.Wrapped;

import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterException;

@Path("/public")
public class TimeLine {

    @GET
    @Produces("application/xml")
    @Wrapped(element="public")
    public Set<PublicTimeLine> getPublic() {
        Twitter twitter = new Twitter();
        List<Status> statuses = null;
        try {
            statuses = twitter.getPublicTimeline();
        } catch (TwitterException e) {
            e.printStackTrace();
        }

        HashSet<PublicTimeLine> publicTimeLine = new HashSet<PublicTimeLine>();
        for (Status status : statuses) {
            publicTimeLine.add(new PublicTimeLine(
                    status.getUser().getName(),
                    status.getText()));
        }
        return publicTimeLine;
    }

}

@XmlRootElement(name = "tweet")
class PublicTimeLine {

    @XmlElement
    String account;
    @XmlElement
    String tweet;

    public PublicTimeLine() { }

    public PublicTimeLine(String account, String tweet) {
        this.account = account;
        this.tweet = tweet;
    }

    public String getAccount() {
        return account;
    }

    public String getTweet() {
        return tweet;
    }

}

その try cache はおかしーじゃねーかというつっこみはなしで。。(笑)

twitter4j を使ってパブリックタイムラインをもらって XML で出力する例です。  @Path(“/public”) を指定しているので、コンテキストルート/public にメソッドがマップされます。 メソッドにさらにアノテーションでパスを指定したり引数をもらうこともできます。

まぁまぁここまではできるひとなら 15分仕事です。 PHP より楽じゃねっすかね。 ローカルではうまくうごくことでしょう。 🙂

で、これを Stax Networks にデプロイするわけですが、、はて、WAR玉 ってデプロイできるかな。 なにか専用の SDK あるみたいですが。。(笑)

Deploying WAR Files – Stax

If you have an a Java web application packaged as a WAR file, you can use the Stax Deploy ANT task from the Stax SDK to deploy your WAR file to the Stax Cloud using an ANT script.

というわけで、ちゃんとドキュメントがありました。 SDK に ant タスクがあるようです。 とりあえず、SDK をどっかにいれてあと ant もいれておきましょう。 (Ubuntu には ant のバイナリパッケージにあるんですが、念のため本家版をつかっています。 Eclipse 内蔵の ant でもいいかもです。)

Ubuntu の場合は、 ~/.profile に以下を書いておくといいかもです。

#Stax Setting
export STAX_HOME=/home/hiromasa/Application/stax/stax-sdk-0.3.6
export ANT_HOME=/home/hiromasa/Application/stax/apache-ant-1.7.1/
export PATH=$PATH:$STAX_HOME:$ANT_HOME/bin

あとは、ドキュメントにかいてあるとおり build.xml にユーザ名とかパスワード、war の stax-application.xml パスをかきます。

stax-application.xml はとりあえず適当に Stax Networks の管理画面で BASIC Servlet and JSP なアプリを作成しておいて、それをダウンロードしてきてそのまんま使うのが楽かもしれません。

stax03

WAR ファイルはとりあえず面倒なので Eclipse のプロジェクトエクスポートでつくっています。 これで ant すればネットワーク越しにデプロイしてくれます。  Morph AppSpace と違ってすぐデプロイしてくれるようです。 URL にアクセスしてみましょう。 🙂

http://djodeko.hiromasa.staxapps.net/api/public

ちゃんと動いていますね。 🙂

さて、Stax Networks は素敵なことにドメインマッピングに対応しています。 とりあえず、自分のドメインの CNAME を設定しておきます。

cname djodeko djodeko.hiromasa.staxapps.net.

最後にドットいれるのを忘れないよう。。

で、名前がひけるようになるまで我慢の子です。 Stax Networks 的に DNS が引ける状態でないとうまく登録してくれません。 もし管理画面で save しても値が空になるようならこの状態です。 ややまってからしましょう。 うまく保存できたら、、

http://djodeko.maple4ever.net/api/public

素敵ですね。 🙂

実験的につくったものなので、まぁ URI かえるといろいろエラーでますが、どうやら Tomcat 使っているみたいです。

ファイルの書き込みがなければほとんどのフレームワーク/ライブラリは素直にうごくような雰囲気です。

DB (MySQL が使える)のほうはまだためしていませんが、JNDI 設定してしまえばあとは同じでしょう。 S2JDBC とか Hibernate とか動くんだと思います。

ふと思い立って、CMS とかも Java 製のものあるのかなとおもって検索してみると、エンタープライズ向けにいくつかあるようですね。 アプリケーションコンテナいるとコネクションプールとかシングルトンつかえるから性能的にはやっぱり有利な部分もあると思います。 PaaS が増えてくるとすればこれらも要チェックかもですね。

とりあえず、Stax は何もしなくてもいろいろ動きそう。 いろんなアプリをデプロイして実験してみるのも面白いかもしれません。

Click Framework を使ってみる

クラウドというキーワードの影響か、Java EE なアプリケーションがデプロイできるインターネットサーバも増えてきました。 てなわけで、お手軽なフレームワークらしい Click Framework をためしてみました。 さすがのぼくもお遊びで Struts 使う元気はありません。。 😛

インターネットで配布される Web のアプリはやはり PHP が多いような気がしますが、ひとたびライブラリだフレームワークだとなると環境を整えるのが面倒なものです。 あれ、パス狂ってるよみたいな。 ファイルの管理も面倒です。

ぼくは Web アプリかくとき Java のほうが便利と感じますが、これは言語的なものよりも、フレームワークやライブラリなど周辺環境的なことのほうが多いのかもしれません。 もちろん、言語も Java のほうがある意味楽ですが。

さて、そんな Java EE アプリの作成を手伝ってくれる Click Framework。

第3回 シンプルかつ強力なコンポーネント指向フレームワーク「Click Framework」:ITpro

JavaのWebアプリケーション・フレームワークのはしりといえば,なんといってもStrutsです。Strutsはデファクトスタンダードの地位を確立し,現在でも多くのユーザーに利用されています。しかし,Servlet APIに薄いラッパーを被せただけのシンプルなフレームワークであり,その後TapestryやJSF(JavaServer Faces)といったより高度に抽象化されたコンポーネント指向のフレームワークが登場したのは自然な流れといえます。

Click もコンポーネント指向ということで、Java のソース上でコントロールをぺたぺた add していけば勝手に HTML をかいてくれます。 といっても前にちらっとかいた、ZK よりも Click さんはもうちょっと自由。 HTML のテンプレートエンジンで部品を挿入する感じのようです。

以下のリンクを参照させていただき、学習しました。

Click Frameworkな日々

以前Clickを元にしたフレームワークで仕事をした事があり、非常に使いやすいフレームワークだなと感じ、そのころからClick自体を業務アプリケーションに使用してみたいと思っていました。

本家ドキュメント。

Click Framework

Click Framework is a modern JEE web application framework, providing a natural rich client style programming model. Click is designed to be very easy to learn and use, with developers getting up and running within a day.

Eclipse のプラグインの使い方。

Eclipse(ClickIDE)環境の構築 – Web View Technologies

Clickはシンプルなフレームワークで、事前に用意するライブラリやXMLの設定ファイルなども非常に少なく、開発中の作業にも難しいXMLの編集等がほとんど無く、またテンプレートを活用し始めるとHTMLの編集も非常に少なく済むため、IDEなどのサポートが無くてもテキストエディタとJDKだけでも十分開発が可能です。

とはいえ、より楽になるに越したことはありません。 Click用の開発環境としては非常に高機能なClick IDEがあり、これとEclipseWTPを組み合わせると非常に開発が楽になるので、お勧めです。

Click は HttpServletRequest がみえる薄めのフレームワークです。 画面1つに対してクラスがひとつ割り当ります。 このため、別画面遷移などではちょっと http/html のレイヤに近い部分の考慮が必要になりますが、ぱらっとかくぶんにはしばりが少ないので良いのかなと感じました。

てなわけで、えーかげんですが1画面。 まず Page クラスを extends して画面に対応するクラスをつくります。

package net.maple4ever.djodeko.facard;
 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
 
import net.sf.click.Page;
import net.sf.click.control.*;
import twitter4j.*;
 
public class Fetch extends Page {
    
    // public フィールドに $ 付けた名称が HTML テンプレートにかける
    public Table table = new Table();
    
    /**
     * イニシャライズメソッド
     */
    public void onInit() {
        
        // テーブルの列設定
        Column c1 = new Column("name", "名前");
        Column c2 = new Column("text", "ステータス");
        table.addColumn(c1);
        table.addColumn(c2);
        // ソートできて8行なんていう設定
        table.setClass(Table.CLASS_ITS);
        table.setPageSize(8);
        table.setShowBanner(true);
        table.setSortable(true);
        
    }
    
    /**
     * HTTP/GET のときに onInit の後、呼ばれる
     */
    public void onGet() {
 
        List<Map<String, String>> list =
            new ArrayList<Map<String, String>>();
        List<Status> statuses;
        
        Twitter twitter = new Twitter();
        try {
            statuses = twitter.getPublicTimeline();
            // twitter からステータスひろってテーブル列名と
            // 対応したハッシュにつめる
            for (Status status : statuses) {
                Map<String, String> record =
                    new HashMap<String, String>();
                record.put("name", status.getUser().getName());
                record.put("text", status.getText());
                // ハッシュをリストにつめる
                list.add(record);
            }
            // テーブルにリストをつめる
            table.setRowList(list);
        } catch (TwitterException e) {
            e.printStackTrace();
        }
        
    }
    
}

こんな感じなのかな・・・。 table というコントロールを作成しています。 GUI みたいに値をつめます。 で、こういうコントロールを public フィールドにおいておくと、Click が 対応する HTML にバインディングしてくれます。

html はこんなかんじで。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Fetch</title>
$imports
</head>
<body>
<h1>Click Freamwork on Morph AppSpace</h1>
<h2>Twitter Public Timeline</h2>
$table
</body>
</html>

HTML の "$table" のところにフレームワークがコントロール(ここではテーブル)の HTML を挿入してくれます。

Java には HTML を書いていない

のがみそですね。

Java のほうには Twitter4J を呼んでいるところがみえるのでお察しかもしれませんが twitter の public タイムラインをテーブルにつめて表示しています。

click01 

ほとんどプログラム書いていないのに、テーブルレンダリングはもちろん、超面倒なページングとテーブルソートが実装されます。 このプログラム自体は、15分かかってないくらいのものですが、これを素の PHP でかいたら何時間かかるか。 $_GET でごにょごにょっ、1行ずつ色違い?あぁいやだいやだ(笑)

これは、ライブラリ jar をぽいぽいいれてちょろっとかいただけなのです。

てなわけで、これを Java EE デプロイ可能な Morph AppSpace サーバにデプロイします。 ここは PC でコマンドうつだけで転送から、起動までやってくれます。

ちなみにコンパイラ準拠レベルは 5.0 におとさないと、UnsupportedClassVersionError しちゃいました。 サーブレットコンテナは Jetty のようです。

java -jar morph-deploy.jar --user [user名] --password [パスワード]
 --config morph_deploy.properties DJOdeko.war

動作をみてみます。(そのうち消しますので期間限定)

Click Freamwork on Morph AppSpace

Twitter Public Timeline

まぁまぁ、アプリとしてみると、ちゃんとキャッシュしろとか例外処理してないとかって話もありますが、15分でページング・ソートまでできちゃうのは明らかに作成効率は良いです。

まだ眺めている程度で、DB つかう場合の接続タイミングとかちょっと不明点もあるのですが、サンプルもたくさんあるのでソース読めばわかることでしょう。 🙂

Click Examples

The Click Examples web application demonstrates Click features and common design patterns.

いろいろな HTML コントロールもみることができます。

Java EE 使えるサーバがあるといろいろ広がりますね。 日本でも Morph みたいなことやってくれる会社がでてくると使いやすいのですが!

こう考えるとクラウドというのは利用者というより開発者視点なんじゃないかと思います。 なんたって、年間 10万円もだせば自分の力ではありえないくらいのアプリケーションよりの設備を、勝手に24時間運用してくれるわけですから、、がんばれば月1万くらいかせげる Web アプリは個人でもつくれるわけで。 2万円儲かりますね(笑)

え"、取らぬ狸の皮算用? 😛

JavaScript も HTML もかかずに Web アプリをつくる

猫も杓子も Web アプリケーションということで、0 インストールの優位性がよかったのか、営業さんの努力の結果か。 いわゆる基幹系の業務アプリも Web テクノロジーで作られるご時世ですが、ここで問題になるのが HTML と JavaScript 。 業務アプリをかくのは、ぼくみたいな業務ロジックをかくプログラマーであるわけで、HTML とか JavaScript とかよーわからん、ってところが正直なところ(笑)

おまけに、その手のアプリケーションで、ユーザインターフェースに多くの人員や工数をさけるほど余裕があるプロジェクトも少なく、かくして、「よーわからん」プログラマー達が英知を結集して、HTML と JavaScript をかきはじめ大変なことになるのはよく見る光景です。 🙂

てなわけで、立ち上がったソフトウェア業界(?)。 JavaScript も HTML もかかずに、ぜんぶ Java でかいちゃおうぜ、っていうフレームワークがいくつかあります。 まずは、彼ら自身も思っていたらしい Google さんの Google Web Toolkit。

Google Web Toolkit – Google Code

現在、ウェブ アプリの記述は退屈で、エラーが発生しやすいプロセスです。90% の時間をブラウザ固有の動作への対処に費やし、JavaScript はモジュール化できないため AJAX コンポーネントの共有、テスト、再利用を難しく、もろいものにしています。

・・・。

退屈でもろいっつったな!!

・・・その通りだ、よく言った(笑)

Web 企業の Google がいうんだから間違いありません。

もうひとつ。 日本でやっている人あんまり見つけられませんでしたが、GPL の ZK。

ZK – Direct RIA

ZK is the leading open source Ajax + Mobile framework. With 700,000 downloads, ZK empowers a variety of companies and institutions, ranging from small to large, including Barclays, Sun Micro, Swiss RE, Alcatel-Lucent, and many others… read the whole story>>

GWT のほうはよくみてませんが、どっちも Java でそれように設計された記述方法で画面をつくると、勝手に HTML と JavaScript を出力してくれます。

いろいろなコントロールが用意されていて、たとえば HTML のフォームにはないようなカレンダーとか、アイコン付きのドロップダウンリストとかサーバサイドのコードで「はりつける」と、うまいこと HTML と JavaScript がでてくれます。

AJAX の部分も隠蔽してくれるようになっているので、基本的に通信経路やエントリポイントについても考える必要が無く、ZK の場合は必要なイベントが発行された時に勝手に xmlrpc でサーバに通信して必要なデータの取得なんかしてくれるイメージです。 ネットワーク的にはなれていることすら意識しないでアプリをかく、というのが目指すところなのだと思います。

ZK も GWT も Java のフレームワークです。 今回はユーザインターフェースの部分だけですが、ZK を先日の Morph AppSpace にデプロイしてみました。

http://another.morphexchange.com/index.zul

いろいろギミックあるのでおしてみてください。

またそのうち消すので期間限定。 ちなみにたまに AppSpace が劇重になるのでアクセスできなかったらすいません)

ZK01

ぼくにはこんなのつくれねーっていう動きですが、20行くらいの XML 定義だけで出力してくれます。 IE7 でもみてみましょう。

ZK02

ちゃんと同じように動きます。 ブラウザの互換などの問題は、フレームワークが吸収してくれるので、ぼくは何の知識もなくクロスブラウザできるわけです。(ちなみに ZK は HTML をはくことだけを目的としていなく、たぶん他の RIA 部品にも対応できる仕組みを持っています)

かっこいいコントロールのデザインや、クロスブラウザ問題などを正しい知識を持った人がフレームワークとして実装し、業務ロジックはこれも正しい知識をもった(ぼくはもってないが。。)人が実装する。 実に合理的です。

Java も HTML も CSS も JavaScript もそれぞれ、本が何冊もかけるようなボリュームがあることです。 それを全部一人で覚えようというのは難しい話。 できるひとがいたとしても、そういう人を集めてプロジェクトをつくったらいくらかかるか分からないわけで、今後もこういった方向は進むのではないかと思います。 というか、ようやく元に戻ったとも言いますが・・・(笑)

あんまり ZK は日本でははやってない風ですが、遊んでいると結構面白いので Java できるひとはやってみるといいかもしれません。 ちなみに、上のサンプルは Java すら一行もかいていません。 .ZULE の xml てきとうにパクってはっただけです 😛

クラウドサーバ(?) Morph AppSpace に Pebble ブログをインストールしてみる

最近はやりのクラウドコンピューティング。 そのプロバイダのひとつである Morph AppSpace に、Pebble という Java でできたブログツールのデプロイを試しにしてみました。

なんだかおこられそうな使い方ですが、Morph AppSpace はインターネットで使える Java のアプリケーションサーバとして使えます。 1cube (1アプリデプロイ/1G容量、帯域) までは無料とのことです。 🙂

クラウドコンピューティングというのは、よく理解していないのですが・・・。

クラウドコンピューティング – Wikipedia

ネットワーク(特にインターネット)という「雲 = クラウド」の向こう側に、サービスを提供するサーバなどがあるが、ユーザーからはもはやサーバの場所も台数も構成も認識できず、単にサービスを受け取っているようなイメージといえる。

ということらしい。 WikiPedia にもありますが、言葉の視点が利用者になっているのでちょっとぼくらには分かりづらい。 実態はなんなんだって話ですが、クラウドというとぼくの中では「Java とかのアプリケーションサーバのレンタルサービス」?

みもふたもないですが、現在のところは Java アプリケーションサーバとか DB とか、Python とか Ruby on Rails とか、アプリケーションを動かすインフラがそろっていて、かつ一般のレンタルサーバよりも高信頼性なサーバで、それをお金を出して借り、そこに好きなアプリケーションを入れてお客さんにサービスを提供する。 といったところなんだと思います。

いまのレンサバでもできるじゃーん、って話ですが、いわゆるレンタルサーバよりもアプリケーションのインストールや運用に特化した環境ができているのが特徴です。

論よりラン(久しぶり)

ってことで、Morph AppSpace は 1cube 無料で使えるということなので早速アプリを入れてみましょう。

Java/GrailsのWebアプリを無料クラウド環境で動かす (1/3) – @IT

本稿では、「Morph AppSpace」というサービスを紹介します。冒頭で紹介した「Google App Engine」では、Pythonで作成したWebアプリケーションしかデプロイ(配置と公開)できません(2008年9月現在)。しかしMorph AppSpaceは、JavaGrails、そしてRuby on Railsで作成したWebアプリケーションをデプロイできます(参考:iPhoneアプリプログラマーに目を向けるMorph Labs)。

デプロイという言葉がききなれないかもしれませんが、要はインストールとかセットアップということです。 Windows のクライアントのソフトウェアは setup.exe とかでインストールしますが、アプリケーションサーバがある環境ではこのような操作をデプロイといいます。

PHP とかファイルコピーで動く環境ではあんまりデプロイっていいませんが、要は Windows で setup.exe を使ってソフトをインストールするのと同じ感覚で、Java とかの Web アプリケーションは、アプリケーションサーバと呼ばれる環境に setup (デプロイ) します。

ここでは、Morph AppSpace のアプリケーションサーバに、Pebble という Java 製のブログツール(WordPress みたいなもん) をデプロイしてみます。

Pebble – Java blog server software

Pebble is a lightweight, open source, Java EE blogging tool. It’s small, fast and feature-rich with unrivalled ease of installation and use. Blog content is stored as XML files on disk and served up dynamically, so there’s no need to install a database. All maintenance and administration can be performed through your web browser, making Pebble ideal for anybody who is constantly on the move or doesn’t have direct access to their host. You can see an example blog here.

アプリのデプロイの詳細は前述の @IT の記事から…。 イメージ的には Java のアプリケーションの玉 WAR ファイルをネットワーク越しに、Morph AppSpace にコマンドを発行してデプロイします。

Peeble の場合は以下のような感じです。

java -jar morph-deploy.jar --user [ユーザー名] --password [パスワード]
  --config [morph で提供されているプロパティファイル名] [PebbleのWAFファイル名]

# Pebble のデプロイでは、"com.sun.syndication.propono.atom.server.AtomServlet " が、Class NotFound してしまうようでしたので、WAR の WEB-INF からこれらを削除していんちき対応しています。

この操作は setup.exe を動かすみたいなもんなので少し時間がかかる。 2分くらいして URL にアクセスしてみると…。

Morph03

おーうごいたうごいた。 (http://another.morphexchange.com/ そのうち消すかもですので期間限定)

ついでに Pebble も紹介。 特別な管理画面をもたず、ログインすると通常画面にメニューが増えるのが特徴の Java でかかれたブログツールです。

Morph02

さすがに WordPress に慣れていると機能が少ないなーと思ったりしてしまいますが、生の Servlet/JSP  でかかれているので Java の勉強にはいいと思います。

PHP だとアプリケーションサーバの考え方が mod_php ではないので、ちょっと考えにくいかもしれないですが、これらの環境で動作する Web アプリケーションはその生存期限が違います。

Morph AppSpace のアプリ管理画面。

Morph01

ここでデプロイしたアプリを管理できます。

PHP はファイルをコピーすれば、Apache が mod_php を呼んで動作させてくれますが、これは http アクセス契機で、アプリが開始終了します。

一方アプリケーションサーバで動作するアプリは、生存し"続け"られます。 アプリケーションサーバ上で明示的に指定するまで終わらないのですが、これを管理するのが上の管理画面です。

この2つ方式、いったい何が違うのかというと、一番分かりやすい例はメモリが使えるということです。

PHP とかはアクセス終了後すぐ終わっちゃうので、何かをメモリに保持しても無駄で初期設定とかいちいち DB とかファイルとかから読み直さねばなりません。 かたや、アプリケーションサーバがある環境ではメモリがつかえるので、初期設定や DB 接続を "維持" できます。

WordPress でも起動後、言語ファイルを読みに行ったりデータベースの接続をしたり、こういった初期設定を1アクセスごとにやっていますが、もしアプリケーションサーバ上で動くソフトであれば、これはアプリ起動時いっぱつだけですみます。 生き続けるのでデータ状態を保持できるのです。 また、コストのかかるデータベース接続も基本的に一度で済みます。

てなわけで、こういった処理が大量にあるエンタープライズアプリでは Java とかのアプリケーションサーバが使える環境でつくられるのが一般的(もちろん他にもたくさん理由はありますが)ですが、コンパイルやデプロイの時間なんかの作業効率が悪い部分もあって、どーしよーと考えられたのが、JRuby や JPython などの Java 上で動くスクリプト言語です。

スクリプト言語でぱきぱき run and debug しつつ、Java のアプリケーションサーバ環境も使えてしまうというおそるべきハイブリット。 Morph AppSpace でも groovy という Java 上で動くスクリプト言語が使えるようです。

とりあえず、Java アプリケーションを自由にデプロイできるレンタルサーバというのはなかなかないので、そういう意味でも Morph AppSpace は結構遊べます。 いまや、プログラマといえば Java 技術者みたいなところもあるくらいなので、PHP よくわからん! って方は試してみるといいかもしれません。 🙂