backlog4jで課題を登録してみる

今度は、backlogへの課題登録を自動化したいという話があり、前回のredmineと似通った要件なので再利用箇所も多く、redmine java api部分をヌーラボ公認のbacklog4jに置き換えて実装してみました。
redmineとの違いはそれなりにありますが、backlog4jの方はKeyとIDを混同しやすい感じがします。例えば、課題のKeyはURLを見ればすぐ解りますが、IDの方は内部的なユニークな数値です。これに注意しながらbacklog用に前回のラッパークラスを置き換えてみました。

上記を呼び出すのはこんな感じ

後日談
GetIssieで3ヶ月経って問題発生・・・たまに課題の取得に失敗するようになりました・・・
下記のようにしましたが、最初からそうしろ!って事ですね。でも、3ヶ月は何も問題なかったのですが・・
public Issue getIssue(String issueKey)

redmine java api でチケットを取得してみる

 前回の続きで、今度はチケットを取得してみます。単純にチケットIDを指定して一つのチケットを取得するのでは無く、条件を指定し一括してチケットを取得して何かをするような要件への対応です。

 下記サンプルでは、クエリーを使用せずに、
ステータスID=2 かつ トラッカーID=10または11 かつ 題名に「テスト」を含む
という条件に一致するチケットを全て取得する内容です。
100件ずつチケットを取得して、100件以上のチケットがあればページ番号を変えて全チケットを取得します。

redmine java api でチケットを登録してみる

 redmineへのチケット登録を自動化したいという話があり、内容的には常時トリガーを拾って登録という感じだったので、javaの常駐プロセスでトリガーを拾う事を前提として、こちらを使用して実装してみました。
https://github.com/taskadapter/redmine-java-api
なお、登録対象のredmineは2.5系でしたが、それほどバージョンを意識しなくても大丈夫そうです。

事前準備として、対象のredmineへapi登録用のユーザーを用意し、登録対象のプロジェクトへの権限を付与、個人設定画面からapiキーを取得します。

その他、プロジェクトidやトラッカーid等のredmine内部で持っているidの値はブラウザからapiで下記のようにidの値を確認してセットとなります。ただ、redmine java apiには、様々なマネージャーがあるので、id指定でなくても都度問い合わせしてidを取得できそうです。

ソース的には下記のようなラッパークラスを作って、登録や更新を呼び出し側で簡略化出来るようにしてます。

下記の呼び出し側では、親チケットを作成してジャーナルを追加、子チケットを2つ作成し関連付けてます。

いろいろやってみましたが、redmineに対して殆どの事は出来そうです。

JAX-RSでWeb画面にドラッグアンドドロップされたファイルを読み込む

テキストファイルをサーバへアップロードしたいという要件があり、Web画面からファイルをドラッグアンドドロップできるようにして、それをJAX-RSで処理する事にしてみました。

下記の参考にさせて頂き、それらを組合わせただけと言えばだけですが。。

Jersey(JAX-RS)でファイルアップロード
HTML5 の File API でドラッグ&ドロップする

まず、JAX-RSのルートパスを指定します

次にファイルを処理するJAX-RS部分を作ります

これでファイルアップローダーのJAX-RSパスは、{コンテンツルート}/api/uploadになりました。

続いてJavaScriptの部分(殆ど上記参考から持ってきただけです。。)

最後にHTML部分のドラッグアンドドロップ部分です。
ここにドロップされたファイルがJAX-RSの処理箇所のInputStream に繋がります。

これでとりあえずはJAX-RSでファイル処理が出来ることが確認出来ました。

最後にPOM。

bootstrap2 datetimepickerを1分単位にする

ちょっと前に作ったJavaEEアプリでbootstrap2のdatatimepickerを使ったのだが、
?p=698
5分刻みは使いにくいという話が出てきて、ググッてみたところ下記を発見。
http://www.malot.fr/bootstrap-datetimepicker/
オプションのminuteStepで値を変えられるみたいなのでやってみました。
1分刻みにするとこうなります。

xhtml側は下記minuteStepのオプションを追加するだけ

デフォルトだと5分刻みなのでこんな感じ

ダイアログが長くなって画面ギリギリだけど、この方が便利ということでこちらでリリース
次作るものはbootstrap3にしないとなあ。。

OracleDBで文字化け発生

今構築中のPHP+apache+OracleDB構成のWeb業務アプリですが、
テスト環境を作ってもらったので動かしてみたところ、全角文字が??に化けて困ったことに。。

アプリケーションの要件上、2つのOracleDB(どちらも12c)に同時接続する必要があり、
一方の文字コードが
NLS_LANG=Japanese_Japan.JA16SJISTILDE で、
もう一方が、
NLS_LANG=Japanese_Japan.AL32UTF8 となっています。

とは言え、DBクライアントとなるphp側としては、Japanese_Japan.AL32UTF8でいいはず。

