Sunday, October 30, 2005

Year 2005: The URL Still Matters

Like many, I am spending a lot of time behind my computer. As a consequence, I sometime need a little break. A few days ago this took the form of going for some "store browsing". Of course, those are online stores I am talking about!

So here I am at the Apple Store, hopping from a shinny PowerBook to the new iPod Video, when the picture of a product that looks interestingly out of place got my attention: a questionably fashionable pink leather case for iPod. What was that doing there? I clicked on the link and while the page was loading reflected on how this was the ultimate proof that the iPod became mainstream. By now I had on screen a page from apple.com just on the Kate Spade Leather Case for iPod. Frankly, how could I resist sending this page to a carefully selected audience? That is when my trouble started.

The link to that page was certainly odd looking:

http://store.apple.com/1-800-MY-APPLE/WebObjects/AppleStore.woa/
71708/wo/2H7A6Ke85IHa3BsnkN01NPFyuLF/1.0.0.17.1.0.8.9.2.11.2.7.8.0.1

What is this "1-800-MY-APPLE" doing in there? And what about this random looking sequence of letters and numbers? Without worrying too much about it, I sent that link and... started receiving complaints: "That link does not work for me!"

Apple certainly understands marketing, but does not understand a facet of social marketing: if Jane recommends a product to her friend Mark, Mark is much more likely to buy it. And a simple way for Jane to do this is to just email the link to that product she wants to recommend. So why prevent this behavior?

A URL to a product should be permanent. What I see in the URL field should look more like http://www.apple.com/store/product/kate-spade-pink and anyone going to the same page should see the same URL.

Apple, repeat after me: we are in 2005, and the URL still matters. And please, don't consider the URL as just additional real estate that you can use to advertise 1-800-MY-APPLE, a direct line to your sales team.

Thursday, October 20, 2005

IBM Gets DataPower

Last August, Intel acquired Sarvega and it was now the time for IBM to acquire DataPower, in a $100 million all-cash deal. DataPower, a company with 50 employees founded by a group of MIT engineers, creates appliances performing specific XML processing tasks like XSLT transformation, XML encryption, or XML Schema validation.

With the acquisition of DataPower, IBM is creating a new division called SOA Appliances. I see this as yet another indication of how important XML technologies and SOA are to IBM and the industry in general.

Congratulation to the whole DataPower team and in particular their CTO, Eugene Kuznetsov, who has been instrumental in the success of the company!

Wednesday, October 12, 2005

W3C XForms 1.0 Second Edition Now a W3C Proposed Edited Recommendation

The W3C XForms working group has just released the first public version of the second edition of the XForms 1.0 specification.

This is an important step forward for XForms, since the working group had collected numerous errata since the initial XForms 1.0 specification was published, almost two years ago. Several versions of the errata had been published since that time, but they required looking at the initial specification and then searching for updates in a separate document, which was quite inconvenient. The latest and greatest of XForms is now available in a single, convenient place. It is expected that this document will become an actual edited recommendation soon.

Since OPS 3.0 is written against the XForms 1.0 specification (be sure to try out the latest beta and the online examples), this is a useful reference for OPS users!

Sunday, October 9, 2005

The OPS Blog Sample Application, Part III

Introduction

In this installment, we examine the new "comment preview" feature of the OPS Blog sample application.

OPS Blog Application Comment Preview Form

Most blog applications' comment pages work this way: you see the text of the blog post, followed by a series of existing comments to the article and a text area which you use to enter a new comment. When you are done writing your comment, you have two possibilities: preview or directly post the comment. The purpose of the preview is to allow you to see what your comment will look like once posted, without actually submitting it. This is useful because most comment editors are not WYSIWYG: they often allow you to enter some special markup, usually inspired by HTML, to format text, add hyperlinks, etc. Surprisingly, you still find blog applications without this feature, which is annoying as you may end up posting garbage if you do not master the particular blog application's formatting markup.

Here is the good news: with the advent of Ajax, used by the OPS XForms engine, the preview functionality doesn't actually need a "Preview" button that reloads entirely the comments page: you can very easily implement a dynamic preview updated as the user types. How does this work?

The Basics

In XForms, you bind controls to nodes of an XML document called an XForms instance. For example, the following XForms instance can contain the name of an author and the actual text of the comment:

  <comment>
      <author>Erik B.</author>
      <text>This blog post rocks!</text>
  </comment>

The author and text nodes are easily bound to XForms controls:

  <xforms:input ref="author" incremental="true"/>
  <xforms:textarea ref="text" incremental="true"/>

Now from there, displaying the comment outside the text area as it is entered simply consists in binding some xforms:output controls to the same nodes:

  <p>
      Comment written by: <xforms:output ref="author"/>
  </p>  
  <p>
      Text of the comment: <xforms:output ref="text"/>
  </p>

Presto! As you type, the text of the comment appears within HTML paragraphs. Note that to achieve this, we had to use the attribute incremental="true" on xforms:input and xforms:textarea, in order to ensure that the XForms engine frequently perform updates as the user types. Without this attribute, the xforms:output controls would only update upon the user changing focus between controls.

Handling Markup

This is not the end of the story. Writing plain text comments is good, but we want to be able to use some markup too. First, we need to choose a format. The easiest way to do this is to choose a very small subset of HTML, using for example the b, i and a tags. What happens if the user types those in the text area? Unfortunately, the output will actually contain the tags as well, and no HTML formatting will take place. This happens because the xforms:output control, by default, outputs plain text, including opening and closing brackets.

How do you get the xforms:output control to output HTML then? There is currently no standard to achieve this in XForms. OPS has chosen to use the appearance="xxforms:html" attribute:

  <p>
      Text of the comment: <xforms:output ref="text"/ appearance="xforms:xhtml"/>
  </p>

Type HTML markup in the text area, and your text will appear formatted with that markup in the preview section!

Adding an XML Service

There is a drawback to this: the user can write any markup he wants, even possibly dangerous one involving for example Javascript, which would then appear in other user's browsers when they view the comment. We would like to filter markup to make sure that we only accept a safe subset of HTML. We also would like to mark the text area invalid when there is a problem. Validation could be done using an xforms:bind with a constraint attribute containing an XPath 2.0 regular expression function. Another solution is to delegate the validation of comments to server-side code. How do you do this? With the replace="instance" feature of the xforms:submission element.

Using the xforms:submission element this way allows you to use XForms to call XML services. An XML service is an online services that you call by sending it a request containing XML, and from which you receive an XML response. This is a powerful yet easy to use feature of XForms. What kind of service do we need for comment preview? One that takes a raw comment containing user markup, and returns an indication of whether the comment is valid or not and possibly, a cleaned-up version of the comment with extra markup added or filtered. We can do this with two XForms instances, and an adequate xforms:submission element:

  <xforms:instance id="comment-request">  
      <comment>
          <text/>
      </comment>
  </xforms:instance>
  <xforms:instance id="comment-response">
      <comment>
          <text/>
      </comment>
  </xforms:instance>
  <xforms:submission id="format-comment-submission" method="post" action="/blog/format-comment" ref="instance('comment-request')" replace="instance" instance="comment-response"/>

How do we use the above submission? We simply detect xforms-value-change events sent by the text area control. Once this happens, we execute an event handler (declaratively, as always with XForms) which sends the format-comment-submission submission. Nodes of the comment-request instance are bound to the text area control, and nodes in the comment-response instance are bound to the xforms:output displaying HTML:

  <xforms:textarea ref="comment/text" incremental="true">  
      <xforms:action ev:event="xforms-value-changed">
          <xforms:send submission="format-comment-submission"/>
      </xforms:action>
  </xforms:textarea>

On the server, we must now react to the /blog/format-comment action. To do this, we write an XPL file responding to that path:

  <page path-info="/blog/format-comment" view="recent-posts/format-comment.xpl"/>

The XPL file is here implemented as a page view. This way, the XPL pipeline can simply output its XML response on its data output, and the default Page Flow Epilogue takes care of serialization, the process of sending the XML back to the web browser. It would have also been possible to implement it as a model pipeline, but then it would have had to take care of XML serialization itself.

