0

バックグラウンド

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 サーバーでカスタム サーブレットを開発する

関連リンク

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

4

1 に答える 1

0

問題は、RFC 2183 の不適切な実装でした。

response.setHeader( "Content-Disposition", "attachment; filename="
  + getFilename() );

を にする;ことはできません,

于 2012-12-03T21:45:07.287 に答える