apacheのhttpd.confを見ると、
setEnv NLS_LANG Japanese_Japan.AL32UTF8
としているのですが、どうも有効にならない模様。

結果、apacheの起動シェルに
export NLS_LANG=Japanese_Japan.AL32UTF8
を入れてもらって解消。
念の為、はしご高とかを画面から入れてみましたが問題無し。

昔(Oracle8とか)は第2水準以上の漢字はトラブルの元だったとの記憶がありますが、今は便利になりましたね。

POIでエクセルファイルを読むにはStreamingReaderが必須っPOI

エクセルファイル内のシートをDBに取り込む要件があり、DBサーバであるlinux上で取り込む処理をする必要が出てきました。
とりあえずCSVにでも変換してしまえば後はどうにでもなるので、Apache POIを使って汎用で使えそうな簡易CSV変換ツールを作ってみました。簡単にテストした後、いざ対象となるエクセルファイルで実行してみたところいつまでたっても終わらないし、メモリを数G食うという異常な状態に。
 テストした時のエクセルは数千程度で、いざ実行したエクセルは数万規模の違いがあり、大量データが含まれるエクセルシートの場合にPOIでは問題があるみたいです。で、こりゃ何とかしないとと調べていくと、それを解消してくれる素晴らしいライブラリを発見。
https://github.com/monitorjbl/excel-streaming-reader

上記サイトのREADMEに従い、下記のようにWorkbookFactory.createの箇所を置き換えるのみでした。(inputはエクセルファイルのInputStream)

変えた後は何事もなかったかのようにちゃんと終わりました。
それにしてもPOIは非推奨メソッドをいつ置き換えてくれるのだろう?

追伸
sheet.getNumMergedRegions() 等、サポートしていないメソッドが多数あるようです。
結合セルなどを意識しないで、単純にエクセルファイルを行毎に順次読み取るような処理には適してます。

カテゴリー: Java

EJBタイマーサービスを使ってみることにした

WebLogicを動かしているサーバ上で数分間隔にとある機能を動作させたいという話があり、常駐プロセス起動とかにしたくないので、EJBタイマーサービスを使ってみることにしました。
タイマーサービスの使用は初めてなので、WebLogic12Cの挙動を調べながらの作りこみです。

結果的に下記のようになりました。
5分間隔(0分2秒,5分2秒,10分2秒,15分2秒・・・)でタイマー処理を実行しています。
なお、トランザクション処理は必要無し、処理結果のエラーハンドリングも不要、指定の間隔で単純に起動されればよいような機能です。

WebLogicにおけるEJBタイマーの挙動として確認できたのは、

①タイムアウトを実装しておかないと30秒以上経つとエラーを吐いて、次のタイマーまでは動くのだが、その次以降はまったく動かなくなる

Caused By: weblogic.transaction.internal.TimedOutException: Transaction timed out after 30 seconds
中略・・
Truncated. see log file for complete stacktrace

なぜ30秒なのかというとトランザクションタイムアウト値がそうなっているっぽい。。
https://docs.oracle.com/cd/E28613_01/web.1211/b65951/ejb_jar_ref.htm#i1506703

何をするわけでもないが、とりあえず@Timeoutのアノテーションをつけたメソッドを追加

②処理時間が次回のタイマー処理開始を超えるとタイマーが止まる

例えば、5分間隔で動作させる場合、処理が5分以上掛かってしまうと、次のタイマー実行時にエラーが吐かれて動かない

<2016/11/15 16時55分07秒 JST> <Error> <EJB> <BEA-011088> <The following error occurred while invoking the ejbTimeout(javax.ejb.Timer) method of EJB ChkTimer(Application: appmgr, EJBComponent: /appmgr).
以下、略・・

なので、処理自体をExecutorServiceでスレッド処理にし、処理遅延が起きないようにしてみました

③永続化はしない方がよい

とりあえずサーバ上で空回りするようタイマー稼動テストを数日間したところ、ちゃんと指定間隔通りに動作していたので、機能を概ね実装していざデプロイしてみると、2重起動している状態に、、
なぜかといろいろ調べた結果、空回り開始時にpersistent=falseを指定していなかったので、ずっと残り続けていた模様。
一度、タイマー起動を無しにしたモジュールでデプロイした後、再度タイマーを有効にしてデプロイすることで、やっと2重起動が止まりました。

実行したいスケジュールや処理内容によっては、結構制御が難しいように思いますが、今回の要件ならOKという事で。

Oracle DB のダンプファイルがインポート出来ない

 今やってる案件で、別ベンダーさん側がメイン部分を作って筆者はその周辺を作っているのですが、そろそろデータが欲しくなったので提供を依頼したところ、ダンプファイルが送られてきました。
 さっそく開発端末のOracleDB11Expressにインポートしてみようとしたところ
>imp
Import: Release 11.2.0.2.0 – Production on 火 10月 4 10:48:15 2016
・・・中略

IMP-00401: ダンプ・ファイル”data_20160928.dmp”
は、データ・ポンプ・エクスポート・ダンプ・ファイルの場合があります
IMP-00000: エラーが発生したためインポートを終了します。

ん?何でかダメみたいとググっていくと、どうやら今時はimpdpを使うらしい。。
筆者はOracle8から9辺りまでは実際の開発に従事してましたが、10以降は社内SEであまり具体的な作業をやる機会が無かったので知りませんでした。

で、impdpとやらでインポートしてみます。
>impdp
・・・中略

接続先: Oracle Database 11g Express Edition Release 11.2.0.2.0 – Production
ORA-39006: 内部エラーが発生しました。
ORA-39065: DISPATCHでマスター・プロセスの予期しない例外が発生しました
ORA-04063: package body “SYS.DBMS_METADATA_UTIL”にエラーがあります。
ORA-06508: PL/SQL: コールしているプログラム単位が見つかりませんでした: “SYS.DBMS
_METADATA_UTIL”

ORA-39097: データ・ポンプ・ジョブで予期しないエラー-6508が見つかりました

あれ?パッケージが無いの?
じゃあ、探そうとOracleインストールディレクトリより、GREPで上記のUTILを探すと下記を発見。
早速実行

>sqlplus sys/**** as sysdba

@C:\oraclexe\app\oracle\product\11.2.0\server\rdbms\admin\dbmsmetu.sql

続けてINVALIDのパッケージをしつこくコンパイルしたり、データ・ディクショナリ系SQLを実行したり・・・
http://otndnld.oracle.co.jp/document/products/oracle11g/111/doc_dvd/server.111/E05771-04/scripts.htm

気を取り直して再度impdp実行
>impdp
・・・中略

ORA-39000: ダンプ・ファイル指定が無効です
ORA-31640: ダンプ・ファイル”C:\oraclexe\app\oracle\admin\xe\dpdump\expdat.dmp”を
読取りのためにオープンできません
ORA-27041: ファイルをオープンできません。

まだダメ。。
下記をちゃんと読んでディレクトリを確認し、既存の設定箇所にダンプを置いて実行。
https://blogs.oracle.com/oracle4engineer/entry/data_pumpexpdpimpdp
>impdp
接続先: Oracle Database 11g Express Edition Release 11.2.0.2.0 – Production
ORA-39001: 引数値が無効です
ORA-39000: ダンプ・ファイル指定が無効です
ORA-39142: 互換性のないバージョン番号4.1が、ダンプ・ファイル”C:\temp\data_20160928.dmp”内にあります

結局、ダンプを作成したOracleのバージョンが12なので無理っぽい。
こちらにもXE特有の問題があるとの事なので、開発端末へのインポートは諦め、テストサーバを作ってもらうまで待つことにします。。
http://freespeedo.blog.fc2.com/blog-entry-1.html#comment3

gitbucketとredmineを連携させてみる

 そろそろちゃんとソース管理をしないとと思い、既に使っているredmineにgitbucketを連携してみました。
redmineを入れているcentOS6サーバにgitbucketを導入してみます。って、下記を見る限り
http://qiita.com/pppurple/items/2e614a836e2184f70997
とりあえずgitbucketを動かすならwarをダウンロードしてJavaコマンド実行するだけのようですが、
java -jar gitbucket.war
では、どうもうまく動作しません。

で、payara-microにデプロイする形で実行してみます。
java -jar payara-micro-4.1.1.163.jar –port=18080 –deploy gitbucket.war

フロントがapacheなので、httpd.confのProxyPass当たりを追加し、とりあえずはgitbucketの画面が出るようになりました。

次はredmine側にリポジトリを登録します。が、リポジトリのパスはどこなんだろうと調べると、gitbucketデフォルトでは起動ユーザーのhomeに隠れて作られているとの事。このパスをそのままredmineのリポジトリに登録してみましたが、NotFound状態・・

リポジトリのパスを変えないとredmine側から参照できないようなので、ホームディレクトリを指定する実行時引数を追加。

結果的にこうなりました。
java -Dgitbucket.home=/var/lib/gitbucket -jar payara-micro-4.1.1.163.jar –port 18080 –deploy gitbucket.war

gitbucket側でリポジトリを新規作成し、サーバ内に出来た拡張子.gitのファイルパスをredmine側のリポジトリのパスに指定します。

やっとredmine側から見れるようになりました。
redminerep

作ったリポジトリへeclipseから強制PUSHするとこんな感じでgitbucketのホームディレクトリを変える前にコミットしたのも含めてredmineから参照出来ました。分散管理っていいですね。
redminerep2

後日、init.shを作って別途サービス登録しておきます。