Skip to content

ognl 3.4.8 - root properties not accessible from lambda #472

@FHannes

Description

@FHannes

@lukaszlenart Thank you for providing a patch for #390 in the 3.4.8 release. I have tested the new release, but unfortunately the issue I encountered still persists. I may have misdiagnosed it when I created my original post. Meanwhile some time has freed up so I was able to create a minimal example, that might provide more insight into the issue.

The following sample provides an exists() method on java.util.List, that takes a lambda expression. I've defined a property test that contains a value, which I want to check if it is present in the list. That property is defined in the root. Up to OGNL version 3.4.4 this returns true as expected. From 3.4.5 onward, it throws an exception ognl.NoSuchPropertyException: java.lang.String.test, which seems to be because it tries to evaluate test as a property of the list item. So #this == #root in that case, instead of the map that was set as root for the context.

package com.example;

import ognl.*;

import java.util.List;
import java.util.Map;

public class OgnlSample {

  public static void main(String[] args) throws OgnlException {
    OgnlRuntime.setMethodAccessor(List.class, new ObjectMethodAccessor() {
      @Override
      public Object callMethod(OgnlContext context, Object target, String methodName, Object[] args) throws MethodFailedException {
        List<?> list = (List<?>) target;
        if (methodName.equals("exists")) {
          return exists(context, list, args);
        }
        return super.callMethod(context, target, methodName, args);
      }

      private static Object exists(OgnlContext context, List<?> list, Object[] args) {
        return list.stream()
            .anyMatch(item -> {
              try {
                Object value = Ognl.getValue(args[0], context, item);
                if (!(value instanceof Boolean)) {
                  throw new RuntimeException("Lambda did not return boolean, returned '" + value + "' instead");
                }
                return (Boolean) value;
              } catch (OgnlException e) {
                throw new RuntimeException(e);
              }
            });
      }
    });

    OgnlContext defaultContext = Ognl.createDefaultContext(Map.of(), null, null);
    defaultContext.setRoot(Map.of(
        "test", "value"
    ));
    Object value = Ognl.getValue("myList.exists(:[ #this.equals(test) ])", defaultContext, Map.of(
        "myList", List.of("value")
    ));
    System.out.println(value);
  }

}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions