jhericks
jhericks

Reputation: 5971

How am I misusing generics with commons beanutils?

I have two simple interfaces:

public interface HasId<ID extends Serializable> extends Serializable {
  T getId();
}

And

public interface HasLongId extends HasId<Long> {
  void setId(Long id);
}

Now, if I have a class:

public class Person implements HasLongId {
  private Long id;
  private String name;

  public Long getId() {
      return this.id;
  }

  public void setId(Long id) {
      this.id = id;
  }

  public String getName() {
      return this.name;
  }

  public void setName(String name) {
      this.name = name;
  }
}

And I instantiate a person, then pass it to BeanUtils I get strange behavior. For example sometimes setting id using BeanUtils works fine and other times, I get an exception because it can't find the "write" method for Id. It seems that during reflection it finds a getter for a Serializable, but not a Long and it does not find a setter for the Serializable. It does not do this consistently, so I suspect that calling person.getClass().getDeclaredMethod("id") will not always return the same Method, but I could be wrong about that.

Anyway, this inconsistent behavior is really maddening because, for example, it will work in Eclipse, but not in Maven, or it will work for a long time and then with some unrelated change somewhere else it will stop working.

Clearly I don't understand generics well enough to understand what is happening, but can anyone explain it to me and also explain how to work around it?

Upvotes: 0

Views: 1056

Answers (2)

duffymo
duffymo

Reputation: 308753

I don't care much for this design - I don't like interfaces merely for getters and setters.

I also wouldn't have that interface extend Serializable; single responsibility is the best advice here.

But I would try it like this:

public interface Identifiable<T extends Serializable> {
    T getId();
    void setId(T newId);
}

public class Person implements Identifiable<Long> {
    private Long id;
    public Long getId() { return this.id; }
    public void setId(Long id) { this.id = id; }        
}

Upvotes: 0

Amir Pashazadeh
Amir Pashazadeh

Reputation: 7302

The version of Apache Commons BeanUtils I have used was not Java 5 aware, so it didn't know about Generics, bridge methods, and so on. I believe that's the problem, which version of BeanUtils are you using? and is it Java 5+ aware?

Upvotes: 2

Related Questions