- PR -

Excel取込み処理でサーバがダウンした

投稿者投稿内容
Java1年生
会議室デビュー日: 2007/10/08
投稿数: 12
投稿日時: 2007-10-08 15:30
はじめまして。

Excel取込み処理にて、サーバがダウンし、
server.logにもログ特にエラーが出力されておらず、
原因が判らないために困っています。

<環境>
OS:Windows 2003 Server
Excel:Office 2003
webサーバ:JBoss 4.0
Java:JDK1.6

Excel取込み処理は、JComを使用しております。
1日で、サーバが2回ダウンし、
2回ともダウン直前の操作履歴が、
Excel取得の操作をした直前だったため、
Excelの取得処理が一番怪しいと思っているのですが、
直接の原因がJComかどうかは、まだ確証は取れていないです。
ダウンした日から、JComsoleにて、
メモリの使用状況をチェックしていますが、
メモリには異常が見られないため、
OutOfMemoryによるサーバダウンではないと思っています。

また、現象は2、3人のユーザーが、
同時にExcel取得を実行した場合で、
発生するようなのですが、
社内では、7人で同時に実行しても発生しなかったため、
原因が判りません。
JComで、複数人数が同時処理する場合は、
特別な記述が必要なのでしょうか?
または、下記ソースの場合で、
記述に悪い点などあれば、御指摘お願いします。




↓JComを使用している処理のソース
=============================================

/**
* Excel帳票を開き、すべての名前ボックス
* のデータを取得し、
* String配列で戻す
*
* @param path
* @param fileName
* @return
*/
private String[] getData(File file) throws Exception {
// 定義が取得されていなければ、定義を取得する
ReleaseManager rm = new ReleaseManager();
ExcelApplication excel = null;
ExcelWorkbook book = null;
String[] str = null;

try {
// 帳票フォーマットを取得
//File file = new File(path + "\\\\" + fileName);

// 読取り可能であれば、ファイルを開き、定義を取得する
//if (file.canRead()) {
//Excelアプリケーションを作成
excel = new ExcelApplication(rm);

//Bookを開く
book = excel.Workbooks().Open(file.getCanonicalPath());
IDispatch names = (IDispatch) book.get("Names");

//名前つきセルの、名前をすべて取得する
int len = (Integer)names.get("Count");
str = new String[len];

//名前付セルのデータを取得する
for (int j = 1 ; j <= len ; j++) {
//Itemオブジェクト取得
IDispatch name =
(IDispatch) names.method("Item", new Object[]{j});
String key = (String) name.get("Name");
str[j-1] = key;

//名前付きセルのデータ取得
IDispatch temp = (IDispatch) name.get("RefersToRange");
ExcelRange range = new ExcelRange(temp);
int rowNum = ((Integer)(((IDispatch)range.get("Rows")).get("Count"))).intValue(); //行数

//単一行データ
String value ="" ;
if (rowNum == 1 && key.indexOf("itm") >= 0) {
value = range.Text().replaceAll(" ", " ").trim();
headCell.put(key, value);
hSheet.put(key, range.Worksheet().Name());
hAddress.put(key, ((String) range.get("Address")).replaceAll("\\\\$", ""));

//複数行データ
} else if (key.indexOf("itm") >= 0) {
String[] values1 = new String[rowNum];
String[] values2 = new String[rowNum];
String[] values3 = new String[rowNum];
for (int k = 0; k<rowNum; k++) {
ExcelRange aryRange = range.Item(k + 1, 1);
String tmp = aryRange.Text();
values1[k] = tmp;
values2[k] = aryRange.Worksheet().Name();
values3[k] = ((String) aryRange.get("Address")).replaceAll("\\\\$", "");
}
bodyCell.put(key, values1);
bSheet.put(key, values2);
bAddress.put(key, values3);
}

//System.out.println("key="+key+" value="+value);
}

//Bookを閉じる
book.Close(false, null, true);
book = null;
//Excel終了
excel.Quit();
excel = null;
//}


} catch (Exception e) {
e.printStackTrace();
//Bookを閉じる
book.Close(false, null, true);
book = null;
//Excel終了
excel.Quit();
excel = null;
//エラーメッセージ
throw new Exception ("Excelファイルデータ取得に失敗しました。");

} catch (Throwable e) {
e.printStackTrace();

} finally {
//タスクを開放する
rm.release();
}

return str;
}

=============================================



