Fix potential lambda argument mismatch (#448)
diff --git a/api/src/main/java/jakarta/el/ELContext.java b/api/src/main/java/jakarta/el/ELContext.java
index ef0f6e3..bfc5ce8 100644
--- a/api/src/main/java/jakarta/el/ELContext.java
+++ b/api/src/main/java/jakarta/el/ELContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2024 Oracle and/or its affiliates and others.
+ * Copyright (c) 1997, 2026 Oracle and/or its affiliates and others.
* All rights reserved.
* Copyright 2004 The Apache Software Foundation
*
@@ -72,7 +72,7 @@
* @see ImportHandler
* @see LambdaExpression
* @see StandardELContext
- *
+ *
* @since Jakarta Expression Language 2.1 and Jakarta Expression Language 3.0
*/
public abstract class ELContext {
@@ -207,7 +207,7 @@
* Retrieves the <code>ImportHandler</code> associated with this <code>ELContext</code>.
*
* @return The import handler to manage imports of classes and packages.
- *
+ *
* @since Jakarta Expression Language 3.0
*/
public ImportHandler getImportHandler() {
@@ -357,7 +357,7 @@
*
* @param arg The formal parameter for the Lambda argument
* @return The object associated with formal parameter. Null if no object has been associated with the parameter.
- *
+ *
* @since Jakarta Expression Language 3.0
*/
public Object getLambdaArgument(String arg) {
@@ -368,7 +368,7 @@
for (int i = lambdaArgs.size() - 1; i >= 0; i--) {
Map<String, Object> lmap = lambdaArgs.elementAt(i);
Object v = lmap.get(arg);
- if (v != null) {
+ if (v != null || lmap.containsKey(arg)) {
return v;
}
}
@@ -381,7 +381,7 @@
* will be in scope during the evaluation of the Lambda expression.
*
* @param args The Lambda arguments map
- *
+ *
* @since Jakarta Expression Language 3.0
*/
public void enterLambdaScope(Map<String, Object> args) {
@@ -413,7 +413,7 @@
* @param <T> The target type for the conversion.
* @param obj The object to convert.
* @param targetType The target type for the conversion.
- *
+ *
* @return object converted to <code>targetType</code>
* @throws ELException thrown if errors occur.
*
diff --git a/api/src/test/java/jakarta/el/TestELContext.java b/api/src/test/java/jakarta/el/TestELContext.java
new file mode 100644
index 0000000..0e22ef7
--- /dev/null
+++ b/api/src/test/java/jakarta/el/TestELContext.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2026 Contributors to the Eclipse Foundation
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0, which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * This Source Code may also be made available under the following Secondary
+ * Licenses when the conditions for such availability set forth in the
+ * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
+ * version 2 with the GNU Classpath Exception, which is available at
+ * https://www.gnu.org/software/classpath/license.html.
+ *
+ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
+ */
+package jakarta.el;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class TestELContext {
+
+ private static final String NAME = "x";
+ private static final String VALUE_NON_NULL = "x";
+ private static final String VALUE_NULL = null;
+
+
+ @Test
+ public void testLambdaScopeWithNullParameter() {
+ ELContext elContext = new SimpleELContextImpl();
+
+ // Set up parameters for outer scope
+ Map<String,Object> outerParams = new HashMap<>();
+ outerParams.put(NAME, VALUE_NON_NULL);
+
+ // Set up parameters for innerscope
+ Map<String,Object> innerParams = new HashMap<>();
+ innerParams.put(NAME, VALUE_NULL);
+
+ // Enter outer scope
+ elContext.enterLambdaScope(outerParams);
+
+ // Should see outer, non-null value
+ Assertions.assertEquals(VALUE_NON_NULL, elContext.getLambdaArgument(NAME));
+
+ // Enter inner scope
+ elContext.enterLambdaScope(innerParams);
+
+ // Should see inner, null value
+ Assertions.assertNull(elContext.getLambdaArgument(NAME));
+ }
+
+
+ private static class SimpleELContextImpl extends ELContext {
+
+ @Override
+ public ELResolver getELResolver() {
+ return null;
+ }
+
+ @Override
+ public FunctionMapper getFunctionMapper() {
+ return null;
+ }
+
+ @Override
+ public VariableMapper getVariableMapper() {
+ return null;
+ }
+ }
+}
diff --git a/spec/src/main/asciidoc/expression-language-spec-body.adoc b/spec/src/main/asciidoc/expression-language-spec-body.adoc
index 2f0921c..84ee619 100644
--- a/spec/src/main/asciidoc/expression-language-spec-body.adoc
+++ b/spec/src/main/asciidoc/expression-language-spec-body.adoc
@@ -3186,6 +3186,10 @@
instances in the list of conditions that cause the empty operator to return
true.
+* https://github.com/jakartaee/expression-language/issues/447[#447]
+ Fix an issue in the `ELContext` class so that expression such as
+ `(x -> (x -> x)(null))(42)` correctly evaluate to `null` rather than `42`.
+
=== Changes between 6.0 and 5.0
* The EL API requires Java 17 as a minimum.