Monday, October 4, 2010

Entity Attribute Value model for flexible normalised data capture


I am reproducing a long winded thesis I wrote on StackOverflow about the appropriate data schemata to facilitate OLAP. I wrote it because OLAP vendors are plain lazy to provide hooks to allow flexible and fast cube generation. OLAP at its current status is useless for engineers and good only for mesmerizing managers and their secretaries with imprecise and out-of-phase information. OLAP software writers seem to be so excited about their multi-dimensional Entity-Relationship schema designing skills, but never thought it necessary to optimise the flexibility and response of their cube building processes. Their response has always been, "Duh, it's OLAP, it takes time to build a cube. OLAP is not meant to be real-time."

Here goes ...
As a generalisation, for multiple dimensional analysis to be effective you need two levels data modelling.
  • A substrate detail capture
  • An abstract cube
The answer is indeed EAV as the substrate detail capture. People can afford to be lazy and skip the detail substrate design. Every data mining tool I had been forced (by management) to evaluate has been inadequate because the inability to perform time-profiling.
Ultimately, it required us to write our own data-mining application - because the amount of kludge to make the software work, albeit ineffectively, equals to the amount of effort it takes to create one that works effectively. And even works extra-ordinarily spectacularly when we fed slices of the abstract cube into SAS/Insight. While the vendors' software took an hour to build the cube, and sometimes 24 hours, we needed our cubes to be built within 5 minutes and frequently within 15 seconds - due to effective substrate data modelling to enable efficient slicing of data to build the cube.
In industrial practice, we might need to flexibly move and range the time window of an analysis to match conditions that occured 6 months ago. Or that, we need to review the performance of processes for the last financial year.
We need to have correct time-phase correlation. Let's say a church has a per night statistic for a particular evangelistic rally as number of people "saved", number of "rededications", number of "contribution$", total contribution$, number of attendance - over 10 nights of the rally.
Then the church has statistics for number of tracts distributed by volunteer and the location each volunteer was assigned, the radio and tv advertisements and google ads placed. So the church statistician would need to collect info from each convert and $contributor - location of residence, when and where a tract was received, when and where an advertisement was encountered. And if they could collect such information from everyone who attended and who told them about it and when and where those who told them about the rally received a tract or encountered an advertisement. With such info at hand, the statistician would then be able a more truthfully matched multi-dimensional cube to let church leaders decide how to effectively organise their future pre-rally out-reach.
Data model optimization may not be possible for churches but for it is very possible for a factory full of equipment, robots, and trained operators. It is extraordinarily helpful to get phase-correlated data to treat an epidemic.
The EAV model is necessary because the number of parameters collectible, and number of attributes, vary from equipment to equipment and from process to process and from disease to disease. We cannot afford to have a table each for each set of parameters. Frequently a process or piece of equipment collects different sets of parameters, depending on the product that is being processed.
Sometimes the number of parameters collected can number a thousand. We cannot have a table with a thousand columns, can we? We even violate data normalization principles to store data in a single row or in a blob because of inefficient data access in a highly normalized table.
Further, we also need to version our data set. Let us say we designed an experiment for 2004. In 2006, we discovered that we needed to include new dimensions and discard some useless dimensions, and so we created a new version of the experiment. Then when we analyse the performance of the experiment between 2002 and 2008, we need to provide proper treatment to the change in the sets of dimensions in the experiment. In biological experiments and social behaviour surveys, the version changes would be more frequent.
I have a relational model of variable-dimensionality for attributes and parameters here:http://appdesign.blessedgeek.com/discrete-flow-resource-management. Not exactly EAV, but gives an idea what industrial multi-dimensional data modelling entails.

Sunday, August 1, 2010

Dear Mr Bob Egan - about your iPhone4 assessment...

I do not accept the argument forwarded in a blog where a certain Mr Bob Egan defends the performance of the iPhone4 and critiques the Consumer Reports' assessment: http://mobileanalyst.wordpress.com/2010/07/12/iphone-4-report-consumer-reports-study-is-full-of-crap/.

I dislike imagining being in the shoes of Mr Bob Egan - as he was annoyed enough to speak his mind without remembering to take in as full an engineering perspective as possible. Presuming he is an engineer and understands the practice of engineering.

Was he calculating on most of us not knowing what engineering analysis is, or perhaps counting on most of us practicing our unique analysis methodologies within our respective fields, and so would not see that his blog posting is flawed?

I would like to forward my proposal that he has calculated wrongly in his estimation of the composition of the population he was attempting to defraud. Most likely, he was not attempting to defraud anyone, but he does not possess the technical integrity to comprehend that the term "engineering grade" has a rather wide spectrum of implications and preferences of implementation.

Using vague terminology such as "scientific" or "engineering" grade - those are very attention catching phrases which he managed to use to implicate how bad the tests were done and how unworthy they are of professional consideration.

Mr Bob Egan, I think you are wrong. But, honestly, I am not sure. In other words, I don't trust your comprehension of engineering practice.

I have done quite some signal analysis myself and even wrote programs to generate and test responses to those signals. But, honestly, I am still struggling to figure out some of those things I did.

What you must be thinking is to conduct the experiments in a way where the parametrics could be easily isolated, that the team did not decouple spurious effects (or what some people who design experiments call noise decoupling). May be they made a mistake of presuming linearity. It may be they deliberately made that simplification - after all, Consumer Reports is not a scientific or engineering journal but a consumer magazine which illustrates their product assessments in ways the general consumer could understand.

Of course, you could fire back and say - that is the trouble, they have oversimplified the experiments as an inaccurate portrayal of the issues to credulous consumers (or to whom some people of your calibre would silently condescend as technological muggles). But, that is not the issue.

Regardless of the amount and exhaustiveness of tests and experiments a technically competent team has performed to solidly justify the performance of a product, there are always the final gates of consumer-simulation burn-in and buy-in. A technologically oblivious group of people uses your product who more often than not manages to squeeze out bugs we never expected. Mr Bob Egan, you must be better than not to know or not to have experienced that.

When the results of the failure come out, do we complain that the technically oblivious consumer-simulation has mixed up all the parameters and their experiments not being designed with engineering grade parametrically isolatable permutations and combinations?

What the Consumer Reports team has done, I suspect, is having successfully achieved an assessment that the iPhone4 will fail consumer expectations terribly. You should admit that - that the iPhone4 is no good in the hands of the consumer. Period, full-stop.

I suspect Mr Bob Egan is an artefact left over from 1980's American engineering practice where we lost out to the Japanese due to poor understanding of what quality engineering is all about. The problem does not afflict every unit, so it must not be the product's fault. Quality engineering, Mr Bob Egan, includes treating field conditions and consumer habits - you should woogle and google on it. Perhaps, he is the usual manager-type for a respectably large company and possesses cursory knowledge of what which equipment does but actually delegates all the hand-dirtying work of working and programming the equipment to less venerable souls like myself.


Perhaps, he is akin to a Tea Party activist yelling all the right words. I, on the other hand, would accept the honour to be perceived as an Apple Cider Party activist. Tea Party is a cursory expression of what happened in Boston that day. The actual underlying activity was the Apple Cider Party that happened afterwards which then became the actual catalyst to the American Revolution. The American rebels threw all the tea overboard but brought home all the apple cider over which they discussed revolutionary plans. Tea partying only addressed the apparent issues, whereas apple cider partying addresses the underlying and more potent core issues. 


Well, what do I know!

http://www.pcworld.com/article/200924/consumer_reports_throws_iphone_4_under_the_bus.html

Monday, July 5, 2010

_Why does the sun go on shining?

I am not a fan of Ruby programming - not because I don't like it but because I have never used it nor do I even know how it looks like.

It is now apparent to me that someone prominent in the Ruby world had abruptly ended _his (or _her) on-line existence about ten months ago. The entity about whom I am discussing signs _himself (or _herself) off as _Why. Last August, all of _his/_her on-line presence were abruptly terminated.

The person that availed himself as _Why in Ruby conferences looked rather like Jack Black, doesn't he? Was Jack Black or a relative of Jack Black's hired to appear as _Why? _Was _Why a time-travelling renegade and could it be that when the relevant time-enforcement agency finally caught up with _Why, they abruptly closed all _his/_her _time infractions?

Anyway ... anyway is my favourite mood-changing word. If anyone reads my earlier post, you might read that I despise the word basically, because the word basically is basically used by people to reflect a change in the mood of conversation. Therefore, I urge people who are fond of using the word basically to transform their speech to using the word anyway, which should more accurately reflect any intent in changing the mood of a conversation. Basically, I cringe being near someone who prepends their phrases with the word basically.

Anyway, being rather unaware of _who _Why _is, or if _he/_she and _his/_her existence and subsequent abrupt disappearance are inventions of Rubyists to desperately call to attention their languishing language, I had scarce intentions to discuss _Why and _Ruby. My apologies to avid Rubyists, but I know that I do not know if Ruby is languishing - it is merely a component of the theory that Rubyists invented _Why.

This is about words that are subtly similar but are poles apart.

Was _Why's presence suddenly terminated or abruptly terminated? An event can be abrupt but not sudden, and the converse is true.

One could plan the abrupt end of a process without being sudden:
We had been planning for months to abruptly end the existence of _Why.
One could experience the suddenness of a non-abrupt event:
_Who was suddenly aware that _she had gradually fallen in love with _Why.

Another pair of words that provokes my displeasure is spontaneous vs automatic. Sometimes (or even frequently), you might encounter a sentence like
When the limousine stopped at the foyer, the concierge automatically rose to open the door for the VIP.
A concierge, any concierge, would beg to offer a more accurate opinion that a concierge is always spontaneous but never automatic! To be spontaneous is human, to be automatic is a machine.

I was boarding a bus in another country and I noticed notices printed beside both the front and back doors of the bus, which said, when translated to English,
Caution: automatic door.
But, but, ... those were remote-controlled doors. The driver had to spontaneously press a button to open or close either door.

Which is preferable: to be precise or be accurate? I remember a Physics professor in Engineering school striving to remind us
Engineering is a science in precision, not accuracy.  My dead grandfather clock is abruptly accurate twice a day, but it will never be precise.
What about the word remember? More often than not, the gerund remembering is used in place of recall. Remember is to place into memory or have in memory. Whereas, recall is to withdraw from memory.

The sentence
I am not remembering if _Why existed or is a mere fragment of my imagination.
means that the speaker intends not to place into memory any present awareness of _Why's existence. Perhaps, the speaker actually meant to say,
I cannot recall if _Why existed or is a mere fragment of my imagination.
(I am unable to withdraw from memory ...)
or, to say,
I do not remember if _Why existed or is a mere fragment of my imagination.
(I do not have in possession in my memory ...)

Thursday, July 1, 2010

Is it logical to over-ride static members?

The Java language (or C#) does not allow static members of a class to be over-ridden. But what if there is a language that does?

Let us say that there is a class written in a hypothetical Java-like language
class DataSource{

  DataSource(Data data){
    this.data = data;
  }

  @override
  static Data getData(){
    return createFormData();
  }
  
  static <T extends Datasource> create(){
    Data data = getData();
    DataSource ds = new DataSource(data);
  }
}

Let us pretend that this language allows static members to be overridden
class GridDataSource
extends DataSource{
  GridDataSource(Data data){
    super(data);
  }

  @override
  static Data getData(){
    return createGridData();
  }
  
  static GridDataSource create(){
    Data data = getData();
    GridDataSource ds = new GridDataSource(data);
  }
}

You want a static method because you want it to be callable without instantiating the class, but you also want any derivative class to be expected to provide the method getData() as well as the factory method create(). For certain derivative classes you wish to over-ride getData() and for others you don't. Therefore, you need to consistently expect the method getData() to be present.

A so-called "OO purist" might say - this is not OO, redesign your algorithm to fit into OO constraints.

Forgive me a million times to be on the offensive - but first of all, who gets to be anointed an "OO purist" and secondly with what authority would such an anointed Chosen One pronounce that this isn't OO other than the few academic papers might have been read?

There should be absolutely nothing wrong with a programmer's preference as long as it is maintainable and extensible with the least of efforts. If a programmer finds this style of programming eases maintenance and extensibility - so be it. So, no debate about if this style of programming is good or bad.

The question to be answered is - is this logical or topologically sound?

At first purview, we could say that this is illogical.
  1. Since the addressability of static members depend on the extension of the class, why don't you just make them class members rather than static members?
    Wrong answer - the factory method has to be static and, therefore, any method it calls has to be static.
  2. The actual implemented class is not known until a class is instantiated.
    Wrong answer - that is due to the constraints of language's run-time architecture.
  3. We would have to implement virtual references in the language and that would defeat the purpose of efficiency of having static members.
    Wrong answer - the run-time efficiency of static members is a side effect/benefit. The main reason for having static members is to be able to address those members without class instantiation.
  4. Having virtual references designed to treat such a feature at run-time decreases run-time efficiency.
    Should the definition of OOP be constrained by the architecture of CPUs rather than linguistic topology? Why, processor makers could pander to virtualization, executable bit, etc and surely they could accommodate a little bit more? However, doesn't C# already have delegates? What about the planned implementation of closures in Java?

Such a feature is easily implemented with C# delegates, which would answer whether it is topologically possible to implement over-rideable static members. End of dispute.
class DataSource{

  delegate Data GetData();
  GetData getDataFuncton;

  // "static constructor" is run when class is loaded
  static DataSource(){
    getDataFuncton = new GetData(getData);
  }

  DataSource(Data data){
    this.data = data;
  }

  static Data getData(){
    return createFormData();
  }
  
  static <T extends Datasource> create(){
    Data data = getDataFuncton();
    DataSource ds = new DataSource(data);
  }
}

With this question settled, there should not be any more excuse not to allow contracting static members in an interface.

Sunday, May 30, 2010

A smarter SmartGWT

Once upon a time, there was a sweet meat vendor in the principality of RajaPutra Sri Nada, which sat at the edge of the expansive Thar desert to its north and the banks of a great river at its south.

His name was Manda-manda Agatha, which roughly meant "slowly-slowly come". It was probably because while he had to haul his heavy wooden cart, wheels creaking, into any village, the impatient children would yell "mandam manda!"

He was not a rich man, selling sweet meats with profits just enough to feed his family hand-to-mouth. Sometimes he watched the gold-trimmed carts of merchants on their way to the great Palace in the capital city of the great Moogle empire. He aspired to be one of those merchants.

"No, no. Correction." A local village chieftain would inflectively declare, "He aspires to be one of the Rajputs lording over those merchants in the service of the great Moogle Emperor."

The Moogle royalty and nobility were enthusiastic connoiseurs of sweet meats. So much, so that the Moogle royalty had devised a special formula of concocting sweet meats - using toffee made with coffee beans and cinnamon specially imported from the faraway kingdoms of Java. All every sweet meat vendor had to do was put their own specialised wrapper around it and the concoction would absorb and fuse the wrapper with its core. And the Moogles did not make it a secret recipe but made the recipe free to anyone who wanted it. Even appointed the benevolent Lord Aapachita II to oversee to its general availability and advertised the formula as Sri-Moogle Madhura Sutra (Sweetness Formula of Moogle the Gracious). For convenience, let's just call the formula SMMS.

Incidentally, for Agatha (Arya Agatha, Sir Agatha - as he preferred to be called), he found that his sweet meat core formula was just as competitive in flavour as that of the royal formula and yet the only people enthusiastic with his sweet meats were village kids. He would expel his breath, "kimartam karma-tam?" Why, why business/activity so dark? Even though he had submitted his formula to Lord Apachita for general availability too.

Until, until he chanced upon, incidentally also, a sweet meat supplies supplier who understood all the intricacies of both Agathaa Karya (Agatha's Concoction) and Madhura Sutra. Let's just call this sweet meat supplies supplier Zamdhiji for convenience' sake.

Zamdhiji had found that Agathaa Karya could have blended so perfectly and almost seamlessly with the royal formula. What was missing was a special sauce that would stitch the two together. Zamdhiji worked tiringly and tirelessly night and day in his spare time in his alchemy chamber and months' later voila! He emerged from his laboratory, eye brow sweating, declaring to everyone - !heurekamen! - and called the combined product Sri-Moogli Madhura Sutra Agathaa Karya, SMMS-AK.

Zamdhiji submitted his concoction to Lord Aapachita too. After which, nearly the whole civilised world got excited. From Arabia and Ethiopia in the west, to Byzantine and Persia in the north, Langka in south, Java and China in the far east. Fellow sweet meat supplies suppliers from the four, five or six corners of the world made contributions to Zamdhiji's karya to further enrich it. And Agatha's business bloomed.

Then Aarya Agatha took a moment in hind-sight. "I need to send my children to the best dharma-sutra sanghas - learning centres - in Lhasa, or Samarkand, or Gujerat or Alexandria. I could feed my family better. Wouldn't it be great if I could also own one of those Polynesian hand-crafted ocean-crossing yachts? And vacation twice yearly on the beaches of Gova?"

So, he created a similar sauce and called it ... well he could not call it SMMS-AK for obvious reasons. So he called it Agathaa Karya Sri-Moogli Madhura Sutra, AK-SMMS.

That was brilliant, he thought and gave himself a pat on his back. He further declared that he is taking all of Agathaa Karya, contributions from people from all over the known-civilised world inclusive, with him. They will no longer be administered by Lord Aapachita. Instead, he submitted them to the ascetic SriPaduka Aarya Matha (the venerated meditative stall-man whose-gracious-sandals-you-are-not-even-worthy-to-lick).

What is the difference? Ooo, the difference between Lord Aapachita and Lord Aarya Matha is huge. But that is beside the point because you can read their respective philosophies and zaastras (legalities) and what their implications would entail to the sweetmeat business from world-wide antara-sangha sutras. The point is ...

Well, the point is, Aarya Agatha has appeared to the known civilised world as an immature untrustworthy greedy business partner.

There was an uproarious uproar within the known civilised world - from Arabia and Ethiopia, to Constantinople, to Baghdad, to China, to Java and Sumatera and to Langka and even Madagascar and Tasmania.

To make matters worse, he declared, "Y'all are a bunch of wimps like puppets in a Javanese wayang opera."

To which, Zamdhiji protested, "Discussing the difference between Lord Aapachita and Lord Aarya Matha and their extreme implications to our business is nothing close to being puppets in a Javanese wayang opera."

To which, Aarya Agatha would shoot back, "True, true - but, but the way y'all whine about it is like being unprofessional puppets in a Javanese wayang opera." Like as though, "y'all could have silently come to my matha (meditation stall) and we could have discussed over it with chai and English muffins, and then I might graciously consider your proposals."

Well, we never knew that puppets in Javanese wayang operas could in any miraculous ways act professionally, did we? Which is also beside the point.

OK, end of debate. Zamdhiji and his collaborators decided - to naraka (hell) with Agathaa Karya, "We come up with Samartha Karya Sri-Moogli Madhura Sutra." A smarter recipe with Moogle's sweetness. Yes, indeed, next time we would be smarter than to fall into deceitful business dealings - I guess that is why they prefixed their new recipe with "Samartha".

Though Samartha is a Sanskrit word, incidentally, people ought to know that Shmarta in Hebrew has an implication of "being watchful and observant".

Thursday, May 20, 2010

ODBC on steroids

So, this has nothing much to do with Java, but I am also a C# programmer.

It is rather discouraging that most (if not all) examples that people post on ADO.NET use it like ODBC on steroids, merely using it to execute SQL statements.

What is the point?

I am unilaterally issuing a recommendation, if possible a technological fatwa, that people should no longer write ADO.NET examples to solely demonstrate SQL execution. Any further examples should demonstrate objects and entities.

The ultimate purpose of using ADO.NET is its ability to project objects and entities and people are either unaware of how to use it that way or are addicted to SQL on ODBC. So - no more monkeys jumping on the bed!

Very very annoyed.

When I issue a technological fatwa, does it mean that I consider myself a guru? Hmm ... embarrassing.

Wednesday, May 19, 2010

Accessing Google UserService from GWT client through RPC

There are times when you create a web app, you would want users to log in to provide user-contextual features. However, you don't wish to manage the log-in accounts. To do that, you could use OpenID or Google Accounts. The strategy is to have Google or an OpenID provider maintain and authenticate user existence. By doing that you do not carry the liability of lost passwords, log-in security, etc.

This tutorial concerns using Google Accounts to maintain the existence of your users in a Google App Engine application.

Google App Engine provides the class UserServiceFactory to facilitate that. UserServiceFactory is then used to generate UserService object, which in turn provides the following features
createLoginURL
createLogoutURL
getCurrentUser
isUserAdmin
isUserLoggedIn

You would use UserService object to generate the login URL for the browser. The browser would be directed/redirected to this URL. On reaching this URL, the Google log-in prompt would be displayed by Google's server.

Once logged in, your application could use the UserService object to inquire about the current user.

However, UserServiceFactory should be used on the server side not the client side. You cannot include it as part of your GWT module because

  • GWT compiler would request for the source code of UserServiceFactory and UserService - because GWT compiler needs to be presented all source code that is to be compiled into Javascript.
  • You cannot run UserServiceFactory and UserService on GWT client because they need to access Google's internal server-side objects.


If that is the case, how then do you pass UserService information to the GWT client? Simple - use RPC.

Server-side interface
You need to create a server-side GWT RPC interface similar to the following.
public interface UserServiceWrapper
extends RemoteService{
  String createLoginURL(String callbackUrl);
  String createLoginURL(String callbackUrl, String authDomain);
  String createLogoutURL(String callbackUrl);
  String createLogoutURL(String destinationURL, String authDomain);
  UserInfo getCurrentUser();
  boolean isUserAdmin();
  boolean isUserLoggedIn();
}

RPC servlet
Then your RPC server-side servlet would implement that interface
public class UserServiceServlet
extends RemoteServiceServlet
implements UserServiceWrapper
{
  final static public UserService userService = UserServiceFactory.getUserService();

  @Override
  public String createLoginURL(String callbackUrl) {
    return userService.createLoginURL(callbackUrl);
  }
  @Override
  public String createLoginURL(String callbackUrl, String authDomain) {
    return userService.createLoginURL(callbackUrl, authDomain);
  }
  @Override
  public String createLogoutURL(String callbackUrl) {
    return userService.createLogoutURL(callbackUrl);
  }
  @Override
  public String createLogoutURL(String destinationURL, String authDomain) {
    return userService.createLogoutURL(destinationURL, authDomain);
  }
  @Override
  public UserInfo getCurrentUser() {
    return mkUserInfo(userService.getCurrentUser());
  }
  @Override
  public boolean isUserAdmin() {
    return userService.isUserAdmin();
  }
  @Override
  public boolean isUserLoggedIn() {
    return userService.isUserLoggedIn();
  }
 
  static public SeriUser mkSeriUser(User user){
    return new SeriUser(
      user.getAuthDomain(),
      user.getEmail(),
      user.getNickname(),
      user.getUserId()
      );
  }
}

You cannot pass Google User object to a GWT client, unless you have the source code or fake the source code for User class. The simple way is to define a serializable SeriUser class and pass an instance of that class to the GWT client.

Client-side interface
Google Plugin for Eclipse would then aid you to create the client-side RPC interface:
public interface UserServiceWrapperAsync{
  void createLoginURL(
    String callbackUrl,
    AsyncCallback<String> callback);
  void createLoginURL(
    String callbackUrl, String authDomain,
    AsyncCallback<String> callback);
  void createLogoutURL(
    String callbackUrl,
    AsyncCallback<String> callback);
  void createLogoutURL(
    String destinationURL, String authDomain,
    AsyncCallback<String> callback);
  void getCurrentUser(
    AsyncCallback<UserInfo> callback);
  void isUserAdmin(
    AsyncCallback<Boolean> callback);
  void isUserLoggedIn(
    AsyncCallback<Boolean> callback);
}

Client-side call
Let us say you have a GWT main client window with a MenuBar.
public class MainMenuBar
extends Composite{
  private final UserServiceWrapperAsync userInfo =
    GWT.create(UserServiceWrapper.class);
  .....

  final Command doLogin = new Command(){
    @Override public void execute() {
      userInfo.createLoginURL(
        "googleLoggedin.jsp",
        loginCallback
      );
    }
   
    AsyncCallback<String> loginCallback = new AsyncCallback<String>()
    {
      @Override
      public void onSuccess(String loginUrl) {
        popupFrame.showPage(loginUrl, "Google Log-in");
      }
     
      @Override
      public void onFailure(Throwable caught) {
        Window.alert(caught.getMessage());
      }
    };
  ....
}

On your MenuBar, you would have a MenuItem [Log in to Google].

  • On clicking this item, it would execute a Command doLogin to either create a NamedFrame in the main window or show a DialogBox embedded with a NamedFrame.
  • Here, popupFrame is the instance of a class extension of DialogBox, which creates a NamedFrame by providing it with the Google login URL.
  • The NamedFrame would access that URL where a Google server would display the Google Accounts log-in page.
  • When users authenticate their account with Google successfully, Google server would redirect the page to the URL of your page which is stored in the String entryPointURL.
  • Hopefully, you have provided a close button on your DialogBox or NamedFrame to either close the frame or the DialogBox.
  • On closing the DialogBox or Frame, the onClose listener would trigger the MenuBar to update itself to show the current user.

The MenuBar would fire a RPC call
userInfo.getCurrentUser()
to the server in order to list the user.

To logout, a MenuItem [Log out] would similarly fire a RPC call to the server
userInfo.createLogoutURL
go through the whole whatnots similar to logging in.

Tuesday, May 11, 2010

Using Vaadin with Google App Engine

Under the current situation of misalignment between Google and Vaadin in creating a project in Eclipse, to develop Vaadin applications that would work with Google Plugin for Eclipse, a few minor hurdles need to be jumped over. This tutorial outlines the simple steps that need to be taken to create a Vaadin project in Eclipse that runs on Google App Engine development environment.

Presuming the Google Plugin for Eclipse is already installed, follow the instructions found in http://vaadin.com/eclipse to install the Vaadin Plugin for Eclipse using [Help - Install new software] in Eclipse.

Have you ever wondered why [Install new software] item is found under [Help] menu in Eclipse? The help item is not instructions on how to install new software but actually installing new software. What are the nerds at Eclipse/IBM up to with this deliberate choice of menu structure? Difference between a nerd and a geek: a geek insists on being meticulously precise, whereas a nerd insists on being meticulously imprecise.

After restarting Eclipse (Do you really need to restart Eclipse? Could we just apply changes?), create a new Vaadin project.  You will find Vaadin section listed under the [New] menu item. If it is not within the first page of menu items, you would have to find it under [Other ...].
  • Give the project a name. Let's say you called it Zebra.
  • Set [Vaadin:Deployment configuration] to Google App Engine Servlet.
  • Choose the Vaadin version, or click download to download the latest one. This step may not be necessary because it is one of the causes of the project needing repair - but we have to fill in something no matter how erroneous, to be allowed to complete defining the project.
  • Then complete the rest as best as you can, before clicking [Finish].

Repairing the Vaadin project to use Google App Engine as development server
With a Vaadin project called Zebra,
  • Right-click on project Zebra for [Properties] item.
  • At [Java Build Path - Libraries tab], delete WebApps (under which is found the vaadin jar).
  • At [Google - App Engine] enable [Use Google App Engine] check box and fill the rest the best you could.

And again, voila Viola!

If you don't make these changes, you would encounter ClassNotFoundException when you try to launch the Vaadin Application. The reason being, there is disagreement of some sort between Vaadin and Google plugins on how plugins should build and dispense library references. Vaadin believes we should stick to the Eclipse standard and apparently Google has no vested interest in doing so.


You might also wish to allow OOPHM (browser plug-in debugging code server) to be used with debugging the project:
  • Delete the library references to vaadin downloaded gwt-user.jar and gwt-dev.jar files.
  • Create a new library reference for the vaadin.version.jar found in the WEB-INF/lib folder. If the jar is not found there, place a copy of the jar file there before making the library reference.
  • At [Google - Web Toolkit] enable [Use Google Web Toolkit] check box and fill the rest the best you could.
You should now be able to create a new Vaadin Application in the project from the context menu.

Do you have trouble correlating the term Out of Process Hosted Mode (OOPHM) with anything meaningful? Out of  what process? I think it is JVM-Based Browser Plug-in Hosting the Client-Side Debugging Co-Operand (of the Server-Side Debugger), which would be JVMBBPHtCSCO(oSSD). That's a mouthful. Hence, regardless being less precise, it is easier to say with a punch "Oophm!" Like someone had just punched you at the tummy.



Monday, May 10, 2010

Vaadin

Vaadin is a rather attractive JEE web application framework, where the client and server components are integrated into a single paradigm. To achieve that,
  • It uses GWT to present skeletal widgets on the client
  • Each client widget has a corresponding server widget component
  • It uses its own client-server communication channel rather than GWT RPC to connect the client and server   parts of a UI component.
  • The server component injects further presentation density into its corresponding client GWT widget skeletal by sending UIDL messages through that channel.
  • UIDL is in JSON, but with origins in XML.

It is a brilliant architecture which gives the server total management of the framework, hence freeing the programmer from having to set-up RPC communications. Entry point classes are defined by extending the Application class. The programmer merely defines classes (must implement Serializable) and instantiates objects just as in any non-webapp Java application.

Whenever a client class refers to an object or class defined in a class running on the server, vice versa, Vaadin takes care of that communication for you. The transparency between client and server resources is so seamless to the programmer that it tends to blur my karma from being conscious of whether I am working on the client or server code.

However, to extend a Vaadin component, you would not only need to construct its GWT skeletal widget but also the server side component. Therefore, you could not simply any old how take a GWT widget and deploy it within the Vaadin framework. However, within a web app, you could certainly mix and mesh Vaadin with pure GWT entry points by URLing each other.

I think Google should buy this company and integrate it with the rest of GWT and present it as GWT 3.0.

Running the Vaadin Samples
Download the latest Vaadin pack and unpack it.
Look for the vaadin-examples project in the unpacked directory and import it into Eclipse.
When the project is imported into Eclipse, look for the launch file vaadin-examples.launch. Run that launch file (by double-clicking on it, obviously).

You could also run it on the command line without importing the project into Eclipse.
Run either the file start.sh (for linux/unix) or start.bat (for Windows).

You will notice that the source files in vaadin-examples are placed within the war folder in WebContent/WEB-INF/src, because the pages of the samples allow you to view the code of the respective sample - and if the http server is to display source code, the source code has to be placed within the war structure.


Modifications required on the launcher
You might notice that examples from Vaadin tend to be hard-coded to run on http port 8888. That makes you mad because you will not be able to run more than one Vaadin example simultaneously on the same machine.

There is a class file  com.vaadin.launcher.DevelopmentServerLauncher. The programmers have created all the handles for the http port to be specified. The programmer has even written the line to read the port number that would be supplied as input argument to the Main class, but the programmer has somehow forgotten to apply that port number.

First test if Vaadin has rectified the file to read the port number. At Eclipse's Launch Configuration window, modify the Java Application launch for vaadin-examples. Find an unused port on your system. Let us say the unused port you found is 8200,  Add the the following argument at the Arguments tab
--httpPort=8200
Then, run the launch for vaadin-examples again (presuming you have stopped it in the first place). If the console output still says http port 8888 is used, they have not rectified it yet.

Here is the patched version of DevelopmentServerLauncher, that would apply the port number read as input argument:

If you wish to run the samples outside of Eclipse on the command line, you have to define an env variable (in unix/linux - a shell variable exported to system env)
VAADIN_PARAMETERS=--httpPort=8200

Voila Viola! (A former colleague had a slight habit of saying this - perhaps, his girlfriend's name was Viola.)

Friday, April 30, 2010

RESTful page caching using request parametric signature.

This article discusses how a web application could avoid regenerating a dynamic web page in the situation where a page is requested more than once or by more than one user.

I implemented this strategy in 2004 while employed with a semiconductor company in Massachusetts - i.e., it's tried and tested (using plain SQL rather than JPA and JSP rather than GWT).


The problem
There are two issues causing web page regeneration.
  1. A user needing to go back to previous pages for some information and then go forward again.
  2. Two or more independent users requesting for the same dynamically generated web page.

These issues are especially aggravating for pages that take a long time to generate.
e.g., a car-hotel-airline booking site scanning its repositories for the best deal, or an enterprise report that is generated by heavy mathematical calculations extracted from a complex combination of data sources.

There are three strategies that can help to solve this issue.
  1. Cache the web page.

  2. Cache the data extract used for generating the web page.
    A web page may need to include attributes individualised for each user and request even though the same information is being displayed. For example, the respective user name and attributes.

    This strategy is worthwhile when the complexity of extracting the data for constructing the web page is very resource consuming and that there are too many individualised user attributes on a page.


  3. Cache the components of the web page and regenerate the web page from those components.
    This is a compromise between the first two strategies. All components of the page are generated and cached except for the individualised page attributes.

Identifying web requests
In any of these solutions, there is one common and significant question to be answered first - how to identify the similarity of web requests. The simple answer is, of course, from the request parameters.

However, the answer to the question is not that simple. There are further three issues to consider before using the request parameters as page identity.
  1. Presence of parameters that do not contribute to the identity of a web page. Such additional parameters would make some web requests seem different when they are actually requesting for the same information.

  2. A cached page would become stale, when fresh data is available affecting the information being requested. Therefore, two requests with the same set of parameters may not be asking for the same web page after the the data repository has been updated.

  3. The identity of a web page is due to a large set of parameters. This is especially true for mathematically generated reports.
The solution is using a parametric signature to identify the web page.


Page signature from request LCD
First, the application architect has to design the LCD (lowest common denominators) of the request parameters of a web page. The architect should design web pages to be identifiable by the least number of request parameters.

Second, every http request to the web application must first go through a signature generator. The signature is the compressed value of LCD parameters. The signature is compared against a cache signature table in a database. If the signature is non-existent, it is stored into the table and a fresh web page is generated from the request parameters. If the signature exists, the cached page is served.

What if two or more requests arrive at the same time requesting for the same uncached page? There would be a race to create the signature record in the table. Therefore, a unique indexed-key has to be defined for the signature field.

The cache signature table comprises the columns (using JPA/JDO pseudocode):
@entity class CacheParamSig{
  @id String signature;
  String reservation;
  Datetime requestDatetime;
}

The algorithm
Let's say that a request is received. It is run through the parametric signature generator:
String paramSig = ParamSigGenerator.generate(request);

Each request races against any other to grab the CacheParamSig record and update it with its reservation semaphore:
String reservation = servername + session.getId();
The datetime of that reservation:
Datetime reservationTime = new Datetime();

First, determine if the page is cached, stale or non-existent:
if (cacheParamSig exists){

  // is another request generating the page?
  if (cacheParamSig.reservation != null){
    return PageIsGenerating;
  }

  else { // page is already generated and cached
    TimeDeterminant =
      Use request parameters to determine what database tables will be used
        to generate the page;

    // Get the latest upload time of those tables
    Datetime latestData = getLatest(TimeDeterminant);

    // is cached page stale?
    if (latestData > cacheParamSig.requestDatetime)
      grab the CacheParamSig record to generate a fresh page;

    else
      deliver the cached page to the browser;
  }
}


AJAX polling required
The browser page sending the request should be an AJAX polling loop, which should be easily implemented using GWT RPC. On receiving PageIsGenerating, the requesting page should wait and then attempt to send the request again.

If the page is stale or non-existent, the request proceeds to grab the CacheParamSig record.


Grabbing the reservation
Now, the request starts to race to grab and place a reservation on the CacheParamSig record:
transaction {
  CacheParamSig cacheParamSig =
    get CacheParamSig record using id paramSig;
  if (cacheParamSig exists){
    cacheParamSig.reservation = reservation;
    cacheParamSig.requestDatetime =  reservationTime;
    update cacheParamSig record;
  }
  else {
    cacheParamSig = new CacheParamSig();
    cacheParamSig.signature = paramSig;
    cacheParamSig.reservation = reservation;
    cacheParamSig.requestDatetime =  reservationTime;
    insert cacheParamSig record;
  }
}
at end of transaction {
  if (if transaction failed because another transaction on the record is running){
    rollback;
    return PageIsGenerating;
  }
}

In JPA-pseudocode,
the grabbing reservation race:
try
{
  transaction.begin();
  CacheParamSig cacheParamSig =
    (CacheParamSig)entityManager.find("CacheParamSig", paramSig);

  // if another request is already generating the page
  if (cacheParamSig.reservation != null){
    transaction.rollback();
    entityManager.close();
    return pageIsGenerating();
  }

  TimeDeterminant determinant = TimeDeterminant.get(request);
  Datetime latest = TimeDeterminant.latest(determinant);

  // if cached page is not stale
  if (latest < cacheParamSig.requestDatetime){
    transaction.rollback();
    entityManager.close();

    // paramSig value points to the cache where the page is stored
    return generatedPage(paramSig);
  }

  // otherwise, reserve the record to generate the page
  cacheParamSig.reservation = reservation;
  cacheParamSig.requestDatetime =  reservationTime;
  entityManager.merge(cacheParamSig);
  transaction.commit();
}

// page does not exist
// create and reserve the record to generate the page
catch (EntityNotFoundException e){
  cacheParamSig = new CacheParamSig();
  cacheParamSig.signature = paramSig;
  cacheParamSig.reservation = reservation;
  cacheParamSig.requestDatetime =  reservationTime;
  entityManager.persist(cacheParamSig);
  transaction.commit();
}

finally
{
  // if another transaction is already generating the page
  if ( transaction.isActive())
  {
    transaction.rollback();
    entityManager.close();
    return pageIsGenerating();
  }
}

// the page is cached into the folder named by the String value of paramCacheSig
generatePageIntoCache(request, paramCacheSig);


After generating the page,
  • end the reservation to tell others possibly waiting for the page, that the page generation has completed,
  • and send the page to the requesting page.
try
{
  transaction.begin();

  // tell others possibly waiting that the page generation has completed
  cacheParamSig.reservation = null;
  transaction.commit();
}
finally
{
  // this is not possible, otherwise something's wrong
  // but catch it anyway just in case

  if ( transaction.isActive())
  {
    transaction.rollback();
    entityManager.close();
    return BigTimeError;
  }

  return generatedPage(paramSig);
}


Further minutiae
This article presents a skeletal. There are minutiae that needs to be taken care of.
  1. Need to treat the case where cached page was not stale, but just at the end of transaction, another request came in and found it stale and reserved the ParamCacheSig record to regenerate the page and is in the process of overwriting the cache while you are attempting to send the cache to the requesting page.
  2. If pageIsGenerating, The GWT RPC response should notify the requesting page each time when the current reservation was started.
  3. A job needs to be scheduled to delete stale ParamCacheSig records, to prevent the table from growing. Depending on the distribution of page possibilities, the schedule could be hourly, daily, weekly, etc.
  4. The skeletals above illustrate only the strategy of caching whole pages. Pages need not be HTML. They could be GIF, XLS, CSV, text or a combination various output formats.
Normally, there are two modes of page generating - scheduled reports and ad-hoc pages. When I implemented this strategy, I merged both modes. I created a ScheduledReports table, where each record contains a scheduled report name and its request parameters  and a JSP interface to that table for users to schedule generation of their pages.

I wrote another JSP to read this table and then to perform a http request to generate the respective page. A job scheduler was used to invoke that JSP.


Page sequence tracker
Another interesting feature I had was a page sequence tracker. In statistical analysis, frequently, the output of a page is fed as input into another page. At the start of analysis, the user would check the box for Start page sequence tracker. In statistical analysis, an analyst would try all sorts of sequences of analysis until he/she hits the jackpot of the perfect sequence. Once the jackpot is hit, the analyst would want to turn those adhoc page requests into a scheduled report. The page sequence tracker merely writes the sequence of parameters into the ScheduledReports table under a sequence group, where the reports are generated sequentially at the scheduled time.

With adhoc and scheduled pages generation performed under the same mechanism, I was even able to analyse the most frequently used parameters and turned them into scheduled reports without users knowing - and occasionally, users were congratulating me on how unbelievably quick the response to some of their more complex statistical queries had become. The pages were generated one hour before they normally sat down to start their analysis after their morning cup of coffee.

Thursday, April 29, 2010

Patch-extending an insider-traded UIBinder widget

This a continuation of the rant on insider-traded UIBinder widgets.

In this example, we wish to extend the behaviour of
com.google.gwt.user.client.ui.MenuBar. UIMenuBar is to be a patch-extension of MenuBar by retaining the package namespace com.google.gwt.user.client.ui.

MenuBar widget has an addSeparator() method. However, the addSeparator() can be used only in Java code but not in UIBinder becausee the insider-traders of UIBinder somehow left that out. Therefore, UIBinder does not have the feature to add a separator between MenuItems.

This tutorial illustrates extending MenuBar so that a separator could be added as a MenuItem of a MenuBar when using UIBinder.

package com.google.gwt.user.client.ui;

public class UIMenuBar
    extends MenuBar
{

    public UIMenuBar() {}

    public UIMenuBar(boolean vertical) {
        super(vertical);
    }

    public UIMenuBar(Resources resources) {
        super(resources);
    }

    public UIMenuBar(boolean vertical, Resources resources) {
        super(vertical, resources);
    }

    @Override
    public MenuItem addItem(MenuItem item) {
        if (item.getText().equals("!")){
            super.addSeparator();
            return null;
        }
           
        return super.addItem(item);
    }
}

Notice the package declaration of UIMenuBar masquerades as the same package as MenuBar's. This is because just as GWT compiler recognises UIMenuBar as MenuBar (due to inheritance), the GWT compiler would attempt to look for the MenuItem class within the same package.

Therefore, if we had extended UIMenuBar as
org.synthful.holymoly.UIMenuBar, the GWT compiler, due to insider-trading, would attempt to look for MenuItems class under the namespace org.synthful.holymoly rather than com.google.gwt.user.client.ui. Then we would have to extend the whole repertoire of classes associated with MenuBar, just to package them as org.synthful.holymoly. But, the shortcoming is only with MenuBar while its associated classes and widgets are rather well behaved, already UIBinder-friendly classes with which we don't wish to mess around.

Note the overridden addItem method. A separator is added instead, if the text of the MenuItem is "!".

Now you can use UIBinder to insert separators into your MenuBar:
<!DOCTYPE ui:UiBinder SYSTEM
  "http://dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder
  xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:gz="urn:import:org.synthful.gwt.widgets.client.ui"
  xmlns:g="urn:import:com.google.gwt.user.client.ui">
  <ui:with field='mainMenu'
  type='holymoly.main.client.MainMenuBar'/>
  <g:UIMenuBar ui:field="menuBar">
   <g:MenuItem ui:field="edit">Edit
     <g:MenuBar ui:field="editMenu" vertical="true">
       <g:MenuItem ui:field="editFile"
         command="{mainMenu.getEditProfileCmd}">Edit File</g:MenuItem>
     </g:MenuBar>
   </g:MenuItem>
   <g:MenuItem>!</g:MenuItem>
   <g:MenuItem ui:field="exit"
     command="{mainMenu.getExitCmd}">Exit</g:MenuItem>
  </g:UIMenuBar>
</ui:UiBinder>

The listing for UIMenuBar is at http://code.google.com/p/synthfuljava/source/browse/#svn/trunk/gwt/widgets/com/google/gwt/user/client/ui.

Extending SmartGWT widgets to be UIBinder-compliant

SmartGWT canvas widgets can seldom share space with GWT widgets. The SmartGWT canvas would push itself in-front to obstruct the visibility of GWT widgets. To share a space between the two sets of widgets, the page design needs to carefully avoid having GWT widgets intersecting into SmartGWT canvas, vice versa. Especially that any part of a GWT sub-menu or pop-up that pops into SmartGWT canvas space would not be visible.

Having understood this constraint, this article describes placing extension wrappers around SmartGWT canvas widgets to allow them to be used as UIBinder widgets. Also note that certain newer SmartGWT widgets do not work well with UIBinder.

As described in a previous article, any GWT to be used as UIBinder widgets should
be
  • an extension class of com.google.gwt.user.client.ui.Widget and
  • implement com.google.gwt.user.client.ui.HasWidgets.

The first SmartGWT widget to extend is, of course, com.smartgwt.client.widgets.Canvas, because all SmartGWT has to be placed onto a Canvas.

import org.synthful.smartgwt.client.HasWidgetsUtil;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.smartgwt.client.widgets.Canvas;

public class UICanvas
    extends Canvas
    implements HasWidgets
{
    @Override
    public void add(Widget w) {
        super.addChild(w);
    }

    @Override
    public Iterator<Widget> iterator() {
        return HasWidgetsUtil.iterator(this);
    }

    @Override
    public boolean remove(Widget w) {
        return HasWidgetsUtil.remove(this, w);
    }

}
Notice the HasWidgetsUtil import highlighted in crimson. HasWidgetsUtil contains common static methods which could be used in most wrappers.

For a Canvas object that does not inherit from com.google.gwt.user.client.ui.Widget, we need to wrap it with a class that extends Widget and expose all the methods of that Canvas object. For example, while com.smartgwt.client.widgets.tab.TabSet inherits Widget, com.smartgwt.client.widgets.tab.Tab does not.

Wrapping Tabset is as simple as wrapping Canvas:

public class UITabset
    extends TabSet
    implements HasWidgets
{   
    @Override
    public void add(Widget w){
        if (w instanceof UITab)
            super.addTab(((UITab)w).tab);
        else
            super.addChild(w);
    }
   
    @Override
    public Iterator<Widget> iterator(){
        return HasWidgetsUtil.iterator(this);
    }

    @Override
    public boolean remove(Widget w){
        return HasWidgetsUtil.remove(this, w);
    }
}
However, to be able to use UIBinder to assign a Tab as a child of a Tabset, we need to wrap the Tab class this way:

package holymoly.smartgwt.ui

import java.util.ArrayList;
import java.util.Iterator;
import org.synthful.smartgwt.client.HasWidgetsUtil;
import com.google.gwt.user.client.ui.HasWidgets;
import com.google.gwt.user.client.ui.Widget;
import com.smartgwt.client.widgets.Canvas;
import com.smartgwt.client.widgets.tab.Tab;

public class UITab
    extends Widget
    implements HasWidgets
{
    public UITab(){
        this.tab = new Tab();
    }
       
    public void add(Canvas w){
        if (this.canvas==null){
                this.canvas = (Canvas)w;
                tab.setPane(this.canvas);
            }
    }
   
    @Override
    public void add(Widget w){
        try{
            this.add((Canvas)w);
        }
        catch(Exception e){}
    }
   
    @Override
    public void clear()    {
    }
   
    @Override
    public Iterator iterator()    {
        ArrayList<Widget> wx = new ArrayList();
        wx.add(this.canvas);
        return wx.iterator();
    }

    @Override
    public boolean remove(Widget w){
        return HasWidgetsUtil.remove(this, w);
    }

    public void setCloseable(boolean closeable){
        this.tab.setCanClose(closeable);
    }
   
    public void setCloseIcon(String closeIcon){
        this.tab.setCloseIcon(closeIcon);
    }
   
    public void setCloseIconSize(String closeIconSize){
        try{
            int z = Integer.parseInt(closeIconSize);
            this.tab.setCloseIconSize(z);
        }
        catch (Exception e){}
    }
   
    public void setDisabled(boolean disabled){
        this.tab.setDisabled(disabled);
    }
   
    public void setTitle(String title){
        this.tab.setTitle(title);
    }
   
    public void setWidth(String width){
        try{
            int z = Integer.parseInt(width);
            this.tab.setWidth(z);
        }
        catch (Exception e){}
    }
   
   
    final protected Tab tab;
    private Canvas canvas;
}

Now we could comfortably use these SmartGWT widgets with UIBinder:
<ui:uibinder
  xmlns:ui="urn:ui:com.google.gwt.uibinder"
  xmlns:z="urn:import:holymoly.smartgwt.ui"
  xmlns:g="urn:import:com.google.gwt.user.client.ui">
  <z:UICanvas ui:field="canvas">
   <z:UITabset ui:field="tabset">
    <z:UITab ui:field="tab1"> closeable="true"
     closeIcon="{someResource.someicon}"
     <g:Label ui:field="tab1content">
      Hello Galaticals!
     </g:Label>
    </z:UITab>
   </z:UITabset>
 </z:UICanvas>
</ui:uibinder>

More examples are found at
http://code.google.com/p/synthfuljava/source/browse/#svn/trunk/gwt/smartgwt.

Wednesday, April 28, 2010

Extending widgets for use with UIBinder

UIBinder, as released with GWT 2, is convenient because it allows us to specify our UI structure through XML.

However, the maturity of UIBinder is left in question because many useful GWT widgets are quite unusable in UIBinder, placing in question the deployment capability of UIBinder in any practical project. Not that they are unusable, but UIBinder allows them to function only as child widgets, and hence, incapable of having children within the UIBinder framework.

This article tells you how to write wrappers around GWT widgets to make them available for use as parent widgets with UIBinder. In fact, you can even place such wrappers around SmargGWT widgets.

Rule: Must implement HasWidgets Interface.
Any GWT widget to be used with UIBinder must implement the interface
com.google.gwt.user.client.ui.HasWidgets.

HasWidgets interface requires your wrapper to make the following methods available.

void add(Widget w);
void clear();
Iterator<Widget> iterator();
boolean remove(Widget w);

This is especially true with widgets that inherit the restriction of the SimplePanel abstract widget. SimplePanel widgets can only have one child and a child is acquired through the setWidget method, without implementing the HasWidgets interface.

Exception to Rule: Otherwise, patch-extend an insider-traded widget.
There are existent UIBinder widgets which do not implement HasWidgets. This is due to GWT insider-trading with some of the repertoire of UIBinder widgets - the GWT compiler recognises the type of those widgets and has insider-coded their UIBinder child and attribute specification and constraints. The only way to overcome the unfair advantage these widgets have is by patch-extending them. We fool the GWT compiler into believing it is compiling one of its own insider-traded widgets by extending such widgets.

You might be asking, if a widget is already capable as a parent widget with UIBinder, what is the point of wrapping them? The reason is to expand the repertoire of widgets allowed to be its children. Since the GWT compiler has already insider-coded what such widgets are allowed to have as children.

What I mean by patch-extending is, placing the extension class within the same package namespace - by stealing into the namespace com.google.gwt.user.client.ui. Primarily, due to needing access to default and protected objects of the original widget.

And, what I mean by insider-trading of UIBinder widgets is the existence of parsers specialised for a bunch of widgets, where we (end-user-programmers) have scantly any way of inserting our own parser:
http://code.google.com/p/google-web-toolkit/source/browse/#svn/trunk/user/src/com/google/gwt/uibinder/elementparsers. Unless we built our own gwt-user.jar.

Wednesday, April 14, 2010

DialogPanel - DialogBox Enhancement Revisit

In http://h2g2java.blessedgeek.com/2009/07/gwt-useable-closeable-scrollable.html, I had presented a skeletal to a DialogBox with a close button on its caption bar. That article explains the reason for such an effort is because the GWT architects have gone through extraordinary lengths to ensure we cannot extend the caption bar to modify its behaviour.

However the alignment of elements in the caption bar of that skeletal is simply skeletal, without CSS to align them. Therefore, I wrote an improvement that includes alignment CSS, but it is still skeletal because the background of the caption bar is transparent and that leaves it to you to filling in the background.

This improvement class DialogPanel, besides having a more presentable caption bar,
  1. uses UIBinder to define the caption bar,
  2. extends DecoratedPanel rather than extending or patching DialogBox,
  3. no longer has a ScrollPanel, because scroll feature is best left to the end-user-programmer by setWidget method.
The event handling scheme is exactly the same as in http://h2g2java.blessedgeek.com/2009/07/gwt-useable-closeable-scrollable.html, so you should refer to that article on the handling of events for DialogPanel.

The source code is found in google code repository at
  1. http://code.google.com/p/synthfuljava/source/browse/trunk/gwt/widgets/org/synthful/gwt/widgets/client/ui/DialogPanel.java and
  2. http://code.google.com/p/synthfuljava/source/browse/trunk/gwt/widgets/org/synthful/gwt/widgets/client/ui/DialogPanel-Caption.ui.xml.

My next plan is to make the DialogPanel resize-able by mouse. So, keep a lookout for its enhancement.

Wednesday, March 10, 2010

Noise words project null percentage points

American news services like the phrase percentage points. Especially CNN and the NYT.

In statistical terms, what is percentage points?
  • The DOW rose three percentage points today.
  • The number of people who support the war in Iraq has fallen by thirty percentage points.
  • The polls show that McCain rose in popularity over Romney by a ten percentage point difference.

Why couldn't they just say,
  • The DOW rose three percent today.
  • The number of people who support the war in Iraq has fallen by thirty percent.
  • The polls show that McCain rose in popularity over Romney by a ten percent difference.

If they wanted to emphasize percent, it would have been more effective had they, instead, said
  • The DOW rose three freakin percent today.
  • The number of people who support the war in Iraq has fallen by thirty awesomest percent.
  • The polls show that McCain rose in popularity over Romney by a ten so-mother-fishering percent difference.

Use of noise words in media projects an air of pomposity and an attempt at increasing the importance of a phrase above others.

Example of noise phrases or words I find unbearable
  • Is your cup half-full or half-empty?
  • With all due respect
  • It never ceases to amaze me
  • Basically
  • In the final analysis of the matter
  • I am going to go to ...
  • quote-unquote
  • per (per your request, per the items listed in the agenda, per the frequency of meetings held, per ... arrggh)
Per is about the most annoying noise word. I think people who use it tend not to know what it actually means and don't know when its use is appropriate, except realising that the word sounds really cool, and macho. Next, is talking to someone who starts every sentence with basically.

Do not say,
I am going to go to work.
I am going to go home.

Say,
I will be going to work.
I am going home.

Otherwise, we might as well say,
I am going to going to going ... to going to go to throw up.

Try not to say, or write,
I have performed the tasks per the instructions in the manual, as agreed upon per the minutes of the meeting, per the requirement of Standard Operating Procedures which follows per ISO 9000. This was done, per our understanding that it is per the coming visit of the honourable Chief Minister of Maharashtra.

Why can't people just simply say, or write,
I have performed the tasks according to the manual, as agreed upon in the meeting, due to the Standard Operating Procedures, which complies with ISO 9000 requirements. It is our understanding that this was for the coming visit of the honourable Chief Minister of Maharashtra.

Tuesday, March 9, 2010

Don't oblige to obligate

Thirty years ago, the word obligated was not an academically accepted word. The accepted word was obliged.

The original word is oblige.

I am not obliged to accept your proposal.
Do not oblige yourself to accept her proposal.

So, if the noun for complicate is complication,
then the noun for the word oblige is obligation.

The word obligate is a reverse mis-derivation of the root from its derived noun obligation.

Anyway, obligated has been accepted into common use. Despite that, I feel obliged to continue using the word oblige rather than obligate.

I have an uncomfortable premonition that a day will come when reverse root mis-derivation of the word registration will cause people to forget that there are words such as register, registrar or registrants  but start saying,
All college registratees must registrate their courses with the respective course registrators to complete the registration cycle.

And after a few generations, it would be registratorize, registratoree, registratorer and registratorization. And in a thousand years', it would be registraterrorization.


The English word toilet is inherited from the French word toilet, which means a dressing room or dressing table. For example, eau de toilet is a phrase for a nice cologne normally dispensed in the dressing room.

Then the English decided an euphemism (dressing up of an unpleasant experience with nicer words) had to be applied to the poop room. Thence the word toilet was used. So the word toilet is actually a very pleasant and nice smelling word to describe a rather smelly situation.

Then, I am supposing, the United States of America was having many non-English speaking immigrants who had no idea of the historical pleasantness of the word toilet and their children decided that a pleasant euphemism had to be applied to the situation in place of toilet. Therefore, we now have a situation where we have bathrooms where you cannot imaginably have a bath or a shower.

In London or Mumbai, you see the signs to the toilets. In the United States, the signs are misleading because you are exhausted and tired shopping all day and you thought that American establishments were so pleasant that you could have a nice warm bath. You follow the signs and there is not a single stall with a shower or a bathtub!

I am imagining that in a hundred years' time, there would be people who would have no idea of the historical pleasantness nor have the linguistic understanding of the word bathroom and decide that a pleasant euphemism has to be used - the realityroom - because in the midst of the deluge of virtual realities in  the future, a mention of reality would be a really pleasant thought.

I encountered another mis-derived word. I was evaluating Liferay. I found it difficult to use the term intanceable.

Instance -> instantiate -> instantiable. Simple. Why do people have to coin the word intanceable? Come on!

When you go for an interview and you have to decide between accepting two jobs, pay a visit to their toilets. If you find that their toilets are unpleasant, the message you should get is that they don't care about their employees.

I find it hard to trust software that do not pay attention to human language semantics. If I find software using terminology I find unpleasant, I would probably find that piece of software hidden with features I would find unpleasant later deep in my projects.