Apt models

Extremely busy weeks behind (and probably ahead too) so I've been unable to post anything interesting for a while. Sorry by that.

I am currently thinking on how to better build the models for Swing applications.

And, of course, I'm thinking of annotations ;-)

JavaBeans for me, please

I would like to build models using JavaBeans (Plain Old Java Objects, or POJOs, say). I would like each property of my JavaBeans to automatically generate PropertyChangeEvents for me.

Of course that's not very difficult to do. I could use java.beans.PropertyChangeSupport to do that.

Let's see an example. Let's say I want to model a Person with two properties: full name and email. I could build a JavaBean like this:


package com.sun.antonio.models;

import java.beans.\*;

public class Person
  implements java.io.Serializable 
{
  private String fullName;
  private String emailAddress;
  private PropertyChangeSupport pcs;

  public Person()  { pcs = new PropertyChangeSupport(this); }

  public String getFullName() { return fullName; }

  public void setFullName( String aFullName )
  {
    String oldName = fullName;
    fullName = aFullName;
    pcs.firePropertyChange( "fullName", oldName, fullName );
  }

  public void addPropertyChangeListener( PropertyChangeListener pcl )
  {
    pcs.addPropertyChangeListener( pcl );
  }
  // removePropertyChangeListener and get/set EmailAddress below removed
}

The code above is simple to write. I could use a java.beans.VetoableChangeSupport too, to add support for vetoable changes. (If you need more information on JavaBeans or bound properties or constrained properties you may want to read more on the topic).

But although simple to write (and to read) it requires too many lines of code. I'm too lazy to do that donkeywork. I'd prefer using a shorter, more compact notation for defining my JavaBeans.

And, although I don't really like code generation stuff, I thought of using a code generation mechanism to generate my JavaBeans.

The incredible autogenerated JavaBean

The very first approach could be, of course, XDoclet JavaBean tags.

So I thought of downloading and setting up XDoclet on my wonderful NetBeans 5.0 Beta. But then I thought that it could be a good idea to use something similar to JAXB 2...

The incredible XML mapping

I happened to pass by Kohsuke Kawaguchi's Blog where I could read:


@XmlRootElement
class Point {
  @XmlElement
  public int x;
  @XmlElement
  public int y;
  Point(...) { ... }
}
Hey! He was defining the XML mapping of a Java object in Java using annotations. This is cool!.

I wanted to do that, too. What about writing something like this?


@JavaBean
class Person
{
  @Property( type=BOUND ) private String fullName;
  @Property( type=CONSTRAINED ) private String emailAddress;
}

This is, I could define a JavaBean annotation and a Property annotation so that classes and attributes marked with these could be used to generate the code I had to write by hand at the top of this entry. Those annotations could automagically create PropertyChangeSupport and VetoableChangeSupport for me, and fire appropriate PropertyChangeEvents when required (on the setter methods).

The idea seems to be interesting. What about this?


@JavaBean
@XmlRootElement
class Person
{
  @XmlElement @Property( type=BOUND ) private String fullName;
  @XmlElement @Property( type=CONSTRAINED ) private String emailAddress;
}

This is, if I use annotations for JavaBeans I can mix these with JAXB2 annotations, so that all my model can be persisted to XML too.

But using annotations for JavaBeans seems to be nothing new. See, for instance, damnhandy's blog on ideas on how to do this.

Apt models

One of the nice things about annotations is that you can generate both source code and class files from them using the apt tool. I'm experimenting with it right now. Maybe I'll post some examples here.

And, well, NetBeans, of course...

Since building an APT based tool to generate JavaBeans seems a little bit too elaborated to me, I thought of building a NetBeans plugin.

And, well, the fact is that... none is needed!!! NetBeans has already a built-in command to do it. It generates PropertyChangeSupport for me (or even VetoableChangeSupport). And takes all the hassle of hand-writing property change listeners and firing property change events.

Since this is a little bit hidden feature, I think it's better to show the process with some screenshots.

First of all I create a plain Java class as usual (File/New/Java Class). And call it, say, Person.

Then I open the class in the Project Window until I can see the "Bean Patterns" node. Like this:

Then a dialog appears. In this dialog you can choose what type of property you want to create (plain, bound, constrained). The nice feature is that NetBeans automagically creates a PropertyChangeSupport for you.

The generated code looks like this:


  /\*\*
   \* Utility field used by bound properties.
   \*/
  private java.beans.PropertyChangeSupport propertyChangeSupport =  new java.beans.PropertyChangeSupport(this);
  
  /\*\*
   \* Adds a PropertyChangeListener to the listener list.
   \* @param l The listener to add.
   \*/
  public void addPropertyChangeListener(java.beans.PropertyChangeListener l)
  {
    propertyChangeSupport.addPropertyChangeListener(l);
  }
  
  /\*\*
   \* Removes a PropertyChangeListener from the listener list.
   \* @param l The listener to remove.
   \*/
  public void removePropertyChangeListener(java.beans.PropertyChangeListener l)
  {
    propertyChangeSupport.removePropertyChangeListener(l);
  }
  /\*\*
   \* Getter for property fullName.
   \* @return Value of property fullName.
   \*/
  public String getFullName()
  {
    return this.fullName;
  }
  
  /\*\*
   \* Setter for property fullName.
   \* @param fullName New value of property fullName.
   \*/
  public void setFullName(String fullName)
  {
    String oldFullName = this.fullName;
    this.fullName = fullName;
    propertyChangeSupport.firePropertyChange("fullName", oldFullName, fullName);
  }
Which is good enough for me, just with a few clicks.

Conclusion

So, although generating JavaBeans with apt (or xdoclet) may be a cool feature, I think I'll stick with NetBeans at the moment. The generated code is excellent and, well, the feature is already integrated in my favourite IDE.

Anyway maybe I'll come back to annotations in the future to generate code... What about a @TableModel annotation that automagically generates a TableModel for you? What about a @ListModel one? And, of course, are you using annotations for your model? Would you like to? What do you think of using the APT tool to generate source code for your Swing applications? (Any ideas/rants/complaints are, of course, welcome).

(Note to NetBeans team: you've earned a free beer whenever you happen to visit Madrid).

Happy modelling,
Antonio

UPDATE:

It seems Core Java II vol. II (Chapter 13) has some examples of APT Annotation Processors to build BeanInfo (I don't own Core Java II yet, I think I should go buy it, right?) Sample code here.

Comentarios:

what about the event bus? ...did the wheels fall off?

Enviado por codecraig en octubre 18, 2005 a las 01:18 PM CEST #

Hi,

I'm exploring how to best attach the "model wheels" into the bus.

After the model wheels are in place I'll move to the controllers and actuators wheels. Or have you any other suggestions? ;-)

Cheers,
Antonio

Enviado por Antonio en octubre 18, 2005 a las 03:56 PM CEST #

Since the UITopics used annotations, and you mention here apt, i though i add my two cents.

First, i wanted to say that a really nice way of consuming annotations (using the metadata they provide) at runtime is by using an AOP tool such as AspectJ. With AOP+Annotations, you can basically say that every method annotated by @TopicListener of every instance of, say, either an interface or a class marked by another annotation, would be automatically added to the UITopics Manager by calling addEventSource. [Not that it couldn't be done this way without annotations, ie by using interfaces only, but you can prove the topic you want to listen to in the annotation, so i like it better with them]

Secondly, after digging i actually found such an implementation, which is actually interesting because it's an event delivery mechanism based on annotations and AOP (it also automates some of the event sending itself as you'll see, so basically only the event consuming and not the event producing is really relevant to the bus). It can be found here [http://www.aspectprogrammer.org/blogs/adrian/2005/03/event_driven_ar.html]

Enviado por liquid en octubre 21, 2005 a las 05:28 AM CEST #

Hi liquid,

Thanks indeed for the pointer!! Making the event delivery mechanism based on annotations (and/or AOP) is quite interesting to me. My little implementation of an event bus uses annotations just for the listeners, and not for the sources. But this is extermely interesting.

You've wont a free beer in your preferred pub in Madrid! ;-)

Cheers,
Antonio

Enviado por Antonio en octubre 21, 2005 a las 12:48 PM CEST #

Enviar un comentario:
Los comentarios han sido deshabilitados.
About

swinger

Search

Archives
« abril 2014
lunmarmiéjueviesábdom
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
    
       
Hoy