The XPL pipeline receives an XML document on its instance input, which is simply the comment-request instance submitted by the XForms engine. Then it calls an XSLT stylesheet that:

  • Parses the comment as an XML fragment using the saxon:parse() function

  • Filters out all disallowed elements and attributes

The stylesheet either fails or returns a cleaned-up version of the user comment, which the XForms engine uses to replace the comment-response instance. In case of failure, we return an error document to the caller.

Validation

We are almost done with the preview feature! The last thing we would like to do now is mark the text area as invalid if the server-side code tells us that it is invalid. We can use the xforms:bind element with a constraint attribute, containing an XPath expression, to achieve this. But what should this XPath expression contain then? For example if it contains false(), the test area is always going to be marked as invalid. If it contains true(), it will always be marked as valid (unless some other constraint makes it invalid). We need to be smart and use the XForms submission response document in comment-response. Here, we decide on a convention: if the response does not contain any text under /comment/text, then we consider that the server is telling us the comment is invalid. The constraint is expressed as follows:

  <xforms:bind nodeset="text" constraint="normalize-space(instance('comment-response')/text) != ''"/>

There is a little problem with this: if the server tells us that the text area is now invalid, we can no longer submit the comment-request instance, because an instance but be valid to be submitted! So we need to add a third XForms instance, which is used strictly for the input and text area controls:

  <xforms:instance id="main">
      <form> 
          <comment>
              <name/>
              <text/>
          </comment>
      </form>
  </xforms:instance>

When we catch value change events, we copy the value from the main instance to the comment-request instance first, using the xforms:setvalue action. The text area element now looks like this:

  <xforms:textarea ref="comment/text" incremental="true" xhtml:rows="10" xhtml:cols="80">
      <xforms:action ev:event="xforms-value-changed">
          <xforms:setvalue ref="instance('comment-request')/text" value="instance('main')/comment/text"/>
          <xforms:send submission="format-comment-submission"/>
      </xforms:action>
  </xforms:textarea>

So we end up with three XForms instance:

  • main: controls requiring user input are bound to this instance

  • comment-request: this is the XML document to send to the XML service to validate comments

  • comment-response: this is the XML document returned by the XML service that validates comments

In the general case, it makes sense to separate the request and response documents from the main XForms instance.

That is it! The code is currently available in CVS and the nightly builds, with some additions such as a "comment date" field, but the ideas above remain valid.

Wednesday, October 5, 2005

Google, Sun, and the Web Based Office Suite

When Google and Sun said they would make a common announcement in a public webcast, technical blogs all around started crank up speculations about what that announcement would be. And with Google in there, it had to be something big.

What Google and Sun finally announced yesterday will not change the world as we know it today, and the most interesting thing did not come from what Google and Sun announced, but from observers' analysis of the situation. Even after the announcement Tom's Hardware wrote:

The Google/Sun joint announcement today apparently does not concern AJAX, or any Google project that uses AJAX. However, OpenOffice 2.0 does include tools with which users can generate so-called XForms, that are deployable on other users' systems by means of AJAX.

Google is known for creating very responsive web applications; web applications that behave more like desktop applications. GMail and Google Maps are two examples. They are doing so leveraging a set of technologies available in modern web browsers, often referenced as Ajax. While people have been using Ajax for a while now, Google has been the first to bring that technology to the masses. They have done that for mail; now could they do it for office applications? If they do, the logical choice would be to use the OpenDocument format now standardized by OASIS. That format uses XForms as its form language, for which we created at Orbeon an Ajax-based implementation in our open source PresentationServer (OPS) product. Now can you see the different pieces starting to come together?

Monday, October 3, 2005

Back Online

At the end of last week, we moved our main office in California from Mountain View to San Mateo. If moving furniture was not fun enough, we also had to move our server rack. This has caused some downtime of our servers, including our email, and of course we have been so busy moving since Thursday that development and our attention to the mailing-list had to slow down.

We are back to work now. Please let us know if you encounter problems with the Orbeon web site and associated services!