[ https://issues.apache.org/jira/browse/JEXL-387?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Garret Wilson updated JEXL-387: ------------------------------- Description: In my [Guise Mummy|https://github.com/globalmentor/guise-mummy] static site generator I'm using JEXL to interpret the built-in [Mesh Expression Language|https://github.com/globalmentor/guise-mummy/tree/main/mesh] (MEXL). Everything was working fine with JEXL 3.1. In fact the entire [Guise Mummy web site|https://guise.io/mummy/] itself was produced using Guise Mummy with MEXL on top of JEXL. But when I upgrade to JEXL 3.2.1, the unit tests break. The MEX+JEXL error message says "Error in MEXL expression `foo.bar`: io.guise.mesh.JexlMexlEvaluator.evaluate:93 undefined property 'bar'", but if you look in the stack trace, you'll see that the problem seems to be a deeper {{NullPointerException}} which {{InterpreterBase.getAttribute(…)}} catches and effectively ignores, making it look like the problem was a missing variable. {code:java} } catch (final Exception xany) { xcause = xany; } {code} Here's the real problem: {noformat} Caused by: java.lang.NullPointerException: Cannot invoke "org.apache.commons.logging.Log.isDebugEnabled()" because "log" is null at org.apache.commons.jexl3.internal.introspection.ClassMap.populateWithClass(ClassMap.java:296) at org.apache.commons.jexl3.internal.introspection.ClassMap.populateWithInterface(ClassMap.java:270) at org.apache.commons.jexl3.internal.introspection.ClassMap.create(ClassMap.java:229) at org.apache.commons.jexl3.internal.introspection.ClassMap.<init>(ClassMap.java:100) at org.apache.commons.jexl3.internal.introspection.Introspector.getMap(Introspector.java:315) at org.apache.commons.jexl3.internal.introspection.Introspector.getMethod(Introspector.java:146) at org.apache.commons.jexl3.internal.introspection.Introspector.getMethod(Introspector.java:133) at org.apache.commons.jexl3.internal.introspection.PropertyGetExecutor.discoverGet(PropertyGetExecutor.java:107) at org.apache.commons.jexl3.internal.introspection.PropertyGetExecutor.discover(PropertyGetExecutor.java:42) at org.apache.commons.jexl3.internal.introspection.Uberspect.getPropertyGet(Uberspect.java:263) at org.apache.commons.jexl3.internal.InterpreterBase.getAttribute(InterpreterBase.java:971) at org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1108) at org.apache.commons.jexl3.parser.ASTIdentifierAccess.jjtAccept(ASTIdentifierAccess.java:104) at org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1156) at org.apache.commons.jexl3.parser.ASTReference.jjtAccept(ASTReference.java:19) at org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1029) at org.apache.commons.jexl3.parser.ASTJexlScript.jjtAccept(ASTJexlScript.java:58) at org.apache.commons.jexl3.internal.Interpreter.interpret(Interpreter.java:193) at org.apache.commons.jexl3.internal.Script.execute(Script.java:188) at org.apache.commons.jexl3.internal.Script.evaluate(Script.java:180) ... 72 more {noformat} Here's the line in question inside {{ClassMap.populateWithClass(ClassMap cache, Permissions permissions, Class<?> clazz, Log log)}}: {code:java} if (pmi != null && pmi != CACHE_MISS && log.isDebugEnabled() && !key.equals(new MethodKey(pmi))) { {code} For some reason your internal {{ClassMap}} class is being passed a {{Log}} that is {{null}}. Looking up the stack trace, it would appear this is coming from your {{Introspector}}. (There is a similar [error on Stack Overflow|https://stackoverflow.com/q/64927054] with no answers; I don't know if they are using JAXL.) * First, passing the {{Log}} around as a parameter is an antipattern. Logging is a cross-cutting concern; passing it around as a parameter is a bad idea. * I wish you were using {{SLF4J}} like practically everyone else instead of {{org.apache.commons.logging}}. * You shouldn't catch {{NullPointerException}} and turn it into a "normal" error condition, trying to say that a variable wasn't defined when really this was an internal error with the library. In any case, for some reason JEXL 3.2.1 isn't initializing its internal logging support. To reproduce this: # Clone [Guise Mummy 0.5.3|https://github.com/globalmentor/guise-mummy/releases/tag/v0.5.3]. # In the overall project {{pom.xml}}, change the version of {{org.apache.commons:commons-jexl3}} from {{<version>3.1</version>}} to {{<version>3.2.1</version>}}. # Run {{mvn clean verify}}. was: In my [Guise Mummy|https://github.com/globalmentor/guise-mummy] static site generator I'm using JEXL to interpret the built-in [Mesh Expression Language|https://github.com/globalmentor/guise-mummy/tree/main/mesh] (MEXL). Everything was working fine with JEXL 3.1. In fact the entire [Guise Mummy web site|https://guise.io/mummy/] itself was produced using Guise Mummy with MEXL on top of JEXL. But when I upgrade to JEXL 3.2.1, the unit tests break. The MEX+JEXL error message says "Error in MEXL expression `foo.bar`: io.guise.mesh.JexlMexlEvaluator.evaluate:93 undefined property 'bar'", but if you look in the stack trace, you'll see that the problem seems to be a deeper {{NullPointerException}} which {{InterpreterBase.getAttribute(…)}} catches and effectively ignores, making it look like the problem was a missing variable. {code:java} } catch (final Exception xany) { xcause = xany; } {code} Here's the real problem: {noformat} Caused by: java.lang.NullPointerException: Cannot invoke "org.apache.commons.logging.Log.isDebugEnabled()" because "log" is null at org.apache.commons.jexl3.internal.introspection.ClassMap.populateWithClass(ClassMap.java:296) at org.apache.commons.jexl3.internal.introspection.ClassMap.populateWithInterface(ClassMap.java:270) at org.apache.commons.jexl3.internal.introspection.ClassMap.create(ClassMap.java:229) at org.apache.commons.jexl3.internal.introspection.ClassMap.<init>(ClassMap.java:100) at org.apache.commons.jexl3.internal.introspection.Introspector.getMap(Introspector.java:315) at org.apache.commons.jexl3.internal.introspection.Introspector.getMethod(Introspector.java:146) at org.apache.commons.jexl3.internal.introspection.Introspector.getMethod(Introspector.java:133) at org.apache.commons.jexl3.internal.introspection.PropertyGetExecutor.discoverGet(PropertyGetExecutor.java:107) at org.apache.commons.jexl3.internal.introspection.PropertyGetExecutor.discover(PropertyGetExecutor.java:42) at org.apache.commons.jexl3.internal.introspection.Uberspect.getPropertyGet(Uberspect.java:263) at org.apache.commons.jexl3.internal.InterpreterBase.getAttribute(InterpreterBase.java:971) at org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1108) at org.apache.commons.jexl3.parser.ASTIdentifierAccess.jjtAccept(ASTIdentifierAccess.java:104) at org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1156) at org.apache.commons.jexl3.parser.ASTReference.jjtAccept(ASTReference.java:19) at org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1029) at org.apache.commons.jexl3.parser.ASTJexlScript.jjtAccept(ASTJexlScript.java:58) at org.apache.commons.jexl3.internal.Interpreter.interpret(Interpreter.java:193) at org.apache.commons.jexl3.internal.Script.execute(Script.java:188) at org.apache.commons.jexl3.internal.Script.evaluate(Script.java:180) ... 72 more {noformat} Here's the line in question inside {{ClassMap.populateWithClass(final ClassMap cache, final Permissions permissions, final Class<?> clazz, final Log log)}}: {code:java} if (pmi != null && pmi != CACHE_MISS && log.isDebugEnabled() && !key.equals(new MethodKey(pmi))) { {code} For some reason your internal {{ClassMap}} class is being passed a {{Log}} that is {{null}}. Looking up the stack trace, it would appear this is coming from your {{Introspector}}. (There is a similar [error on Stack Overflow|https://stackoverflow.com/q/64927054] with no answers; I don't know if they are using JAXL.) * First, passing the {{Log}} around as a parameter is an antipattern. Logging is a cross-cutting concern; passing it around as a parameter is a bad idea. * I wish you were using {{SLF4J}} like practically everyone else instead of {{org.apache.commons.logging}}. * You shouldn't catch {{NullPointerException}} and turn it into a "normal" error condition, trying to say that a variable wasn't defined when really this was an internal error with the library. In any case, for some reason JEXL 3.2.1 isn't initializing its internal logging support. To reproduce this: # Clone [Guise Mummy 0.5.3|https://github.com/globalmentor/guise-mummy/releases/tag/v0.5.3]. # In the overall project {{pom.xml}}, change the version of {{org.apache.commons:commons-jexl3}} from {{<version>3.1</version>}} to {{<version>3.2.1</version>}}. # Run {{mvn clean verify}}. > v3.2.1 breaks with logger-related NullPointerException > ------------------------------------------------------ > > Key: JEXL-387 > URL: https://issues.apache.org/jira/browse/JEXL-387 > Project: Commons JEXL > Issue Type: Bug > Environment: Java 17; Windows 10 > Reporter: Garret Wilson > Priority: Major > > In my [Guise Mummy|https://github.com/globalmentor/guise-mummy] static site > generator I'm using JEXL to interpret the built-in [Mesh Expression > Language|https://github.com/globalmentor/guise-mummy/tree/main/mesh] (MEXL). > Everything was working fine with JEXL 3.1. In fact the entire [Guise Mummy > web site|https://guise.io/mummy/] itself was produced using Guise Mummy with > MEXL on top of JEXL. > But when I upgrade to JEXL 3.2.1, the unit tests break. The MEX+JEXL error > message says "Error in MEXL expression `foo.bar`: > io.guise.mesh.JexlMexlEvaluator.evaluate:93 undefined property 'bar'", but if > you look in the stack trace, you'll see that the problem seems to be a deeper > {{NullPointerException}} which {{InterpreterBase.getAttribute(…)}} catches > and effectively ignores, making it look like the problem was a missing > variable. > {code:java} > } catch (final Exception xany) { > xcause = xany; > } > {code} > Here's the real problem: > {noformat} > Caused by: java.lang.NullPointerException: Cannot invoke > "org.apache.commons.logging.Log.isDebugEnabled()" because "log" is null > at > org.apache.commons.jexl3.internal.introspection.ClassMap.populateWithClass(ClassMap.java:296) > at > org.apache.commons.jexl3.internal.introspection.ClassMap.populateWithInterface(ClassMap.java:270) > at > org.apache.commons.jexl3.internal.introspection.ClassMap.create(ClassMap.java:229) > at > org.apache.commons.jexl3.internal.introspection.ClassMap.<init>(ClassMap.java:100) > at > org.apache.commons.jexl3.internal.introspection.Introspector.getMap(Introspector.java:315) > at > org.apache.commons.jexl3.internal.introspection.Introspector.getMethod(Introspector.java:146) > at > org.apache.commons.jexl3.internal.introspection.Introspector.getMethod(Introspector.java:133) > at > org.apache.commons.jexl3.internal.introspection.PropertyGetExecutor.discoverGet(PropertyGetExecutor.java:107) > at > org.apache.commons.jexl3.internal.introspection.PropertyGetExecutor.discover(PropertyGetExecutor.java:42) > at > org.apache.commons.jexl3.internal.introspection.Uberspect.getPropertyGet(Uberspect.java:263) > at > org.apache.commons.jexl3.internal.InterpreterBase.getAttribute(InterpreterBase.java:971) > at > org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1108) > at > org.apache.commons.jexl3.parser.ASTIdentifierAccess.jjtAccept(ASTIdentifierAccess.java:104) > at > org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1156) > at > org.apache.commons.jexl3.parser.ASTReference.jjtAccept(ASTReference.java:19) > at > org.apache.commons.jexl3.internal.Interpreter.visit(Interpreter.java:1029) > at > org.apache.commons.jexl3.parser.ASTJexlScript.jjtAccept(ASTJexlScript.java:58) > at > org.apache.commons.jexl3.internal.Interpreter.interpret(Interpreter.java:193) > at org.apache.commons.jexl3.internal.Script.execute(Script.java:188) > at org.apache.commons.jexl3.internal.Script.evaluate(Script.java:180) > ... 72 more > {noformat} > Here's the line in question inside {{ClassMap.populateWithClass(ClassMap > cache, Permissions permissions, Class<?> clazz, Log log)}}: > {code:java} > if (pmi != null && pmi != CACHE_MISS && log.isDebugEnabled() && > !key.equals(new MethodKey(pmi))) { > {code} > For some reason your internal {{ClassMap}} class is being passed a {{Log}} > that is {{null}}. Looking up the stack trace, it would appear this is coming > from your {{Introspector}}. (There is a similar [error on Stack > Overflow|https://stackoverflow.com/q/64927054] with no answers; I don't know > if they are using JAXL.) > * First, passing the {{Log}} around as a parameter is an antipattern. Logging > is a cross-cutting concern; passing it around as a parameter is a bad idea. > * I wish you were using {{SLF4J}} like practically everyone else instead of > {{org.apache.commons.logging}}. > * You shouldn't catch {{NullPointerException}} and turn it into a "normal" > error condition, trying to say that a variable wasn't defined when really > this was an internal error with the library. > In any case, for some reason JEXL 3.2.1 isn't initializing its internal > logging support. > To reproduce this: > # Clone [Guise Mummy > 0.5.3|https://github.com/globalmentor/guise-mummy/releases/tag/v0.5.3]. > # In the overall project {{pom.xml}}, change the version of > {{org.apache.commons:commons-jexl3}} from {{<version>3.1</version>}} to > {{<version>3.2.1</version>}}. > # Run {{mvn clean verify}}. -- This message was sent by Atlassian Jira (v8.20.10#820010)