Anthyhime
ぬし
会議室デビュー日: 2002/09/10
投稿数: 437
投稿日時: 2007-10-08 18:13
java-comブリッジを使うのであればEXCELの複数人同時使用で障害が発生するのは、特に不思議ではないですね。
EXCELそのものがそうした設計になっていない可能性が高いと思います。
同時起動を抑制するようにするか、もしくはPOIなどのJAVAのネイティブライブラリを利用するように書き直すかが対処法になると思います。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-10-08 18:42
何でも当てはまる話ですが、
同時起動に対応していないようなものをサーバで利用する場合は、
同時実行数を制御しなければなりませんね。
同期化等を利用して制御するのがよいかと思います。
Java1年生
会議室デビュー日: 2007/10/08
投稿数: 12
投稿日時: 2007-10-08 18:50
かつのりさん、Anthyhimeさん、早速の返答ありがとうございます。

この様な現象は、不定的に発生してしまうのでしょうか?
例えば、JComのこのメソッドを連続してコールされると、
現象が再現できるなどといった条件はあるのでしょうか?

顧客に、今回の現象を説明する際、
再現試験をした後、対応パッチをあてると、
同じ再現試験をしても再発しないことを確認させたいのですが、
可能なのでしょうか?
(JComをPOIにする以外に、何かいい対策があれば教えてください。)
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-10-08 19:36
http://support.microsoft.com/kb/257757/ja

再現云々以前に、サーバサイドでExcelを動作させることについて、
マイクロソフトは推奨もサポートも一切していません。

引用:

この様な現象は、不定的に発生してしまうのでしょうか?
例えば、JComのこのメソッドを連続してコールされると、
現象が再現できるなどといった条件はあるのでしょうか?


これはJComの作者に問い合わせるしかないでしょう。

JComは簡単に言えばExcelをJavaから直接操作するためのライブラリです。
POIはExcelのファイルを操作するためのライブラリです。
JComを利用した同時操作がトラブルの原因と言い切れるのであれば、
そもそも仕組みが違うのでPOIでは同じ現象は起こりません。
Java1年生
会議室デビュー日: 2007/10/08
投稿数: 12
投稿日時: 2007-10-08 20:09
かつのりさん

> これはJComの作者に問い合わせるしかないでしょう。
>
> JComは簡単に言えばExcelをJavaから直接操作するためのライブラリです。
> POIはExcelのファイルを操作するためのライブラリです。
> JComを利用した同時操作がトラブルの原因と言い切れるのであれば、
> そもそも仕組みが違うのでPOIでは同じ現象は起こりません。

サーバサイドで、Excelを使用すると、
様々な問題が発生する可能性があるということですね。
ありがとうございます。
せめて、try-catchで、エラーをcatchできて、
処理できればいいのですが、JVMがダウンしてしまうので、
対策ができなくて困っています。
JComについて、少し確認してみます。
また、POIであれば、このような状況にはならないようなので、
そちらも検討してみます。

ありがとうございました。

a-san
ベテラン
会議室デビュー日: 2004/06/01
投稿数: 53
投稿日時: 2007-10-08 21:42
JCom作者の渡辺(a-san)です。
みなさんのご指摘の通りです。
Excelは複数同時に実行できるようには対応していないので、JComに限らずOLEオートメーションを使うタイプ(Jacobなど)はどれもダメです。

どうしてもJComを使うのであれば、複数同時に実行しないようにサーバアプリを作れば、回避することはできるでしょう。

しかしExcel自体がそれほど安定して動作するわけではないので、JComよりは(Excelの不要な)POIの方をオススメします。
Java1年生
会議室デビュー日: 2007/10/08
投稿数: 12
投稿日時: 2007-10-08 22:34
a-sanさん、ご回答ありがとうございます。

実は、このサイトを拝見していて、他のJCom関連の書き込みも多々返答していただいているのを見て、a-sanさん一度、質問をしたいと思っていました。
本当に助かります。

JComのjava-docを拝見したのですが、
ReleaseManager に、下記記載があったのですが、
このように、何らかの方法によって、
トラブルの回避は可能でしょうか?
また、同時アクセスの対応は、
下記プログラムによって可能でしょうか?

御教授いただければ、助かります。
よろしくお願いします。



// 比較的寿命の長いプログラム
ReleaseManager rm = new ReleaseManager();
try {
IDispatch foo = new IDispatch(rm ,progid);
// ...
for(int i=0; i<files.length; i++) {
rm.push();
// ...
rm.pop(); // for文の中で生成されたオブジェクトを解放
}
} catch(JComException e) {
e.printStackTrace();
} finally {
rm.release();
}

スキルアップ/キャリアアップ(JOB@IT)