You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by ta...@apache.org on 2026/07/24 11:51:28 UTC
(myfaces) 02/02: [perf] optimize ELResolver impls
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch 4.1.x
in repository https://gitbox.apache.org/repos/asf/myfaces.git
commit f2ba02f827fd3ef6b6cd95e8e2ad73bd54b9967a
Author: tandraschko <ta...@apache.org>
AuthorDate: Thu Jul 16 13:58:40 2026 +0200
[perf] optimize ELResolver impls
(cherry picked from commit b41d0d9f280a8650505daf90202351e834726d18)
---
.../el/resolver/ResourceBundleResolver.java | 18 +++++--
.../el/resolver/ScopedAttributeResolver.java | 59 ++++++++++++++++++++--
2 files changed, 70 insertions(+), 7 deletions(-)
diff --git a/impl/src/main/java/org/apache/myfaces/el/resolver/ResourceBundleResolver.java b/impl/src/main/java/org/apache/myfaces/el/resolver/ResourceBundleResolver.java
index 29ccca2af..55418ba57 100644
--- a/impl/src/main/java/org/apache/myfaces/el/resolver/ResourceBundleResolver.java
+++ b/impl/src/main/java/org/apache/myfaces/el/resolver/ResourceBundleResolver.java
@@ -128,6 +128,13 @@ public Object getValue(final ELContext context, final Object base, final Object
{
return null;
}
+ // fast path: when no <resource-bundle> var is configured in faces-config, this resolver can
+ // never resolve anything - skip the per-identifier Application.getResourceBundle/getBundleName
+ // chain that otherwise runs for every EL identifier (e.g. #{row} on every table cell).
+ if (runtimeConfig(context).getResourceBundles().isEmpty())
+ {
+ return null;
+ }
final ResourceBundle bundle = getResourceBundle(context, (String)property);
if (bundle != null)
@@ -155,6 +162,10 @@ public Class<?> getType(final ELContext context, final Object base, final Object
{
return null;
}
+ if (runtimeConfig(context).getResourceBundles().isEmpty())
+ {
+ return null;
+ }
final ResourceBundle bundle = getResourceBundle(context, (String)property);
if (bundle != null)
@@ -217,12 +228,11 @@ private static ResourceBundle getResourceBundle(final ELContext context, final S
protected RuntimeConfig runtimeConfig(ELContext context)
{
- final FacesContext facesContext = facesContext(context);
-
- // application-level singleton - we can safely cache this
+ // application-level singleton - we can safely cache this (only resolve the FacesContext on
+ // the first call; this runs per EL identifier so avoid the lookup once cached)
if (this.runtimeConfig == null)
{
- this.runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
+ this.runtimeConfig = RuntimeConfig.getCurrentInstance(facesContext(context).getExternalContext());
}
return runtimeConfig;
diff --git a/impl/src/main/java/org/apache/myfaces/el/resolver/ScopedAttributeResolver.java b/impl/src/main/java/org/apache/myfaces/el/resolver/ScopedAttributeResolver.java
index e5fc6f6ad..5e551d41b 100644
--- a/impl/src/main/java/org/apache/myfaces/el/resolver/ScopedAttributeResolver.java
+++ b/impl/src/main/java/org/apache/myfaces/el/resolver/ScopedAttributeResolver.java
@@ -104,10 +104,63 @@ public Object getValue(final ELContext context, final Object base, final Object
context.setPropertyResolved(true);
- final Map<String, Object> scopedMap = findScopedMap(facesContext(context), property);
- if (scopedMap != null)
+ final FacesContext facesContext = facesContext(context);
+ if (facesContext == null)
+ {
+ return null;
+ }
+ final ExternalContext extContext = facesContext.getExternalContext();
+ if (extContext == null)
+ {
+ return null;
+ }
+
+ final boolean startup = (extContext instanceof StartupServletExternalContextImpl);
+
+ // A single get() per scope instead of findScopedMap()'s containsKey()+get(): servlet
+ // request/session/application attributes are never null, so a non-null get() means the key
+ // is present. This halves the attribute-map lookups for the very hot case of resolving a
+ // UIData/UIRepeat row var (e.g. #{row}) once per cell. Mirrors the reference
+ // ScopedAttributeELResolver. The view map is a plain Map that may legitimately hold a null
+ // value, so it keeps the containsKey() check.
+ Object value;
+
+ // request scope (not available at startup)
+ if (!startup)
+ {
+ value = extContext.getRequestMap().get(property);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+
+ // jsf 2.0 view scope
+ UIViewRoot root = facesContext.getViewRoot();
+ if (root != null)
+ {
+ Map<String, Object> viewMap = root.getViewMap(false);
+ if (viewMap != null && viewMap.containsKey(property))
+ {
+ return viewMap.get(property);
+ }
+ }
+
+ // session scope (not available at startup)
+ if (!startup)
+ {
+ value = extContext.getSessionMap().get(property);
+ if (value != null)
+ {
+ return value;
+ }
+ }
+
+ // application scope
+ value = extContext.getApplicationMap().get(property);
+ if (value != null)
{
- return scopedMap.get(property);
+ return value;
}
return null;