5

Xpages から PDF を作成するための Paul Calhoun の Apache FOP ソリューションを実装しようとしています (Notes In 9 #102 から)。処理を行う xAgent を実行しようとすると、次の Java 例外が発生します --> OutputStream が既に使用されている間はライターを取得できません

私が Paul のコードから行った変更は、パッケージ名を変更したことだけです。SSJS 行に例外が発生したときに分離しました。 var jce: DominoXMLFO2PDF = new DominoXMLFO2PDF(); その行はクラスをインスタンス化するだけで、カスタム コンストラクターはありません。コード自体ではないと思いますが、構成の問題です。SSJS コードは、あるべき beforeRenderResponse イベントにあります。xAgent では何も変更していません。

Paul のサンプル データベースから私のデータベースに jar ファイルをコピーしました。ビルド パスが 2 つのデータベース間で同じであることを確認しました。すべてが正常にコンパイルされます (これをすべて行った後)。この例外は、xpages のみの例外のようです。

4

3 に答える 3

12

このエラーで実際に起こっていることは次のとおりです。

XPage は本質的にサーブレットです... XPage で発生するすべてのことは、サーブレット エンジンの上にあるレイヤーにすぎません。基本的に、サーブレットが接続を開始するもの (ブラウザなど) に送り返すことができるデータには、テキストとバイナリの 2 種類があります。

通常の XPage は、テキスト (具体的には HTML) を送信します。一部の xAgent は、JSON や XML などのテキストも送信します。ただし、これらのシナリオのいずれにおいても、Domino は Javaライターを使用して応答コンテンツを送信します。これは、ライターが文字データの送信用に最適化されているためです。

バイナリ コンテンツを送信する必要がある場合は、代わりにOutputStreamを使用します。これは、ストリームが一般的なバイト データの送信用に最適化されているためです。したがって、PDF、DOC/XLS/PPT、画像などを送信する場合は、テキストではなくバイナリ データを送信するため、ストリームを使用する必要があります。

問題は (すぐにわかるように、しゃれです)、応答ごとに 1 つしか使用できないことです。

HTTP クライアントは、応答のコンテンツ タイプを通知されると、そのコンテンツを処理する方法を想定します。したがって、期待するように指示するとapplication/pdf、バイナリ データのみを受信することが期待されます。逆に、期待するように指示するとapplication/json、文字データのみを受け取ることを期待しています。約束されたコンテンツ タイプと一致しないデータが応答に含まれている場合、ほとんどの場合、応答全体が無効なります

したがって、Domino はその無限の知恵により、1 回の要求でどちらか一方のみを送信できるようにすることで、この間違いを犯さないように保護し、その規則に従わない場合は例外をスローします。

残念ながら...バイナリ コンテンツを送信しようとしたときにコードに例外があった場合、Domino はそれを消費者に報告したいと考えています... コンシューマーは出力ライターを呼び出して、何か問題が発生したことを報告する HTML を送信しようとしますただし、出力ストリームのハンドルを既に取得しているため、Domino は出力ライターのハンドルを取得できません。これは、応答ごとに 1 つしか使用しないという独自のルールに違反するためです。これにより、報告された例外がスローされ、実際に問題を引き起こした例外がマスクされます (この場合、おそらくClassNotFoundException )。

では、この誤った指示ではなく、実際の問題を確認するにはどうすればよいでしょうか? 私たちはtry:

try {
  /*
   * Move all your existing code here...
   */
} catch (e) {
  print("Error generating dynamic PDF: " + e.toString());
} finally {
  facesContext.responseComplete();
}

これが推奨されるアプローチである理由は 2 つあります。

  1. コードに問題が発生した場合でも、Domino が例外をスローすることはありません。代わりに、それをログに記録します (printコンソールに送信してログに記録する代わりに、OpenLog に投げたり、好みのログ メカニズムが何であれ)。これは、Domino がエラーをユーザーに報告しようとしないことを意味します。
  2. 重要なfacesContext.responseComplete()呼び出し (Domino に自身のコンテンツを送信しないように最終的に指示するもの) をfinallyブロックに移動することで、確実に実行されます。ブロック内にそのままにしてtryおくと、例外が発生した場合にスキップされます。これは、直接スキップするためcatchです ... したがって、Domino は例外をキャッチしたために例外を報告していませんが、それでも応答を呼び出そうとします。私たちがそうしないように言わなかったので、作家。

上記のパターンに従い、コードに何か問題がある場合、ブラウザは不完全または破損したファイルを受け取りますが、ログは根本的な原因とは関係のないエラーを報告するのではなく、何が問題なのかを教えてくれます。問題。

于 2013-10-30T00:10:19.953 に答える
0

私はこの質問をほとんど削除しましたが、例外を検索するときにグーグルでほとんど出回っていないので、自分で答えることにしました.

問題は xAgent にあり、不適切な行 importPackage があります。これを修正すると、すべてが機能しました。例外の言い回し: 「OutputStream が既に使用されている間は Writer を取得できません」はかなり誤解を招くものです。他に何がこの例外をトリガーするのかはわかりませんが、別の説明は「Java クラス ??yourClass?? が見つかりません」です。

この質問を見つけた場合は、同じ問題を抱えている可能性があります。例外が実際に言っていることを無視し、アプリケーション全体でパッケージ ステートメントをチェックします。Java コードはそれ自体でエラーになりますが、Java を参照する SSJS は実行時までエラーになりません。そのコードに注目してください。

于 2013-10-29T21:10:40.907 に答える