Fessの管理画面でファイルアップロードができない問題の修正

Docker環境などでFessの管理画面から画像ファイルなどをアップロードできなくなっていた問題を修正しました。

原因

管理画面でファイルをアップロードする際、FessAdminActionvalidateFilePathメソッドでファイルパスのバリデーションが行われます。このバリデーションでは、アップロード先のパスが許可されたディレクトリ配下にあるかをチェックしていますが、従来はfess.var.pathのみを許可ディレクトリとして参照していました。

Docker環境では、アップロードされたファイルの保存先がfess.webapp.pathfess.conf.path配下になるケースがあり、これらのパスが許可されていなかったためアップロードに失敗していました。

修正内容

validateFilePathメソッドを修正し、以下の3つのシステムプロパティすべてを許可ディレクトリとしてチェックするようにしました。

  • fess.var.path
  • fess.webapp.path
  • fess.conf.path

ファイルパスがこれらのいずれかのディレクトリ配下にあれば、バリデーションを通過するようになります。また、バリデーション失敗時のエラーメッセージも改善され、すべての許可パスが表示されるようになりました。

この修正はFess 15.5.0に含まれる予定です。詳細はPR #3028を参照してください。

Fessのドキュメントをエクスポートする機能を追加

Fessでクロールしてインデックスに保存されたドキュメントを、HTMLファイルとしてエクスポートする機能を追加しました。検索インデックスに格納されているテキスト情報をファイルとして取り出せるようになります。将来的にはJSON形式などへの対応も検討しています。

概要

新しいスケジュールジョブ IndexExportJob を追加しました。このジョブはOpenSearchのインデックスからドキュメントをスクロール検索で取得し、各ドキュメントをHTMLファイルとしてファイルシステムに書き出します。ドキュメントのURLのパス構造がそのままディレクトリ構造に反映されます。

設定

fess_config.properties に以下の設定項目が追加されています。

プロパティデフォルト値説明
index.export.path/var/lib/fess/exportエクスポート先のベースディレクトリ
index.export.exclude.fieldscacheエクスポートから除外するフィールド(カンマ区切り)
index.export.scroll.size100スクロール検索のバッチサイズ

エクスポートされるHTMLの構造

各ドキュメントは以下のような構造のHTMLファイルとして保存されます。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>ドキュメントのタイトル</title>
<meta name="fess:url" content="https://example.com/page">
<meta name="fess:host" content="example.com">
<meta name="fess:last_modified" content="2025-01-01T00:00:00">
<!-- その他のメタ情報 -->
</head>
<body>
ドキュメントのテキスト内容
</body>
</html>

titlecontentlang はHTML要素として直接使用され、それ以外のフィールドは fess: プレフィックス付きのmetaタグとして出力されます。exclude.fields で指定したフィールド(デフォルトでは cache)はエクスポートから除外されます。

ファイルの保存先

ドキュメントのURLに基づいてディレクトリ構造が決定されます。

  • https://example.com/docs/guide.htmlexample.com/docs/guide.html
  • https://example.com/docs/example.com/docs/index.html
  • https://example.com/docs/pageexample.com/docs/page.html

パスコンポーネントに含まれるファイルシステムで使用できない文字はアンダースコアに置換されます。また、URLのパースに失敗した場合は _invalid/ ディレクトリにSHA-256ハッシュ名で保存されます。

使い方

管理画面のスケジューラーに「Index Exporter」ジョブが登録されています(デフォルトでは無効)。ジョブを有効にしてcron式を設定するか、手動で実行できます。

ジョブのスクリプトは以下の通りです。

return new org.codelibs.fess.job.IndexExportJob()
    .query(org.opensearch.index.query.QueryBuilders.matchAllQuery())
    .execute()

query() メソッドでエクスポート対象のドキュメントをフィルタリングすることもできます。

まとめ

この機能により、Fessのインデックスに保存されているドキュメント情報をHTMLファイルとして取り出すことができます。バックアップやデータ移行、他のシステムとの連携などに活用できます。

FessのJUnitテストでheadlessモードを有効化

FessのJUnitテスト実行時に、X Window(ディスプレイ)にアクセスしようとしてテストが失敗するケースがありました。CI/CD環境やDockerコンテナなど、GUIのない環境でも安定してテストを実行できるよう、headlessモードを有効化する設定を追加しました。

問題の背景

Javaアプリケーションでは、AWTやSwingなどのGUIコンポーネントを使用するコードがあると、テスト実行時にディスプレイ環境へのアクセスが発生することがあります。以下のような環境では、X11サーバーが存在しないためテストが失敗します。

  • CI/CDパイプライン(GitHub Actions、Jenkinsなど)
  • Dockerコンテナ
  • X11転送なしのSSH接続先サーバー

変更内容

pom.xmlのテストプロファイル設定で、JVMの起動引数に-Djava.awt.headless=trueを追加しました。

<test.command.args>--illegal-access=permit -Djava.awt.headless=true</test.command.args>

この設定により、テスト実行時にJavaがheadlessモードで動作し、ディスプレイなしの環境でもAWT関連の処理が正常に動作するようになります。

headlessモードとは

Javaのheadlessモードは、キーボード、ディスプレイ、マウスといった入出力デバイスがない環境でもJavaアプリケーションを動作させるための機能です。headlessモードでは、以下のような処理が可能です。

  • フォントの読み込みとレンダリング
  • 画像の生成・加工
  • 印刷処理

一方で、ウィンドウの表示やユーザー入力の受付など、実際のディスプレイが必要な操作は利用できません。

まとめ

-Djava.awt.headless=trueオプションの追加により、Fessのテストがヘッドレス環境でも安定して実行できるようになりました。CI/CD環境でのビルドやテストの信頼性が向上します。