BeansBinding: not only for the GUI?
"Beans binding" is, in general, any Java technology that allows to automatically bind some properties in a plain JavaBean class to a GUI form. There have been libraries around for beans binding since a few years, but the thing is getting more and more interest because of JSR-295, an official specificaion from Sun together with its reference implementation ("Beans Binding in capitals) that is also supported by NetBeans 6.
Don't worry: this is not Yet Another Tutorial on NetBeans and BeansBindings since there are already around (even though it seems there's nothing about the use of JSR-295 with NetBeans RCP projects). My point is about using Beans Binding for other purposes than merely bind a form - you know that I like to use stuff also for different things than the ones it has been designed for.
Just be warned that this is only work in progress at the time.
The context: blueMarine Metadata
Let me start with the context, which is a new sub-project of blueMarine which is called blueMarine Metadata and, as it appears obvious from its name, it has the responsibility for managing metadata of photos. In a few words, the requirements are:
- The system must be able to manage different items of metadata (for instance, two common kinds for photos are EXIF and IPTC, but we should also consider geotags and other stuff that could come up in future) and the code for managing a new metadata item must be pluggable.
- The system must be able to manage different sources of metadata. For instance, an obvious metadata source is the image file itself (e.g. a JPEG or a TIFF), but there is also XMP (a "sidecar" format invented by Adobe, that is an extra file just placed side by side to the original photo file) and there could be a persistent database for performing fast queries.
- The persistent technology must be pluggable - JPA being the most common one, but it should not be exclusive; also the underlying database should not be constrained to be a RDBMS.
- Components must be reusable as there are different targets for them, blueMarine being only the primary one, and web applications another possibility.
I'm particularly sensible about reusability as this metadata stuff will evolve in some interesting stuff in the next months, but I'm not going to tell you more about it now (yes, this is a little teaser ;-). At the moment I would just like to point out that the NetBeans integrated support for Beans Binding is great for writing GUI forms quickly.
Common design patterns
Since this module is being developed mostly by TDD and I have a very good test coverage, I can afford to do some experimenting, especially in the area of persistence.
Let's first look at this diagram:
The upper part of the diagram shows a very common pattern that people use, probably influenced by some J2EE blueprints:
- the GUI calls the Business components
- the Business components call the Persistence components
The left-to-right arrows not only reflect the flow of the incoming requests, but also the dependencies of components:
- GUI components depend on Business components
- Business components depend on Persistence components
This approach is clearly influenced by J2EE blueprints - in fact, many parts of blueMarine are designed on it, clearly reflecting the fact that when I started the project I was at 99% a J2EE architect. There are two major drawbacks here:
- While the approach is well suited to Web 1.0, where every transaction is initiated by the client (information is "pulled"), there is no support for changes that might initiate, for any reason, from the business tier. This can be managed by a full fledged MVC pattern, and in fact rich desktop applications have been using it for decades (and Web 2.0 started too). To avoid introducing a dependency from the Business tier to the GUI, MVC uses the Observable pattern: the Business object exposes a "listener" API, that the GUI uses to register and receive notification of changes.
- The Business objects depend on the Persistence technology, which is not good since it forces you to use a specific technology. Usually people solve this by introducing factories and interfaces for decoupling, which works but introduces complexity. A better solution here is to apply Inversion Of Control and have Persistence depend on Business. At this point the interaction between the Business and the Persistence can be implemented with a specular kind-of-MVC by means of listeners, so Persistence receives change notifications from Business.
I've not drawn the capability of Persistence to be the originator of changes and call Business to modify it since if we're thinking of a database this usually doesn't occur; but in my case, where Persistence could be an image file, this might happen if somebody changes it on the disk with another editing tool. So replicating the MVC has a further benefit.
Beans Binding for Persistence
And now my point. Beans Binding is basically used as an alternate approach to implement MVC for the GUI and the Business objects without requiring you to write specific listeners; instead, Beans Binding takes advantage of the standard
java.beans.PropertyChangeListener implemented in the Java runtime, posing as an additional requirement that all the involved objects are compliant with the JavaBeans specification (remember that a "real" JavaBean is not the same as a POJO, as it must have proper event notification upon every property change). This is an annoyance that I'll address at the end of this post, but I anticipate that it's just a boilerplate code issue, not a design problem.
But if the relationship between Business and Persistence can be expressed as a kind-of-MVC, why don't we use Beans Binding to take care of the relationship between Business and Persistence too?
It's basically what I've done so far in the first sketch of the blueMarine Metadata subproject, as explained by the upper part of this diagram:
Now Form, Domain Object and Persistence are pretty much decoupled each from the other - it's up to two special services, the UI Binder and the Persistence Binder, to use JSR 295 for keeping them synchronized. Any change in any object will properly reflect into the others: this happens both if the user types something in the form (and the update is propagated to the Business and Persistence objects) and if something changes in Persistence (and the update is propagated to the Business and the Form); of course changes could also originate in the Business Object (e.g. a timer triggers) and the other two are updated.
Keep in mind that the Business Object mustn't be a passive thing such as a Value Object, but it can contain business logic too (i.e. a property change might originate some computing); on the other hand, the "Binders" are Services that need to be invoked only once, to set up bindings, and then they don't have a further role in the evolution of the object states. I like this approach since it seems to overcome the classic scheme of "active-Services" versus "passive-Objects", instead here each object is active and its design is only driven by the domain model.
Also, in the example the Persistence object seems to be modeled on the Domain Bean (same properties), but this is not a constraint. For instance, in blueMarine I have implemented a persistent module where every property from every JavaBean is storead as the tuple ("metadata group", "metadata property name", "value") in a single table. Beans Binding gives you a lot of flexibility.
There are two problems in this design, both related to the specific technology available now:
- Transactions. What should demarcate them? Thinking of a user that is typing in the Form, and wants changes to be persisted, we should have something as: the user types, but Beans Binding doesn't propagate changes immediately; instead, when the user presses a "Save" button we have the sequence "press Save -> begin TX -> propagate changes -> commit TX". Another approach (which is the one I want for blueMarine) could be that each change is automatically committed to the database while the user types in the form (the sequence is "type -> begin TX -> propagate changes -> commit TX"). Unfortunately, the current support for JSR 295 by NetBeans Matisse for NetBeans RCP projects doesn't allow you to do any customized transaction demarcation (the problem is addressed only when JSR 295 is used in conjunction with the "Swing Application Framework", JSR 296) - indeed, with NetBeans RCP there will be no transaction at all in the generated code.
- The infamous AWT Thread. Changes that originate from the Business Object or the Persistence are not executed in the AWT Thread, but any change to the Form must be performed from within it; unfortunately JSR 295 at the moment doesn't support this automatically.
My solution is to add two decorators:
- The Transactional Decorator ensures that every property change (incoming from the left side of the diagram) is wrapped by a begin TX/commit TX (of course we might think of putting this decorator at the left of the Business Object if we want transactions to have an effect on it, but this is just a minor detail).
- The AWT Thread Decorator ensures that every property change (incoming from the right side of the diagram) is performed by a
But of course we don't want to code these decorators by hand. We could use java.lang.reflect.Proxy to generate a dynamic proxy, but unfortunately it requires an interface and Java Beans don't have any (rant: why the JavaBeans specification doesn't take care of interfaces?). A solution can be provided by the CGLIB library, which allows to create a dynamic proxy starting from a concrete class, by means of bytecode manipulation:
public class TransactionalBeanFactory
public EntityManager entityManager;
public <T> T createTransactionalDecorator (final T object)
final Enhancer e = new Enhancer();
public Object intercept (final Object obj,
final Method method,
final Object args,
final MethodProxy proxy)
boolean demarcateTransaction = ...;
final Object result = proxy.invokeSuper(obj, args);
A similar approach could be used for the AWT Thread Decorator.
If you're thinking of AOP, yes, we are basically implementing an aspect here. But I prefer to do it manually with CGLIB rather than resorting to AspectJ for simplicity, as I don't want to add another complex library (and a new language) to my project.
What about boilerplate code?
It's known that properly implementing JavaBeans with all the listener stuff is a PITA. While for the UI stuff you could just extend the
AbstractBean class from SwingLabs, and 90% of the work is done, this is not a viable solution for the Business and the Persistence objects for two reasons:
- It's bad to use a Swing specific library in these tiers;
- I don't like solutions requiring inheritance.
At the moment I've resorted to some quick and dirty tool for automatically generating the required boilerplate code, but I think I'll try the CGLIB approach again, by generating a decorator that turns a simple POJO into a full-fledged JavaBean. Before doing this I'll carefully search if there's already something implemented for this.
The current state of this stuff is that tests pass, but the thing doesn't work in production yet, since CGLIB has some conflicts with the NetBeans RCP classloader. This is something that I hope to fix soon. There are other specific desing issues that I'm dealing with, most notably another module of blueMarine where I'm trying to apply this scheme but it falls short of a specific case. But this is just preliminary work, expect updates from me in future.
In the meantime, I'd like to have some feedback from you.
PS If this works, I wonder wheter the JSR-295 package name
org.jdesktop.beansbinding is somewhat inappropriate, since the scope of the technology goes beyond the desktop. Perhaps
org.beans.beansbinding would be better?