[ 
https://issues.apache.org/jira/browse/WW-5690?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Lukasz Lenart updated WW-5690:
------------------------------
    Description: 
{{DefaultDispatcherErrorHandler.init()}} built a FreeMarker configuration and 
loaded {{/org/apache/struts2/dispatcher/error.ftl}} on *every* startup — 
including production, where the problem report is never rendered. 
{{handleError(...)}} only reaches it when devMode is on; otherwise it delegates 
to the container's error page via {{sendErrorResponse(...)}}.

So every Struts application paid to initialise FreeMarker for a page most of 
them never show.

h2. Change

{{init(ServletContext)}} now only stores the servlet context. A new {{protected 
getTemplate()}} loads the template on first use and caches it in a {{volatile}} 
field.

No lock: two threads racing on the very first error may both load it, which is 
harmless — FreeMarker caches templates in its own {{Configuration}} — and 
cheaper than locking a path taken once per application lifetime.

h2. Behavioural change

A missing or unparsable {{error.ftl}} used to throw {{StrutsException}} from 
{{init()}} and fail the application at boot. It now surfaces on the first 
dev-mode error, where the existing {{catch}} in {{handleErrorInDevMode(...)}} 
degrades to {{sendError(code, "Unable to show problem report: ...")}}. A 
dev-only template should not stop a production application starting.

h2. Scope

Startup cost only. The {{FreemarkerManager}} injection, the 
{{freemarker.template.Template}} import and {{error.ftl}} itself all remain — 
removing them is WW-5693.

This ticket was originally filed as "Remove core's FreeMarker dependency from 
DefaultDispatcherErrorHandler" and has been narrowed to the change that 
actually shipped.

  was:
Part of the WW-5689 lean-core work, but self-contained and shippable in 7.x.

*Scope note.* This is about _core's own_ dependency on FreeMarker. Applications 
using the Struts tag library still require FreeMarker regardless: 
{{struts.ui.templateSuffix}} defaults to {{ftl}} and all 129 bundled theme 
templates are {{.ftl}}. What these tickets buy is that a REST/JSON-only 
application — one that never renders a tag — stops paying for FreeMarker.

h2. Current behaviour

{{DefaultDispatcherErrorHandler}} renders the dev-mode error report through 
FreeMarker:
* it holds an injected {{FreemarkerManager}}
* {{init(ServletContext)}} calls {{freemarkerManager.getConfiguration(ctx)}} 
and loads {{/org/apache/struts2/dispatcher/error.ftl}}
* only {{handleErrorInDevMode(...)}} ever uses the resulting template

{{init()}} is *unconditional*. It runs at dispatcher startup and initialises 
the whole FreeMarker configuration even in production mode, where the template 
is never rendered — {{handleError(...)}} goes to {{sendErrorResponse(...)}} and 
delegates to the container's error page.

h2. Proposal

Render the dev-mode error report without FreeMarker — a plain Java renderer is 
sufficient for what {{error.ftl}} produces.

Failing that, the minimum acceptable change is to make the template load lazy 
and gate it on devMode, so a production deployment never touches FreeMarker 
through this path.

{{DispatcherErrorHandler}} is already a pluggable bean, so a FreeMarker-based 
handler can remain available for anyone who has customised {{error.ftl}}.

h2. Compatibility

{{error.ftl}} is an internal template, not a documented extension point. If the 
plain renderer lands, note the change in the migration guide for anyone who has 
overridden it.

        Summary: Defer loading the dev-mode error template until first use  
(was: Remove core's FreeMarker dependency from DefaultDispatcherErrorHandler)

> Defer loading the dev-mode error template until first use
> ---------------------------------------------------------
>
>                 Key: WW-5690
>                 URL: https://issues.apache.org/jira/browse/WW-5690
>             Project: Struts 2
>          Issue Type: Task
>          Components: Core
>            Reporter: Lukasz Lenart
>            Assignee: Lukasz Lenart
>            Priority: Major
>             Fix For: 7.4.0
>
>          Time Spent: 10m
>  Remaining Estimate: 0h
>
> {{DefaultDispatcherErrorHandler.init()}} built a FreeMarker configuration and 
> loaded {{/org/apache/struts2/dispatcher/error.ftl}} on *every* startup — 
> including production, where the problem report is never rendered. 
> {{handleError(...)}} only reaches it when devMode is on; otherwise it 
> delegates to the container's error page via {{sendErrorResponse(...)}}.
> So every Struts application paid to initialise FreeMarker for a page most of 
> them never show.
> h2. Change
> {{init(ServletContext)}} now only stores the servlet context. A new 
> {{protected getTemplate()}} loads the template on first use and caches it in 
> a {{volatile}} field.
> No lock: two threads racing on the very first error may both load it, which 
> is harmless — FreeMarker caches templates in its own {{Configuration}} — and 
> cheaper than locking a path taken once per application lifetime.
> h2. Behavioural change
> A missing or unparsable {{error.ftl}} used to throw {{StrutsException}} from 
> {{init()}} and fail the application at boot. It now surfaces on the first 
> dev-mode error, where the existing {{catch}} in {{handleErrorInDevMode(...)}} 
> degrades to {{sendError(code, "Unable to show problem report: ...")}}. A 
> dev-only template should not stop a production application starting.
> h2. Scope
> Startup cost only. The {{FreemarkerManager}} injection, the 
> {{freemarker.template.Template}} import and {{error.ftl}} itself all remain — 
> removing them is WW-5693.
> This ticket was originally filed as "Remove core's FreeMarker dependency from 
> DefaultDispatcherErrorHandler" and has been narrowed to the change that 
> actually shipped.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to