MetaWidget: the 'sweet spot' of automatic UI development
As much as possible, Metawidget does this without introducing new technologies. It inspects, at runtime, an application's existing back-end architecture (such as JavaBeans, annotations, XML configuration files) and creates components native to its existing front-end framework (such as Swing, Java Server Faces, Struts or Android).
![[image]](http://mowser.com/img?url=http%3A%2F%2Fwww.jroller.com%2Fdk%2Fresource%2Fmetawidget.png)
Recently I had some discussions with the father of MetaWidgets (Richard Kennard). One questions I raised was later answered in his blog which you should read first to understand what follows. Before I pushed the send button in my mail client I decided to post my reply here:
1. Separation of Concerns:
I still think the solution I gave is better in most cases and I give my reasons:
if (contact instanceof PersonalContact) metawidget.setFields("firstname","lastname","dateOfBirth");
else metawidget.setFields("firstname","lastname","phone");
Flexibility: One wants to automatically create many different Views based on a single Bean with components of different sequence and visibility. In this case @UiComesAfter, @UIHide would be useless and a single line setFields(...) more suitable. I wouldn't remove the option to set these annotations but rather to offer setFields(...) as an more flexible alternative alternative. Cluttering: Usually many JPA annotations like @Column(nullable=false) or those for Hibernate Validation are already in place - adding further annotions like @UiComesAfter, @UIHide to basically every field of your bean strongly reduces clarity. Straitforward: I think Richard and I both agree that one of the key principles of MetaWidget is the possibility to directly use your unchaged domain objects to automatically build your views. Adding @UiComesAfter, @UIHide to basically every field doesn't really follow that principle. Concerns: And last, as far as 'concerns' goes, and this may be debatable, I believe the sequence and visibility of a view's components should be the concern of the view itself or, if you want to go through the hassle, a view-domain object between your domain and your view. IIRC, JGoodies Binding does something like this for component visibility where a view-domain (ValueModel) holds this state and synchronizes all other states between domain and view. The sequence of view components is however always a concern of the view itself.
2. Duplication of Declaration
One complain against the suggested metawidget.setFields("firstname","lastname","dateOfBirth"); is that it introduces duplication by using hardcoded strings named after the Bean's fields...but so is the MetaWidget AddressBook example by effectively restating that the domain has a firstname field by using the getValue(...) method:
mContactSearch.setFirstnames( (String) metawidgetSearch.getValue( "firstnames" ) );
mContactSearch.setSurname( (String) metawidgetSearch.getValue( "surname" ) );
String type = (String) metawidgetSearch.getValue( "type" );
To resolve this dilemma I suggested to define String-constants in your beans for some of its fields, and refer to them throughout your code: in bean annotations, the infamous metawidget methods setField(...) and getValue(...), etc.:
public class BusinessBean
public static final String FIELD_FIRSTNAME = "firstname"; // String constant
private String firstname;
@NamedField(name=BusinessBean.FIELD_FIRSTNAME) // used to *name* the field/getter
@UiComesAfter(BusinessBean.FIELD_TITLE)
public String getFirstname() {return firstname;}
this way the original name of the field/getter is fully ignored and the new name is used whenever one calls a metawidget-method from the view:
instead of metawidgetSearch.getValue("firstname"), one writes:
metawidgetSearch.getValue(BusinessBean.FIELD_FIRSTNAME)
and instead of metawidget.setFields("firstname","lastname","dateOfBirth"), one writes:
metawidget.setFields(BusinessBean.FIELD_FIRSTNAME, BusinessBean.FIELD_LASTNAME, BusinessBean.FIELD_DATEOFBIRTH)
The String constants are used everywhere - in the Domains' annotations, metawidget method calls and possibly resource bundles. In my opinion this improves separation of concerns and clarity, reduces duplication of declaration and error-prone design. Even refactoring of your bean or GUI is now much more easily done now. I acknowledge that some people do not want to change their Beans by adding String constants (since I questioned the additions of @UiComesAfter, @UIHide myself). Still, I see the String-constants and the @NamedField annotation and the setFields(...) method only as an advantageous option for cases with specific concerns such as flexibility. I agree, the default behaviour of MetaWidget should be as it is now. You just take your Beans, modify it with @UiComesAfter, @UIHide and duplicate field names in error-prone getValue(...) method calls as long as one has the option to do otherwise.
3. Not just Java
With the exception of HibernateInspector which is usually already there I am no fan of writing additional XML as a way to define component sequence. It seems I have at least one supporter: (Richard's Interview at Javalobby.com):
"I remember the first releases of JPA were coming out. I thought being able to annotate your domain objects instead of writing XML mapping files was awesome - it had this real spirit of 'Don't Repeat Yourself'. We'd gone from having to manage duplicate field declarations in 3 places (your database schema, SQL statements, domain objects) to just 2 places (your domain objects and an XML mapping file) to just 1 place (an annotated domain object). I thought that was great."
Sometimes your own words fall back on you like blood-hounds on their master ;)




Thanks again for your thoughtful comments. There's a lot to reply to in one go!
1. Whilst I disagree you 'have to do an instanceof check in the AddressBook example' (it's just to show a different icon, not for anything functional), I agree with your points about cluttering and straightforward. It is unfortunate that a) we are entering an era of an explosion of annotations on our business objects, and b) the Java bytecode spec doesn't retain ordering information.
2. Duplication: I completely agree getValue() is not the best approach, and that it introduces duplication. It is important to understand, however, that getValue is not the preferred approach. I supply it because that's all Swing can do 'out of the box'.
Much better options exist in other frameworks (eg. Java Server Faces) and thankfully Swing also now has Beans Binding (JSR 295). So you can turn on Beans Binding support (or Apache BeanUtils support) in Metawidget and never use getValue/setValue, and have no more duplication.
The AddressBook example does this in ContactDialog.
3. Those dogs do bite :)
However, I think you misunderstand me: I was not saying we should all use XML. I was saying that if you use a technology that indicates field ordering/visibility you don't need @UiComesAfter. XML is one of those technologies. So are SQL schemas. So are JRuby classes for all I know.
The point is if you start putting field ordering into the Metawidget you are locked in to that approach forever. If you leave it in the Inspectors, you are open to new technologies as they come along.
In conclusion, you're certainly raising good points and are thinking in the same 'space' Metawidget is trying to fill. I welcome your feedback and, if you get time, would welcome your contributions too (perhaps a SwingMetawidget.setValidatorClass - like UIMetawidget has, but using JGoodies)?
Richard.
Posted by Richard Kennard on April 27, 2008 at 12:10 AM EDT #
1. For me the hardcoded strings in @UiComesAfter and getValue(...) is unpleasant and I can't see why defining String constants in one's bean wouldn't help. Also the big overhead of adding code to my beans with all the @UiComesAfter and the many @UIHides when I only want to show 2 Fields of two dozens in my UI and the limitation that I can only build a somewhat fixed view as given by the annotations in my bean. setFields(...) would solve that problem but I understand that in your eyes the risk outweighs the benefits for MetaWidget.
3. I got you there. It is a question of which poison to take, @UIComesAfter/@UIHide and a fixed UI versus a technology such as XML/SQL schema with a fixed UI. I don't like both unless solutions, reason why I did suggest setFields ;)
Btw, I believe you misread my email. I didn't recommend JGoodies Validation but only their clever validation-user-notification approaches as shown in the Validation-Demo (http://jgoodies.com/freeware/validationdemo/index.html). Hibernate Validation seems to do the job already and it should be possible to connect it with the mentioned validation-result-notification.
Cheers,
Dieter
Posted by Dieter Krachtus on April 27, 2008 at 01:38 AM EDT #