Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not possible to transform String to enumeration value in special case #90

Open
josemgimenez opened this issue Mar 1, 2016 · 5 comments
Labels

Comments

@josemgimenez
Copy link

This small class reproduces an issue we had with JUEL and OpenJDK 1.7. The interesting thing of this case is that RALPH is internally a subclass of Actor, so it is not an enum and it is not possible to transform into a member of the enumeration and according to the EL specification it should work.

package com.juel;

import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.TreeValueExpression;
import de.odysseus.el.util.SimpleContext;

public class App
{
    public static enum Actor
    {
        HOMER, BART, RALPH
        {
            @Override
            public String greeting()
            {
                return "I'm special";
            }
        };

        public String greeting()
        {
            return "Hi, I'm " + name();
        }
    }

    public static void main(String[] args) throws Exception
    {
        ExpressionFactoryImpl expressionFactory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        context.setVariable("actor", expressionFactory.createValueExpression(Actor.HOMER, Actor.class));
        context.setVariable("actor2", expressionFactory.createValueExpression(Actor.RALPH, Actor.class));

        TreeValueExpression e = expressionFactory.createValueExpression(context, "${actor == 'HOMER'}", boolean.class);
        System.out.println(e.getValue(context));

        TreeValueExpression e2 = expressionFactory.createValueExpression(context, "${actor2 == 'HOMER'}", boolean.class);
        System.out.println(e2.getValue(context)); // kaboom!
    }
}

Output:

true
Exception in thread "main" javax.el.ELException: Cannot coerce 'HOMER' of class java.lang.String to class com.juel.App$Actor$1 (incompatible type)
    at de.odysseus.el.misc.TypeConverterImpl.coerceStringToType(TypeConverterImpl.java:287)
    at de.odysseus.el.misc.TypeConverterImpl.coerceToType(TypeConverterImpl.java:348)
    at de.odysseus.el.misc.TypeConverterImpl.convert(TypeConverterImpl.java:365)
    at de.odysseus.el.tree.Bindings.convert(Bindings.java:138)
    at de.odysseus.el.misc.BooleanOperations.eq(BooleanOperations.java:161)
    at de.odysseus.el.tree.impl.ast.AstBinary$4.apply(AstBinary.java:52)
    at de.odysseus.el.tree.impl.ast.AstBinary$SimpleOperator.eval(AstBinary.java:31)
    at de.odysseus.el.tree.impl.ast.AstBinary.eval(AstBinary.java:110)
    at de.odysseus.el.tree.impl.ast.AstEval.eval(AstEval.java:51)
    at de.odysseus.el.tree.impl.ast.AstNode.getValue(AstNode.java:31)
    at de.odysseus.el.TreeValueExpression.getValue(TreeValueExpression.java:122)
    at com.juel.App.main(App.java:37)
@beckchr
Copy link
Owner

beckchr commented Mar 1, 2016

Hi!

RALPH is an enum. Please use something like ${actor2.toString() == 'HOMER'}.

@josemgimenez
Copy link
Author

Hi,
Thanks for the response. Our current workaround is using the enum's method ".name()" to get its name.

The question is whether it should work correctly or not, as it's quite a big corner case and I couldn't find anybody with the same issue.

Also, when I mean that it is not an enum I mean that if you run System.out.println(Actor.RALPH.getClass().isEnum());
you get false on OpenJDK 1.7

@beckchr beckchr added the bug label Mar 1, 2016
@beckchr
Copy link
Owner

beckchr commented Mar 1, 2016

Using name() is better than toString() of course. Whether it should work is a good question. And to be honest, it probably should...

@lzg14
Copy link

lzg14 commented Apr 25, 2018

In the "context", we know the "actor2" is a "com.juel.App$Actor", but when evaluate "${actor2 == 'HOMER'}", the eq function treat "actor2" as a Object, o1.getClass will get "com.juel.App$Actor$1". There is no way JUEL know how to convert 'HOMER' to a "com.juel.App$Actor$1". So special RALPH is indeed different from HOMER and BART. And I don't think this is a bug.
see BooleanOperations.java 136~170

@sfuhrm
Copy link

sfuhrm commented May 12, 2023

Implemented spec of JUEL is JSP 2.2 == EL 2.1:

Chapter 1.8.2 2 says:

1.8.2 A {==,!=,eq,ne} B
...
■ If A or B is an enum, coerce both A and B to enum, apply operatorr
...

Next spec EL 3.0:

The JSR-000341 Expression Language 3.0 Final Release specification from 2013 1 states in chapter 1.9.2:

1.9.2 A {==,!=,eq,ne} B
...

  • If A or B is an enum, coerce both A and B to enum, apply operator
    ....

From my understanding this officially means since JUEL wants to implement EL2.1, it is a bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants