自分用Mavenリポジトリを作る

※この投稿は、丸太式 Advent Calendar 2014の8日目です

自分で作った物のJAR(fat jarではない)をMavenリポジトリにデプロイしておけば何かと便利な気がしたのと、ExCellaをMavenで管理できないのはやっぱり不便なので、自前のMavenリポジトリを用意してみました。

必要なもの

  • Javaの実行環境
  • 適当なサーバ
  • Nginx等のフロントサーバがあるといいですね

やること

  • Sonatype NEXUS OSSをダウンロード
  • 適当なディレクトリに展開
  • 展開したディレクトリで、以下のコマンドをを実行
    % bin/nexus start
    ※Windowsならbin\nexus.bat startで良いんじゃないでしょうか
    フォアグラウンドで実行するなら、startの部分をconsoleにすれば良かったはず。

NetBeansでpersistence.xmlを生成してHibernateを使ったらはまった話

※この投稿は、丸太式 Advent Calendar 2014の7日目です

現象

NetBeans 8.0.1でJPAの持続性ユニットをHibernateを使うようにして作成すると、EntityManagerFactoryでEntityManagerを作れない。
※Persistence Unitを正しく指定しても、見つからない旨の例外が発生する

原因

NetBeansが生成するHibernate向けのpersistence.xmlの内容で、providerorg.hibernate.ejb.HibernatePersistenceが設定されるが、このクラスは@Deprecatedでありなにやら挙動が違うらしい。

対応

persistence.xmlのproviderに、org.hibernate.jpa.HibernatePersistenceProviderを設定する。
このクラスは、org.hibernate.ejb.HibernatePersistenceのJavadocに記載されている、代替となるクラスらしい。

ExCellaを使ってJavaアプリケーションからExcel出力

※この投稿は、丸太式 Advent Calendar 2014の4日目です

ExCellaとは

JavaのプログラムからExcelファイルを操作するライブラリとしては、Apache POIが有名ですが、決まったテンプレートに値を設定して出力するような使い方をする場合に必要なコード量が多いと思います。
また、出力する項目は変えずに値を設定するセルをかえるだけでもプログラムを書き換える必要があり、とても扱いやすいとは言えません。
ExCellaは、そんな扱いづらいPOIのラッパーとして利用できるOSSのライブラリです。

ExCellaのコンポーネント

ExCellaは3つのコンポーネントで構成されており、それぞれのJarと、一緒にダウンロードできる依存ライブラリのJarをクラスパスに追加することで利用できます。
※現状Mavenで管理することはできませんが、GitHubのリポジトリを見る限りでは今後対応する方針のようです。
* ExCella Core
ExCellaのコアとなるコンポーネント。
他のコンポーネントから共通で利用される。
* ExCella Trans
データ移行の為のコンポーネント。
ExcelファイルやCSVファイルからSQLやJavaオブジェクトを生成できる。
* ExCella Reports
Excelの帳票を出力する際に用いるコンポーネント。
テンプレートに埋め込まれたタグを置換して、ファイルに出力できる。

Excel帳票出力のサンプルコード

ExCella Reportsを使った帳票出力のサンプルコードです。
単純にタグと値を一対一で置換する場合、これだけのコードで出力できます。

String templatePath; // テンプレートファイルのパス
String outputPath; // 出力先のファイルパス
 
// 1. ExCellaのReportBookオブジェクト(Excelのワークブックに相当)を生成する
ReportBook reportBook = new ReportBook( templatePath, outputPath, ExcelExporter.FORMAT_TYPE);
// 2. ExCellaのReportSheetオブジェクト(Excelのシートに相当)を生成する
ReportSheet reportSheet = new ReportSheet( "シート名");
// 3. テンプレートのタグを置換する値を設定する
// この例では、テンプレート中の ${tagName} を tagValue に置換します
reportSheet.addParam( SingleParamParser.DEFAULT_TAG, "tagName", "tagValue"); 
// 4. ReportBookにReportSheetを追加する
reportBook.addReportSheet( reportSheet);
// 5. 帳票出力処理を行う
ReportProcessor processor = new ReportProcessor();
processor.process( reportBook);

ExCella Reportsは単純な1対1の置換だけでなく、指定範囲の繰り返し置換にも対応しています。
詳しくは、公式のドキュメントをご覧ください。

最後に

ExCellaはOSSのプロダクトとしてはコミュニティがあまり活発ではありませんが、帳票文化が根付いている日本ではかなり便利に使えると思います。

参考リンク

Oracleのリストの最大数を考慮したHibernate Criteria

※この投稿は、丸太式 Advent Calendar 2014の2日目です

DBMSのOracleには、IN句等に渡せるリストの最大長に制限があることは皆さんご存じだと思います。
ご存じ無い方のために例を示しますと、以下の二つのSQLでは、前者は成功し、後者は失敗します。

SELECT * FROM AnyTable WHERE AnyColumn IN (1, 2, 3, (), 1000);
SELECT * FROM AnyTable WHERE AnyColumn IN (1, 2, 3, (), 1000, 1001);
-- →ORA-01795: リストに指定できる式の最大数は1000です。

そもそもこんなSQLが発行されているのが大きな間違いですが、保守開発などどうしても大きく変更できないときは、このようにしてお茶を濁すことになります。

SELECT *FROM AnyTable WHERE AnyColumn IN (0から1000) OR AnyColumn IN (1001以降);

単純ですね。IN句を1000要素毎に分割してORでつないだだけです。

さて、ここでJavaからHibernateのCriteriaを使う場合に、Collectionの要素が1000件を超えるとやはりエラーとなってしまいます。
OracleのDialectでは対応出来ていないため、Criteriaに条件を指定する際には以下のように工夫する必要があります。

Collection<T> theCollection; // 要素数が1000を超えるかもしれないコレクション
Criteria criteria = session.createCriteria(AnyTable.class);
// criteria.add(Restrictions.in("AnyColumn", theCollection)); //←これではtheCollection.size() > 1000の場合にエラー
List<T> tmpList = new ArrayList<>(theCollection);
Junction disjunction = Restrictions.disjunction();
while (tmpList.size() > 1000) {
  List<T> subList = tmpList.subList(0, 1000);
  disjunction.add(Restrictions.in("AnyColumn", subList));
  tmpList = tmpList.subList(1000, tmpList.size());
}
if (!tmpList.isEmpty()) {
  disjunction.add(Restrictions.in("AnyColumn", tmpList));
}
criteria.add(disjunction);

面倒ですね。
コレクションを渡してdisjunctionを返すユーティリティメソッドを作っておくと多少は楽になるかもしれません。

まとめ

こんな事をするくらいなら、はじめからサブクエリを使いましょう。

XOOPS CubeのProfileモジュールをServiceManagerに登録する

XOOPS Cubeのコアに同梱されているProfileモジュールは、ユーザー情報の項目を自由に追加できるモジュールです。
XOOPS CubeのServiceManagerは、モジュール間の連携を実現するXCube_Serviceを管理するコンポーネントです。
コア同梱のモジュールは基本的にServiceManagerにサービスを登録していますが、なぜかProfileモジュールだけは登録されていません。
そこで、登録するためのモジュールプリロードとパッチ(後述)を作りました。

コード

とりあえずコードはGistにあげておきました。

ちょっと解説

Definitions.class.php.patchはご覧の通りパッチファイルです。
メソッドを追加しただけですが、これがないとFATALになります。
呼び出し元を改変することも考えましたが、サービスの機能を減らす修正となってしまうのでこうなりました。
特に怪しい挙動もないので問題なく動作するとは思いますが、自己責任でお願いします。

RegisterService.class.phpはモジュールプリロードです。
このプリロードがServiceManagerへの登録を行います。
こちらのファイルはXOOPS_ROOT_PATH/modules/profile/preloadに配置してください。

まとめ

Profileモジュールのサービスは戻り型にXCube_Objectを継承したクラスを定義していますが、実際に帰ってくるのが配列だったりするので注意が必要っぽいです。
XOOPS Cubeのモジュール開発やカスタマイズに関するドキュメントが少ない印象があるので、こういうネタはもっと拡充したいですね。

参考

PHP – XOOPS Cube ServiceManager – Qiita


Photo By: Robert SchroederCC BY-NC-SA 2.0

[XOOPS Cube] Protectorモジュールに初Pull Requestした話

XOOPS Cubeの定番モジュールである「Protector」に、これまた定番のALTSYSがインストールされていないときにメニューの「一般設定」リンクがXOOPS2のSystemモジュールを指してしまうバグを見つけたので、修正してPull Request、すぐにマージされました。
管理メニューのリンクは正しく生成されているので、管理メニューから移動している限り見つけにくいバグです。

コードについてはhttps://github.com/xoopscube/protector/pull/3をご覧ください。

発生条件

ALTSYSがインストールされていないという1点だけです。
ALTSYSがインストールされている場合、Protector自身のadmin/index.phpを指すようにリンクが生成されます。
しかしALTSYSがインストールされていない場合、Systemモジュールのadmin.phpを指すリンクとなります。
Protector自身はALTSYSのインストールが必須ではないので、これではXOOPS CubeでALTSYSを使わずにProtectorを使いにくくなってしまいます。

修正

ALTSYSの有無を判定している部分で、ALTSYSがインストールされていない場合にlegacyモジュールの有無を判定し、インストールされていればlegacy/admin/index.phpを指すリンクを生成するようにしました。

蛇足

今回Pull Requestを出したのはXOOPS Cubeのリポジトリでしたが、よく見たらXoopsXのProtectorにも同様のバグがありました。
XoopsXは確かALTSYSが必須になっていたような気がするので、ほとんど気づけないですね。
最近のXOOPS Cubeコミュニティは、XoopsXとXOOPS Cubeで別のリポジトリを持ってしまっているせいで外から構造がよくわからなくなっている気がします。


Image By: Barbara DieuCC BY-NC-SA 2.0

Eclipseにプラグインをインストールする3つの方法

私事ですが、4月1日より社会人として某SIerで働き始めました。(そのあたりの話はSideDにあります。)
メインで使うIDEがEclipseなので、改めてプラグインをインストールする方法を確認しておきます。

※注意:Windowsまたはzipから展開して使っている場合の方法です。
Linuxディストリビューションで提供されているパッケージをインストールした場合は少し変わってくる箇所があるかと思います。

想定しているEclipseは、Eclipse 4.3.2 Kepler  Pleiades All in Oneです。日本語化されたメニュー項目で説明するので、Pleiadesを用いていない場合は適宜読み替えてください。

1. プラグインファイルをダウンロードしてディレクトリに配置する

最も単純なインストール方法です。プラグイン作者のWebページからダウンロードして、Eclipseをインストールしたディレクトリ以下のpluginsやfeaturesディレクトリに配置します。
操作方法を迷う必要はありませんが、プラグインの説明を読まないと正しく配置できない場合があるのが欠点です。また、プラグイン間の依存関係がある場合に解決するのが難しくなります。

2. 「ヘルプ」->「新規ソフトウェアのインストール」からインストールする

1では出来なかった依存関係の解決を含めて自動でプラグインをインストールすることが出来ます。
プラグインのダウンロードからインストールまで、すべてを任せることが可能です。但し、プラグイン作者毎にプラグインの一覧とダウンロード元を取得するために”ソフトウェア・サイト”*1を設定する必要があります。
言い換えれば、ソフトウェア・サイトを設定すればあとは自動でインストールできると言うことです。

3.Eclipse Marketplaceからインストールする

