バックグラウンド
ADF タスク フローを使用して、さまざまな形式 (PDF、区切り記号付き、HTML など) でレポートを生成します。
問題
HTTP ヘッダーは 2 回送信されています。1 回はフレームワークによって、もう 1 回は Bean によって送信されます。
ソースコード
ソースコードには以下が含まれます:
- ボタンアクション
- マネージド Bean
- タスク フロー
ボタンアクション
ボタンのアクション:
<af:commandButton text="Report" id="submitReport" action="Execute" />
マネージド Bean
Managed Bean はかなり複雑です。へのコードresponseComplete
が呼び出されていますが、アプリケーション フレームワークが HTTP ヘッダーを書き込むのを防ぐのに十分早く呼び出されていないようです。
HTTP 応答ヘッダーのオーバーライド
/**
* Sets the HTTP headers required to indicate to the browser that the
* report is to be downloaded (rather than displayed in the current
* window).
*/
protected void setDownloadHeaders() {
HttpServletResponse response = getServletResponse();
response.setHeader( "Content-Description", getContentDescription() );
response.setHeader( "Content-Disposition", "attachment, filename="
+ getFilename() );
response.setHeader( "Content-Type", getContentType() );
response.setHeader( "Content-Transfer-Encoding",
getContentTransferEncoding() );
}
問題対応完了
getFacesContext().responseComplete();
Bean の実行と構成
public void run() {
try {
Report report = getReport();
configure(report.getParameters());
report.run();
} catch (Exception e) {
e.printStackTrace();
}
}
private void configure(Parameters p) {
p.put(ReportImpl.SYSTEM_REPORT_PROTOCOL, "http");
p.put(ReportImpl.SYSTEM_REPORT_HOST, "localhost");
p.put(ReportImpl.SYSTEM_REPORT_PORT, "7002");
p.put(ReportImpl.SYSTEM_REPORT_PATH, "/reports/rwservlet");
p.put(Parameters.PARAM_REPORT_FORMAT, "pdf");
p.put("report_cmdkey", getReportName());
p.put("report_ORACLE_1", getReportDestinationType());
p.put("report_ORACLE_2", getReportDestinationFormat());
}
タスク フロー
タスク フローは、Bean のrun()
メソッドを参照する Execute を呼び出します。
entry -> main -> Execute -> ReportBeanRun
どこ:
<method-call id="ReportBeanRun">
<description>Executes a report</description>
<display-name>Execute Report</display-name>
<method>#{reportBean.run}</method>
<outcome>
<fixed-outcome>success</fixed-outcome>
</outcome>
</method-call>
Bean はrequest
、いくつかの管理プロパティを使用してスコープに割り当てられます。
<control-flow-rule id="__3">
<from-activity-id>main</from-activity-id>
<control-flow-case id="ExecuteReport">
<from-outcome>Execute</from-outcome>
<to-activity-id>ReportBeanRun</to-activity-id>
</control-flow-case>
</control-flow-rule>
<managed-bean id="ReportBean">
<description>Executes a report</description>
<display-name>ReportBean</display-name>
<managed-bean-scope>request</managed-bean-scope>
...
</managed-bean>
これ<fixed-outcome>success</fixed-outcome>
は間違っていると思います。メソッド呼び出しを別のタスクに戻したくありません。
制限
レポート サーバーは、Web サーバーからの要求を排他的に受け取ります。セキュリティ上の理由から、ブラウザーがレポート サーバーの URL を使用して直接ダウンロードすることはできません。
エラー メッセージ
生成されるエラー メッセージ:
サーバーから重複したヘッダーを受信しました
エラー 349 (net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION): 複数の異なる Content-Disposition ヘッダーを受信しました。これは、HTTP 応答分割攻撃から保護するために許可されていません。
それでも、レポートは生成されています。フレームワークが HTTP ヘッダーを書き込まないようにすると、この問題は解決します。
質問
タスク・フローを使用してマネージドBeanを呼び出してPDFを生成する際に、ADFでHTTPヘッダーを設定するにはどうすればよいですか?
アイデア
いくつかの追加のアイデア:
- ページ ライフサイクル フェーズ リスナーをオーバーライドする (
ADFPhaseListener
+PageLifecycle
) - Web サーバーでカスタム サーブレットを開発する
関連リンク
- http://www.oracle.com/technetwork/middleware/bi-publisher/adf-bip-ucm-integration-179699.pdf
- http://www.slideshare.net/lucbors/reports-no-notes#btn次へ
- http://www.techartifact.com/blogs/2012/03/calling-oracle-report-from-adf-applications.html?goback=%2Egde_4212375_member_102062735
- http://docs.oracle.com/cd/E29049_01/web.1112/e16182/adf_lifecycle.htm#CIABEJFB
ありがとうございました!