3

I have an input (JSF) that should be bound to a property in my bean. This property represents another bean and has an auxiliar method that checks if it's null (I use this method a lot).

The problem is that the binding is failing to get the proper getter and setter. Instead of reading the method that returns the bean, it reads the one that return a boolean value.

The property name is guest. The methods are:

  • getGuest;
  • setGuest;
  • isGuest (checks if guest is null).

JSF is trying to bind the object to isGuest and setGuest, instead of getGuest and setGuest.

I cannot rename isGuest to guestIsNull or something, because that would'nt make to much sense (see the class below).

Finally, my question is: how can I bind this property to the object without renaming my methods? Is it possible?

I also accept suggestions of a better method name (but the meaning must be the same).


Entity

@Entity
public class Passenger {

    private Employee employee;
    private Guest guest;

    public Passenger() {
    }

    @Transient
    public boolean isEmployee() {
        return null != this.employee;
    }

    @Transient
    public boolean isGuest() {
        return null != this.guest;
    }

    @OneToOne
    public Employee getEmployee() {
        return this.employee;
    }

    public void setEmployee(Employee employee) {
        this.employee = employee;
    }

    @OneToOne
    public Guest getGuest() {
        return this.guest;
    }

    public void setGuest(Guest guest) {
        this.guest = guest;
    }

}

JSF

<h:inputText value="#{passenger.employee}" />
<h:inputText value="#{passenger.guest}" />
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555

3 Answers3

4

Change the method name to isGuestNull.

The problem you're seeing is due to the fact that the EL lets you use getFoo or isFoo as the naming style for getter methods that return booleans.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • It's by the way not specifically JSF which does that, but EL. – BalusC Feb 14 '11 at 18:38
  • Renaming the method does work, but it changes the meaning of it. _hasGuest_ also changes the meaning, but it's a little more usual. Well, one thing is for sure: renaming the method is the way. Thanks. – William Brombal Chinelato Feb 14 '11 at 23:07
2

No, that's not possible. You've to rename them.

Another way is to add a single getter returning an enum which covers all cases.

public enum Type {
    GUEST, EMPLOYEE;
}

public Type getType() {
    return guest != null ? Type.GUEST
         : employee != null ? Type.EMPLOYEE
         : null;
}

with

<h:something rendered="#{passenger.type == 'GUEST'}">
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Yes, renaming is the only way. The enum on the other hand is not a good option for me, because _isGuest_ is intended to hide the implementation (_if null_). The enum will force every user to check the type manually. – William Brombal Chinelato Feb 14 '11 at 23:09
  • Enums allows for more fine-grained control. But if you don't need this, then just rename, yes :) – BalusC Feb 14 '11 at 23:20
1

Binding to any property using any method is possible and quite easy if you create your custom ELResolver (apidocs). elresolvers are registered in faces config, and they are responsible, given an Object and a String defining a property, for determining the value and type of the given properties (and, as the need arises, to change it).

You could easily write your own ELResolver that would only work for your chosen, single type, and use (for example in a switch statement) the specific methods you need to write and read properties. And for other types it would delegate resolving up the resolver chain. It's really easy to do, much easier than it sounds.

But don't do it. The standard naming pattern of properties predates EL by many years. It is part of the JavaBeans™ standard - one of the very few undisputed standards in Javaland, working everywhere - from ant scripts, through spring configuration files to JSF. Seeing methods isPerson and getPerson in one class actually makes me fill uneasy, as it breaks something I always take for granted and can always count on.

If you like DDD and want to have your method's names pure, use an adapter. It's easy, fun, and gives a couple of additional lines, which is not something to sneer at if you get paid for the ammount of code produced:

public class MyNotReallyBean {

  public String checkName() { ... }
  public String lookUpLastName() { ... }
  public String carefullyAskAboutAge() { ... }

  public class BeanAdapter {
     public String getName() { return checkName(); }
     public String getLastName() { return lookUpLastName(); }
     public String getAge() { return carefullyAskAboutAge(); }
  }
  private static BeanAdapter beanAdapter = new BeanAdapter();

  private BeanAdapter getBeanAdapter(){ return beanAdapter; }

}
fdreger
  • 12,264
  • 1
  • 36
  • 42