Tuesday, July 13, 2010

Eclipse RCP product export and ${target.os}

It's a fine day today. My small little Eclipse-RCP app is looking all fine and healthy.

I open my plugin.xml and click on the round, green "Launch an Eclipse application" icon and it works great.
Sometimes I use Run->Run History->and pick the latest one, and again, it works flawlessly.

Cool. Now let's package it up in an EXE.

Here's the problem.

You'd think it's just a matter of creating a product configuration file, right? Just right click on the plugin project, choose New->Product Configuration. Then select "Use a launch configuration" and point it to our trusted, tested, working launch configuration.

Do it, and it won't work. I tried it with Eclipse 3.5 (Galileo) as well as Helios, and it just doesn't work.

You application refuses to start. You look at the logs in the "configuration/" folder and you see cryptic stuff like this:

org.osgi.framework.BundleException: The activator org.eclipse.ui.internal.WorkbenchPlugin for bundle org.eclipse.ui.workbench is invalid


java.lang.NoClassDefFoundError: org.eclipse.swt.SWTError


Well, the SWT jars are there. The Windows-specific ones are there too. I *have* done a Synchronize before export, I did choose to include all dependencies, including the optional ones.

The problem, as it happens to be, is a tiny little thing called the "Program Arguments".
This is what you get by default from the new Product Configuration wizard:



And this says that the product is to be launched on an OS named "${target.os}". I have heard of Windows XP, Linux, AIX, Solaris, but never something claled ${target.os}.

Of course, the launch configuration has the same string and it works fine.. but it gets replaced by the actual value of the OS when it runs. But the poor product configuration doesn't know that and treats it verbatim.

I'm running on Windows XP, not ${target.os}. So it doesn't recognize the target platform. It doesn't recognize the platform-specific SWT JARs, and it fails.

I tired for a minute or so to figure out what the right values for these variables were for Windows XP / J2SE 5.0, but I couldn't get them. Deleting them (blanking out the Program Arguments box completely) worked for me, though. So I won't care about it until I come across a problem with it again.

Sunday, July 11, 2010

What's wrong with the JSF 2 ui:repeat

The single little thing that's been able to hold my attention repeatedly over the past few weeks in JSF 2 has been the "ui:repeat" tag.

To begin with, it's quite simple. It's so very simple that it's authors probably find it too trivial to explain what it does. This is all you get in its tag library documentation:



Ok. So it's an alternative to c:forEach, or h:dataTable, right? Maybe they just created this tag for some political reasons(if there're two more tags in the same spec and the same impl for the same purpose, you do get the doubt), but that's fine with me as long as it works.

"As long as it works".. hmm... yes.. and that's the tricky part. It seems to be that there are a number of issues with ui:repeat. Most importantly, when you have nested ui:repeats, things start behaving real crazy.

OK. So what if it has bugs? It's an alternative to c:forEach and h:dataTable, right? Let's use c:forEach instead.

And so, when you start using c:forEach, you realize that it's a totally different tag, with a totally different purpose.

Ok. So ditch that c:forEach. Let's see what the bugs with ui:repeat and apply patches ourself.

The first thing - ui:repeat doesn't recognize model updates.
The fix is quite simple. In the process method of UIRepeat, just add a simple check (as suggested by the proposed patch on the bug report):

if (PhaseId.RENDER_RESPONSE.equals(phase) && !hasErrorMessages(faces)) {
if(isNestedInIterator()){
this.childState = null;
}
}


And the second thing - ui:repeat botches up input fields - checkboxes, textboxes and all sorts of EditableValueHolders in general. That has also been reported.
The fix is pretty simple, though if you are like me, new to JSF, and stuck with it, with no other way out, you'd need to hit your head against the code for anywhere between three to five days before you figure it out.

In the populate method of the SavedState inner class, just change this one line:
this.value = evh.getValue();
to
this.value = evh.getLocalValue();




The root cause of this second bug is an API design flaw -
The JSF ValueHolder interface has two methods getValue and setValue, but interestingly, they are not complementary. That is, if you use the setValue method and push in some value, you may not get that same value out of the getValue.
Why? Because that's how it has been designed.

Defies conventions and common-sense expectations? Certainly does. Bad API? Definitely.

The method ought to be named setLocalValue, not setValue.

I wonder how these seemingly simple bugs in code and documentation seem to be around for years in such a high quality, high visibility software library.

Saturday, June 12, 2010

TinyMCE as a JSF 2 composite component

I was looking for a rich text editor that I could use on a jsf page, but quite surprisingly, there seems to be nothing useful.

So I tried creating one of my own by using TinyMCE.

It wasn't actually very tough to do.. here's what kind-of worked:

First, I downloaded TinyMCE, and then copied in the tinymce_3_3_7\tinymce\jscripts\tiny_mce folder into my WebContent/resources.

Then I created my composite component facelet file, tinymce.xhtml under the resources/editors folder.

The component itself is quite simple. It just includes the TinyMCE javascript in the head of the document, and outputs a simple text area. Configuration for TinyMCE is done in the tinymce_init.js.




In tinymce_init.js, I have:

tinyMCE.init({
mode : "specific_textareas",
theme : "simple",
debug : true,
editor_selector : "tinymce"
});

Then in my view page, I use it like this:

<h:head />
<h:body>
<h:form id="form">
<h2>Summary:</h2>
<test:tinymce value="#{bean.summary}"/>

<h:panelGrid id="details" layout="block">
<h:commandButton value="Add details..." action="#{bean.showDetails}"
rendered="#{not bean.detailsAdded}">
<f:ajax render="details" />
</h:commandButton>
<h:commandButton value="Remove details" action="#{bean.hideDetails}"
rendered="#{bean.detailsAdded}">
<f:ajax onevent="ajaxAdjust" render="details"/>
</h:commandButton>
<h:panelGrid id="details2" layout="block" rendered="#{bean.detailsAdded}">
<h2>Details:</h2>
<test:tinymce value="#{bean.details}"/>
</h:panelGrid>
<br />
</h:panelGrid>
<h:commandButton value="Save"/>
</h:form>
</h:body>



So that stuff gets saved upon AJAX postbacks, I added this to tinymce_init.js:

ajaxAdjust=function(evt){
if(evt.status=='begin'){
tinyMCE.triggerSave();
}
};


And here's what I have finally, with everything I need:
- As many rich text editors as I want on a page,
- These editors work nicely with JSF 2, VDL and f:ajax
- These are simple editors - they don't have tens of buttons and options that confuse users

Saturday, May 15, 2010

IDs, passwords and emails

I don't know why it happens so often, but it does. You register for a new account on a site, pick a password for yourself and click Submit. Voila! The account is created.

But hey, wait. Did you notice that it just sent you an email with the password in plaintext, just in case you forget it later?

There's nothing more frustrating than realizing in one glance that:
1. Your password is being stored in plaintext on their system.
2. Your password was posted on public insecure internet in plaintext.
3. Your email provider has a copy of that email, with the password in plaintext.

Saturday, April 10, 2010

Making oceans , drop-by-drop

It's amazing how some companies make good money and run profitably.

Take, for example, an advertisement I saw behind an auto-rickshaw today that offers holograms, at 1 paisa per piece. I couldn't believe it - 1 paisa is the selling price of something? I am wondering how much can the seller earn out of this? Assuming that he's selling it at double the cost, it would still get him just 0.5 paisa of profit per hologram. And because it's a company, 50% of that would be taxed. That leaves 0.25 paisa per hologram. Now, if he needs to employ one factory worker for a modest salary of Rs. 5000 per month, just count how many holograms he must make per month?

5000*100/0.25 = 20,00,000 - Twenty lakh holograms! Just to support one factory worker!

I am amazed how this works out. There must be hundreds of people working in that company - many of who would be getting much much more than 5000 Rupees per month. In addition, it needs to invest in all the massive infrastructure and logistics, and advertisements like the one I saw today.

Churning out hundreds of crores of holograms is one thing, but getting sales deals closed for such a massive amount, month on month, every single month, is another astonishing feat that I can't even imagine how it's done.

It's not just with this hologram company. Chocolates that sell for 50 paisa in small retail shops - they have a huge distribution chain to support in addition to being profitable to the manufacturer. Assuming that the retail shopkeeper gets 10 paisa, the middleman gets 10 paisa, and the manufacturer sells it at double the cost price, and pays 50% tax, he gets 80/(2*2) = 20 paisa per chocolate. And it's not at all clear to me as to how you could make crores of children eat your brand of chocolate, each month, which is what you must accomplish to remain profitable.

Fantastic, isn't it? I would love to discover how this works.. maybe some day I'll figure it out.

Friday, April 9, 2010

Agile Agile

No doubt Agile is interesting.

One of the most beautiful arguments Agile makes is that creating a grand plan upfront is not the best thing to do, because such a plan would invariably be based on a limited knowledge of what you're going to be building. That is true - as you progress on the work, you get to know more of it, and there's no point in sticking to a plan that you made when you were in ignorance of this new knowledge.

Now, let's apply the same thing to Agile itself.

Let me explain. Look at the whole thing at one level above all this. You've got a set of people who want to build something. Now you need a process that orchestrates these folks and gets the work done. Is it fair to pick a process out of the blue and apply it to the system and stick to it? You picked the process when you had limited knowledge on how it would behave. As you worked your way forward, you know more about the system, and naturally, it makes no sense to stick to that old process that you picked upfront when you were in ignorance of all this new knowledge of the system.

So, it's OK to begin by saying that let's have two-week iterations, a stakeholder demonstration at the end of the iteration, a retrospective meeting, daily scrums, planning poker, story points, incremental builds, unit tests and all this.

But then, you must *consciously* modify the process, based on your experiences of how it's going. Process changes must not come out of frustration, angry stakeholders, and sev-1 issues. It must be in the form of a proactive meta-process that continuously modifies the process to suit changing circumstances.

If someone says that "here is a standard Agile practice, follow it" - treat him with suspicion. There is really no standard. Agile is for self-motivated, self-organizing, self-improving people. It is not for those lambs that want to be told what to do. Any team that works on a set of imposed standards is a set of lambs - expect nothing heroic from it.

Thursday, April 8, 2010

Power cuts in the night

When it's night, not so deep, though, .. 7 o'clock - 9 o'clock that is, houses and streets are lit by electric tube-lights, bulbs, lamps and the like.

People are awake, and that's why they want the lights to be on.

And if there happens to be a power cut, as it happens not-so-infrequently these days in Bangalore, the lights go off.

So what do people do then? They light candles, kerosene lamps, battery-operated lamps, and backup generators. When people know that a power cut may happen, they prepare for it, so that they can get back to their work.

The larger picture is that the Sun doesn't shine all the time, and even when it does, it isn't everywhere we want. That's why we need artificial lighting in the first place.

When the Sun cuts off its power, we use our backups - the power grid, the tube-lights etc and do our work. And when our backups fail, we fall back to our secondary backups - candles, generators etc and do our work. When our secondary backups fail, we fall back to our tertiary backups - torches, cell phone flashlights etc, and do our work.

What happens all these backups fail? We open our eyes wide open and try to suck in any little piece of light that happens to stray around, and try to do our work.

And this is where the most interesting point is.

As long as we can feed our eyes enough light, we can get work done. If you want a lean-and-mean system, just do the minimum that gets the work done. The Sun is free anyway, and we don't need to worry about it, but the backups that we maintain come at a big cost. What's the point in spraying light all around in the street when there's nobody looking? What's the point spraying room full of light when the eyes in the room are not looking everywhere, every time? A lot of our backups are wasteful, and I believe that sooner or later, there will be widespread measures to contain this waste - at all levels.

I see a future where the night, even the urban night - would be dark - like a dark forest. There would be lights, of course, but just-in-time and just-the-minimum that will enable people to comfortably see. And, oh yes, everyone would have devices on their eyes that will magnify the tiny pieces of stray light - probably, something of a contact-lens that doubles up as a night vision device - or worse yet, people getting born with genetically modified eyes that can see in the night.. like a wild animal, you know..