[Mondrian] Failed to load user-defined function ... does not implement the required interface 'mondrian.spi.UserDefinedFunction'

Franco Graziosi fg123 at fga-software.com
Mon Jul 20 04:56:01 EDT 2009


Hello,

H have created a simple user defined function to simplify zero-divide
prevention instead of using each time an iif wrapper. The function takes
two arguments and if the second - denominator - is zero or null
it returns null.  That function alone works fine. I created a variant
called "increase" that computes an increase instead of ratio and,
following Mondrian documentation, I tried to put both function in same
class varying the defined name. (I actually did the reverse and not working
went back to define a single function and discovered the cause of the 
problem).

Here is the class that implement both functions:

        package net.cbsolution.ps.pisa.fns;

        import mondrian.olap.Evaluator;
        import mondrian.olap.Syntax;
        import mondrian.olap.type.NumericType;
        import mondrian.olap.type.Type;
        import mondrian.spi.UserDefinedFunction;

        public class Ratio implements UserDefinedFunction {
          private boolean isIncrease;
         
          public Ratio(String name) {
            if ("Ratio".equals(name))
              isIncrease = false;
            else if ("Increase".equals(name))
              isIncrease = true;
          }

          @Override
          public Object execute(Evaluator evaluator, Argument[] arguments) {
            final Object arg0 = arguments[0].evaluateScalar(evaluator);
            final Object arg1 = arguments[1].evaluateScalar(evaluator);
            if (arg0 == null || arg1 == null || (!(arg0 instanceof
        Number))  || (!(arg1 instanceof Number)))
              return null;
            double denom = ((Number)arg1).doubleValue();
            if (denom == 0)
              return null;
            double result = ((Number)arg0).doubleValue() / denom;
            if (isIncrease)
              result -= 1.0;
            return result;
          }

          @Override
          public String getDescription() {
            return "Return a ratio between two numbers, prevent zero
        divide and null values returning null in such cases";
          }

          @Override
          public String getName() {
            if (isIncrease)
              return "Increase";
            else
              return "Ratio";
          }

          @Override
          public Type[] getParameterTypes() {
            return new Type[] { new NumericType(), new NumericType() };
          }

          @Override
          public String[] getReservedWords() {
            return null;
          }

          @Override
          public Type getReturnType(Type[] parameterTypes) {
            return new NumericType();
          }

          @Override
          public Syntax getSyntax() {
            return Syntax.Function;
          }

        }


And here is the schema code:

    <UserDefinedFunction name="Ratio" 
class="net.cbsolution.ps.pisa.fns.Ratio" />
    <UserDefinedFunction name="Increase" 
class="net.cbsolution.ps.pisa.fns.Ratio" />

I get the following exception:

    Mondrian Error:Failed to load user-defined function '': class 
'net.cbsolution.ps.pisa.fns.Ratio' does not implement the required 
interface 'mondrian.spi.UserDefinedFunction'

Looking at stack trace I went to the problem (mondrian.olap.Util : 2280):

       try {
            udf = (UserDefinedFunction) udfClass.newInstance();
        } catch (InstantiationException e) {
            throw MondrianResource.instance().UdfClassWrongIface.ex("",
                    className, UserDefinedFunction.class.getName());
        } catch (IllegalAccessException e) {
            throw MondrianResource.instance().UdfClassWrongIface.ex("",
                    className, UserDefinedFunction.class.getName());

Mondrian code tries to instantiate with a zero-argument constructor that 
obviously do
not exists. (Note: if I define a zero argument constructor the function 
is instantiated but
I get a duplicate Ratio and no Increase).

Are multiple-name functions really supported?

fg





More information about the Mondrian mailing list