31

I upgraded my Java EE web application to use newer PrimeFaces version and suddenly the call of an overloaded bean method in an action attribute of PrimeFaces commandlink did not work anymore. I tried to use JSF default commandlink to test it and this one did not work either.

The method signatures are as follows:

public void updateA(B b);
public void updateA(A a);

It always tried to cast A to B.

More curious, how could it work before the upgrade?

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
djmj
  • 5,579
  • 5
  • 54
  • 92

2 Answers2

41

EL does not support it, no. It'll always be the first method of the Class#getMethods() array whose name (and amount of arguments) matches the EL method call. Whether it returns the same method everytime or not depends on the JVM make/version used. Perhaps you made a Java SE upgrade in the meanwhile as well. The javadoc even says this:

The elements in the array returned are not sorted and are not in any particular order.

You should not rely on unspecified behaviour. Give them a different name.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 1
    Is there any (technical) reason why this is not supported in JSF 2 any more? I'm pretty sure that this was possible in JSF 1.x versions, wasn't it? – MrD Mar 06 '14 at 14:53
  • This is not JSF specific. – BalusC Mar 06 '14 at 15:11
  • I had an equal problem, but in my case not always the first one was used. It seems to be quite randomly chosen. – Alex VII Aug 04 '14 at 12:36
  • 2
    @alexvii: as answered, the `getMethods()` doesn't necessarily return a fixed order. – BalusC Aug 04 '14 at 15:00
  • 6
    The fact that the searching for the most accurate overloaded method does not work with EL, sucks. – Jagger Mar 05 '15 at 09:44
4

The way you can get around this is to create a generic method and do the 'routing' inside that method. I know that this might not be ideal, but you end up with less configurations in functions and XHTML pages.

if (A.class.isInstance(obj)) {
    A o = (A) obj;
    return method(o, highRes);
} else if (B.class.isInstance(obj)) {
    B o = (B) obj;
    return method(o, highRes);
} else if (C.class.isInstance(obj)) {
    C o = (C) obj;
    return method(o, highRes);
} else {
    throw new FacesException("Unsupported Conversion: " + obj);
}
Tiny
  • 27,221
  • 105
  • 339
  • 599
Ioannis Deligiannis
  • 2,679
  • 5
  • 25
  • 48
  • 2
    Not ideal at all, in fact, it's a terrible suggestion. Besides some very specific cases (such as the implementation of the equals() method), you should never use this type of comparisons. Quoting Scott Meyers, from Effective C++: 'Anytime you find yourself writing code of the form "if the object is of type T1, then do something, but if it's of type T2, then do something else," slap yourself'. – jpangamarca Oct 01 '18 at 13:22