このエラーで実際に起こっていることは次のとおりです。
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 つあります。
- コードに問題が発生した場合でも、Domino が例外をスローすることはありません。代わりに、それをログに記録します (
print
コンソールに送信してログに記録する代わりに、OpenLog に投げたり、好みのログ メカニズムが何であれ)。これは、Domino がエラーをユーザーに報告しようとしないことを意味します。
- 重要な
facesContext.responseComplete()
呼び出し (Domino に自身のコンテンツを送信しないように最終的に指示するもの) をfinally
ブロックに移動することで、確実に実行されます。ブロック内にそのままにしてtry
おくと、例外が発生した場合にスキップされます。これは、直接スキップするためcatch
です ... したがって、Domino は例外をキャッチしたために例外を報告していませんが、それでも応答を呼び出そうとします。私たちがそうしないように言わなかったので、作家。
上記のパターンに従い、コードに何か問題がある場合、ブラウザは不完全または破損したファイルを受け取りますが、ログは根本的な原因とは関係のないエラーを報告するのではなく、何が問題なのかを教えてくれます。問題。