Saturday, July 30, 2005

A strategy for binding "complex" properties in Cocoon Forms

First, a short introduction about the problem context.

Cocoon Forms provides a binding framework for both loading object properties into form widgets and saving form values into object properties.
This is done through the association of every form widget you want to bind, with a JXPath expression leading to a particular object property.
This is an XML snippet showing a binding example:

<fb:value id="name" path="name"/>
<fb:value id="street" path="address/street"/>

We associate the value of the "name" widget with the "name" property of some object passed by Cocoon control flow, and the "street" widget value with the "street" property contained by the object "address" property.
For bigger clarity, this is a code snippet for the object used in our binding example:

public class Person {
private String name;
...
private Address address;
...
}

And this is its Address property:

public class Address {
private String street;
...
}

The address property is a sort of "complex", or "composite", property.

The problem arises when you want to save form values into a Person object just created, which has a null address property: this will throw a JXPathException because the JXPath context used by Cocoon doesn't know how to create the address property.
So, the following binding:

<fb:value id="street" path="address/street"/>

Will not work.
And, like it, the binding of every complex property with a default null value.

Solutions?

A first one could be to set the address property to a new Address into the Person constructor or in Cocoon control flow, but this is very poor, because requires you to change the business code, or hack the control flow.

A better solution is to use JXPath factories and Cocoon custom binding.
Let me explain my idea.

First of all, create a JXPath factory for making Address objects; this is very simple:

public class AddressFactory extends AbstractFactory {

public boolean createObject(JXPathContext context, Pointer pointer, Object parent,
String name, int index) {

pointer.setValue(new Address());

return true;
}
}

The factory must be set in the JXPath context object, which will use the createObject() method for creating null properties, like "address" in our example (for additional details see the JXPath User Guide and its javadoc).

The question is: how to do that in Cocoon?
The answer is, you can guess it, in custom binding.

First, configure it:

<fb:custom id="street" path="." builderclass="com.example.JXPathConfiguratorFactory" factorymethod="makeConfigurator">
<fb:config relative="address/street" factory="com.example.AddressFactory"/>
</fb:custom>

JXPathConfiguratorFactory is the factory which will make JXPathConfigurator objects through its method "makeConfigurator".
It must be configured, through the "fb:config" element, with two attributes:

  1. The JXPath expression relative to the "path" attribute. In our example this is called "relative".
  2. The fully qualified class name of the JXPath factory (previously shown) to use, here called "factory".

Important: why do we need two different "path" and "relative" attributes?
The reason is that if you set the JXPath expression in the "path" attribute of the "fb:custom" element, Cocoon will try to create the path BEFORE calling the custom binding, causing the well known JXPathException.
So, we must set the "path" attribute to the current context path (which should be existent), and the "relative" path to the desired JXPath expression.

Finally, write the JXPathConfiguratorFactory, as you usually do, and the JXPathConfigurator:

public class JXPathConfigurator extends AbstractCustomBinding {

private Element config;

...

protected void doSave(Widget widget, JXPathContext context) throws Exception {

JXPathContext configContext = JXPathContext.newContext(config);
String relative = (String) configContext.getValue("@relative");
String factory = (String) configContext.getValue("@factory");

context.setFactory((org.apache.commons.jxpath.AbstractFactory) Class.forName(factory).newInstance());

context.createPathAndSetValue(relative,widget.getValue());
}
}

It will simply set the factory into the JXPathContext object, create the null property and set the widget value!

I think that this solution has mainly three advantages:

  1. Non-invasiveness : it doesn't require you to change business code or control flow, but only your binding configuration file.
  2. Reusable : AddressFactory can be used whenever you need a property of type "Address", and the JXPathConfigurator can be used with every JXPath factory.
  3. Simple.

I'd like to know your opinion and ideas.

And, as usual ... have a good coding!

Sunday, July 24, 2005

Me and AJAX

AJAX, Asynchronous Javascript And XML, is one of those acronyms you have surely read of in some web sites like TheServerSide or XML.com.
It is one of those technologies which rises a great hype, with everyone talking and talking about it.
However, I must admit, I've never read much about it, being too much absorbed by other technologies and ideas, and being a strong supporter of server-side code against client-side javascript.
So, as soon as I've seen its capabilities, I've suddenly got surprised.

How have I encountered it?

A few days ago, as usual, I was working with Cocoon Forms when, testing a form made by my colleague Ugo Cei, I noticed its great responsiveness in combo box dynamic loading and data validation. So, I started browsing the code and while talking with Ugo I've discovered that the high responsiveness was due to AJAX automatic support in Cocoon Forms.
This got my interest, in particular when I discovered that many services like Google Suggest are driven by AJAX.

"Amazing!" I said. "This is great!"

However, after a few hours, my anti-javascript nature began to threat me and my new friend, AJAX... I started to doubt about its support and behavior in different browsers like IE or Mozilla, and so about its real usefulness in production environments.

This led me to further documenting, reading a bunch of good articles which let me understand how AJAX really works: and well, I must say, my anti-javascript nature, this time, was wrong.

So, how does it work?

I'll do a very short description, because you can find a longer (and better) one in the good articles cited at the end of this post.

All the magic lies into a particular javascript object: XMLHttpRequest.
This object lets you, from javascript code, sending an asynchronous request to the server the containing page come from, and receiving an XML document which will be processed by a callback javascript function when the asynchronous request gets completed.
Asynchronous means that the client doesn't wait for the server response, and the web page remains responsive. Moreover, the server doesn't send the whole page, but only an XML document containing the information requested by the client, which will be processed by the callback function, updating data without page reloading.
Here is a step-by-step summary:

  1. The web page editor associates a javascript function to an event of an HTML control, say a combo box which, once selected, must fill a text field.
  2. This function, called when the user selects some item into the combo box, creates the XMLHttpRequest object which makes an asynchronous request to the server, sending the value of the selected item and then suddenly returning.
  3. Meanwhile, the server-side code makes some business logic and sends back the data, formatted in an XML document.
  4. When this asynchronous request/response completes, the callback function takes the XML data from the XMLHttpRequest object and processes it, through the javascript DOM binding, updating the text field.
  5. All updates gets suddenly displayed.

What about my previous doubts?

The XMLHttpRequest object, invented by Microsoft (I've always said that Microsoft guys are able to do something good, in particular when working in rooms with windows closed, in order to keep away from noises and bugs), is still not standard, but implemented by all major browsers, from IE to Mozilla. So, interoperability should not be a problem, and if you want to be safe, you can implement a sort of fallback behavior, like Cocoon does.
Moreover, all the business logic lies server-side (as it MUST be): client side javascript simply makes view processing.

And the advantages?

You can answer by yourself.
Thanks to AJAX, you gain a more responsive interface, which can make the web a sort of new experience, with new
applications like Google Suggest.

Now the links moment:

http://www.adaptivepath.com/publications/essays/archives/000385print.php
https://bpcatalog.dev.java.net/nonav/ajax/index.html
http://www.xml.com/pub/a/2005/02/09/xml-http-request.html

And, if Google has AJAX, why should we not?

Try clicking the "In-line view syndication titles ..." link on the bottom of the sidebar...

Saturday, July 23, 2005

Montag WS-I Basic Profile Compliance

This is the first great goal : Montag web services are officially compliant to the WS-I Basic Profile 1.1 recommendations.

It took me an hard work to code and test services WSDLs and all the related stuff in order to achieve this ... but it was very worthwhile and now I feel happy for this result.

Moreover, for this piece of good work I must thank Alex Saloustros for his precious .Net testing, and David Law for his testings about WS-I Basic Profile Compliance.

Congratulations, boys!

Wednesday, July 20, 2005

Talking about Montag

Montag is my main effort into the Open Source Community.

It is a SOAP Web Services system for interacting with Native XML Databases, but here I don't want to talk about what it is, and what is not ... for this, you can take a look at its web site.
I'd rather want to take a look at its future.

Montag 0.8 will have, first of all, a consistent core code refactoring and rewriting, in order to support new features and better accommodate future changes.
The new features released for the next version will be:
  • New services and full document/literal style for all services, based on WS-I Basic Profile.
  • New authorization system based on per-service permissions, different from the Unix-like permission system implemented by many Native XML Databases.
  • New authentication system using WS-Security UsernameTokenProfile.
  • Support for specific non-XML:DB Native XML Databases, like Berkeley DB XML.
All these changes and features are already in development or will start soon to be, but will obviously require a considerable amount of time to be completely developed.
So, prior to the 0.8 final version, a certain number of binary development snapshots will be released, in order to give "fresh meat" to Montag users and to test new features.
They will not be documented, except for some news announcement, but will be supported in the mailing list.

Stay tuned.
Montag's story continues.

Sunday, July 17, 2005

It is sunday, it is late evening and tomorrow a new week begins.

On Monday 11 July I've joined Pro-Netics, in Rome, where I will work with great technologies and great minds.



It promises to be a very interesting job and a very exciting experience.
I hope to talk more about it later.

But now ... Shakespeare's Hamlet waits for me.

Good night.

(nice dreams)
Hello all.

It took me a long time to start a blog, but now ... here I am.

What about this blog?

I'll talk mainly about Computer Science, which is my work and my main interest, but also about music and literature, which are my passion, and about every other thing will make sense for me.
Hoping I will find the time!

The play begins.

Welcome.