Friday, December 08, 2006
Wednesday, December 06, 2006
Check .NET Framework version
%systemroot%\Microsoft.NET\Framework
The folder contains .NET Framework folders which represent versions:
.NET Framework product version | Service pack level | Version |
.NET Framework 1.0 | Original release | 1.0.3705.0 and 7.0.9466.0 |
.NET Framework 1.0 | Service pack 1 | 1.0.3705.209 |
.NET Framework 1.0 | Service pack 2 | 1.0.3705.288 and 7.0.9502.0 |
.NET Framework 1.0 | Service pack 3 | 1.0.3705.6018 and 7.0.9951.0 |
.NET Framework 1.1 | Original release | 1.1.4322.573 and 7.10.3052.4 |
.NET Framework 1.1 | Service pack 1 | 1.1.4322.2032 (if you have the MSI-based 1.1 SP1 installed) or 1.1.4322.2300 (if you have the OCM-based 1.1 SP1 installed on Windows Server 2003) and 7.10.6001.4 |
.NET Framework 2.0 | Beta 1 | 2.0.40607.16 and 8.0.40607.16 |
.NET Framework 2.0 | Beta 2 | 2.0.50215.44 and 8.0.50215.44 |
.NET Framework 2.0 | Original release | 2.0.50727.42 and 8.0.50727.42 |
.NET Framework 2.0 | Service pack 1 | 2.0.50727.1433 and 8.0.50727.1433 |
.NET Framework 2.0 | Service pack 2 | 2.0.50727.3053 and 8.0.50727.3053 |
.NET Framework 3.0 | Original release | 3.0.04506.26 (on Windows Vista) and 3.0.04506.30 (on downlevel operating systems) |
.NET Framework 3.0 | Service pack 1 | 3.0.04506.648 |
.NET Framework 3.0 | Service pack 2 | 3.0.04506.2152 |
.NET Framework 3.5 | Original release | 3.5.21022.8 and 9.0.21022.8 |
.NET Framework 3.5 | Service pack 1 | 3.5.30729.1 and 9.0.30729.1 |
.NET Framework 4 | Original release | 4.0.30319.1 and 10.0.30319.1 |
Saturday, November 25, 2006
AJAX Matters Blog » AJAX Tutorials
Tuesday, November 21, 2006
How To Build A PC -- The Tom's Hardware Guide
The first step in building a system is to choose the right components. These general guidelines should help the new or rusty builder avoid common mistakes that might otherwise turn cash into trash.
read more | digg story
Monday, November 20, 2006
MAKE IT A POINT TO READ THIS !!!
shorter tempers, wider freeways, but narrower viewpoints. We spend more,
but have less. We buy more, but enjoy less. We have bigger houses and smaller families, more conveniences, but less time. We have more degrees but less sense, more knowledge, but less judgment, more experts, yet more problems, more medicine, but less wellness.
We spend too recklessly, laugh too little, drive too fast, get too angry, stay up too late, get up too tired, read too little, watch TV too much, and pray too seldom. We have multiplied our possessions, but reduced our values. We talk too much, love too seldom, and hate too often. We've learned how to make a living, but not a life. We've added years to life not life to years.
We've been all the way to the moon and back, but have trouble crossing the street to meet a new neighbor. We conquered outer space but not inner space. We've done larger things, but not better things. We've cleaned up the air, but polluted the soul. We've conquered the atom, but not our prejudice. We write more, but learn less. We plan more, but accomplish less. We've learned to rush, but not to wait. We build more computers to hold more information, to produce more copies than ever, but we communicate less and less.
These are the times of fast foods and slow digestion, big men and small character, steep profits and shallow relationships. These are the days of two incomes but more divorce, fancier houses, but broken homes. These are days of quick trips, disposable diapers, throwaway morality, one night stands, overweight bodies, and pills that do everything from cheer, to quiet, to kill.
It is a time when there is much in the showroom window and nothing in the stockroom.
Remember, spend some time with your loved ones, because they are not going to be around forever. Remember, say a kind word to someone who looks up to you in awe, because that little person soon will grow up and leave your side. Remember, to give a warm hug to the one next to you, because that is the only treasure you can give with your heart and it doesn't cost a cent.
Remember, to say, "I love you" to your partner and your loved ones, but most of all mean it. A kiss and an embrace will mend hurt when it comes from deep inside of you. Remember to hold hands and cherish the moment for someday that person will not be there again.
Give time to love, give time to speak and give time to share.
Friday, November 17, 2006
Lamborghini Police Car
Tuesday, November 14, 2006
Monday, November 06, 2006
Friday, November 03, 2006
MacOS X Demo
This is a demonstration of what the Mac OS can do, particularly if you are a new user to the Mac or if you've never had one and are wondering what it can do for you or if it is something you would like to try. |
Wednesday, November 01, 2006
For Saurada...With Love
This post is dedicated to Saurav Ganguly. The most successful captain in the history of Indian cricket. His aggressiveness, his attitude, his behaviour, good or bad, was an inspiration for me. His aggressiveness was a lesson for me in the life to face it, straight in its eyes, without fear.
I was one of those people who stopped watching cricket, or lost interest in cricket, after Saurav’s elimination from the team. Does the
The reason for writing this is, I saw an advertisement of Pepsi, on Saurav cheering for Team
The Ad was really touching, starting Saurav saying “ I am Saurav Ganguly, Hope you people didn’t forgot me, for what was happened last few months, I was really upset and angry. Now I forgot all and trying to return the team by working hard, who knows weather I get one more chance to wave my shirt in the field once again, for celebrating victory”………………Its continues and last he is saying “ Cheer for India, don’t u follow your Dada’s words”
It is agreed Ganguly is running in a bad patch for a long time. But is
The Australian Media said, yesterday, “yes we once feared Team
Is motivation is the important thing needed for a leader, I think so…..All will say he is arrogant, rude…yes he is…It is that arrogance that make Steve Waugh wait for dada for a toss, it’s the same aggressiveness that bring Killer Instinct in the team. It is with the same arrogance he shown while supporting Yuvraj Singh, Harbhajan Sing, and Virender Sehvag while they were in the early days and were not performing. But the great leader kept confidence in him, and that we all know how they proved to us that how much important are them to the team.
Team
It’s a known thing that Sachin also played an important role in expelling Saurav from team, but one should notice that he was at his best while playing under Saurav, than any other captain.
All captains in the world agree unanimously that it is His Presence, which changes the Team to an unbeatable one. Under him they won the ICC champions trophy (even though they shared it with Srilanka due to rain) and reached the finals of World Cup only after 1983.
I cheer for him, Come back DADA………….
Saturday, October 28, 2006
Ten reasons Linux and BSD are vastly superior to Windows - Part I
read more | digg story
Friday, October 27, 2006
Steve Jobs' Best Quotes Ever
read more | digg story
Sunday, October 15, 2006
40+ Ways to Make Money on the Internet
read more | digg story
Sunday, October 08, 2006
What the Internet could have been like
read more | digg story
Sunday, September 10, 2006
CSS tips and tricks!
รข��ve been writing CSS for about 2 years now and I still feel like every time I open up a blank file and begin writing CSS for a new design I learn something new.
For those of you that are new to CSS or experts always looking for a new trick, here are some of things I do on a regular basis to keep my code organized (kind of).
read more | digg story
Wednesday, August 23, 2006
Ball tampering: learn the craft
So what exactly is ball tampering and how is it done? Former India skipper Krishnamachari Srikkanth takes us through the intricacies.
read more | digg story
Indian masala for Queen's English
A case in point of the post-colonial success of English is that the word Hinglish (Hindi plus English) is now officially an English word, meriting a place in the new Indian edition of the Concise
read more | digg story
Great lessons from Dhirubhai Ambani
read more | digg story
The 5 secrets of making wealth
read more | digg story
The Mother of All Windows XP Tweaking Guides
read more | digg story
Hack Attack: Top 10 Ubuntu apps and tweaks
read more | digg story
Hacking Into Almost Any Windows XP Machine, With Just A Few Tricks.
read more | digg story
Cheat Sheet: Web 2.0
read more | digg story
Tuesday, August 22, 2006
Internet Explorer 7 v FireFox 2.0 comparison
read more | digg story
Linux Shell Scripting Basics
read more | digg story
Look At All These Passwords!
read more | digg story
Bill Gates gets an invoice from a unhappy customer
read more | digg story
Monday, August 21, 2006
Why Was Gandhi Never Awarded the Nobel Peace Prize?
read more | digg story
Thursday, August 17, 2006
CSS Frames
read more | digg story
5 HTML elements you probably never use (but perhaps should)
read more | digg story
Saturday, August 05, 2006
Saying the right thing at the right time
He takes the aspirins and notices a note on the table. "Honey, breakfast is on the stove, I left early to go shopping. Love You!" So he goes to the kitchen and sure enough there is a hot breakfast and the morning newspaper. His son is also at the table, eating. Martin asks, "Son, what happened last night?"
His son says, "Well, you came home around 3 AM, drunk and delirious. Broke some furniture, puked in the hallway, and gave yourself a black eye when you stumbled into the door."
Confused, Martin asks, "So, why is everything in order and so clean, and breakfast is on the table waiting for me? I should expect a big quarrel with her!"
His son replies, "Oh, that! Mom dragged you to the bedroom, and when she tried to take your clothes n shoes off, you said, "Lady leave me alone! I'm married!"
Moral
Self-induced hangover -- $100.00
Broken furniture -- $2,000.00
Breakfast -- $10.00
Saying The Right Thing While Drunk- PRICELESS
Wednesday, August 02, 2006
Getting Yahoo! Mail Beta!!
1. Log in to your Yahoo Mail account
2. On the top left, besides “mail” button, there is one down arrow, click there..
3. Go to “option”
4. On the left panel, click on account information…
5. Click on “edit” under membership information
6. In the last panel..u will find “yahoo content”, which would be something like, U.S.-English, or India or something…click on it
7. Select “English-United Kingdom”
8. Save changes
9. Go back to your mail window..
10. Now keep this window open, and in a new window, open www.mail.yahoo.com, and login…u’ll get an invitation to join “yahoo mail beta version”!!!!
You can change the content back to ur country, no probs watsoever.
Monday, July 31, 2006
DR. A. P. J. Abdul Kalam's Speech in Hyderabad
Why are we in India so embarrassed to recognize our own strengths, our achievements? We are such a great nation. We have so many amazing success stories but we refuse to acknowledge them. Why?
We are the first in milk production.
We are number one in Remote sensing satellites.
We are the second largest producer of wheat.
We are the second largest producer of rice.
Look at Dr. Sudarshan, he has transferred the tribal village into a self-sustaining, self-driving unit. There are millions of such achievements but our media is only obsessed in the bad news and failures and disasters.
I was in Tel Aviv once and I was reading the Israeli newspaper. It was the day after a lot of attacks and bombardments and deaths had taken place. The Hamas had struck. But the front page of the newspaper had the picture of a Jewish gentleman who in five years had transformed his desert into an orchid and a granary.
It was this inspiring picture that everyone woke up to. The gory details of killings, bombardments, deaths, were inside in the newspaper, buried among other news.
In India we only read about death, sickness, terrorism, crime. Why are we so NEGATIVE? Another question: Why are we, as a nation so obsessed with foreign things? We want foreign T. Vs, we want foreign shirts. We want foreign technology.
Why this obsession with everything imported. Do we not realize that self-respect comes with self-reliance? I was in Hyderabad giving this lecture, when a 14 year old girl asked me for my autograph. I asked her what her goal in life is. She replied: I want to live in a developed India.
For her, you and I will have to build this developed India . You must proclaim. India is not an under-developed nation; it is a highly developed nation. Do you have 10 minutes? Allow me to come back with a vengeance.
Got 10 minutes for your country? If yes, then read; otherwise, choice is yours.
YOU say that our government is inefficient.
YOU say that our laws are too old.
YOU say that the municipality does not pick up the garbage.
YOU say that the phones don't work, the railways are a joke, The airline is the worst in the world, mails never reach their destination.
YOU say that our country has been fed to the dogs and is the absolute pits.
YOU say, say and say. What do YOU do about it?
Take a person on his way to Singapore . Give him a name - YOURS. Give him a face - YOURS. YOU walk out of the airport and you are at your International best. In Singapore you don't throw cigarette butts on the roads or eat in the stores. YOU are as proud of their Underground links as they are. You pay $5 (approx. Rs. 60) to drive through Orchard Road (equivalent of Mahim Causeway or Pedder Road) between 5 PM and 8 PM. YOU come back to the parking lot to punch your parking ticket if you have over stayed in a restaurant or a shopping mall irrespective of your status identity... In Singapore you don't say anything, DO YOU? YOU wouldn't dare to eat in public during Ramadan, in Dubai. YOU would not dare to go out without your head covered in Jeddah. YOU would not dare to buy an employee of the telephone exchange in London at 10 pounds ( Rs.650) a month to, 'see to it that my STD and ISD calls are billed to someone else.'YOU would not dare to speed beyond 55 mph (88 km/h) in Washington and then tell the traffic cop, 'Jaanta hai main kaun hoon (Do you know who I am?). I am so and so's son.
Take your two bucks and get lost.' YOU wouldn't chuck an empty coconut shell anywhere other than the garbage pail on the beaches in Australia and New Zealand .
Why don't YOU spit Paan on the streets of Tokyo ? Why don't YOU use examination jockeys or buy fake certificates in Boston??? We are still talking of the same YOU. YOU who can respect and conform to a foreign system in other countries but cannot in your own. You who will throw papers and cigarettes on the road the moment you touch Indian ground. If you can be an involved and appreciative citizen in an alien country, why cannot you be the same here in India ?
Once in an interview, the famous Ex-municipal commissioner of Bombay , Mr.
Tinaikar, had a point to make. 'Rich people's dogs are walked on the streets to leave their affluent droppings all over the place,' he said.
'And then the same people turn around to criticize and blame the authorities for inefficiency and dirty pavements. What do they expect the officers to do? Go down with a broom every time their dog feels the pressure in his bowels?
In America every dog owner has to clean up after his pet has done the job.
Same in Japan . Will the Indian citizen do that here?' He's right. We go to the polls to choose a government and after that forfeit all responsibility.
We sit back wanting to be pampered and expect the government to do everything for us whilst our contribution is totally negative. We expect the government to clean up but we are not going to stop chucking garbage all over the place nor are we going to stop to pick a up a stray piece of paper and throw it in the bin. We expect the railways to provide clean bathrooms but we are not going to learn the proper use of bathrooms.
We want Indian Airlines and Air India to provide the best of food and toiletries but we are not going to stop pilfering at the least opportunity.
This applies even to the staff who is known not to pass on the service to the public. When it comes to burning social issues like those related to women, dowry, girl child! and others, we make loud drawing room protestations and continue to do the reverse at home. Our excuse? 'It's the whole system which has to change, how will it matter if I alone forego my sons' rights to a dowry.' So who's going to change the system?
What does a system consist of ? Very conveniently for us it consists of our neighbours, other households, other cities, other communities and the government. But definitely not me and YOU. When it comes to us actually making a positive contribution to the system we lock ourselves along with our families into a safe cocoon and look into the distance at countries far away and wait for a Mr.Clean to come along & work miracles for us with a majestic sweep of his hand or we leave the country and run away.
Like lazy cowards hounded by our fears we run to America to bask in their glory and praise their system. When New York becomes insecure we run to England . When England experiences unemployment, we take the next flight out to the Gulf. When the Gulf is war struck, we demand to be rescued and brought home by the Indian government. Everybody is out to abuse and rape the country. Nobody thinks of feeding the system. Our conscience is mortgaged to money.
Dear Indians, The article is highly thought inductive, calls for a great deal of introspection and pricks one's conscience too.... I am echoing J.
F. Kennedy's words to his fellow Americans to relate to Indians.....
'ASK WHAT WE CAN DO FOR INDIA
AND DO WHAT HAS TO BE DONE TO MAKE INDIA WHAT AMERICA AND OTHER WESTERN COUNTRIES ARE TODAY'
Lets do what India needs from us.
Thank you,
Dr. Abdul Kalaam
( PRESIDENT OF INDIA )
Saturday, July 22, 2006
Thought for the day..
Playright Tom Stoppard, quoted in the London Express.
Make it thought for the year, or...probably thought for the rest of your life...
Wednesday, July 19, 2006
Its all about life..
Remember, spend some time with your loved ones, because they are not going to be around forever. Remember, say a kind word to someone who looks up to you in awe, because that little person soon will grow up and leave your side. Remember, to give a warm hug to the one next to you, because that is the only treasure you can give with your heart and it doesn't cost a cent.
Remember, to say, "I love you" to your partner and your loved ones, but most of all mean it. A kiss and an embrace will mend hurt when it comes from deep inside of you. Remember to hold hands and cherish the moment for someday that person will not be there again.
Give time to love, give time to speak and give time to share.
HAVE A WONDERFUL DAY!!!
Sunday, May 28, 2006
Top 25 Free New York Experiences
- Walk across the Brooklyn Bridge
- Gaze up at the ceiling of the New York City Public Library's
Reading Room - Marvel at the bustle of Grand Central Terminal
- Ride the Staten Island Ferry for awesome views of the city and the Statue of Liberty (free)
- Listen in on a choir rehearsal at St. Thomas Church
- Browse the art galleries in Chelsea and Soho
- Check out famous film sites
- Visit the Bronx Zoo (free on Wednesdays; donation suggested)
- Be entertained by Washington Square Park's street performers
- Walk Somewhere and Everywhere
- Whitney Museum of American Art (Friday 6-9 pm; pay what you wish)
- Play in Central Park
- Museum of Modern Art (Free Fridays 4-8 pm)
- Smell the flowers at the New York Botanical Garden (free Sat. 10-noon; Wed.)
- Head to Brooklyn for the thrills of Coney Island's Astroland ($2-5 a ride)
- Catch Shakespeare in the Park
- Metropolitan Museum of Art ($15 suggested donation)
- Kayak on the Hudson at the Downtown Boathouse (free)
- Attend a reading at one of the city's many independent bookstores
- Watch a free flick during the summer in Bryant Park
- Catch a free show at the Apple store in Soho
- See what's moored at Pier 63
- Check out the sculptures in Madison Square Park
- Pick up lunch at the Shake Shack
- Enjoy Free Wi-Fi: Bryant Park, Battery Park, Union Square Park
Tuesday, March 28, 2006
Google Adsense Ads gets disabled
Upon contacting them further, they kept on beating around the bush without any strong proof....haha (they never had one!) Google disabled all my friends Adsense accounts when they reached close to $40 and so unless you are a big website with CTR<1% dont ever use Adsense....it sucks BIG TIME!
Monday, March 20, 2006
Email Etiquettes
Why do you need netiquette? For two reasons: It creates an impression of professionalism. And it ensures the correct message gets across. Some simple rules, if followed while sending e-mail, make all the difference
between a good professional impression and a bad one.
Want to improve your English?
Why are you writing to me?
State the purpose of your e-mail -- it is a good practice to have a subject line that explains what follows and how high on the priority list it should be. This information has to be in two places:
i. The subject box, which is part of the compose e-mail form. Here, state the reason for your mail. If you are writing it to apply for leave, you could say 'Leave application'.
ii. Subject line in the main e-mail body;๏พ just as you๏พ would in any formal business letter. Here, you could say:
Sub: Leave application, April 1-April 15 2006
Conference call rules you must know
Greet me right!
Address people you don't know as Mr, Mrs, Ms or Dr. Address someone by first name only if you are on a first name basis with each other; it is๏พ okay, under these circumstances, to use๏พ first names on a๏พ formal business missive. If you do not know the name of the person, or whether it is a man or a woman, it is best to address the person concerned as: Dear Sir / Madam,๏พ Whomsoever it may concern,๏พ The Manager; etc.
And your point is?
Get to the point. Verbosity and extreme terseness are two ends of a spectrum, you should try for the middle -- state your point without sounding rudely brief or chatty. Remember to state your point and what you
expect from the reader of your mail in clear terms. There should also be a clear structure -- an introduction, body and conclusion.
Do introductions frighten you?
2 use or not 2 use็ชถ๏ฝฆ.
Never use 'sms-ese' or informal abbreviations in your email. U instead of you, 2 instead of to or too, plz instead of please, thanx instead of thanks and 4 instead of for are a strict no-no. While are all right for personal e-mail, they show a level of informality not encouraged in formal business communication. Frequently used abbreviations you may use include FYI (for your information), Pvt., Ltd., Co., etc.,๏พ OK.
The magic of spells็ชถ๏ฝฆ
Though using a spell check is a must, don't rely on it completely. The most common areas of errors and confusion are -- two, too and to.
For eg:
Wrong: I would like two order too other books two.
Correct: I would like to order two other books, too.
A hit or miss effort with spellings does not help -- use a dictionary.
Write right็ชถ๏ฝฆ
Good grammar is very important. A correctly framed sentence, with proper punctuation in place, is what you should aim at. Be very careful with commas, especially, as they change the meaning of a sentence.
A good example would be:
Wrong: All foreign tea, tree, oils are free from duty.
Correct: All foreign tea tree oils are free from duty.
Use action words and 'I' statements -- they evoke a sense of reassurance in the reader.
For eg:
On receipt of your earlier mail, I/ we have already set things in motion and I/ we assure you that you will receive your order on time.
I was responsible for the day-to-day working and administration of the office; planning, scheduling, and achieving targets were my areas of contribution.
Mind your P's and Q's
Though a friendly tone is encouraged, basic corporate etiquette rules do apply. So, maintain a well-mannered, friendly polite stance. Gender-neutral language is politically correct -- couch your e-mail accordingly. This essentially means you should not assume a person's gender on the basis of the designation, keep the e-mail neutral.
Attachment breeds detachment็ชถ๏ฝฆ
With worms, viruses, and spam, nobody wants to open attachments anymore, not even if the e-mail is from one's own mother. If you do need to send an attachment, confirm this with the recipient first.
Like an arrow shot from a bow็ชถ๏ฝฆ.
An e-mail is like the spoken word -- once sent, you can't recall it. By the time you press the recall button, chances are it has already reached and, with it, your recall message. This compounds the embarrassment. So,
think before you dash off something.
The KISS rules็ชถ๏ฝฆ.
Keep It Short and Simple. Use simple sentences, words that don't need a dictionary. Use universal formats -- not all systems support HTML rich style, or tables and tabs. You could lose much by way of appearances if
your recipient's system can't support all that fancy formatting you spent hours working on.
Smile please!
Smileys and other emoticons are a way to add 'body language' to e-mail. When used appropriately and sparingly, smileys do bring a touch of personalisation to otherwise impersonal mail. Of course, due care with
regards to the appropriateness of the communication must be taken. You would not use emoticons in job application covering letters, while delivering bad news (delay in order, loss of job, etc). Use discretion.
Emoticons are generally used to add comfort to the communication or soften the blow. The most common smiley faces are probably these:
:-) OR :)๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ Just a smile / can be used for greeting, or making a point gently.
:-( OR :(๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ To show mild displeasure or that something is not going the way you want it to.
;-)๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ Equivalent to a wink -- used to convey that a particular comment is a๏พ joke and๏พ not to be๏พ taken too seriously.
;->๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ ๏พ To be used sparingly, and with people you know well, as this signifies a provocative comment.
Humour doesn't travel
What seems funny to you may be offensive to someone else. Remember, humour doesn't travel well. Jokes about religion, sports, political figures, and women may come across as tasteless and should be avoided at all costs.
Swift and prompt
Be prompt in replying. That is why we have the Internet. If a prompt response were not expected, one would use the postal service.
CAPITAL, MY DEAR FELLOW
IF YOU WRITE IN CAPITALS, IT SEEMS AS IF YOU ARE SHOUTING. You could get really angry responses to your e-mail if you do so, and trigger a flame war.
Fw. Fw. Fw.
Do not forward chain letters -- simply delete them. Also avoid forwarding them to professional contacts.
Shh็ชถ๏ฝฆ It's a secret็ชถ๏ฝฆ
If it is a secret, don't send it via e-mail -- you never know where it will end up.
Connections็ชถ๏ฝฆ
Keep the thread of the message as part of your mail; this will help keep the context handy. The thread is the previous message/s in context to which this e-mail is being written. Last but not least, please, please read the e-mail before you click the 'Send' button. It will save you a lot of embarrassment and misunderstanding.
Thursday, March 09, 2006
Bridge the gap between Struts and Hibernate
Extend Struts for a more object-oriented relationship with Hibernate
Summary
Hibernate and Struts are currently among the most popular open source libraries on the market. Effectively, they are the default developer selections among competing libraries when building Java enterprise applications. Although they are often used in conjunction with one another, Hibernate was not primarily designed to be used with Struts, and Struts was released years before the birth of Hibernate. To put them to work together, some challenges remain. This article identifies some of the gaps between Struts and Hibernate, particularly related to object-oriented modeling. It also describes a solution for bridging these gaps that involves an extension to the Struts framework. All Web applications built upon Struts and Hibernate can derive benefit from this generic extension. (1,870 words; March 6, 2006)
n the book Hibernate in Action (Manning, October 2004), authors Christian Bauer and Gavin King reveal the paradigm mismatch between the two worlds of the object-oriented domain model and the relational database. Hibernate does an excellent job at the persistence layer of gluing these paradigms together; however, a mismatch remains between the domain model (the Model-View-Controller model layer) and HTML pages (the MVC view layer). In this article, we examine this mismatch and consider an approach for resolving the disparity.
The paradigm mismatch rediscovered
Let's look at a classic parent-child relationship example (illustrated in the code below): product and category. The Category
class defines an identifier id
of type Long
and a property name
of type String
. The Product
class also has an id
of type Long
as well as a property category
of type Category
, representing a many-to-one relationship with instances of the Category
class (i.e., many Product
s can belong to one Category
).
/**
* @hibernate.class table="CATEGORY"
*/
public class Category {
private Long id;
private String name;
/**
* @hibernate.id generator-class="native" column="CATEGORY_ID"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @hibernate.property column="NAME"
*/
public String getName() {
return name;
}
public void setName(Long name) {
this.name = name;
}
}
/**
* @hibernate.class table="PRODUCT"
*/
public class Product {
private Long id;
private Category category;
/**
* @hibernate.id generator-class="native" column="PRODUCT_ID"
*/
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* @hibernate.many-to-one
* column="CATEGORY_ID"
* class="Category"
* cascade="none"
* not-null="false"
*/
public Category getCategory() {
return category;
}
public void setCategory(Category category) {
this.category = category;
}
}
It is desirable that a product be re-categorized, so our HTML view provides a drop-down list of all categories to which products can be assigned:
The categoryId
field specifies the user selection of a Category
. In Struts, we define ProductForm
as an ActionForm
subclass to collect the user's inputs from the HTTP request:
public class ProductForm extends ActionForm {
private Long id;
private Long categoryId;
...
}
Here's the mismatch: in the Product
domain object, the category
property is of type Category
, whereas the ProductForm
only has a categoryId
property of type Long
. This mismatch not only increases inconsistency, but also involves special code for converting between primitive type identifiers and associated objects.
Part of this discrepancy is due to the HTML form itself: it resembles a relational model, instead of an object-oriented model. The object-oriented versus relational mismatch in the persistence layer is addressed by object-relational mapping (O/RM). The similar mismatches in the view layer still remain. The key is finding a solution to make them work together seamlessly.
Struts capabilities and limitations
Fortunately, Struts is able to render and interpret nested object properties. The category drop-down list can be rewritten using the Struts page-construction (html
) tag library:
No Category
We assume that categories
is a list of all the Category
objects. Now we can change ProductForm
to be more object-oriented by exchanging the categoryId
property for a category
property of type Category
. This change will render the copying of property values between Product
and ProductForm
a trivial task, because they have mostly the same properties and types:
public class ProductForm extends ActionForm {
private Long id;
private Category category;
...
}
Once we have created and configured the rest of the Struts actions, the configuration, validators, the JavaServer Pages (JSP), and the data persistence layer with Hibernate, and start to test, we immediately run into a NullPointerException
when accessing ProductForm.category.id
. Of course! The category
reference has not been set yet, and Hibernate also sets many-to-one associated objects to null if no value is in the corresponding database field. Struts requires all objects to be instantiated before rendering (when displaying a form) and populating (when submitting a form).
Let's look at how we bridge this gap by using ActionForm.reset()
.
(Not so) notorious Struts ActionForm
During my first week using Struts, one of my main questions was why I had to maintain exactly the same two copies of properties and getter and setter methods between domain objects and ActionForm
beans. This tedious exercise has become one of the major complaints within the Struts community.
In my opinion, ActionForm
beans exist for good reasons. First, they can be distinguished from domain objects because they serve different roles. In the MVC pattern, domain objects are part of the model layer, while ActionForm
beans are part of the view layer. Because the fields on the Webpages may differ from those in the database, some custom conversion is common. Second, the ActionForm.validate()
function comes in handy for nonstandard validation rules not covered by the validator framework. Third, there may be other custom, view-specific behavior that we require, as shown below, but don't want to implement as part of the domain layer, especially when a persistence framework manages domain objects.
Submitting a form
Let's leverage one of ActionForm
's built-in methods—reset()
—to address the mismatch between the view and model layers. The reset()
method is called before the ActionForm
properties are populated by the controller servlet when handing a request. The method is typically used when checkbox fields must be explicitly set to false
so unchecked checkboxes can be correctly recognized. reset()
is also a perfect place for instantiating associated objects required during view rendering. The code will look like this:
public class ProductForm extends ActionForm {
private Long id;
private Category category;
...
public void reset(ActionMapping mapping, HttpServletRequest request)
{
super.reset( mapping, request );
if ( category == null ) { category = new Category(); }
}
}
Before Struts populates ProductForm
with the user submitted values, it calls reset()
so the category
property will have a non-null reference. Please note that it is necessary to check category
to see if it is null as explained next.
Editing a form
So far, I have addressed the problem that occurs when a form is submitted. What about when rendering a form? The html:select
tag also expects a non-null reference, so we're going to call the reset()
method again before the form is rendered. We do that by adding a line in the action class. In our case, the EditProductAction
:
public class EditProductAction extends Action {
public final ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response ) throws Exception
{
...
Product product = createOrLoadProduct();
ProductForm productForm = (ProductForm)form;
PropertyUtils.copyProperties( productForm, product );
productForm.reset( mapping, request );
...
}
}
I assume readers are familiar with Struts action classes and the Jakarta Commons Beanutils package. The createOrLoadProduct()
method creates a new Product
instance or loads an existing record from the database, depending on whether a create or modify action is being invoked. After productForm
is populated, the productForm.category
property value is set; therefore, it is ready for rendering. We must also ensure we don't accidentally overwrite associated objects if they are indeed valid and loaded by Hibernate. So before the object is instantiated, we must check to see if it is null.
Because the reset()
method is defined in ActionForm
, we can generically rewrite the above code and move it into a superclass, e.g., CommonEditAction
, that deals with Struts action routines:
...
Product product = createOrLoadProduct();
PropertyUtils.copyProperties( form, product );
form.reset( mapping, request );
...
If you want a read-only view of a form without editing it, either check to see if the associated object is null on the JSP page or copy the domain object to the ActionForm
bean and call the ActionForm
bean's reset()
method.
Saving a domain object
We solved the problem when submitting and rendering a form, so Struts is happy. What about Hibernate? When a user selects a null ID option—in our example, the "no category" option—and submits the form, productForm.category
is a newly created Category
instance with id
equal to null. When the category
property is copied to the product
object and then persisted, Hibernate complains that product.category
is a transient object and needs to be persisted first. Of course, we know it is empty and don't want it to be persisted; so we need to set product.category
to null before the product
is persisted. We also don't want to change the way Hibernate works; so we choose to clean up these temporary objects before they are copied to the domain object by adding a method in ProductForm
:
public class ProductForm extends ActionForm {
private Long id;
private Category category;
...
public void reset(ActionMapping mapping, HttpServletRequest request) {
super.reset( mapping, request );
if ( category == null ) { category = new Category(); }
}
public void cleanupEmptyObjects() {
if ( category.getId() == null ) { category = null; }
}
}
We call the cleanupEmptyObjects()
method in SaveProductAction
right before the property values are copied from the ActionForm
bean to the domain object; so if ProductForm.category
is just the "placeholder" instance with a null ID, it will be set to null. Then ProductForm.category
will be copied to the domain object, and the corresponding property in the domain object will also be set to null:
public class SaveProductAction extends Action {
public final ActionForward execute( ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response ) throws Exception
{
...
Product product = new Product();
((ProductForm)form).cleanupEmptyObjects();
PropertyUtils.copyProperties( product, form );
SaveProduct( product );
...
}
}
One-to-many relationships
I have not yet addressed the one-to-many relationship of Category
to Product
. We can add it to the Category
metadata:
public class Category {
...
private Set products;
...
/**
* @hibernate.set
* table="PRODUCT"
* lazy="true"
* outer-join="auto"
* inverse="true"
* cascade="all-delete-orphan"
*
* @hibernate.collection-key
* column="CATEGORY_ID"
*
* @hibernate.collection-one-to-many
* class="Product"
*/
public Set getProducts() {
return products;
}
public void setProducts(Set products) {
this.products = products;
}
}
Note that setting the Hibernate cascade
property to all-delete-orphan
indicates that Hibernate should automatically persist all Product
objects in the set when persisting the containing Category
. It's not usually necessary to persist child objects along with the parent object; often, it's better to control child persistent operations separately. In our case, it is convenient to do so if we are allowing the user to edit the Category
and its Product
s on the same page. Dealing with the contained set of Product
s is fairly straightforward:
public class CategoryForm extends ActionForm {
private Set productForms;
...
public void reset(ActionMapping mapping, HttpServletRequest request) {
super.reset( mapping, request );
for ( int i = 0; i < productform =" new">
}
public void cleanupEmptyObjects() {
for ( Iterator i = productForms.iterator(); i.hasNext(); ) {
ProductForm productForm = (ProductForm) i.next();
productForm.cleanupEmptyObjects();
}
}
}
Every project will have different requirements and variations, so I am not going describe every aspect of this particular implementation. The idea here is to demonstrate how one-to-many relationships can fit into the generic solution.
Work a bit smarter
We now have no problem viewing, editing, or submitting forms, and saving associated objects, but it remains somewhat cumbersome to reset and clean up all the associated placeholder objects for each ActionForm bean. We facilitate this task by implementing an abstract ActionForm class to manage this routine job.
For the generic implementation, we must iterate over all the domain objects managed by Hibernate, discover their identifiers, and test the values. Fortunately, the org.hibernate.metadata package contains two utility classes to retrieve domain object metadata. We use the ClassMetadata class to check if the object is Hibernate-managed, and if it is, we obtain the value of its identifier property. We also leverage the utility functionality in the Jakarta Commons Beanutils package to more easily obtain JavaBean metadata:
import java.beans.PropertyDescriptor;
import org.apache.commons.beanutils.PropertyUtils;
import org.hibernate.metadata.ClassMetadata;
public abstract class AbstractForm extends ActionForm {
public void reset(ActionMapping mapping, HttpServletRequest request) {
super.reset( mapping, request );
// Get PropertyDescriptor of all bean properties
PropertyDescriptor descriptors[] =
PropertyUtils.getPropertyDescriptors( this );
for ( int i = 0; i < propclass =" descriptors[i].getPropertyType();" classmetadata =" HibernateUtil.getSessionFactory()"> // This is a Hibernate object
String propName = descriptors[i].getName();
Object propValue = PropertyUtils.getProperty( this, propName );
// Evaluate property, create new instance if it is null
if ( propValue == null ) {
PropertyUtils.setProperty( this, propName, propClass.newInstance() );
}
}
}
}
public void cleanupEmptyObjects() {
// Get PropertyDescriptor of all bean properties
PropertyDescriptor descriptors[] =
PropertyUtils.getPropertyDescriptors( this );
for ( int i = 0; i < propclass =" descriptors[i].getPropertyType();" classmetadata =" HibernateUtil.getSessionFactory()"> // This is a Hibernate object
Serializable id = classMetadata.getIdentifier( this, EntityMode.POJO );
// If the object id has not been set, release the object.
// Define application specific rules of not-set id here,
// e.g. id == null, id == 0, etc.
if ( id == null ) {
String propName = descriptors[i].getName();
PropertyUtils.setProperty( this, propName, null );
}
}
}
}
}
Our new abstract AbstractForm class extends Struts ActionForm and provides our generic behavior for resetting and cleaning up many-to-one associated objects. When the relationship cardinality is reversed (i.e., for one-to-many relationships), each case is quite different, so just implementing the custom behavior in the specific ActionForm bean implementation proves a better approach.
Our final task is to change all of our ActionForm bean classes (ProductForm, CategoryForm, etc.) to inherit from AbstractForm, instead of ActionForm.
Conclusion
Struts and Hibernate are popular and powerful frameworks that can be extended to work more effectively with one other by bridging the gap between the domain model and the MVC view. This article describes a generic implementation of such a bridge that can be used in any Struts and Hibernate project with no major changes to the existing code.