Skip to content

fix(script): warn at startup about settings that use a missing script engine - #3451

Merged
marevol merged 1 commit into
mainfrom
fix/warn-missing-script-engine-at-startup
Sep 15, 2026
Merged

marevol merged 1 commit into
mainfrom
fix/warn-missing-script-engine-at-startup

Conversation

@marevol

@marevol marevol commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

Problem

Found while verifying the 15.8 → 15.9 upgrade path: a ZIP upgrade that follows the upgrade guide, on the same OpenSearch, without fess-script-groovy.

Groovy has shipped as a plugin since 15.9 (#3425), and an upgrade does not rewrite anything stored in the index:

  • The startup bulk load of fess_config.scheduled_job only creates documents that do not exist yet (OpType.CREATE in SearchEngineClient), so all 14 bundled jobs keep script_type=groovy.
  • A web or file config, data config or document boost rule saved before 15.9 has no script type, and an unset type means groovy (CrawlingConfig#getScriptType, AbstractDataStore#getScriptType, DocBoostMatcher).
  • A 15.8 fess_config.properties carried over in Step 3 of the guide keeps job.default.script=groovy.

All of these fail only when they run, and the startup log does not mention groovy at all:

Setting Without the plugin Where it shows up
groovy scheduled job fails on every run: groovy is not found. ... A plugin may be missing, such as fess-script-groovy for groovy. the job log. But 9 of the 14 bundled jobs have job logging off, so for them only a Failed to execute job warning in fess.log
web/file config with field.script.* indexes no documents while the crawl job reports ok failure URLs with ScriptEngineException
data config with a handler script values that are not a bare parameter name cannot be evaluated at crawl time
document boost rule boosts nothing one warning in the crawler log when the rule is first evaluated (#3412)
groovy: path mapping maps nothing a warning when the mapping is first used
job.default.script=groovy new jobs default to groovy nowhere

Change

MissingScriptEngineReporter (new, org.codelibs.fess.helper) runs once from AllJobScheduler#schedule. At that point the DI container has started, so every script engine plugin has registered, and no job has run yet. The job scheduler is started by LastaPrepareFilter, so the check runs in the web application only, never in the crawler or other child processes. It runs again only when the scheduler is rebooted by a configuration reload, such as restoring a backup.

It loads, one bounded query per kind (the existing page.*.max.fetch.size limits):

  • scheduled jobs, using ScheduledJob#getScriptType
  • web and file configs that have a field.script.* parameter, using CrawlingConfig#getScriptType
  • data configs that have a handler script, using script_type with an unset value counted as groovy
  • document boost rules, using the same resolution as DocBoostMatcher
  • path mappings whose replacement prefix is groovy: or javascript: (PathMappingHelper.SCRIPT_ENGINE_NAMES)
  • job.default.script

For every engine that ScriptEngineFactory#hasScriptEngine does not know, it logs one warning. For each kind of setting the warning gives a count and up to three names (ids for boost rules and path mappings). It names the plugin in the wording ScriptEngineFactory already uses, and says where each kind takes javascript instead. On an index written by 15.8.0:

WARN  Settings use the script engine groovy, which is not registered, so their scripts cannot run: scheduled jobs=15 [Default Crawler, Suggest Indexer, Log Aggregator, ...], web configs=1 [legacy-web], file configs=1 [legacy-file], data configs=1 [legacy-data], document boost rules=1 [<id>], path mappings=1 [<id>], properties=1 [job.default.script]. A setting without a script type uses groovy. A plugin may be missing, such as fess-script-groovy for groovy. To use JavaScript instead, rewrite each script and set javascript as its script type: the Execution Method of a scheduled job, the Script Type of a document boost rule, config.script.type=javascript in the Config Parameter of a web or file config, script_type=javascript in the Parameter of a data config, the javascript: prefix of a path mapping Replacement, and job.default.script in fess_config.properties.

The check never throws. If a kind of setting cannot be read, it is skipped and the failure is logged at debug, and the other kinds are still reported. If every engine in use is registered, nothing is logged.

This does not repeat what #3412 and the path mapping helper log. Those warnings appear when a boost rule or mapping is first used, in whichever process uses it. This one is a startup inventory in fess.log.

A data config is counted as soon as it has a handler script. One whose values are all bare parameter names would still work without an engine, but that cannot be told apart without the data.

Verification

MissingScriptEngineReporterTest (8 tests):

  • test_collect_findsSettingsWhoseEngineIsNotRegistered: groovy and unset job types are counted and a javascript job is not. A web config without field scripts, or with config.script.type=javascript, is not counted, and neither is a data config with script_type=javascript or with no handler script. A boost rule with no type is counted. Of the path mappings, groovy: is counted and https://…/$1, javascript: and function:encodeUrl are not. job.default.script=groovy is counted.
  • test_collect_isEmptyWhenEveryEngineIsRegistered, test_collect_groupsByEngineName, test_summarize
  • test_report_warnsOncePerEngine, test_report_isSilentWhenNothingIsMissing, test_report_skipsSettingsThatCannotBeLoaded, test_report_neverThrows

Upgrade reproduction. I installed the 15.8.0 ZIP on OpenSearch 3.8.0 and, through the admin API, created:

  • a groovy job
  • a web config with a Groovy field script, and one without scripts
  • a file config and a data config with scripts
  • a boost rule
  • a groovy: path mapping, and an https://…/$1 one

Then I stopped 15.8.0 and started 15.9 on the same index, with 15.8's system.properties and fess_config.properties copied over as the guide says:

  • 15.9.0-SNAPSHOT distribution of main: the startup log has one warning (the CORS notice) and no line mentioning groovy.
  • The same distribution with this change: that warning plus the one above. It lists the 14 bundled jobs and the custom one, the web config with a script but not the one without, and the groovy: mapping but not the https: one.
  • The same distribution with this change and fess-script-groovy installed: no warning, and the custom Groovy job runs ok with GROOVY:2.

mvn test: 7495 tests, 0 failures, 0 errors.

… engine

An installation upgraded from 15.8 keeps groovy wherever it is stored, and
Groovy ships as the fess-script-groovy plugin since 15.9. The startup bulk load
of fess_config.scheduled_job only creates jobs that do not exist yet, so all 14
bundled jobs keep script_type=groovy, and a crawl config, data config or
document boost rule saved before 15.9 has no script type, which also means
groovy. Without the plugin each of them fails, but only when it runs, and
nothing at startup says so:

- A groovy job fails whenever it runs with "groovy is not found". Nine of the
  bundled jobs have job logging off, so their only trace is a "Failed to
  execute job" warning in fess.log.
- A web or file config with a field script indexes no documents while its
  crawl job reports ok; the documents end up as failure URLs with a
  ScriptEngineException.
- A document boost rule boosts nothing and a groovy: path mapping maps
  nothing. Both are reported, but only where and when they are first used.

MissingScriptEngineReporter runs from AllJobScheduler#schedule. By then the DI
container has started, so every script engine plugin has registered, and no
job has run yet. The scheduler is started by LastaPrepareFilter, so this
happens in the web application only, not in the crawler or the other child
processes. The reporter reads the scheduled jobs, web, file and data configs,
document boost rules and path mappings, resolves the script type each one runs
with, counting an unset type as groovy just as the runtime does, and logs one
warning per engine that has no registered ScriptEngine. For each kind of
setting the warning gives a count and up to three names (ids for boost rules
and path mappings), names the plugin in the wording ScriptEngineFactory
already uses, and says where that kind takes javascript instead.

Only settings that evaluate a script are counted: crawl configs with a
field.script.* parameter, data configs with a handler script, and path
mappings whose prefix is groovy: or javascript:, the prefixes PathMappingHelper
treats as scripts. job.default.script is reported too: a 15.8
fess_config.properties copied during the upgrade still sets it to groovy, and
the scheduler's create form offers it as the default for new jobs.

The check is one query per kind against the fess_config indices, bounded by
the existing page.*.max.fetch.size settings, and it never throws: a kind that
cannot be read is skipped and logged at debug.
@marevol marevol added this to the 15.9.0 milestone Sep 15, 2026
@marevol marevol self-assigned this Sep 15, 2026
@marevol
marevol merged commit 388952f into main Sep 15, 2026
2 checks passed
marevol added a commit to codelibs/fess-docs that referenced this pull request Sep 15, 2026
…fig and plugin upgrades (#536)

An installation that upgrades from 15.8 by following install/upgrade.rst
still ends up with several things broken that the guide did not mention.
All seven languages of the development tree (15.9) are updated.

- Groovy: every job 15.8 seeded is stored as groovy and the startup
  seeding is create-only, so Default Crawler and the other bundled jobs
  fail without fess-script-groovy, mostly visible only in fess.log.
  The section now lists every kind of stored setting that 15.9
  evaluates as Groovy and what each does without the plugin, tells
  upgraders to look for the startup warning, and gives both ways out:
  install the plugin, or switch each kind to JavaScript with the field
  that selects its engine (Thumbnail Purger's 1000L literal needs an
  edit).
- Index Exporter: the stored script names
  org.opensearch.index.query.QueryBuilders, removed by
  codelibs/fess#3439; give the replacement script and fix the examples
  in config/admin-index-export.rst.
- Carried-over configuration: ZIP Step 3 copies fess_config.properties
  and fess.in.sh, and RPM keeps a modified fess_config.properties. List
  the keys whose 15.8.0 value now misbehaves (job.default.script,
  job.template.script, crawler.file.protocols, search_engine.http.url,
  the jcifs options, removed keys) and what a 15.8 fess.in.sh lacks.
  Say that DEB overwrites the file without prompting or a backup.
- jcifs 3.x property names (codelibs/fess#3433): SMB connect and session
  timeouts now take effect, 35 s to 60 s.
- The four keys removed by codelibs/fess#3435.
- Plugins: bin/fess-setup upgrade plugins and check; what a Playwright
  crawl configuration does without the plugin.
- Replace the ZIP size figure, which did not match the released
  fess-15.8.0.zip, with the Playwright driver bundle's share of it.

The startup warning, the Playwright crawler warning and path mappings
being left unapplied describe codelibs/fess#3451, #3445 and #3452.
@marevol
marevol deleted the fix/warn-missing-script-engine-at-startup branch September 16, 2026 13:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant