The Source for Java Technology Collaboration
User: Password:



Rémi Forax

Rémi Forax's Blog

Mixing property language support and bean bindings

Posted by forax on September 24, 2007 at 03:14 PM | Comments (21)

Recently, Shannon posts version 1.0 of beanbindings, even if this version is not ready for production use, it is stable enough to create a small demo mixing property language support and beanbindings.

The idea is to create a bean (here MyBean) with a bound property (label) and to bind this property to two different textfields.

properties-meet-bindings.png

Defining a bean

Because i use the property support directly integrated in the language, defining such bean is easy. AbstractBean provides the basic support for managing property change listeners.

 public static class MyBean extends AbstractBean {
    property String label bound;
    
    private <B,T> void propertyChanged(java.lang.Property<B,T> property,Object oldValue,Object newValue) {
      firePropertyChange(property,oldValue,newValue);
    }
    
    @Override
    public String toString() {
      return "label "+label;
    }
  }

Wrap the property to someting understandable

By default bean bindings only supports two kinds of property bean property that uses bean introspector and EL property that uses EL script but the framework is easily extensible and let you create your own property implementation.

So i've created a new kind of property (here LangProperty) that exposes a java.lang.Property as a property understandable by the bindings framework.

And mix

And now mixing the language support and the API together is as simple as that:

    LangProperty<MyBean,String> labelProperty =
        LangProperty.create(MyBean#label);
    
    JLabel label = new JLabel("Label:");
    JTextField field = new JTextField(20);
    Bindings.createAutoBinding(READ_WRITE, 
        bean, labelProperty,
        field, BeanProperty.create("text")).bind();
    
    JLabel anotherLabel = new JLabel("Another label:");
    JTextField anotherField = new JTextField(20);
    Bindings.createAutoBinding(READ_WRITE, 
        bean, labelProperty,
        anotherField, BeanProperty.create("text")).bind();

The notation sharp ('#') is used to get an objet typed java.lang.Property that allow to get and set the value of the property.

Want to test it

You want to test it by yourself, ok, here a zip containing the code, the beanbindings jar and the javac.jar patched to understand properties.
Download properties-meets-bindings.zip

Use this line to compile

 java -Xbootclasspath/p:javac.jar com.sun.tools.javac.Main -XDallowProperty -cp beansbinding-1.0.jar *.java

And this one to execute

 java -Xbootclasspath/p:javac.jar -cp .:beansbinding-1.0.jar Sample

You must include javac.jar at runtime only because it contains the class java.lang.Property and i am too lazy to create two jars.

WARNING, i have re-written the bound property support in the patched compiler last night so i think it will not work on another example :)

