tag:blogger.com,1999:blog-352680142023-11-15T09:38:29.534-08:00A box of chocolatesJWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-35268014.post-37766326086950810572010-05-17T19:20:00.000-07:002010-05-17T19:21:55.132-07:00Install ack on mac osxmkdir ack<br />cd ack<br />wget http://search.cpan.org/CPAN/authors/id/P/PE/PETDANCE/ack-1.86.tar.gz<br />tar xzvf ack-1.86.tar.gz <br />wget http://search.cpan.org/CPAN/authors/id/P/PE/PETDANCE/File-Next-1.02.tar.gz<br />tar zxvf File-Next-1.02.tar.gz <br />cd File-Next-1.02<br />perl Makefile.PL <br />make<br />make test<br />sudo make install<br />cd ../ack-1.86/<br />perl Makefile.PL <br />make<br />make test<br />sudo make installJWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-26933561546617997462009-12-25T11:35:00.000-08:002009-12-25T11:37:03.855-08:00Change mysql root passwordAfter mysql is installed, run the following command:<div><br /></div><div>mysqladmin -u root -p password YOUR_NEW_ROOT_PASSWORD</div>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-46945212416062044342009-09-22T21:36:00.000-07:002009-09-22T21:37:00.057-07:00Back to blogNo blog for a long time...I will be back.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com1tag:blogger.com,1999:blog-35268014.post-19016534429784219012008-03-25T20:27:00.000-07:002008-03-25T20:50:57.993-07:00Google Code PasswordGoogle code provides a great integrated experience with Subversion repository. You can login into Google code with your GMail username. But be careful, you should use <a href="http://code.google.com/hosting/settings">"GoogleCode.com Password"</a> instead of the GMail password. Or you won't be able to authenticate and will get the following error:<br /><blockquote><br />svn: PROPFIND request failed on '/svn'<br />svn: PROPFIND of '/svn': authorization failed (https://projectname.googlecode.com)<br /></blockquote>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-67922115487433425862008-03-20T14:25:00.000-07:002008-03-20T14:42:13.774-07:00Intellij Ruby Plugin SetupI tried to install Intellij Ruby Plugin on Mac OS X Leopard. Following the instruction, the installation was fairly straight forward. Then I tried to add Ruby SDK into the plugin. I started with /usr/lib/ruby, /usr/bin/ruby, /usr/bin as home directory, and got "The directory selected is not a valid home for Ruby SDK". What?...My ruby installation does exist in this directory. Actually, Ruby SDK home path has to be /usr<br /><br />Hope this will save you some time...<br /><br />BTW: Intellij collapsed twice after I set up the ruby plugin. Not sure what's going on there.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com1tag:blogger.com,1999:blog-35268014.post-87187772595503243552008-02-27T15:20:00.000-08:002008-03-08T07:59:26.687-08:00SVNLabelIncrementer in CruiseControlSVNLabelIncrementer in CruiseControl is supposed to get the latest revision number for the project, and use this revision number as part of the cruisecontrol build number.<br /><br />Unfortunately, we always got the revision number from the last successful build as the new label. For example, if the local working copy has revision-10 before CruiseControl build, and the current SVN repository revision is 12. We will get 10 as the revision number even if we get revision 12 code in the build. It's kind of annoying, isn't it?<br /><br />After some investigation, we found that the SVNLabelIncrementer class was using "svnversion" command to get the revision number. Let's look at the definition of "svnversion":<br /><br /><blockquote></blockquote><span style="font-style: italic;">svnversion — Summarize the local revision(s) of a working copy.<br /><br /></span>Apparently, that's not what we want. We want the revision number of the <span style="font-weight: bold;">remote</span> repository.<br /><span style="font-style: italic;"><br /></span>In the end, we modified the code to use "svn info" to get the remote svn repository revision. I have attached the code here, hope this helps other folks.<br /><br /><blockquote style="font-style: italic;"><br />package net.sourceforge.cruisecontrol.labelincrementers;<br /><br />import org.jdom.Element;<br />import java.io.BufferedReader;<br />import java.io.IOException;<br />import java.io.InputStreamReader;<br /><br />/*<br /> To properly set this up put the following in your cruise config.xml<br /><br /> <plugin name="labelincrementer" classname="net.sourceforge.cruisecontrol.labelincrementers.SVNLabelIncrementer"><br /><br /> <labelincrementer prebuildincrementer="true" targeturl="http://remote-repo" defaultlabel="build.765" username="username" password="password"><br />*/<br /><br />public class SVNLabelIncrementer extends DefaultLabelIncrementer {<br /><br /> private String targetURL;<br /><br /> private String username="";<br /><br /> private String password="";<br /><br /><br /><br /> public String incrementLabel(String oldLabel, Element buildLog) {<br /><br /> String SVNRev = "";<br /><br /> try {<br /> SVNRev = getSvnRevision();<br /> } catch (IOException e) {<br /> e.printStackTrace();<br /> }<br /><br /> String label = getNonSubversionPartOfLabel(oldLabel);<br /> if (SVNRev == null || SVNRev.equals(""))<br /> return oldLabel;<br /><br /> return label + "." + SVNRev;<br /> }<br /><br /><span style="color: rgb(255, 0, 0);"> protected String getSvnRevision() throws IOException {</span><br /><span style="color: rgb(255, 0, 0);"> Process p = null;</span><br /><span style="color: rgb(255, 0, 0);"> try {</span><br /><span style="color: rgb(255, 0, 0);"> String[] commands = new String[]{"svn", "info", targetURL, "--username", username, "--password", password};</span><br /><span style="color: rgb(255, 0, 0);"> p = Runtime.getRuntime().exec(commands);</span><br /><br /><span style="color: rgb(255, 0, 0);"> BufferedReader stdInput = new BufferedReader(new</span><br /><span style="color: rgb(255, 0, 0);"> InputStreamReader(p.getInputStream()));</span><br /><span style="color: rgb(255, 0, 0);"> String thisLine = stdInput.readLine();</span><br /><span style="color: rgb(255, 0, 0);"> while (thisLine != null) {</span><br /><span style="color: rgb(255, 0, 0);"> if (thisLine.startsWith("Revision:")) {</span><br /><span style="color: rgb(255, 0, 0);"> return thisLine.split(":")[1].trim();</span><br /><span style="color: rgb(255, 0, 0);"> }</span><br /><span style="color: rgb(255, 0, 0);"> thisLine = stdInput.readLine();</span><br /><span style="color: rgb(255, 0, 0);"> }</span><br /><span style="color: rgb(255, 0, 0);"> } finally {</span><br /><span style="color: rgb(255, 0, 0);"> if (p != null)</span><br /><span style="color: rgb(255, 0, 0);"> p.destroy();</span><br /><span style="color: rgb(255, 0, 0);"> }</span><br /><span style="color: rgb(255, 0, 0);"> return "";</span><br /><span style="color: rgb(255, 0, 0);"> }</span><br /><br /> public boolean isValidLabel(String label) {<br /> return super.isValidLabel(getNonSubversionPartOfLabel(label));<br /> }<br /><br /> private String getNonSubversionPartOfLabel(String label) {<br /> int index = label.lastIndexOf(".");<br /> if (index == -1)<br /> index = label.length();<br /> return label.substring(0, index);<br /> }<br /><br /> public String getTargetURL() {<br /> return targetURL;<br /> }<br /><br /> public void setTargetURL(String targetURL) {<br /> this.targetURL = targetURL;<br /> }<br /><br /> public String getUsername() {<br /> return username;<br /> }<br /><br /> public void setUsername(String username) {<br /> this.username = username;<br /> }<br /><br /> public String getPassword() {<br /> return password;<br /> }<br /></labelincrementer></plugin><blockquote></blockquote> public void setPassword(String password) {<br /> this.password = password;<br /> }<br />}<br /><br /><br /><br /></blockquote>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com1tag:blogger.com,1999:blog-35268014.post-78099014688762693842007-09-10T17:16:00.000-07:002007-09-10T17:33:33.661-07:00Install and Config MPlayer on Ubuntu<span class="on" style="display: block;" id="formatbar_CreateLink" title="Link" onmouseover="ButtonHoverOn(this);" onmouseout="ButtonHoverOff(this);" onmouseup="" onmousedown="CheckFormatting(event);FormatbarButton('richeditorframe', this, 8);ButtonMouseDown(this);"></span>I tried to install realplayer on Ubuntu 7.0.4, no luck, even if I fixed the RealPlayer and SCIM conflict. Suggested by Yi, I decided to install MPlayer.<br /><br />Follow the instruction on: <a href="http://ubuntuguide.org/wiki/Ubuntu:Feisty#How_to_install_MPlayer_Multimedia_Player">http://ubuntuguide.org/wiki/Ubuntu:Feisty#How_to_install_MPlayer_Multimedia_Player</a>, to install MPlayer.<br /><br />There was some extra steps to get MPlayer to play a rmvb file on my Vostro 200 box with Intel GMA 3100(G33) graphics card and DELL E207WFP wide screen LCD.<br /><br />Error code: error opening/initializing the selected video_out (-vo)device<br />Solution: Open a mplayer, select configure (right click mouse --> Preferences) select Video section and after select xv or x11<br /><br />Error code: cannot find the codec matching -vo and video format 0x30345652<br />Solution: install codec available in aptitude using the command:<br /><br /><span style="font-style: italic;">sudo aptitude install gstreamer0.10-pitfdll gstreamer0.10-ffmpeg gstreamer0.10-gl gstreamer0.10-plugins-base gstreamer0.10-plugins-good gstreamer0.10-plugins-bad gstreamer0.10-plugins-bad-multiverse gstreamer0.10-plugins-ugly gstreamer0.10-plugins-ugly-multiverse libxine-extracodecs w32codecs</span><br /><br />Error: The video does not zoom correctly<br />Solution: <span style="font-style: italic;">sudo gedit /etc/mplayer/mpalyer.conf</span><br />and uncomment the following setup:<br /><span style="font-style: italic;"> monitoraspect=16:9</span><br /><span style="font-style: italic;"> zoom=true</span><br /><br />Now I could play the rmvb video files without any problems. Next time, I'll get audio fine tuned.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com1tag:blogger.com,1999:blog-35268014.post-89737502533105295522007-09-09T12:46:00.000-07:002007-09-09T12:50:18.268-07:00Google Pinyin only supports Windows OSI can't imagine that Google Pinyin does not support Linux/Unix OS.<br /><span style="font-style: italic;"></span><blockquote><span style="font-style: italic;">系统要求</span><br /><span style="font-style: italic;">Microsoft Windows 2000 SP4 / XP / Vista</span><br /><span style="font-style: italic;">Internet Explorer 6.0+</span><br /></blockquote>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-23114137439015383702007-09-09T12:34:00.000-07:002007-09-09T12:44:41.860-07:00How to beautify Chinese characters using Windows fonts in Ubuntu如何使用xp带的字体来进行Ubuntu中文美化<br /><br />The font comes with Ubuntu looks really ugly. Here is a way to beautify Chinese Characters using Windows fonts like SimSun.<br /><br />Copy simsun.ttc, tahoma.ttf from windows/fonts directory to /usr/share/fonts/zh_CN/TrueType,then update Ubuntu fonts list using the following command:<br /><br /><blockquote style="font-style: italic;">sudo mkdir -p /usr/share/fonts/zh_CN/TrueType<br />sudo cp simsun.ttc /usr/share/fonts/zh_CN/TrueType/<br />sudo cp tahoma.ttf /usr/share/fonts/zh_CN/TrueType/<br />sudo chmod 644 /usr/share/fonts/zh_CN/TrueType/*<br />cd /usr/share/fonts/zh_CN/TrueType/<br />sudo mkfontscale<br />sudo mkfontdir<br />sudo fc-cache /usr/share/fonts/zh_CN/TrueType/<br /></blockquote>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-203029332347771012007-09-08T23:18:00.000-07:002007-09-10T05:37:50.658-07:00Install and config Ubuntu on Vostro 200Last week, I bought a new Vostro 200 from Dell with $4xx. Since I started working, I have not really worked on Linux environment at any client site. I feel that I'm disconnected from Linux, and it's the time to pick it up.<br /><br />After I consulted several folks, I decided to go with the latest Ubuntu Desktop(7.04). Installation is straight forward. Downloading image, create installation CD, install it like Windows...After two hours, I had Ubuntu desktop running on my machine.<br /><br />Oh, yeah!... But, wait...it's not done yet...and the pain starts...It took me quite a bit of time to have everything configured correctly. I would like to share my experience with other folks.<br /><br />Firstly, I could not connect to network It looks like Ubuntu did not have the right Ethernet driver. The network card comes with the mother board, and it's supposed to use Intel(R) PRO/10/100/1000/10GbE Drivers. Here is what I did:<br /><ul><li>Download e1000-7.6.5.tar.gz from <a href="http://sourceforge.net/project/downloading.php?group_id=42302&use_mirror=internap&filename=e1000-7.6.5.tar.gz&63333463">http://sourceforge.net/project/downloading.php?group_id=42302&use_mirror=internap&filename=e1000-7.6.5.tar.gz&63333463</a></li></ul><ul><li>tar xfvz e1000-7.6.5.tar.gz</li><li>cd e1000-7.6.5/src</li><li>sudo make install</li><li>sudo modprobe e1000</li></ul>Now you should see a wired connection available.<br /><br />The next big problem was graphics card and monitor. The machine came with Intel GMA 3100(G33), but the driver comes with Ubuntu is out of date. Ubuntu only showed resolution up to 1280x1024, and it tried to stretch Dell E207WFP LCD to use this resolution. To fix the graphics card driver issue, I downloaded xserver-xorg-video-intel_2.1.0-1ubuntu1_i386.deb from <a href="http://ubuntuforums.org/attachment.php?attachmentid=37549&d=1183829057">http://ubuntuforums.org/attachment.php?attachmentid=37549&d=1183829057</a>, you need have an account to download this file, double click the file and follow the prompt to install the driver. Instructed by an Ubuntu forum post, I modifed /etc/X11/xorg.conf to use the latest driver: In "Device" section, change Driver from "vesa" to "intel".<br /><br />Restarted the computer, I see graphics card driver recognized. But after I logged into my account, the monitor went black and the following appeared in bright yellow in the middle of the window:<br /><br /><blockquote><span style="font-style: italic;">1: Analog Input</span><br /><span style="font-style: italic;">Cannot Display The Video Mode</span><br /><span style="font-style: italic;">Optimum Resolution 1680x1050 60 Hz</span></blockquote><br /><br />To solve this issue, I had to modify xorg.conf again, and put my monitor HorizSync/VertRefresh frequency in the "Monitor" section, as well as add wide screen resolution "1680x1050" into "Screen"-->"Display"-->"Modes" section.<br /><br />This is a sample xorg.conf file with my changes highlighted(<span style="font-weight: bold;">just find your own monitor specs and make corresponding changes, don't copy it to your configuration</span>):<br /><blockquote style="font-style: italic;"><br />Section "InputDevice"<br />Driver "wacom"<br />Identifier "cursor"<br />Option "Device" "/dev/input/wacom"<br />Option "Type" "cursor"<br />Option "ForceDevice" "ISDV4" # Tablet PC ONLY<br />EndSection<br /><br />Section "Device"<br />Identifier "Generic Video Card"<br />Driver <span style="color: rgb(255, 0, 0);">"intel"</span><br />BusID "PCI:0:2:0"<br />EndSection<br /><br />Section "Monitor"<br />Identifier "DELL E207WFP"<br />Option "DPMS"<br /><span style="color: rgb(255, 0, 0);"> HorizSync 30-83 </span><br /><span style="color: rgb(255, 0, 0);"> VertRefresh 56-75</span><br />EndSection<br /><br />Section "Screen"<br />Identifier "Default Screen"<br /># Device "Intel"<br />Device "Generic Video Card"<br />Monitor "DELL E207WFP"<br />DefaultDepth 24<br />SubSection "Display"<br />Depth 1<br />Modes <span style="color: rgb(255, 0, 0);">"1680x1050"</span> "1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"<br />EndSubSection<br />SubSection "Display"<br />Depth 4<br />Modes <span style="color: rgb(255, 0, 0);">"1680x1050" </span>"1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"<br />EndSubSection<br />SubSection "Display"<br />Depth 8<br />Modes <span style="color: rgb(255, 0, 0);"> "1680x1050" </span>"1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"<br />EndSubSection<br />SubSection "Display"<br />Depth 15<br />Modes <span style="color: rgb(255, 0, 0);">"1680x1050"</span> "1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"<br />EndSubSection<br />SubSection "Display"<br />Depth 16<br />Modes <span style="color: rgb(255, 0, 0);">"1680x1050"</span> "1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"<br />EndSubSection<br />SubSection "Display"<br />Depth 24<br />Modes <span style="color: rgb(255, 0, 0);">"1680x1050"</span> "1280x1024" "1152x864" "1024x768" "800x600" "720x400" "640x480"<br />EndSubSection<br />EndSection<br /><br />Section "ServerLayout"<br />Identifier "Default Layout"<br />Screen "Default Screen"<br />InputDevice "Generic Keyboard"<br />InputDevice "Configured Mouse"<br />InputDevice "stylus" "SendCoreEvents"<br />InputDevice "cursor" "SendCoreEvents"<br />InputDevice "eraser" "SendCoreEvents"<br />EndSection<br /><br />Section "DRI"<br />Mode 0666<br />EndSection<br /></blockquote><br /><br />Hope my experience will help.<br /><blockquote></blockquote>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com3tag:blogger.com,1999:blog-35268014.post-54642818744729235722007-09-07T09:18:00.000-07:002007-09-07T09:22:04.933-07:00"Skipped" Unit Tests<span style="font-style: italic;">Tests run: 11, Failures: 0, Errors: 0, Skipped: 5</span><span><br /><br />This is a test report from a client CruiseControl site. What's the point to write unit tests and have them "skipped"?<br /></span>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-74282746107207098652007-08-26T06:30:00.000-07:002007-08-27T15:14:16.547-07:00FitNesse and PerforcePerforce is a pessimistic locking version control system(all checked-in files are read only). FitNesse requires the files are open for edit while you make changes. It's a pain when you see "no permission" error until you save you changes, especially for QA folks who just transferred from manual testing to automated testing.<br /><br />To solve this issue, we added a link in the FitNesse website, which allows them to make all the FitNesse "open for edit":<br /><br />1. Implement Responder class(let's name it P4EditResponder) in FitNesse, and include it in Fitnesse classpath. And the code can be as simple as one line:<br /><span style="font-style: italic;"> Runtime.exec("p4 edit //FITNESSE_ROOT/...");<br /></span><br />2. Add plugins.properties in the FitNesse working directory, including the following item:<br /> <span style="font-style: italic;">Responders=p4edit:P4EditResponder<br /></span><br />3. Now you can use it in your FitNesse page:<br /> <span style="font-style: italic;">[[Open For Edit][?responder=p4edit]]</span><br /><br />4. Done! It's simple like that.<br /><br />Check out <a href="http://fitnesse.org/FitNesse.PluginUsage">http://fitnesse.org/FitNesse.PluginUsage</a> if you still have issue.<br /><br />I still have some issues with FitNesse and Perforce, any help is appreciated:<br /><br />1. How to add a directory recursively into Perforce using windows command line? I would like to add another link on FitNesse page to allow QA folks to add new files into Perforce and checkin all the changes.<br /><br />2. How does Perforce ignore works? I would like to ignore FitNesse version control and not checking in the zip files generated by FitNesse version control. Or just disable version control when FitNesse generates a new page.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com1tag:blogger.com,1999:blog-35268014.post-65592272081063985862007-04-11T14:49:00.000-07:002007-04-11T14:55:07.363-07:00Google was caught by stealing Sohu Pinyin dictionarySeveral days ago, I talked about the new Google Pinyin. Unfortunately, the latest news says that Google stole Sohu's Chinese dictionary: <a href="http://www.chinadaily.com.cn/bizchina/2007-04/11/content_847897.htm">http://www.chinadaily.com.cn/bizchina/2007-04/11/content_847897.htm</a>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-2959514837271085072007-04-05T19:35:00.000-07:002007-04-08T13:52:38.317-07:00Google just released Pinyin Input methodGoogle just released its Chinese input method: <a href="http://tools.google.com/pinyin/">http://tools.google.com/pinyin</a>. It works very similar to Ziguang input(紫光). As always, you will not be disappointed by Google. As a big google fan, I'll say bye-bye to 紫光.<br /><br />个人感觉Google还能火很长一段时间。昨天刚刚发布的Google Pinyin,今天在mitbbs上就已经被炒得十分火爆了。 Google就靠这些简单实用的小软件培养了一批铁杆的Google迷,想想它的市场会有多大。JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-20252206414856674552007-04-03T19:47:00.000-07:002007-04-05T20:21:22.441-07:00Hibernate Exception - Simultaneously Fetch Multiple BagsToday I bumped into the following Hibernate exception:<br /><br /><pre style="border: 1px solid rgb(0, 0, 0); padding: 0.02in; background: rgb(230, 230, 230) none repeat scroll 0% 50%; margin-bottom: 0.2in; -moz-background-clip: -moz-initial; -moz-background-origin: -moz-initial; -moz-background-inline-policy: -moz-initial;"><span style=";font-family:Times New Roman,serif;font-size:11;" ><br />javax.persistence.PersistenceException: org.hibernate.HibernateException: cannot simultaneously fetch multiple bags<br /> at org.hibernate.ejb.Ejb3Configuration.createEntityManagerFactory(Ejb3Configuration.java:217)<br /> at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:114)<br /> ........</span></pre>What's the problem? Because I have multiple one-to-many mappings in my hibernate object, and all of them require EAGER loading.<br /><br />Check out this link: <a href="http://jroller.com/page/eyallupu?entry=hibernate_exception_simultaneously_fetch_multiple">http://jroller.com/page/eyallupu?entry=hibernate_exception_simultaneously_fetch_multiple</a>, it shows you three ways to fix the issue.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-1071713677420501672007-03-24T20:07:00.000-07:002007-04-05T20:11:42.052-07:00ThoughtWorks is hiring...Thoughtworks is hiring in US right now. If you want to work with cool and smart people, check it out: <a href="http://www.thoughtworks.com/jobs/United-States-Job-Openings.html">http://www.thoughtworks.com/jobs/United-States-Job-Openings.html</a>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-41157456276979853162007-03-03T21:37:00.000-08:002007-04-05T20:12:01.665-07:00How to display an image within a JSP from DatabaseI'm using Spring/Struts2/Hibernate in my current project. We have a requirement to upload an image into database, then display that image on the website within a jsp page. We wrote a servlet to stream out the image from database, but there is no way to test the code outside of the web container.<br /><br />Then I tried to find a way to inject the Spring beans into the Servlet. Fortunately, Spring provides FrameworkServlet: <span style="font-style: italic;">Base servlet for servlets within the web framework. Allows integration with an application context, in a JavaBean-based overall solution. </span>By extending FrameworkServlet, I could load Spring WebApplicationContext by setting "contextConfigLocation" parameter in web.xml.<br /><br />This above solution made my code much simpler. Unfortunately, I still could not test the code outside of the web container, since it's so difficult to setup WebApplicationContext from a unit test. In the end, I had to do some tradeoff, by overwriting the initFrameworkServlet() method in FrameworkServlet, I could unit test the rest of the code but this method.<br /><span style="font-size:85%;"><br /><span style="font-style: italic;"></span></span><blockquote><span style="font-size:85%;"><span style="font-style: italic;">public class ImageStreamServlet extends FrameworkServlet {</span><br /><br /><span style="font-style: italic;"> private MyService myService;</span><br /><br /><span style="font-style: italic;"> protected void setMySerivce(MySerivce myService) {</span><br /><span style="font-style: italic;"> this.myService= myService;</span><br /><span style="font-style: italic;"> }</span><br /><br /><span style="font-style: italic;"> @Override</span><br /><span style="font-style: italic;"> protected void doService(HttpServletRequest request,</span><br /><span style="font-style: italic;"> HttpServletResponse response) throws Exception {</span><br /><br /><span style="font-style: italic;"> String id = request.getParameter("id");</span><br /><span style="font-style: italic;"> MyObject myObject = MyService.findById(Long.parseLong(id));</span><br /><span style="font-style: italic;"> if (myObject != null) {</span><br /><span style="font-style: italic;"> response.reset();</span><br /><span style="font-style: italic;"> response.setContentType(myObject.getImageType());</span><br /><span style="font-style: italic;"> IOUtils.write(myObject .getImageData(), response</span><br /><span style="font-style: italic;"> .getOutputStream());</span><br /><br /><span style="font-style: italic;"> }</span><br /><br /><span style="font-style: italic;"> /**</span><br /><span style="font-style: italic;"> * This method is not covered by test...</span><br /><span style="font-style: italic;"> */</span><br /><span style="font-style: italic;"> protected void initFrameworkServlet() throws ServletException {</span><br /><span style="font-style: italic;"> super.initFrameworkServlet();</span><br /><span style="font-style: italic;"> myService = (MyService ) getWebApplicationContext()</span><br /><span style="font-style: italic;"> .getBean("myService ");</span><br /><span style="font-style: italic;"> }</span><br /><br /><span style="font-style: italic;">}</span></span><br /></blockquote><br />Basically, MyService can be mocked out in my test now:)JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-58815952079709916632007-02-01T21:10:00.000-08:002007-04-05T20:12:28.047-07:00First Impression of RubyThis week, I attended a company internal ruby/rails training.<br /><br />Here is some thoughts after the training:<br /><br />Technically:<br />1. Ruby on rails uses <a href="http://softwareengineering.vazexqi.com/files/pattern.html">convention over configuration</a>. The only so called configuration file is "routes.rb". Feeling the pain of adding/modifying 5+ files to create one web page in Tapestry/Spring/Hibernate application, "convention over configuration" is definitely a no-brainer.<br />2. Ruby class is never final. You can override/overwrite a method on the fly.<br />3. Implementing a "filter" in Ruby on Rails is simple comparing to Java Servlet Filters. It's plain ruby code, and can be easily tested.<br /><br />Future:<br />Ruby/rails requires high quality developers. If you don't have developers following TDD and other agile principles, the project can easily be screwed up. So consulting companies with high quaility developers can easily get high rate for the work.<br /><br />Consulting companies always try to chase the latest and greatest technology to achieve their financial goals. But with strong typed language like Java or .Net, consulting rate went down quickly after a lot of "regular" developers moved over. But Ruby itself has raised the bar, those companies who have chased ruby/rails should be able to charge the high rate for a longer period of time comparing to java/.net.<br /><br />On the other hand, due to the above reason, I don't think Ruby/Rails can compete the market with Java/.Net in the near future.<br /><br />Questions:<br />1. How is the general performance of the ruby application?<br />2. How does Ruby on Rails work with legacy code/database?<br />3. When will the Ruby open source continuous integration server available?<br />4. For people used to strong typed language, what's the easiest way to switch over?<br />5. Ajax and RoR?JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-82296376677078558472006-12-21T14:20:00.000-08:002007-04-05T20:12:46.248-07:00Timeout in CruiseControlIn my Cruisecontrol setup, I need to make an ant call to ruby scripts. Originally, I setup CruiseControl timeout in AntBuilder, somehow it could not kill ruby process. CruiseControl will wait till the end of ruby process, and show timeout error in the report.<br /><br />I started looking at Ant exec task timeout, <exec timeout="18000"> which I expect the process times out after 5 hours, but the build always times out within one minute.<br /><br />What's wrong?<br /><br />Don't laugh at me. Cruisecontrol AntBuilder use <span style="font-weight: bold;">seconds </span>to measure timeout, but Ant Exec task uses <span style="font-weight: bold;">milliseconds</span>!</exec>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-74676122737487115562006-12-18T22:08:00.000-08:002006-12-18T22:12:52.507-08:00How to start Organizational TransformationIn big companies, how to start working on Agile Organizational Transformation? Starting from selected projects is a good idea. Picking various projects is extremely important. You may want to pick projects to cover different business domains, platform, programming languages, etc.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-62866676708951729812006-12-05T13:37:00.000-08:002006-12-05T20:30:09.979-08:00Organic Java Developers?Today at lunch time, we went to SF ferry building farmer's market to get some coffee. Everything in the market had a marker "organic", and the price was crazily expensive. Paulo, one of my colleagues, said, we should name ourselves organic java developers. We use open source tools, cage free:) <br /><br />Sure, you could not be called organic java developers several months ago, because Java itself was not open source yet. Now you can:)JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-77747525272799592362006-11-13T22:10:00.000-08:002006-11-13T23:05:14.710-08:00Ruby on rails for startups?Ruby on rails is one of the hottest buzz words at this moment. Comparing R/R to the current J2EE and .Net. I would like to raise a question about the performance and scalability, since I have not found any industrial data yet. <br /><br />Until the performance/scalability is proved, I treat R/R as a great tool for startup companies. Startup companies should be able to dive into their prototype quickly and raise the money based on the prototype. But what they are going to do next...is a secret:)JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com1tag:blogger.com,1999:blog-35268014.post-57567388974837730772006-11-02T12:07:00.000-08:002007-08-27T18:09:47.274-07:00CruiseControl setup for multiple projects/releases<p face="Verdana" size="10pt" style="margin: 0in;">I tried to set up <a href="http://cruisecontrol.sourceforge.net/">CruiseControl </a>to handle multiple releases among different projects. All the projects share the same build scripts (which is a whole build project, sounds odd, ah?).</p><p face="Verdana" size="10pt" style="margin: 0in;"><br /></p> <p face="Verdana" size="10pt" style="margin: 0in;">My original plan for the file structure was:</p> <p face="Verdana" size="10pt" style="margin: 0in;"> </p> <p face="Verdana" size="10pt" style="margin: 0in;">___CruiseControl (cc installation)</p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">|__projects___ config.xml</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___webapps</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___trunk</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___release1</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___release2___build</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___project1_quick</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___project1_nightly</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___project2_quick___checkout</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___target</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___logs</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___artifacts</p><p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><br /></p> <p style="margin: 0in; font-family: Tahoma; font-size: 8pt; color: rgb(102, 102, 102);"> </p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">With this file structure, everything related to the project is under one directory tree. If you want to remove an obsolete project from cc, you don't have to delete files from multiple places. </p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;"> </p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">But I hit a road blocker when I tried to set up logs and artifacts. There is no way to archive the above goal if I don't modify CC source code. I could make the build without any problem, but the reporting system crashes. Since CC index page will look for projects under default logs directory. After considering the design carefully, I think it makes sense for CC to setup this way, since it will avoid another setup to tell cc the available projects.</p><p style="margin: 0in; font-family: Verdana; font-size: 10pt;"><br /></p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;"> </p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">Now I will change projects directory setup to a flat file structure like what I did at other clients:</p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;"> </p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">___CruiseControl (cc installation)</p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">|__projects___ config.xml</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___webapps</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___checkout</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|<span style=""> </span>|___trunk-build</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|<span style=""> </span>|___release1-build</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|<span style=""> </span>|___release2-build</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|<span style=""> </span>|___trunk-project1-quick</p><p style="margin: 0in 0in 0in 1in;font-family:Verdana;font-size:10pt;"><span style=""></span>|<span style=""></span> |___release-project1-nightly</p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;"><span style=""> </span>||<span style=""> </span>...</p> <p style="margin: 0in 0in 0in 0.5in;font-family:Verdana;font-size:10pt;"><span style=""> </span>|___target (the same as checkout)</p> <p style="margin: 0in 0in 0in 0.5in; font-family: Verdana; font-size: 10pt;"><span style=""> </span>|___logs (the same as checkout)</p> <p face="Verdana" size="10pt" style="margin: 0in 0in 0in 0.5in;"><span style=""> </span>|___artifacts (the same as checkout)</p><p face="Verdana" size="10pt" style="margin: 0in 0in 0in 0.5in;"><br /></p> <p style="margin: 0in 0in 0in 0.5in; font-family: Verdana; font-size: 10pt;"> </p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;">But I'm still wondering if there is a better way to remove obsolete projects/release branches easily.</p> <p style="margin: 0in; font-family: Verdana; font-size: 10pt;"> </p>JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-70024556852436216732006-10-26T12:39:00.000-07:002006-10-31T16:58:18.131-08:00OOPSLA 2006Last week, I attended the <a href="http://www.oopsla.org/2006/">OOPSLA 2006</a> at Portland, OR. For the last several years, I tried several times to register for this conference. Every time, my registration was canceled due to different reasons. Finally, I made it in 2006:)<br /><br />In general, it's a great conference with great hot topics, like AOP (Aspect oriented programming), MDD (Model driven design). On the other hand, I was a bit disappointed because it's more academic than industrial oriented. There was no talks about "Web2.0" during the whole conference. After more than 6 years of work in various industries, I'm more concerned about the actual usage than academic research.<br /><br />There was an interesting talking: <a href="http://www.oopsla.org/2006/submission/onward/the_geography_of_programming.html">The Geography of Programming</a>. But it's just the start of the search. I'm curious to see more search result coming out.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0tag:blogger.com,1999:blog-35268014.post-1159915662475289492006-10-03T15:29:00.000-07:002006-10-31T16:57:49.893-08:00Leaving Instiki, joining TracRecently, I helped a team to solve their wiki problem. They were using a Ruby wiki named <a href="http://www.instiki.org/">Instiki </a>0.10. The wiki stopped creating snapshot after one server power outage. In the end, it took 40 minutes to restart the wiki.<br /><br />Firstly, I upgraded Instiki to the latest version which is using database. But several unexpected problems happened afterwards:<br /><ol><li>We got segmentation error from time to time, and Instiki automatically shuts down. The error comes from sqlite driver.<br /></li><li>Server runs out of memory several times a day, and Instiki automatically shuts down.<br /></li><li>The performance of the page is unbearble. It takes 30 seconds to do a search with around 1000 pages.<br /></li></ol>After doing some research, we decided to move away from Instiki. Trac was picked as our new Wiki. Luckly, in Instiki, we could export all your pages into textile files. With the help from Simon, my colleague, I created a simple textile to trac wiki converter using Perl. It will look through the input directory for all the files with .textile extension, convert them into trac format, and dump the new files into specified directory. Then we used "trac-admin wiki load" command to load these pages into your trac wiki. Bingo!<br /><br />The script was not perfect. I had to manually change several pages manually. At least, it's a good start. If anybody wants to get the script, feel free to shoot me an email.JWhttp://www.blogger.com/profile/11411066144394956652noreply@blogger.com0