Eclipse Marketplace Clientプラグインをインストールすることで、Eclipse Marketplaceからプラグインをインストールすることが出来ます。
Marketplaceからプラグインをインストールする場合、2で触れたソフトウェア・サイトを設定する必要もありません。すべてMarketplace Clientにお任せです。
ただし、環境によってはMarketplace Clientがインストールされていません。ですがご安心ください。Eclipseにデフォルトで設定されているソフトウェア・サイトからインストールすることが出来ます。
2のやり方で、ソフトウェア・サイトを選択する「作業対象」を”すべての~”として、検索ボックスに”market”と入力すれば、マーケットプレース・クライアントが出てきます。これをインストールすれば素敵なMarketplaceライフの始まりです。

以上3つの方法があります。プラグインによっては、1でしかインストールできない場合や3ではインストールできない場合などありますので、個別に確認しましょう。
特にEclipseのプラグインを配布しているWebサイトは英語で書かれていることがほとんどですが、英語を読めるに越したことはないので、がんばって読みましょう。


Photo By: Arun SkariahCC BY-NC-SA 2.0

*1 以前はアップデートサイトと呼んでいたような気がします

自作mikutterプラグインまとめ(2014年3月版)

なんかTwitterの鳥っぽい感じがした By: Macomb PaynesCC BY-NC-SA 2.0

私はRubyで書かれたクロスプラットフォームのTwitterクライアント「mikutter」の愛用者です。
mikutterの特徴の1つとして、簡単なRubyスクリプトでいくらでも機能を拡張できるプラグイン機構があります。
私も幾つか自作プラグインを公開しているので、まとめておきます。
mikutterプラグイン、mikutterコマンドなど興味がある方は、http://mikutter.hachune.nethttp://yuzuki.hachune.net/wikiをご覧ください。

mikutter-focus-to-hometimeline

ホームタイムラインタブにフォーカスを移動するmikutterコマンドを提供するプラグインです。
mikutterコアで投稿ボックスにフォーカスを移動するコマンドは提供されていますが、マウスを極力使いたくない人種(含自分)としてはホームTLにキーボードだけで移動したいのです。
http://github.com/bis5/mikutter-focus-to-hometimeline

mikutter_growl_gntp

クロスプラットフォームの通知アプリケーションである「Growl」に対して新着通知を行うプラグインです。
Linuxではlibnotifyやnotify-osdというプログラムで通知できる環境がほとんどですが、RubyからWindowsAPIを通じてバルーン通知やトースト通知を行うのは非常に面倒です。Growlを使えば、少ないコード量で簡単に通知機能を実装できます。
Growlはリモートホストからの通知にも対応しており、このプラグインはリモートホスト上のGrowlに対しても通知を飛ばせるようになっています。mikutterプラグインでバッチ処理を行い、管理用ホストに完了通知を行うような、本来のプラグインホストとして乗りようにおいて有用な気がします(でっちあげ)。
http://github.com/bis5/mikutter_growl_gntp

mikutter-googl

goo.glで短縮されたURLを展開して表示するプラグインです。
展開するのにわざわざAPIキーを使っているので、今後利用者が増えてきたらAPI Limitに引っかかるかもしれません。そうなったらそうなったでそのときに考えたいとは思います。
http://github.com/bis5/mikutter-googl

my_wishlist

Amazon.co.jpの欲しいものリストのURLを投稿ボックスに挿入します。
設定画面で挿入する欲しいものリストのIDを設定する必要があります。
欲しいものリストを公開してテロの被害者になりたい方におすすめのプラグインです。ちなみに私はまだ被害を受けたことはありません。http://github.com/bis5/my_wishlist

mikutter_kokoro_no_koe

。○(こんな感じに心の声っぽくテキストを整形するプラグインです。)
。○(それ以上でもそれ以下でもありません。)
。○(形が気に入らない方はフォークして自分の心の声を表すプラグインを作ってください)
http://github.com/bis5/mikutter_kokoro_no_koe