Skip to content

Custom function pipe error #83

Open

Description

@sergeevik

test in jsonata

describe("custom function pipe", () => {
    // Platform specific
    describe("$add(1,2) ~> $add(?, 3)", function() {
        it("should return 6", async function() {
            function add(a, b) {
                return a + b;
            }

            var expr = jsonata("$add(1,2) ~> $add(?, 3)");
            expr.registerFunction("add", add);
            var result = await expr.evaluate();
            var expected = 6;
            expect(result).to.be.equal(expected);
        });
    });
});

success resturn 6

test in jsonata java

  @Test
  public void testCustomFunctionPipe() {
    var expression = Jsonata.jsonata("$add(1, 2) ~> $add(?, 3)");
    expression.registerFunction("add", new JFunction(new JFunctionCallable() {
      @SuppressWarnings("rawtypes")
      @Override
      public Object call(Object input, List args) throws Throwable {
        return (Integer) args.get(0) + (Integer) args.get(1);
      }
    }, null));
    Assertions.assertEquals(6, expression.evaluate(null));
  }

thrown Exception

Proc not found null

com.dashjoin.jsonata.JException: Attempted to invoke a non-function
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata.applyInner(Jsonata.java:1782)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata.apply(Jsonata.java:1705)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata.evaluateApplyExpression(Jsonata.java:1547)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata._evaluate(Jsonata.java:203)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata.evaluate(Jsonata.java:131)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata.evaluate(Jsonata.java:2607)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.Jsonata.evaluate(Jsonata.java:2568)
	at com.dashjoin.jsonata@0.9.9-local4/com.dashjoin.jsonata.CustomFunctionTest.testCustomFunctionPipe(CustomFunctionTest.java:65)

I need to use this call chain for another custom method. I used a simple "add" as an example.
In my case I can't use Fn2 because I need "input" data, but all Fn* interfaces pass only arguments.

Activity

  1. sergeevik commented on Jan 25, 2026

    @sergeevik
    ContributorAuthor

    Some searching didn't lead to a solution but did reveal one "bug" that may not have been discovered yet.

    Functions.java (2144 row)

        public static Method getFunction(Class clz, String name) {
            Method[] methods = Functions.class.getMethods();
            for (Method m : methods) {
                // if (m.getModifiers() == (Modifier.STATIC | Modifier.PUBLIC) ) {
                //     System.out.println(m.getName());
                //     System.out.println(m.getParameterTypes());
                // }
                if (m.getName().equals(name)) {
                    return m;
                }
            }
            return null;
        }
    

    clz args ignored.

    row Method[] methods = Functions.class.getMethods(); must be replace to Method[] methods = clz.getMethods();

  2. sergeevik commented on Jan 25, 2026

    @sergeevik
    ContributorAuthor

    fix 2 bug #85

    1. JFunction without name throw Excception
    2. Without exist method impl (if set JFunctionCallable) processing no have info about number of args, provided the opportunity to indicate this

    add three tests with new behavior

  3. aeberhart commented on Jan 27, 2026

    @aeberhart
    Contributor

    Thanks for reporting this issue @sergeevik. Seems to be caused by combining a custom function with partial function application.

    With respect to your PRs. You're right that the clz parameter in com.dashjoin.jsonata.Functions.getFunction(Class, String) is ignored. When I run the test suite, clz is Function.class in 100% of the calls.

    JFunction.getNumberOfArgs is only called from partialApplyNativeFunction. Rather than explicitly passing the number in the constructor, we should probably compute it from the definition (e.g. $sum(?,3)) which would be method.getNumberOfAgrs() - 1. The default 0 (if method == null) is probably wrong.

    Do you have a test case where this causes an issue?

  4. sergeevik commented on Jan 27, 2026

    @sergeevik
    ContributorAuthor

    @aeberhart
    example in first post

    first problem was lost procedure by name and i catche exception com.dashjoin.jsonata.JException: Attempted to invoke a non-function

    then i fix it by provide function name in JFunction constructor, and it's work. my function (even it is anonymus function) called.

    second problem was args, becase i create JFunction with JFunctionCallable, attribute 'method' was null and getNumberOfArgs return 0, and my function recieve empty list of args.
    I fix it - add in constructor param numberOfArgs.

    about

    Rather than explicitly passing the number in the constructor, we should probably compute it from the definition (e.g. $sum(?,3))

    partialApplyNativeFunction create function wrapper by _native.functionName (which was null before first fix) and getNumberOfArgs (which return 0 before second fix).
    Not understand how compute it from the definition if definition creates from this two params (name and number of args)

  5. sergeevik commented on Jan 27, 2026

    @sergeevik
    ContributorAuthor

    about

    With respect to your PRs. You're right that the clz parameter in com.dashjoin.jsonata.Functions.getFunction(Class, String) is ignored. When I run the test suite, clz is Function.class in 100% of the calls.

    in test yes it's work. But if need add custom function, no way to provide info, becouse the function is searched in Functions.class and not in my class

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions