Monday, May 05, 2008

What is getOutputMarkupPlaceholderTag

Let us take a table with 1 row and 2 columns. I want to show only one column at a time.
for example, in the pic above, first cell contains list of data with a radio button to select and a edit button. On the right side, we have editing screen with save and cancel button. Now we want to display only either of these cells.

<table>
<tr>
<td>
<div id="viewBlock">
Some content comes here
</div>
</td>
<td>
<div id="editBlock">
</div>
</td>
</tr>
</table>

On screen load, only table of contents will be shown. Now on selection of a record and click of Edit, first will be hidden and second cell will be visible.

To acheive this, we can use wicket ajax components. Say we create two webmarkupcontainers viewBlock and editBlock. Set the editBlock's visibility to false. And show it onclick of the ajax button Edit. But what happens is the first cell will be hidden but the second cell is not shown on click of edit button. This is because, when the setVisible(false) is called on a component, it is not redenered on the screen. So the placeholder is also missed on the rendered html.


<table>
<tr>
<td>
<div id="viewBlock">
Some content comes here
</div>
</td>
<td>
</td> DIV tag missing !
</tr>
</table>

Due to this, when you click on Edit button, the html code for second cell comes to the frontend but not rendered because of unavailability of parent place holder.

So we have set the getOutputMarkupPlaceholderTag property on both viewBlock and editBlock containers to true.

<table>
<tr>
<td>
<div id="viewBlock">
Some content comes here
</div>
</td>
<td>
<div id="editBlock">
</div> --No content. only place holder !
</td>
</tr>
</table>

Friday, April 04, 2008

London Wicket Event

A week ago, I reserved a seat for London Wicket Event held at Google office on April 2nd. It was the first event I attended after wetting my hands on Wicket.

To tell you the truth, Wicket is amazing. Full of flexibility, as a Java developer you get more control, no big configuration XMLs to maintain, LITTLE or NO JAVA SCRIPT !!! You can do more wonders, less coding, easy code maintenance and more over everything is JAVA.

Around 27 people in the conference room were from different companies and different domains but they were all murmuring only one buzz word "WICKET".

The event went very well with one presenter explaining about the DOJO integration with Wicket while Al gave a superb presentation on doing Photoshop like activities with our Wicket. Once it was completed, then we formed small groups discussing the solutions for various real scenarios we faced.

If you like to attend the event, watch out this space.

Saturday, December 08, 2007

Wii Trailer

I love Wii. Planning to try this soon!!

Friday, November 30, 2007

SQL Query - Order of Execution

When a query is submitted to the database, it is executed in the following order:
FROM clause
WHERE clause
GROUP BY clause
HAVING clause
SELECT clause
ORDER BY clause

So why is it important to understand this?
When a query is executed,
First all the tables and their join conditions are executed filtering out invalid references between them.
Then the WHERE clause is applied which again filters the records based on the condition given.
Now you have handful of records which are GROUP-ed
And HAVING clause is applied on the result.
As soon as it is completed, the columns mentioned are selected from the corresponding tables.
And finally sorted using ORDER BY clause.
So when a query is written it should be verified based on this order, otherwise it will lead wrong resultsets.

Example:
Recently I came across the following problem.

The original query was
SELECT DISTINCT so.departure_airport, so.airport_name
FROM special_offers so, special_offers_groups_join sogj
WHERE so.resort_code = '000170' AND so.accomodation_code = '015397'
AND so.departure_date = '2008-01-13'
AND so.nights = '7'
AND sogj.group_id = '1'
AND sogj.special_offer_id = so.special_offer_id
ORDER BY price ASC

Table data:
departure_airport airport_name price
'MAN' 'Manchester Airport' 344
'MAN' 'Manchester Airport' 288
'MAN' 'Manchester Airport' 316
'BRS' 'Bristol' 289
'BRS' 'Bristol' 345
'BRS' 'Bristol' 317
'BHX' 'Birmingham Airport' 343
'BHX' 'Birmingham Airport' 287
'BHX' 'Birmingham Airport' 315

Here the query is executed as follows:
All the records from both the tables are taken.
Conditions mentioned in the WHERE clause is applied fetching say 9 records.
Now the distinct of departure_airport and airport_name alone is taken since price is not in SELECT clause. This gives you three rows randomly selected (mostly in the order of insertion to the table!)
And the result is sorted based on price (incorrect price column due to distinct keyword).
So the output is not ordered properly based on price!

So we need to rewrite the query as follows:
All the records from both the tables should be taken.
Conditions mentioned in the WHERE clause needs to applied on the resulting resultset.
Group the resultset based on departure_airport and airport_name to get the minimum price in each group.
Departure_airport airport_name minprice
'BHX' 'Birmingham Airport' 287
'BRS' 'Bristol' 289
'MAN' 'Manchester Airport' 288

Select the columns departure_airport, airport_name and min(so.price) from the resultset.
And finally apply the ORDER By clause which orders the resultset based on the column min(so.price).
So the query should be:

SELECT so.departure_airport, so.airport_name, MIN(so.price) AS minprice
FROM special_offers so, special_offers_groups_join sogj
WHERE so.resort_code = '000170'
AND so.accomodation_code = '015397'
AND so.departure_date = '2008-01-13'
AND so.nights = '7'
AND sogj.group_id = '1'
AND sogj.special_offer_id = so.special_offer_id
GROUP BY so.departure_airport,so.airport_name
ORDER BY minprice;

Thursday, November 29, 2007

Custom Condition in ANT

Here is an example of custom ant task.

The custom condition validates the current execution time with the time interval specified.


package com.package.ant.customTask;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.condition.Condition;
import org.joda.time.DateTime;
import org.joda.time.MutableDateTime;

/**
* This class checks whether the current time lies between the specified time
* range.
*
* @author Srikanth NT
*
*/
public class BetweenTimeRangeCondition implements Condition {
private String startTimePeriod = "00:01";
private String endTimePeriod = "06:30";

/**
* @see org.apache.tools.ant.Task#execute()
*/
public boolean eval() throws BuildException {
DateTime startsAt = getValidTime(startTimePeriod);
DateTime endsAt = getValidTime(endTimePeriod);

if (startsAt.isAfter(endsAt)) {
throw new BuildException("Start time period cannot be greater than End time period.");
}

return (startsAt.isBeforeNow() && endsAt.isAfterNow());
}

/**
* Validates the given time.
* @param timePeriod
* @return
* @throws BuildException
*/
private DateTime getValidTime(String timePeriod) throws BuildException {
MutableDateTime testCalendar = new MutableDateTime();
if (timePeriod.indexOf(':') != 2 && timePeriod.lastIndexOf(':') != 2) {
throw new BuildException("Time period '" + timePeriod + "' should be in the format 'hh:mm' (24 Hour).");
}

try {
testCalendar.setHourOfDay(Integer.parseInt(timePeriod.split(":")[0]));
testCalendar.setMinuteOfHour(Integer.parseInt(timePeriod.split(":")[1]));
testCalendar.setSecondOfMinute(0);
} catch (Exception e) {
throw new BuildException("Time period '" + timePeriod + "' should be in the format 'hh:mm' (24 Hour).");
}
return testCalendar.toDateTime();
}

/**
* @param startTimePeriod
*/
public void setStartTimePeriod(String startTimePeriod) {
this.startTimePeriod = startTimePeriod;
}

/**
* @param endTimePeriod
*/
public void setEndTimePeriod(String endTimePeriod) {
this.endTimePeriod = endTimePeriod;
}

}


And in the build.xml include the following lines.

<typedef name="betweentime" classname="com.package.ant.customTask.BetweenTimeRangeCondition" classpath="BetweenTimeRangeCondition.class" />

<fail message="Failing the build.">
<condition>
<not>
<betweentime startTimePeriod="00:01" endTimePeriod="06:30" />
</not>
</condition>
</fail>