General


In most Java projects you have a lot of classes written only for the purpose of holding some data.

If you need a bean class which can hold an int, a String and an instance of Foo you have to implement the following class:

public class BadExample {

    private int intValue;
    private String stringValue;
    private Foo foo;

    public Foo getFoo() {
        return this.foo;
    }

    public void setFoo(Foo foo) {
        this.foo = foo;
    }

    public int getIntValue() {
        return this.intValue;
    }

    public void setIntValue(int intValue) {
        this.intValue = intValue;
    }

    public String getStringValue() {
        return this.stringValue;
    }

    public void setStringValue(String stringValue) {
        this.stringValue = stringValue;
    }

}


Of course you could use a Map/HashMap to hold the data but you would lose type-safety (and running into the problems of synchronisation of the map): Why not let Java do this boring job? Use Java Bean Proxy!

You only have to define the interface:

public interface NiceExample {

    Foo getFoo();

    void setFoo(Foo foo);

    int getIntValue();

    void setIntValue(int intValue);

    String getStringValue();

    void setStringValue(String stringValue);

}



The rest is done by Java Bean Proxy. To get an instance use BeanProxyBuilder:

    NiceExample niceExample = BeanProxyBuilder.on(NiceExample.class).build();
    niceExample.setIntValue(44);
    System.out.println(niceExample.getIntValue()); // Will of course result in "44"


BeanProxyBuilder will return a dynamic (runtime) instance for NiceExample.class which implements hashcode, equals and toString correctly Additionally this runtime instance is clone- and serializable.

Initialzation

If you'd like to initialize your beans (by default all object values are null and primitives 0/false) you can annotate them using @Initializer and set the attribute to the class that should be initialize the bean: @Initializer(NiceExampleInitializer.class). The referenced class has to implement exactly one public static method that accepts instances of the bean class (NiceExample), e.g.
    public static void initialize(NiceExample bean) {
        bean.setStringValue(""); // return empty strings instead of null
    }


The proposed way to use this is creating an inner class:

    @Initializer(Foo.Init.class)
    public static interface Foo {
        static class Init {
            public static void initialize(Foo foo) {
                foo.setBar("");
            }
        }

    [...]

    }


PropertyChangeSupport


If you need PropertyChangeSupport (or even VetoableChangeSupport) all you have to do is let your interfaces extend DefaultPropertyChangeEventProvider (and/or DefaultVetoablePropertyChangeEventProvider if you like to support vetos)


public interface NiceExample extends DefaultPropertyChangeEventProvider {

    [...]snipped[...]

}

DefaultPropertyChangeEventProvider declares two methods: 
so everyone having a reference to NiceExample can register/deregister listeners using these two methods.

If you come with your own interface declaring add and remove methods you can still use them, simply annotate them with @PropertyChangeEventLinker, if your add/remove have other names than add* and remove* you can use PropertyChangeEventLinker's attributes: @PropertyChangeEventLinker(addMethod = "nameOfAddMethod", removeMethod = "nameOfRemoveMethod")


If modifications of several attributes should not fire PropertyChangeEvents you can do this annotating the attributes with these annotations:


http://sourceforge.net/projects/beanproxy/

Have a lot of fun!