Cheers,
Rémi


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • this is great, there was a group of people on the binding spec (including myself) which asked, "what happens if we introduce properties in Java SE 7?" It's good to see Shannon's re-work accommodating this solution. Ideally, I would've liked to see the onus of bindings being intrinsic to the UI components, but that's a bit of a change beyond the scope of the JSR.

    Posted by: jhook on September 24, 2007 at 08:28 PM


  • Hi jacob, one requirement of the property spec is to be able to
    retrofit awt/swing components to use property.
    If this work is done and if some helper methods are added
    to Component. We end with a more concice syntax
    which i think cover 80% of the use cases:


    MyBean bean=...
    JTextField field = new JTextField(20);
    field.createAutoBinding(JTextComponent#text,
    bean,MyBean#label).bind();


    Rémi

    Posted by: forax on September 25, 2007 at 12:54 AM


  • Remi,
    I don't mean any offense and I'm trying to ask an honest question because I'm just stumped by this post (and other discussions on the subject).
    I mean no disrespect, but I can't see a single advantage of this approach over existing approaches and I can see quite a few disadvantage in overhead (memory/speed), type safety/compiler checks etc... This approach is neither compatible with existing beans nor is it short in syntax (it even has arguably more cumbersome syntax) than the bean-properties equivalent which works now on Java 5....
    I'm not trying to be a jerk here but can you please highlight a single advantage besides the fact that this is on its way to becoming a JSR?

    Posted by: vprise on September 25, 2007 at 02:02 AM


  • Overheads ??

    If you use bean approach, you use an introspector with a
    cache that relies on reflection that in order to be effective
    generates at runtime a specific byte-code.
    I use the compiler to generate that specifc byte-code.
    So there is no memory overhead, perhaps just a small
    one because the generated byte-code is a bit larger
    About the speed, comparing to reflection, i create less object
    have neither security checks nor boxing, array wrapping, etc.
    there is a clear gain here.


    syntax is shorter and above all more readable
    that the current way to create a property:


    public static class MyBean extends AbstractBean {
    private String label;
    public String getLabel() {
    return label;
    }
    public void setLabel(String newLabel {
    String oldLabel=this.label;
    this.label=newLabel;
    firePropertyChange(property,oldLabel,newLabel);
    }

    @Override
    public String toString() {
    return "label "+label;
    }
    }


    About the fact that property spec to use # (sharp), if you have an idea to
    remove it, i'am open.

    Futhermore, the implementation is fully backward compatible with the
    bean spec. I don't follow you on that point ?

    You can use an introspector on an object that use property.

    Do you have a specific use case ?


    Rémi

    Posted by: forax on September 25, 2007 at 03:35 AM

  • "....property support directly integrated in the language..."

    If you need to subclass AbstractBean, then I would argue property suppert is not in the language, its in the API. Oh well, semantics. ;)

    Anyway, I am torn about the bennefit of BeansBinding. In a recent project I abandoned BeansBinding over old-fashined listeners for a variety of reasons.
    For instance, I had the problem that an event is only fired if the new value is different than the old value. This means, that you can not rely on setXxx methods in the constructor to do initialization unless you know specifically that the field value is different that what you are assigning.

    I'm still rooting for native support of properties and events in Java, it would simplify things so much and make the Java world more consistant.

    Posted by: mrmorris on September 25, 2007 at 04:27 AM

  • The overhead I was talking about is for String lookups for the binding not the "properties" which are POJO's, the current implementation of bean properties uses reflection but can use instrumentation if I wanted to make a language level change (like you did or instrumentation work). The theoretical overhead of bean properties when features such as binding/observability/ORM are involved is considerably lower since you don't need String lookup/hashing and can invoke a method directly. Obviously properties are not very helpful without these features.
    I was comparing the binding related syntax to the bean properties syntax examples of which are plenty in the web site. Furthermore, the current bean properties syntax can be made even more concise using a language change approach.
    About the # syntax, we have our differences but I was referring to this code:

    Bindings.createAutoBinding(READ_WRITE,
    bean, labelProperty,
    field, BeanProperty.create("text")).bind();

    Which essentially means everything needs to degrade to a string eventually for "backwards compatibility" despite not being backwards compatible.
    On backwards compatibility: you can't use this without a special compiler or Java 7, where bean-properties work unmodified in Java 5. Theoretically you would be able to maintain your compiler to perform backports but from experience Java (at least 5) won't allow the source level to be lower than the target argument... This essentially means that the bean won't be backwards compatible reasonably.

    Posted by: vprise on September 25, 2007 at 04:42 AM


  • @mrmorris, AbstractBean is not a part of the property API,
    if you have a bound property the compiler only requires a
    method propertyChanged.


    You are right, there is a problem when you want to initialize
    a property in the constructor.
    The current version of the property spec says that
    if you change the value of a property in the constructor,
    the setter is not called, it's too dangerous because it leads to
    an unsafe publication of a not fully constructed instance.
    But the compiler currently doesn't respect that part
    of the specification :(

    @vprise, ok you don't like the way to create a binding.
    So you hit the wrong guy, you should talk to shannon :)
    I think the syntax to create a binding is not simple
    because the binding framework want
    to support several kind of properties.
    Don't forget that you can specify a property using EL script.

    About compatibility, you have 2 choices:

    use beanbindings and bean property which requires
    1.5 compiler an relies on String
    use beanbindings and compiler property support which
    will require the java version in which such compiler is
    available (for sure not the 1.5 :) )
    that ensure type safety without String/String lookup.

    The code generated by the patched compiler
    will never run on an already existing java platform
    without some option to alterate the bootclass path
    because it required the class java.lang.Property
    to be present at runtime.


    Rémi

    Posted by: forax on September 25, 2007 at 05:41 AM

  • OK, now that we understand each other... Yes, binding is Shannon's responsibility but this post is about that and as I said properties without binding (ORM is also a binding of sort) isn't much.
    So lets go back to my original question: why should someone use this? Are there advantages over bean properties?If not, then why not leverage your skills in compiler customization and leverage bean properties into the syntax modifications (or at least the concepts behind it)?

    Posted by: vprise on September 25, 2007 at 05:54 AM


  • Why should someone use bindings ?

    I think you can take a look to the overview of that tutorial
    http://www.javalobby.org/java/forums/t17672
    or this wiki.

    Bean properties only provide a way to access to any properties
    in a generic way by their name. It doesn't say how to keep
    two properties in sync, convert them, validate them etc.


    Do you suggest to have a syntax to bind properties
    like JavaFX does ?

    Posted by: forax on September 25, 2007 at 07:03 AM

  • Why should someone use objects?
    POJO's do not live in a void they are usually built in order to integrate with something such as a persistence engine a front end UI etc... So sure you can look at your spec as something completely neutral from the actual use case most people will apply... However, I think you will agree with me that these use cases are common and important.
    Assuming these use cases are important we would like them to work as best as possible. No, I'm not suggesting a language change (such as Java FX's approach of language level binding) I am suggesting that you do exactly what you did now which is:
    Apply your properties solution to a common real world use case and then analyze how much your approach improves over this use case.
    That is why the bean-properties project integrates ORM, UI bindings, validation etc... These elements are needed by 90% of the users of beans (otherwise just use a POJO I think there should be a distinction between the two), so we want to show how easy it is to build such infrastructure and how much the use cases are improved.
    Your current properties approach relies too much on legacy concepts which just don't scale well to the more "creative" use cases. Even simple observability becomes far more cumbersome notice that this has nothing to do with your language syntax and everything to do with POJO's were never designed for this!
    POJO JavaBeans were designed as simple drag and drop GUI builder components and the whole paradigm got way out of hand.

    Posted by: vprise on September 25, 2007 at 07:43 AM

  • I miss some simple powerpoint slides which show me "This was hard to do without properties and is so easy with them. Look !".

    For now, all I understand is that you can avoid reflection, hence a new compile check. Ok. But I find it a little short. Add some new fonctionalities like built-in change event listeners and I can understand it.

    I'm sure I'm missing something here.

    Posted by: nopjn on September 25, 2007 at 05:22 PM

  • I fully understand the use of properties. However I am a little sceptical on the design of the language additions. I would think of the properties as a special enumeration of each class.


    E.g.: MyBean.properties.label (where 'properties' is an enum type)

    Posted by: montechristos on September 27, 2007 at 01:05 AM


  • @vprise, use cases are important. The use case number one
    is a very simple one, i want to access/modify a property
    and be able to change its implementation without refactoring
    nor recompilation.

    i don't think observability is simple, there are several
    ways to observe a property depending if you want create
    an event, reuse it,
    send some information or not. That why current property spec let
    the user write its own method firePropertyChanged.

    @nopjn, sorry i haven't this kind of slides yet but you can read my old
    blog entries. i hope it will convince you that properties as language
    feature are really usefull.

    @montechristos, yes properties share some commons with enums
    but enum value are ordered and typed by the enum class,
    properties are not ordered and must surface its type.

    Rémi

    Posted by: forax on September 27, 2007 at 01:35 AM

  • @vprise, nopjn: Just yesterday I had to refactor a central business object of a heavy app (> 100 kloc). I had to find all usages of a certain property. With an IDE at hands, it was easy to check all dependencies and usages of this property within the Java code. But then I had to check all UI bindings, in which the property is encoded as string, and then I had to check all JPA queries containing the property, again as string. Guess what, unfortunately the property was called "name"... I really think we should get rid of strings identifying properties!

    Posted by: scotty69 on September 27, 2007 at 05:17 AM

  • @Remi, I don't understand how the use case of access/modify a property relates to your current properties suggestion?
    Do you mean reference existing get/set combos with the "." or "#" modifier such as bean.property even when the property keyword was not used?
    Observability is trivial once you view properties as objects, once you accept that idea lots of things become much simpler. The ideas of meta-data associated with the property and the fact that a user can customize this meta-data (which is not possible with Class) is a remarkably powerful tool.
    @scotty69, avoiding Strings is the main benefit I list for bean-properties in the faq ;-)
    Refactoring bean-properties is a joy.

    Posted by: vprise on September 27, 2007 at 11:10 AM

  • @Remi, Couldn't the type be a parameter of the enum? Also in case of collections another parameter could specify the type of contained objects? Also, this enum could extend an interface common to all the properties of all the classes. (I have developed such a construct not so long ago).

    Posted by: montechristos on September 27, 2007 at 12:50 PM


  • @vprise, why do you need getter/setter ?

    metadata in Java => Annotation. So java.lang.annotation.ElementType
    should be augmented and java.lang.Property should implement
    java.lang.reflect.AnnotedElement.

    I don't want to embed a code with properties, only metadata
    and because properties are observables, you can retrieve those
    metadata in method propertyChanged.

    @montechristos, no. Example:


    class A {
    property int a;
    property double b;
    }


    A#a is a Property<A,Integer> and
    A#b is a Property<A,Double>.
    There is no way to do that with enum value.

    Posted by: forax on September 28, 2007 at 01:19 AM

  • I would argue that annotations are a meta-data system for compile time, since some meta-data can mutate and some meta-data doesn't fit the declarative paradigm (assuming all the current problems in annotations are fixable which I don't think they are)...
    Meta-data in bean-properties is user customizable which is remarkably powerful, in order to integrate ORM we can extend the meta data objects (BeanContext and PropertyContext) and add ORM specific information into these elements. Why is this important?
    Because during compiler time you don't know basic things like table name etc... regarding ORM, we can hint a default using annotations (which we do) but the only other alternative is to load state from XML (which is how Java EE works: hints from annotation and deployment overriding with XML DD). So Java EE essentially contains a meta-data location in parallel to annotations which is only exposed to the user via XML (the deployment descriptor). Bean-properties allow you to programmatically customize meta-data which has huge advantages in terms of compiler checks e.g. we can declare a relation between two properties programmatically and this is verified by the compiler. Since annotations currently don't allow pointers (see my comment above about annotations) this is impossible to do with them.
    These examples are valid for ORM, but customizable meta-data is critical for localization (JSR 295 uses or used property names for table columns!), validation etc... You can say that this is not a part of a property spec and you would be right... But a property specification should be designed with thought about enabling these features which current properties can't possibly enable (without making java.lang.Class/java.lang.annotation.ElementType implode).

    Posted by: vprise on September 28, 2007 at 07:51 AM

  • @Remi. I am suggesting this, but it should not be explicit. I see it as an implicit enum called 'properties'.


    class A {
    int a;
    double b;
    ArrayList l;

    enum properties implements Property {
    a(A.class, Integer.class);
    b(A.class, Double.class);
    l(A.class, ArrayList.class, String.class);
    }
    }

    Posted by: montechristos on September 29, 2007 at 06:58 AM

  • The formating took out the ArrayList of String

    Posted by: montechristos on September 29, 2007 at 07:01 AM

  • Apart from the syntax of the Properties, I would like to ask:
    1) Could one iterate over the Properties of a class?
    2) Could you get the Field from the Property?
    3) Could you get the Property from the field?

    Posted by: montechristos on September 29, 2007 at 07:08 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds