tag:blogger.com,1999:blog-88381589311365829522024-03-13T05:13:37.046+01:00java.net.BlogTomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.comBlogger17125tag:blogger.com,1999:blog-8838158931136582952.post-59271849462323746572009-06-15T23:36:00.008+02:002009-06-16T00:05:18.137+02:00Mounting Samba shares from FirefoxEver since I dumped <a href="http://www.gnome.org/">Gnome</a> for <a href="http://icculus.org/openbox/index.php/Main_Page">pure</a> <a href="http://awesome.naquadah.org/">WMs</a> and <a href="http://live.gnome.org/Nautilus">heavy file managers</a> for their <a href="http://thunar.xfce.org/index.html">lighter counterparts</a>, my only problem was with <a href="http://us1.samba.org/samba/">samba</a> shares. I used to mount them with <a href="http://live.gnome.org/Nautilus">Nautilus</a>, Gnome's native file manager, but unfortunately, this doesn't work with <a href="http://thunar.xfce.org/index.html">Thunar</a> or <a href="http://pcmanfm.sourceforge.net/">PCManFM</a>.<br /><br />A bit of googling reveals that many people asked the question:<br /><blockquote><a href="http://www.google.com/search?q=mount+samba+shares+thunar">How can I mount samba shares in thunar?</a></blockquote>The solution usually boils down to one of these things:<br /><ul><li> Mount the share manually, using <a href="http://linux-cifs.samba.org/">mount.cifs</a></li><li><a href="http://ubuntuforums.org/showthread.php?t=304131">Mount the whole network with fuse</a> </li><li>Use a specializes application like <a href="http://www.bnro.de/%7Eschmidjo/">LinNeighborhood</a> or <a href="https://launchpad.net/pyneighborhood">pyNeighborhood</a></li></ul>None of these solutions really satisfied my requirements -- I went with manual mounting for a while, but that is a tedious task, mounting the whole network or running specializes application just seems impractical. Furthermore, I wanted to be able to mount shares just by clicking on smb:// links in firefox.<br /><br />In the end, I wrote my own solution. See it in action.<br /><br /><object height="344" width="425"><param name="movie" value="http://www.youtube.com/v/t58Y_GXT9WM&hl=en&fs=1&rel=0&hd=1"><param name="allowFullScreen" value="true"><param name="allowscriptaccess" value="always"><embed src="http://www.youtube.com/v/t58Y_GXT9WM&hl=en&fs=1&rel=0&hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" height="344" width="425"></embed></object><br /><br />It is a simple bash scripts which takes the URL and mounts all available shares. The <a href="http://github.com/kremso/smbmounter/tree/master">current version of the smbmounter script</a> can be found on github.<br /><br />Download the script and place it somewhere. Then edit it and change the variable FM to your preferred file manager (default is thunar) and variable MOUNT_ROOT to the root directory where all shares shall be placed (default is /media/samba).<br /><br />mount.cifs needs to run as root, so to be able to let the script run unattended (which is important if you want to use it from firefox) you need to set passwordless permission for either mount.cifs or this script. This can be done in /etc/sudoers. This is an example which will allow this for all members of group <i>wheel</i>.<br /><br /><pre>%wheel ALL=NOPASSWD: /sbin/mount.cifs</pre><br />For an extra paranoia, modify the script to use gksudo instead of sudo.<br /><br />Setting it as a protocol handler in firefox is a bit tricky. Following steps apply for Firefox 3.0.*, Firefox 2 configuration is slightly different and I never managed to set it in Firefox 3.5b4 (but hey, it's beta).<br /><br />Open about:config and create new <b>boolean</b> property<br /><br /><pre>network.protocol-handler.external.smb = true</pre><br />and new <b>string</b> property<br /><br /><pre>network.protocol-handler.app.smb<br /><br /></pre>Leave this one empty -- for now. Now click the smb:// link, the format should be smb://hostname_or_ip/ The dialog will appear, asking for external application to launch. Select this script and check remember. Now go and mount.Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com2tag:blogger.com,1999:blog-8838158931136582952.post-60975589990755568512009-01-19T21:20:00.005+01:002009-01-19T21:42:12.130+01:00Enigma ported to Linux<div style="float: right; margin-left: 3em; margin-top: 0px;"><script type="text/javascript">digg_url = 'http://tkramar.blogspot.com/2009/01/enigma-ported-to-linux.html';</script><script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></div> <p>Inspired by the wonderful <a href="http://lifehacker.com/5124643/enigma-desktop-customization-update-now-available">Enigma desktop by Kaelri</a>, featured at <a href="http://lifehacker.com">Lifehacker</a>, I decided to port at least some of the beautiful design to my Linux desktop.</p><p>The result is this:</p><div class="separator" style="clear: both; text-align: center;"><a href="http://4.bp.blogspot.com/_GFNxMeHpbcw/SXTRC7z2MWI/AAAAAAAAAW4/f37Nwxw-n8Y/s1600-h/2009-01-19-201153_1280x800_scrot.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://4.bp.blogspot.com/_GFNxMeHpbcw/SXTRC7z2MWI/AAAAAAAAAW4/f37Nwxw-n8Y/s320/2009-01-19-201153_1280x800_scrot.png" /></a></div><p>Compared to the original theme:</p><div class="separator" style="clear: both; text-align: center;"><a href="http://3.bp.blogspot.com/_GFNxMeHpbcw/SXTRfJTk18I/AAAAAAAAAXA/LM9_itUJY_s/s1600-h/enigma11preview.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="http://3.bp.blogspot.com/_GFNxMeHpbcw/SXTRfJTk18I/AAAAAAAAAXA/LM9_itUJY_s/s320/enigma11preview.jpg" /></a></div><p>My desktop features</p><ul> <li>Simple calendar — I even considered adding google calendar events using <a href="http://code.google.com/p/gcalcli/">gcalcli</a>, but the desktop was way too crowded</li> <li>RSS news</li> <li>Remember The Milk tasks</li> <li>Weather Forecast</li> <li>and system stats</li></ul><p>Almost everything you see is drawn on desktop using conky. There are however, few major drawbacks:</p><ul> <li>With conky you get either full transparency, or no transparency at all. It's all or nothing</li> <li>Conky cannot draw pictures.</li></ul><p>So how did I get the transparent sidebars and icons? Gotcha! They are part of the desktop background.</p><p>I also decided to omit the analog clock — this is certainly doable with <a href="http://www.gdesklets.de/">gdesklets</a> or <a href="http://www.screenlets.org/index.php/Home">screenlets</a>, but I almost fainted when I saw the dependencies. My desktop stays lightweight, no matter what. I tried the lightweight <a href="http://adesklets.sourceforge.net/">adesklets</a> but the result was disappointing.</p><p>To recreate this desktop you need:<ul> <li>"Patched" background — I provide a GIMP layered image, you just need to replace the background layer for the image of your choice</li> <li>Conky and conky configuration files</li> <li>Weather fonts — fonts displaying weather conditions (included)</li> <li><a href="http://www.rutschle.net/rtm/">RTM command line tool</a> for the RTM task list</li> <li>I am using <a href="http://code.google.com/p/tint2/">tint2</a> as the panel, but any transparent panel (such as gnome-panel) should do</li></ul></p><p>Installing the RTM command line tool might be tricky, as the author notes, you need to install RTMAgent perl module first:</p><blockquote>This package is split in two components:<ul><li>RTMAgent.pm: a Perl module that implements the low-level API. It provides a UserAgent object which lets you call all of RTM's API methods as normal Perl methods. You will need to install it from CPAN: <code>cpan install WebService::RTMAgent</code></li><li>rtm: a Perl script that uses RTMAgent to implement a command line interface. Just put it in your path.</li></ul></blockquote><p>It seems that there are two flavors of the cpan installation scripts, mine required the following syntax: <code>cpan -fi WebService::RTMAgent</code>, where <code>-fi</code> stands for <em>force install</em>, as one of the dependencies failed its unit tests. Your cpan scripts syntax might vary, check the corresponding manual first.</p><p>After installing the RTMAgent, run <code>rtm --authorise</code>, follow the generated link and allow RTM API access. This should be done only once, before the first run.</p><p>Don't forget to change your username and password in scripts/gmail.py and set your location code in scripts/conkyForecast.template. See the <a href="http://ubuntuforums.org/showthread.php?t=869328">instruction for the weather forecast config.</a></p><p>That should be all. Both wallpaper and conky configs are designed for 1280x800 resolution, you'll probably have to move things a bit for different resolutions. Unpack <a href="https://dl.getdropbox.com/u/397175/enigma-linux.zip">the attached archive</a> to ~ (archive contains hidden files, you have been warned), set the background, set up rtm, gmail and weather forecast and run ~/scripts/start_conky.</p><a href="https://dl.getdropbox.com/u/397175/enigma-linux.zip">DOWNLOAD the background and scripts.</a><p>Credits:<ul> <li><a href="http://chrfb.deviantart.com/art/quot-ecqlipse-2-quot-PNG-59941546">"ecqlipse 2" icons</a> by chrfb</li> <li>Wallpaper - packed with original enigma, author unknown.</li> <li>Weather forecast script by <a href="http://www.kaivalagi.com/">kaivalagi</a></li> <li>RTM scripts by <a href="http://www.rutschle.net">Yves Rutschle</a></li> <li>Gmail script by <a href="http://ubuntuforums.org/showthread.php?t=680265">lvleph</a></li></ul></p><p>I am aware, that the desktop still has some rough edges, but I am posting this in the spirit of<blockquote>Release early, release often.</blockquote></p><div style="float: right;"><script type="text/javascript">digg_url = 'http://tkramar.blogspot.com/2009/01/enigma-ported-to-linux.html';digg_skin = 'compact';digg_window = 'new';</script><script src="http://digg.com/tools/diggthis.js" type="text/javascript"></script></div>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com54tag:blogger.com,1999:blog-8838158931136582952.post-44473259957294157132008-09-16T20:38:00.004+02:002008-09-16T20:52:10.657+02:00Introduction to Association Rules Mining<div style="text-align: justify;">Association rules are part of every data miner's arsenal. Haven't heard about it? I am pretty sure you've had. Association rules are a substantial part of every e-shop, of every supermarket and every tool that aims to analyze data.</div><br /><div class="separator" style="clear: both; text-align: center;"><a href="http://bp3.blogger.com/_GFNxMeHpbcw/SIsolFQyHEI/AAAAAAAAAN0/U9_7lJRgO8M/s1600-h/2008-07-26-153516_1280x800_scrot.png" imageanchor="1" style="border: 0pt none ; background-color: transparent; margin-left: 1em; margin-right: 1em;"><img src="http://bp3.blogger.com/_GFNxMeHpbcw/SIsolFQyHEI/AAAAAAAAAN0/8g2vF0Y4Y-o/s400-R/2008-07-26-153516_1280x800_scrot.png" style="border: 0pt none ;" /></a></div><br /><div style="text-align: justify;">Does the picture look familiar? If you've ever bought something at amazon, you might have noticed that they are kinda obsessed with showing you items related to your order. Where do they get this information? It is not stored statically in the database, instead it is computed from the overall orders using the association rules mining algorithms.</div><br /><div style="text-align: justify;">Do you think that items in your favorite supermarket are organized randomly? No, they are organized in a way that maximizes a chance that the items are bought. Again, this is information, that can be easily discovered using association rules mining algorithms.</div><br /><div style="text-align: justify;">From the previous paragraphs you might suspect, that association rules express relations (associations) between items. More formally, association rule is an implication of form A -> B, where the left side, A, is called premise and it represents a condition which must be true, for the right side, B (conclusion) to hold. A rule A->B can be interpreted as</div><br /><div class="rule">If A happens, than B happens.</div><div style="text-align: justify;">This is a very generic interpretation, because the true interpretation depends on the domain.I am now a supermarket employee and I got following rule from the mining software:</div><br /><div class="rule">Bread -> Milk</div>The rule can be translated as:<br /><br /><div class="rule">Customers, who bought bread, also bought milk</div>Now I magically transform into a website traffic analyst and see a rule<br /><br /><div class="rule">/news/obama.html -> /sport/tour-de-france.html</div>and I instantly know that<br /><br /><div class="rule" style="text-align: justify;">those, who read news about Barrack Obama, also read news about <i>le Tour</i> and not only that, I know that those who are <i>interested</i> in Barrack Obama are <i>interested</i> in Tour de France.</div>Woosh, flash of light and I am now a doctor, looking at the rule<br /><br /><div class="rule">vasculitis -> paraneoplastic syndrome</div>and I see that there is a serious chance that my vasculitis patients will suffer paraneoplastic syndrome.<br /><br /><div style="text-align: justify;">The important thing is, that association rules helped me to discover hidden knowledge (that's why they call it data <i>mining</i>), but the more important thing is, that I can act based on the knowledge. I can move the milk closer to bread to sell more of it together and generate more income. I can recommend stuff to my e-shop visitors, I can treat my vasculitis patients and run some tests to detect paraneoplastic syndrome early and maybe save lives.</div><br /><div style="text-align: justify;">So what do you need to get started? You need data of course, but not just <i>any</i> data, you need data in a form of <i>transactions</i>. These transactions have nothing to do with the database transactions. Instead, the transaction is a logical group of somehow related items. You might have groups of market basket items, groups of links clicked on one web page visit, group of one patient's diseases.. Such groups are then called transactions.</div><br /><div style="text-align: justify;">When I said, that rule interpretation depends on domain, it was only half of the truth. The other half is, that the interpretation also depends on your transactions. The interpretation simply depends on <i>what</i> you are mining, and <i>what</i> you are mining is based on how you define your transaction.</div><br /><div style="text-align: justify;">I'll now do a simple, manual association rule mining, using the classical market basket analysis example. We define our transaction as a content of a basket.</div><br /><table id="transactions"><thead><tr><th>Transaction Id</th><th>Items</th></tr></thead><tbody><tr><td>1</td><td>bread, milk, butter, cocoa, cheese</td></tr><tr><td>2</td><td>bread, butter, milk, cheese</td></tr><tr><td>3</td><td>bread, butter, olives</td></tr><tr><td>4</td><td>milk, sugar, butter, cheese</td></tr></tbody></table><br /><div style="text-align: justify;">We have four baskets, four customers and their data. Looking at the items, we see, that transactions 1,2,3 contain bread and butter. We have just found our very first rule.</div><br /><div class="rule">bread -> butter</div>There are other rules in our data, for example rule<br /><br /><div class="rule">milk -> cheese</div><div style="text-align: justify;">found in transactions 1,2,4. Although association rule mining may seem like a very trivial task at the first look, imagine finding the rules in dataset of billions of transactions.</div><br /><div style="text-align: justify;">The rules presented so far have all one big downside. There is no way to tell which rule is <i>better</i>, it is impossible to compare them. To get past this limitation, we can add several classifiers to the rule, which will represent the strength of the rule. They are commonly known as <i>interestingness measures</i>, because the strength of the rule is equal to its interestingness.</div><br /><div style="text-align: justify;">The two classical measures, which were introduced by R. Agrawal, an association rule pioneer, are called <b>support</b> and <b>confidence</b>. Support is a measure, which represents how often did the rule apply. It is a percentage of all transaction, where the items in the rule were found.</div><br /><div style="text-align: justify;">Confidence is a percentage of all transactions, which contain items on the left and on the right side of the rule.</div><br /><div class="separator" style="clear: both; text-align: center;"></div><table id="transactions"><thead><tr><th>Id</th><th>Transactions</th><th>bread + cheese</th><th>bread -> cheese</th><th>cheese -> bread</th></tr></thead><tbody><tr><td>1</td><td>bread, cheese, honey, apples</td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td></tr><tr><td>2</td><td>milk, bread, cheese, pasta</td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td></tr><tr><td>3</td><td>milk, bread, apples</td><td><br /></td><td><img alt="X" src="http://4.bp.blogspot.com/_GFNxMeHpbcw/SM_29hzUQ7I/AAAAAAAAAQQ/qzLpXMJ3OLU/s320-R/120px-Crystal_button_cancel.svg.png" style="border: medium none ;" /></td><td><br /></td></tr><tr><td>4</td><td>bread, milk</td><td><br /></td><td><img alt="X" src="http://4.bp.blogspot.com/_GFNxMeHpbcw/SM_29hzUQ7I/AAAAAAAAAQQ/qzLpXMJ3OLU/s320-R/120px-Crystal_button_cancel.svg.png" style="border: medium none ;" /></td><td><br /></td></tr><tr><td>5</td><td>milk, pasta, cheese</td><td><br /></td><td><br /></td><td><img alt="X" src="http://4.bp.blogspot.com/_GFNxMeHpbcw/SM_29hzUQ7I/AAAAAAAAAQQ/qzLpXMJ3OLU/s320-R/120px-Crystal_button_cancel.svg.png" style="border: medium none ;" /></td></tr><tr><td>6</td><td>milk, bread, cheese</td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td><td><img alt="O" src="http://1.bp.blogspot.com/_GFNxMeHpbcw/SM_2RKXDXWI/AAAAAAAAAQI/44x4mMpmAms/s320-R/600px-Symbol_OK.svg.png" style="border: medium none ;" /></td></tr></tbody></table><br /><div style="text-align: justify;">Look at the table above. Bread and cheese can be found in transactions 1,2,6, we have total six transactions, so the support of the rule bread -> cheese and cheese -> bread is 3/6 or 50%. Now take the rule bread -> cheese. Our customers bought bread in transactions 1,2,3,4,6, but bought cheese only in transactions 1,2 and 6. So five customers bought bread, but only three of them bought also a cheese, so the support of the rule is 3/5.</div><br /><br /><div class="sidebar"><h3>Sidebar: Rules or patterns?</h3><br /><div style="text-align: justify;">Very often, these two terms are treated as synonyms. But it is not true, association rules are not the same as associations patterns. Patterns tell only <i>what</i> items are associated, whereas rules tell what items and <i>how</i> they are associated. An example of pattern might be</div><br /><div class="rule">bread, butter</div><div style="text-align: justify;">All this pattern tells is that bread and butter are bought together, but it does not tell you whether people buy bread only if they buy butter or vice versa. This also means that patterns do not have confidence, only support.</div></div><br /><div style="text-align: justify;">It should be pretty clear from the examples, that both interestingness measures are important, because they both quantify the rule and express its strength. But not only that, the interestingness measure are the key concept, that actually enables the mining.</div><br /><div style="text-align: justify;">Association rule mining is formally defined as a process of finding the rules, where the support and confidence of the rule are greater than the user provided values of minimum support and minimum confidence, further referred to as <i>minconf</i> and <i>minsup</i>. The two values actually prune the search space and make mining possible.</div><br /><div style="text-align: justify;">Take the last example. There is a rule milk -> apples [1/6, 1/1], which can be found in only one transaction. Is this rule interesting? It isn't and yet it is there. This is not a problem if we have six items in six transactions, but it would be great problem, had we thousands of items in billions of transactions. If you specify minsup=0.5, minconf=0.8 you will effectively filter out all uninteresting items. If you specify the values too low, you will end up with tons of rules, because the items will be associated with each other in all possible ways. On the other side, if you specify the values too high, you might not find a single rule. There is no universal advice as to what values should you set, the best way is to experiment.</div><br /><div style="text-align: justify;">What we'll be talking about next time? In the next posts I will show some practical examples using RapidMiner mining tool, explain the algorithm behind, tell about the problems this model has and explain why support and confidence are bad measures.<br /></div><br /><br /><div style="text-align: justify;"></div><div style="text-align: justify;"></div><div class="intro"><div class="separator" style="float: left; margin-top: -13px;"><a href="http://feeds.feedburner.com/javanetblog" imageanchor="1" style="border: 0pt none ; background-color: transparent; margin-left: 1em; margin-right: 1em;"><img src="http://bp3.blogger.com/_GFNxMeHpbcw/SI4pT6_c5KI/AAAAAAAAAOo/KEjZ7bOn0DA/s400-R/rss-orange.png" style="border: 0pt none ; height: 70px; width: 70px;" /></a></div>This is the first post in the Association Rule Mining series. Interested? Consider <a href="http://feeds.feedburner.com/javanetblog">subscribing to my feed</a> to catch up with updates.</div><script type="text/javascript">var dzone_url = 'http://tkramar.blogspot.com/2008/09/introduction-to-association-rules-minig.html';</script><br /><script type="text/javascript">var dzone_title = 'Introduction to Association Rules Mining';</script><br /><script type="text/javascript">var dzone_blurb = '';</script><br /><script type="text/javascript">var dzone_style = '2';</script><br /><script language="javascript" src="http://widgets.dzone.com/widgets/zoneit.js"></script>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com4tag:blogger.com,1999:blog-8838158931136582952.post-69893358914167291682008-07-03T21:32:00.003+02:002008-07-03T21:38:51.021+02:00HowTo: Automatically Backup Windows Machines to One Centralized Data Storage<p>I recently needed to set up an automatic backup for a few Windows workstations and few virtual machines running under VirtualBox. All data should be transferred to one standalone storage -- a RAID 0 <a href="http://www.raidsonic.de/en/pages/products/external_cases.php?we_objectID=5052" title="Icy Box product page">Icybox</a> disks.</p>
<p>Having read about <a href="http://samba.anu.edu.au/rsync/" title="incremental file transfer utility">rsync</a>, the first idea was to set up rsync to do the backup. Rsync however requires an rsync daemon, or a unix shell on both synced machines. Although it is possible to run rsync on Windows using <a href="http://www.cygwin.com/" title="Cygwin is a Linux-like environment for Windows">cygwin</a>, there is no way to get rsync running on the Icybox.</p>
<h3>Sidebar: What is rsync?</h3>
<p>To clarify things a bit: rsync is a tools for remote synchronization of files. Feed it with two arguments -- the source folder and the destination folder and it will <em>intelligently</em> sync their contents. It will not blindly copy one folder over another, it will detect which files are outdated in the destination and will only copy these, saving your bandwidth and transfer time.</p>
<h3>Working around the problem</h3>
<p>I solved the problem with Icebox and Windows machines using a third, "man in the middle" server, which is actually running rsync and performing the backup between the mounted network shares.</p>
<p>The scheme is simple. Icybox is one big smb share, so I mount it on the "middle" server (/media/shares/users-backup). Each user is sharing all folders, that need to be backed up, and they are mounted too. I mount the user shares in one parent directory (/media/shares/users/username), which allows me to run rsync recursively on /media/shares/users, so the whole mounting machinery gets transparent for rsync.</p>
<p>Running the command rsync /media/shares/users /media/shares/users-backup will nicely backup all mounted shares to the remote disk. Note, that rsync is blissfully unaware of the fact that it is syncing two remote directories -- it thinks it is doing just a local copy. It also doesn't care what shares are mounted -- what is mounted at the time rsync runs is backed up.</p>
<p>The rsync command is added to cron and it is run each day at 1:00 am. All that is required from the users is to share their backup folders. The shares might be even protected with passwords (on both sides).</p>
<h3>Show me teh code</h3>
<p>To cook this delicious meal, we would need:<br />
<ul>
<li> rsync </li>
<li> smbfs and/or cifs </li>
<li> cron </li>
</ul>
<h4>Step 1: Mount</h4>
<p>The mounting needs to be done in /etc/fstab so it can be mounted at system startup and by executing mount -a command.</p>
<p>Open the /etc/fstab file and add one line for each of your shares:<br />
<pre>//tomas/projects /media/shares/users/tomas/ smbfs ro,user,guest,nounix 0 0 </pre>
If your shares are standars Windows shares, or samba shares, use the smbfs option, if you are using nfs use cifs. Smbfs is unmantained and replaced by cifs, but unfortunately, cifs cannot resolve netbios hostnames. If your hosts are are using dhcp addresses, using hostnames instead of IPs is always a good idea.</p>
<p>It might happen that you will not be able to mount you share with smbfs. If this is the case, double check, that your share name <strong>does not end with a slash</strong>.Using //tomas/projects is ok, but using //tomas/projects/ will get you a nice "is not directory" error. If your share name is ok, but you are still unable to mount, try the cifs option.</p>
<h4>Step 2: Write the rsync script</h4>
This is nothing complicated, just run rsync and log the times. As the first thing, we remount the shares, so if someone turned on or off the computer since the last mount, we get the current state.<br />
<pre>#!/bin/bash
echo -e "\n===Rsync Start: `date` ===" >> /var/log/rsync-users.log
mount -a -o remount >> /var/log/rsync-users.log
rsync --verbose --stats --recursive --checksum --update --times/media/shares/users/ /media/shares/users-backup/ | tee -a/var/log/rsync.log
echo "===Rsync Stop: `date`===" >> /var/log/rsync-users.log</pre>
To ignore some files and directories, I use the --exclude-from option and pass it the file with each exclusion pattern on new line. The following sample is used in the script that backs up our vmware servers.<br />
<pre>.*
*.vmem
*.WRITELOCK
*.log
</pre>
<h4>Step 3: Add rsync to cron</h4>
<p>Edit /etc/crontab and add following line:<br />
<pre>1 0 * * * backup /home/backup/rsync-users</pre>
The second column specifies a user, which the script should run under.</p>
<p>That's it. The machinery starts at 1 am and all computers that are turned on are backed up. The backup is incremental so it usually takes only few minutes to resync.</p>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com0tag:blogger.com,1999:blog-8838158931136582952.post-5153978956178526012008-06-25T23:29:00.012+02:002008-08-02T10:33:18.774+02:00Create new eclipse workspace -- with all your old settingsIt's all a matter of taste. Do you like to have just one workspace for all your projects, or do you prefer to have multiple separate workspaces?<br /><br />Sure, the first way seems to be the official, supported. It should be easy to manage the workspace -- given the tools like working sets (and working set filters), mylyn and the ability to close projects.<br /><br />But I still don't get it.<br /><br />I hate when my workspace is overflowing with projects, I want to have as many workspaces as projects.<br /><br />So I create new workspace and live happily ever after.<br /><br />But wait -- all my settings are gone. All <a href="http://tkramar.blogspot.com/2008/02/effective-eclipse-v-template-mix.html">my carefully crafted custom templates</a>, all <a href="http://tkramar.blogspot.com/2007/10/effective-eclipse-ii-shortcut-keys_16.html">my keybindings</a>, <a href="http://tkramar.blogspot.com/2007/10/effective-eclipse-i-setup.html">my font settings</a>, everything is gone.<br /><h3>It's all text, fortunately</h3><br />Lucky us. All eclipse settings are saved as a plain text in the workspace directory. So if you want to create new workspace, but preserve your settings, I have two answers for you:<br /><h4>The short answer</h4>All settings are stored in the <span style="font-family:courier new;">.metadata/.plugins/org.eclipse.core.runtime/.settings</span> directory. I mean -- all relevant settings. If you look into <span style="font-family:courier new;">.metadata/.plugins</span> directory there are many more directories with settings, but they are too project specific. I've walked trough these configuration files one by one, believe me, nothing useful lies hidden there.<br /><br /><span style="font-style: italic;">So the short answer is:</span> If you want to create a new eclipse workspace and preserve all your settings, simply copy the<span style="font-family:courier new;"> .metadata/.plugins/org.eclipse.core.runtime/.settings</span> directory into your new workspace directory.<br /><h4>The long answer</h4>Let the code do the talk for me.<br />I have created a (simple) <a href="http://github.com/kremso/cpew/tree/master%2Fcpew?raw=true">shell script that automates new workspace creation</a>. The downside is that it requires either *nix or windows with <a href="http://www.cygwin.com/">cygwin</a>. It has been tested by me, I and myself so it should work (most of the time).<br /><br />To use it, save it somewhere, make it executable (<span style="font-family:courier new;">chmod +x new-workspace.sh</span>) and run it either in interactive mode<br /><pre>./new-workspace.sh -i</pre>where it will ask you the details, or with paths to your workspaces (the new workspace directory will be created for you, just specify the path)<br /><pre>./new-workspace.sh old-workspace new-workspace.</pre>If the script doesn't work for you, drop me a comment. Feel free to improve it (you may drop me a comment too).<p><strong>Update: </strong> the pastebin page expired (although I'd swear I checked the keep forever option), so I moved the script over to <a href="http://github.com/kremso/cpew/tree/master">github</a>.</p>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com4tag:blogger.com,1999:blog-8838158931136582952.post-11298774383511710252008-05-27T21:10:00.010+02:002008-05-27T22:31:47.453+02:00Making JavaDoc a bit more usableFirst of all, I know people realized <a href="http://java.sun.com/j2se/javadoc/">JavaDoc</a> is a pain in the ass to use. I am also well aware of all those "let's make better JavaDoc" projects out there. Just for reference, there is<br /><ol><li><a href="http://www.javadoconline.com/">Javadoc online</a>, which is a simple JavaDoc search engine</li><li><a href="http://www.docjar.com/">Docjar</a>, with its tiny, unintuitive flash based JavaDoc browser, which takes ages to load</li><li><a href="http://www.allimant.org/javadoc/">Windows Help format JavaDoc</a></li><li><a href="http://getahead.org/doctree/">Doctree</a> -- directory of (all) JavaDoc sites<br /></li><li><a href="http://globaldocs.info/">Globaldocs</a>, a JavaDoc browser</li></ol>I am also well aware that each modern IDE can display JavaDoc, if you configure the proper URL first.<br /><br />Call me old-fogyish, but I tried most of them and always ultimately returned to the (good?) ol' JavaDoc.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/SDxqcdw2hjI/AAAAAAAAAMI/2UBuUH8Z-FI/s1600-h/gm.png"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/SDxqcdw2hjI/AAAAAAAAAMI/2UBuUH8Z-FI/s400/gm.png" alt="" id="BLOGGER_PHOTO_ID_5205152306591860274" border="0" /></a><br />Fortunately, I found a way to cure JavaDoc's biggest wound -- it's inability to let me search for a class or a method. The cure is called <a href="http://www.greasespot.net/">Greasemonkey</a> and <a href="http://userscripts.org/scripts/show/23200">JavaDoc Search Frame</a> or <a href="http://userscripts.org/scripts/show/1428">JavaDoc Incremental Search</a> script. How does it work? <a href="https://addons.mozilla.org/en-US/firefox/addon/748">Install Greasemonkey</a> and install the script. Point your browser on some <a href="http://java.sun.com/j2se/1.5.0/docs/api/">JavaDoc site</a> and enjoy the search.<br /><br />Fortunately, it will work on (almost) all JavaDocs in the wild and requires no support from the JavaDoc creator. When the class html frame is loaded, Greasemonkey runs the script and the script automagically adds the search box.<br /><br /><h3>JavaDoc Incremental Search</h3><br />This is the older of the two scripts. It will display a search box above the class list and will filter out the classes as you type.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/SDxnmNw2hhI/AAAAAAAAAL4/DnPCNfAxPrw/s1600-h/javadoc-jis.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/SDxnmNw2hhI/AAAAAAAAAL4/DnPCNfAxPrw/s400/javadoc-jis.png" alt="" id="BLOGGER_PHOTO_ID_5205149175560701458" border="0" /></a><br /><br /><h3>JavaDoc Search Frame</h3><br />Based on the JavaDoc Incremental Search. This script completely removes the packages frame and spans the class frame vertically. It can search package names too and groups the results into packages, classes, interfaces etc.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/SDxoqNw2hiI/AAAAAAAAAMA/aeG2sCcAeIg/s1600-h/javadoc-jsf.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/SDxoqNw2hiI/AAAAAAAAAMA/aeG2sCcAeIg/s400/javadoc-jsf.png" alt="" id="BLOGGER_PHOTO_ID_5205150343791805986" border="0" /></a>Now, if only I could also search the methods..Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com1tag:blogger.com,1999:blog-8838158931136582952.post-82891210153192820752008-02-28T23:10:00.008+01:002008-02-29T01:22:45.389+01:00Effective Eclipse V: Template mixThe same way I try to avoid the redundancy in my code, the same way I try to avoid the redundancy in my writing. I am lazy and templates do the most writing for me. Eclipse comes bundled with predefined templates, but they are too general and not all of them are too useful. The real power is in custom templates. In this article I would like to show you how to create them and list few useful pieces for inspiration.<br /><h3>What are templates</h3><br />Exactly as the name suggests, templates are little pieces of code with defined placeholders. An example of simple template is<br /><pre>System.out.println(${text});<br /></pre>Each template has a name, which serves as a shortcut to the template itself. You type the name, press <span style="font-style: italic;">CTRL + SPACE</span> and it will be expanded.<br /><br />Our first template would expand to<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/R7bSx-AFpkI/AAAAAAAAAJ4/Ta2PIZwTeOE/s1600-h/templates.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/R7bSx-AFpkI/AAAAAAAAAJ4/Ta2PIZwTeOE/s400/templates.png" alt="" id="BLOGGER_PHOTO_ID_5167549378353014338" border="0" /></a>I will not explain here what it all means, I already did this in <a href="http://tkramar.blogspot.com/2007/10/effective-eclipse-iii-dont-write-code.html">my previous post on templates</a>. What is important now, is that the ${text} placeholder (variable) was highlighted and can be edited immediately.<br /><br />The true power of templates can be fully seen in more complex templates. The first power point lies in the fact, that you can have more than one variable with same name. Our second template will have more variables:<br /><pre>int ${increment} = ${value};<br />y = ${increment} + ${increment};</pre>and will expand to<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R7bUkeAFplI/AAAAAAAAAKA/rVX8WxNRMI0/s1600-h/increment.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R7bUkeAFplI/AAAAAAAAAKA/rVX8WxNRMI0/s400/increment.png" alt="" id="BLOGGER_PHOTO_ID_5167551345448035922" border="0" /></a>When you start typing now, all occurrences of <span style="font-style: italic;">increment </span>variable will be changed. You can then switch to the next variable by pressing <span style="font-style: italic;">TAB</span> key. In the end, you can have<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R7bVROAFpmI/AAAAAAAAAKI/Fd3c4APDjU0/s1600-h/increment-result.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R7bVROAFpmI/AAAAAAAAAKI/Fd3c4APDjU0/s400/increment-result.png" alt="" id="BLOGGER_PHOTO_ID_5167552114247181922" border="0" /></a>in just three key presses - one for <span style="font-style: italic;">i</span>, one for <span style="font-style: italic;">TAB </span>and one for <span style="font-style: italic;">2</span>.<br /><br />To make it even better, the template system provides predefined variables, which will be expanded depending on their context. I will not list them, you can find them under the <span style="font-style: italic;">Insert variable </span>button.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R7bWuOAFpoI/AAAAAAAAAKY/s533y3CfrKY/s1600-h/builtin-variables.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R7bWuOAFpoI/AAAAAAAAAKY/s533y3CfrKY/s400/builtin-variables.png" alt="" id="BLOGGER_PHOTO_ID_5167553711975016066" border="0" /></a>Notice, that you are not getting only a list, you are also getting a description and an usage example.<br /><br />To make it clear, I will illustrate one builtin variable - ${enclosing_type}. When this one is expanded you will get a name of the class (or interface, enum) in which your template was expanded.<br /><br />"But how can I use it?", I hear you asking. I have prepared few templates just for inspiration, I believe that after reading this you will find thousands others and I believe that you will create them and share them with us.<br /><br /><h3>Custom templates</h3><br />Open <span style="font-style: italic;">Window -> Preferences </span>and type <span style="font-style: italic;">Templates </span>into the search box.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R7bZluAFppI/AAAAAAAAAKg/rrATd10SXK0/s1600-h/creating-template.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R7bZluAFppI/AAAAAAAAAKg/rrATd10SXK0/s400/creating-template.png" alt="" id="BLOGGER_PHOTO_ID_5167556864481011346" border="0" /></a><br />You will get a list of all editors, and their respective template settings. This is because templates are closely bound to editors - you will get different builtin variables in different editors. Also note, that your list may vary from my list, it all depends on installed plugins.<br /><br />Now you must decide what type of template you would like to create. If it is a Java template, which will be applicable in context of classes, interfaces and enums, then choose <span style="font-style: italic;">Java -> Editor -> Templates</span>. If you create a Java template you won't be able to use it in XML editor, that's quite expected.<br /><br />So click on the <span style="font-style: italic;">New</span> button, to get a dialog. Here it is, in all its glory:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R7bdTeAFpqI/AAAAAAAAAKo/Dipk-uFaH6M/s1600-h/new-template.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R7bdTeAFpqI/AAAAAAAAAKo/Dipk-uFaH6M/s400/new-template.png" alt="" id="BLOGGER_PHOTO_ID_5167560948994909858" border="0" /></a><span style="font-style: italic;">Name</span> is the name of the template. Choose it well, because it will serve as a shortcut to your template. After you type the name of the template (or at least a few characters from its name) and hit <span style="font-style: italic;">CTRL+SPACE</span> it will be expanded.<br /><br /><span style="font-style: italic;">Description</span> is what you will see next to the template name when the template name is ambiguous.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R2rmmTQ-COI/AAAAAAAAAGg/JxrQha-rzCk/s1600-h/sysout.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R2rmmTQ-COI/AAAAAAAAAGg/JxrQha-rzCk/s400/sysout.png" alt="" id="BLOGGER_PHOTO_ID_5146179069905078498" border="0" /></a><span style="font-style: italic;">Pattern</span> is the template body. And the <span style="font-style: italic;">Context</span>? This varies in every editor. If you look in the combobox in Java templates, you will see <span style="font-style: italic;">Java</span> and <span style="font-style: italic;">Javadoc</span>. It is simple a context within the respective editor in which the template would be applicable.<br /><br />Check <span style="font-style: italic;">Automatically insert</span> if you want the template to expand automatically on ctrl-space when there is no other matching template available. It is usually good idea to leave the checkbox checked, otherwise you would get a template proposal "popup". See what happens when I uncheck it on <span style="font-style: italic;">sysout</span> template.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R7bjqeAFprI/AAAAAAAAAKw/VHTgcr64ZQk/s1600-h/sysout-automatically-insert-disabled.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R7bjqeAFprI/AAAAAAAAAKw/VHTgcr64ZQk/s400/sysout-automatically-insert-disabled.png" alt="" id="BLOGGER_PHOTO_ID_5167567941201667762" border="0" /></a>If I would have checked it, it would automatically expand, as there is no other template matching <span style="font-style: italic;">sysout*</span> pattern.<br /><br /><h3>My list</h3><br />So here is the list I promised. I have categorized it.<br /><br /><span style="font-weight: bold;">Java </span><span style="font-style: italic;">(Java->Editor->Templates)<br /></span><ul><li><span style="font-weight: bold;">logger </span>- create new Logger<br /><pre>private static final Logger logger = Logger.getLogger(${enclosing_type}.class.getName());</pre>Notice the usage of ${enclosing_type} variable. This way you can create a logger in few hits. After the template expands, you will probably get red lines, indicating that Logger clas could not be found. Just hit <span style="font-style: italic;">CTRL + SHIFT + O</span> to invoke the <span style="font-style: italic;">organize imports </span>function. <a href="http://tkramar.blogspot.com/2007/10/effective-eclipse-ii-shortcut-keys_16.html">You are using shortcuts, aren't you?<br /><br /></a></li><li><span style="font-weight: bold;">loglevel</span> - log with specified level<br /><pre>if(${logger:var(java.util.logging.Logger)}.isLoggable(Level.${LEVEL})) {<br />${logger:var(java.util.logging.Logger)}.${level}(${});<br />}<br />${cursor}<br /></pre>Let me explain the details. ${logger:var(java.util.logging.Logger)} uses a builtin "<span style="font-style: italic;">var</span>" variable. It starts with<span style="font-style: italic;"> logger</span>, the default name, in case the <span style="font-style: italic;">var</span> variable finds no match. It is then followed by <span style="font-style: italic;">var(java.util.logging.Logger)</span>, what will evaluate to the name of the variable (member or local) of the specified type (in our case of the Logger type). Further, the ${cursor} variable marks the place where the cursor will jump after you press enter. So the result after expanding could be<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R7breuAFpsI/AAAAAAAAAK4/WHcC_SZ--E4/s1600-h/loglevel.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R7breuAFpsI/AAAAAAAAAK4/WHcC_SZ--E4/s400/loglevel.png" alt="" id="BLOGGER_PHOTO_ID_5167576535431227074" border="0" /></a>You might wonder what is the purpose of the if. It is there only for performance gain. If specified level is not allowed the logging method will never be called and we can spare JVM some string manipulation to build the message.<br /><br /></li><li><span style="font-weight: bold;">readfile </span>- read text from file<br /><span style="font-size:100%;"><br />Never can remember how to open that pesky file and read from it? Nor can I, so I have a template for it.</span><br /><pre>BufferedReader in;<br />try {<br />in = new BufferedReader(new FileReader(${file_name}));<br />String str;<br />while ((str = in.readLine()) != null) {<br />${process}<br />}<br />} catch (IOException e) {<br />${handle}<br />} finally {<br />in.close();<br />}<br />${cursor}<span style="font-size:100%;"><br /></span></pre></li></ul><span style="font-size:100%;"><span style="font-weight: bold;">Maven </span>(<span style="font-style: italic;">Web and XML -> XML Files -> Templates</span>)<br /></span><ul><li><span style="font-weight: bold;">dependency</span> - maven dependency<br /><pre><dependency><br /><groupId>${groupId}</groupId><br /><artifactId>${artifactId}</artifactId><br /><version>${version}</version><br /></dependency><br />${cursor}</pre></li><li><span style="font-weight: bold;">parent</span> - maven parent project definition<br /><pre><parent><br /><artifactId>${artifactId}</artifactId><br /><groupId>${groupId}</groupId><br /><version>${version}</version><br /><relativePath>{$path}/pom.xml</relativePath><br /></parent><br />${cursor}</pre></li></ul><span style="font-size:100%;"><span style="font-weight: bold;">web.xml </span>(<span style="font-style: italic;">Web and XML -> XML Files -> Templates</span>)<br /></span><ul><li><span style="font-weight: bold;">servlet </span>- new servlet definition<br /><pre><servlet><br /><servlet-name>${servlet_name}</servlet-name><br /><servlet-class>${servlet_class}</servlet-class><br /><load-on-startup>${0}</load-on-startup><br /></servlet><br /><br /><servlet-mapping><br /><servlet-name>${servlet_name}</servlet-name><br /><url-pattern>*.html</url-pattern><br /></servlet-mapping><br />${cursor}<br /></pre></li></ul><span style="font-weight: bold;">JSP pages </span><span style="font-size:100%;">(<span style="font-style: italic;">Web and XML -> JSP Files -> Templates</span>)<br /></span><ul><li><span style="font-weight: bold;">spring-text </span>- spring text field with label and error<br /><pre><label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label><br /><spring:input path="${path}" cssClass="${input_class}"/><br /><spring:errors path="${path}"/> <br/><br />${cursor}</pre></li><li><span style="font-weight: bold;">spring-checkbox</span><br /><pre><label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label><br /><spring:checkbox path="${path}" cssClass="${input_class}"/> <br/><br />${cursor}<br /></pre></li><li><span style="font-weight: bold;">spring-select</span><br /><pre><label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label><br /><spring:select path="${path}" cssClass="${input_class}"><br /><spring:options items="${items}" itemLabel="${label}" itemValue="${value}"/><br /></spring:select><br /><spring:errors path="${path}"/> <br/><br />${cursor}<br /></pre></li><li><span style="font-weight: bold;">spring-generic</span><br /><pre><label for="${path}" class="${label_class}"><fmt:message key="${path}"/></label><br /><spring:${type} path="${path}" cssClass="${input_class}"/><br /><spring:errors path="${path}"/> <br/><br />${cursor}<br /></pre>These are my favorites. They regularly save me a huge amount of time. Creating spring forms has never been easier for me.</li></ul>In some editor types you can set the template to 'new', for example, in XML editor it is <span style="font-style: italic;">new XML. </span>This is really useful, as you can prepare the skeleton of a new file. For example, this is what I use to create new Spring servlet configuration for freemarker application.<br /><pre><?xml version="1.0" encoding="UTF-8"?><br /><beans xmlns="http://www.springframework.org/schema/beans"<br /> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xmlns:context="http://www.springframework.org/schema/context"<br /> xsi:schemaLocation="http://www.springframework.org/schema/beans<br /> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd<br /> http://www.springframework.org/schema/context<br /> http://www.springframework.org/schema/context/spring-context-2.5.xsd"><br /><br /><context:component-scan base-package="" /><br /><br /><bean id="freemarkerConfig" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><br /><property name="templateLoaderPath" value="/"/><br /></bean><br /><br /><bean id="viewResolver" class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver"><br /><property name="viewClass" value="org.springframework.web.servlet.view.freemarker.FreeMarkerView"/><br /><property name="exposeSpringMacroHelpers"><value>true</value></property><br /><property name="cache" value="true"/><br /> <property name="prefix" value="/pages/"/><br /> <property name="suffix" value=".ftl"/><br /></bean><br /><br /><bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"><br /> <property name="basename"><value>messages</value></property><br /></bean><br /></beans></pre>Now, I can create new XML file from template and it will be ready to use. Before I knew about templates, I used to copy this from an older project, or search for it in Spring documentation. Now I don't have to..<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R8c7SeAFptI/AAAAAAAAALY/2CjGehof9oY/s1600-h/new-xml.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R8c7SeAFptI/AAAAAAAAALY/2CjGehof9oY/s400/new-xml.png" alt="" id="BLOGGER_PHOTO_ID_5172167885535422162" border="0" /></a>If you can overcome the initial laziness and create your own templates from the pieces of code you really use, than this investment will shortly return in form of less typing. If you have some interesting templates, please, share them with us.<br /><br />You can <a href="http://www.mediafire.com/?yhy0zyy5wwi">download the templates</a> mentioned in this post and import them using the <i>Import</i> button in the editor template settings.Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com2tag:blogger.com,1999:blog-8838158931136582952.post-53617148579538339232008-02-15T23:58:00.002+01:002008-02-16T00:23:26.109+01:00And so I wasted my time: OC4J and EJB Syntax error in source<pre>oracle.oc4j.admin.internal.DeployerException:<br />Error initializing ejb-module;<br />Exception Error in application ejb-module:<br />Error loading package at file:/opt/oracle/ejb.jar,<br />Error compiling /opt/oracle/ejb.jar:<br />Syntax error in source</pre>This was all I got from OC4J as a response to my attempt to deploy application. Compilation went fine, so it had to be some error in generated wrapper code.<br /><br />Google search yielded only three results, including one from oracle forums with unanswered question. So I begun removing last changes, line by line, to discover the source of the error. In the end, it turned to be a missing RemoteException in remote interface. Doing it remotely, without IDE and XDoclet I forgot to add this one.<br /><br />So I am writing it now, hoping that your search yielded four results and that one of them - mine, just saved you an hour of precious time.<br/>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com0tag:blogger.com,1999:blog-8838158931136582952.post-88233721103594506852008-02-09T15:01:00.000+01:002008-02-09T15:34:48.223+01:00Add jQuery autocompletion to your EclipseIt's easy with <a href="http://www.langtags.com/jquerywtp/">jQueryWTP</a>. It is not an <a href="http://eclipse.org/">Eclipse</a> plugin, it is a nice tool, which modifies some <a href="http://www.eclipse.org/webtools/">WTP</a> plugin autocompletion definitions to make it support<a href="http://jquery.com/"> jQuery</a>.<br /><br />Installation is easy:<br /><ul><li>run the tool</li><li>find the plugin jar and patch it</li></ul>The complete instructions with a video guide are available on the <a href="http://www.langtags.com/jquerywtp/">jqueryWTP homepage</a>.<br /><br />It works nicely, there is one gotcha however, which is not mentioned in the official instructions. You must choose the correct jar, the one, which is being used by WTP. It is possible to have multiple version of the same plugin jar - it is even anticipated if you update your plugins. So choose the correct version - it should be the most recent, with the highest version number. If you are unsure, try all of them, but don't forget to do a backup of the original plugin jar.<br /><br />It can spare you few key strokes and eventually few trips to <a href="http://visualjquery.com/">visualjquery.</a><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R6228eAFpgI/AAAAAAAAAJY/aBmBWaDkS3Y/s1600-h/jquerywtp-demo.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R6228eAFpgI/AAAAAAAAAJY/aBmBWaDkS3Y/s400/jquerywtp-demo.png" alt="" id="BLOGGER_PHOTO_ID_5164985497625667074" border="0" /></a>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com12tag:blogger.com,1999:blog-8838158931136582952.post-21348664940908383722008-02-03T15:09:00.000+01:002008-02-09T15:50:07.391+01:00Effective Eclipse IV: Fix it, quicklyYou are in trouble. Red lines are everywhere. There is no easy way out, so you just either start googling what went wrong, or start a copy&pasting session. If it is so smart, it can tell me that I have an error in my code, why cannot it just fix it?<br /><br />Well, let me introduce you a powerful ally: <span style="font-weight: bold;">Quick Fix.<br /><br /></span>A small example<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/R6W6PzhCN9I/AAAAAAAAAIQ/b62Nd99YjJs/s1600-h/exception.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/R6W6PzhCN9I/AAAAAAAAAIQ/b62Nd99YjJs/s400/exception.png" alt="" id="BLOGGER_PHOTO_ID_5162737328539711442" border="0" /></a>On the image above is a well-known situation. The method is throwing a checked exception, so the calling method must either enclose it in a try-catch block, or rethrow it. A typical solution to this problem is to manually write the try-catch block or throws clause. But there is a better way, the way of quick fix.<br /><br />It can be invoked in two ways<br /><ul><li>clicking on the bulb, left of the line number</li><li>hitting <span style="font-weight: bold;">CTRL + 1 </span>- the preffered way<span style="font-weight: bold;"><br /></span></li></ul>The result will be..<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R6W8TDhCN-I/AAAAAAAAAIY/Wk7xFgx4mmU/s1600-h/quick-fix.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 475px; height: 181px;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R6W8TDhCN-I/AAAAAAAAAIY/Wk7xFgx4mmU/s400/quick-fix.png" alt="" id="BLOGGER_PHOTO_ID_5162739583397541858" border="0" /></a>..that quick fix will propose you both fixes. In the yellow box is a preview, it looks messy, but the code will be properly formatted. If you don't like the generated code, you can change it under <span style="font-style: italic;">Window->Preferences->Java->Code Style->Code Templates</span>. I don't like the default <span style="font-style: italic;">e.printStackTrace()</span>, so I changed the <span style="font-style: italic;">Catch block body</span> template to<br /><pre>logger.severe("Exception caught: " + ${exception_var});<br /></pre>Whenever a red line appears, quick fix can eliminate it. It is applicable not only to the situation above, it can fix:<br /><ul style="font-weight: bold;"><li>Typos<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/R6XBDzhCN_I/AAAAAAAAAIg/iKiceUrRR94/s1600-h/fix-typo.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/R6XBDzhCN_I/AAAAAAAAAIg/iKiceUrRR94/s400/fix-typo.png" alt="" id="BLOGGER_PHOTO_ID_5162744818962675698" border="0" /></a></li><li>Imports<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R6XBnjhCOAI/AAAAAAAAAIo/nBC6hbQAs8M/s1600-h/fix-import.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R6XBnjhCOAI/AAAAAAAAAIo/nBC6hbQAs8M/s400/fix-import.png" alt="" id="BLOGGER_PHOTO_ID_5162745433142999042" border="0" /></a></li></ul><ul><li><span style="font-weight: bold;">Casting<br /><br /></span>Starting with the simple casts...<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R6XDBThCOBI/AAAAAAAAAIw/GjvHU7VjjyY/s1600-h/fix-cast.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R6XDBThCOBI/AAAAAAAAAIw/GjvHU7VjjyY/s400/fix-cast.png" alt="" id="BLOGGER_PHOTO_ID_5162746975036258322" border="0" /></a><br />.. to even more intricate<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R6XE_DhCOCI/AAAAAAAAAI4/gDJrKvw7p7o/s1600-h/fix-cast-list.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R6XE_DhCOCI/AAAAAAAAAI4/gDJrKvw7p7o/s400/fix-cast-list.png" alt="" id="BLOGGER_PHOTO_ID_5162749135404808226" border="0" /></a></li><li><span style="font-weight: bold;">and any other kind of problem I am unable to think up at the moment.</span></li></ul>I found quick fix helpful even in the desperate situations like this one:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R6XHaThCODI/AAAAAAAAAJA/8_P0weYaAkA/s1600-h/problem.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R6XHaThCODI/AAAAAAAAAJA/8_P0weYaAkA/s400/problem.png" alt="" id="BLOGGER_PHOTO_ID_5162751802579499058" border="0" /></a><br />Project needs to migrate WTP metadata? Ok then, have your fun.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R6XHoThCOEI/AAAAAAAAAJI/LgKjCZOiESY/s1600-h/problem-fix.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R6XHoThCOEI/AAAAAAAAAJI/LgKjCZOiESY/s400/problem-fix.png" alt="" id="BLOGGER_PHOTO_ID_5162752043097667650" border="0" /></a><br />When there is nothing to fix, <span style="font-style: italic;">quick fix </span>turns itself to a <span style="font-style: italic;">quick refactoring</span>. Let's see what will it propose on our list.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R6XJQThCOFI/AAAAAAAAAJQ/EeC6b40vr4E/s1600-h/infer.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R6XJQThCOFI/AAAAAAAAAJQ/EeC6b40vr4E/s400/infer.png" alt="" id="BLOGGER_PHOTO_ID_5162753829804062802" border="0" /></a><br />See, it provides all sorts of context sensitive advices. Refactoring, renaming, annotations, everything is there, hidden under one shortcut key. A powerful shortcut key, definitely.<br/>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com2tag:blogger.com,1999:blog-8838158931136582952.post-66088523402548687602008-02-02T14:30:00.001+01:002008-04-26T10:09:24.276+02:00Improve your jQuery-fu, write plugins<p><br /><a href="http://jquery.com/">jQuery</a> is a simple, yet powerful JavaScript library, which really changed my point of view of JavaScript-ing. A new wave JavaScript they call it and it receives this title righteously. The code you create is a <span style="font-weight: bold;">pure elegance.</span><br /></p><blockquote><span style="font-style: italic;">You start with 10 lines of jQuery that would have been 20 lines of tedious DOM Javascript. By the time you are done it's down to two or three lines and it couldn't get any shorter unless it read your mind.</span><br /></blockquote><p>But of course it can get shorter. It can get shorter by refactoring your script into jQuery <span style="font-weight: bold;">plugin</span>.</p><p>When it comes to writing, plugins people (including me) usually back off in horror. I heard about jQuery plugins long ago, but never dared to write one. Somewhere in my mind crept a thought, that</p><ul><li>It must be hard and thus left only to true masters</li><li>It must require a deep knowledge of jQuery</li><li>what could I possibly gain?</li></ul><span style="font-style: italic;">(I come from a Java world if you wonder).</span><p>None of the above is true. Writing jQuery plugin is as easy as writing jQuery script. It does not require any special knowledge. All that is needed, is to extend a jQuery object. Something like</p><pre>$.fn.myPlugin = function() {<br />$this = $(this);<br />// plugin code<br />return $this;<br />}<br /></pre>Remember? This is JavaScript, not Java and the code above is the only thing needed to create a plugin. Inside the function, <span style="font-style: italic;">$this</span> is reference to the jQuery object the plugin was called at.<br /><pre>$("table").myPlugin().addClass("surprise");<br /></pre>Now, <span style="font-style: italic;">$this</span> is table and you can do all sorts of things with it. Because the plugin returns <span style="font-style: italic;">$this</span>, jQuery operations can be chained.<p></p><p><span style="font-weight: bold;">By extending jQuery object, you do not only inherit its fields and methods, you inherit its elegance.</span></p> <p> Now, back to my question, what could you possibly gain by creating a plugin? Mainly </p> <ul> <li> <span style="font-weight: bold;">Higher degree of reusability</span> JavaScript scripts are generally reusable, but when you create a plugin you can move it up one level. It is similar to refactoring the common code into reusable classes. </li> <li> <span style="font-weight: bold;">Configurability</span> This is related to the first point. The usual scenario without plugin is to have a snippet of code, then copy and paste it over to html and change the code to customize its behavior. It is much easier with plugin. You can write your plugin to accept some settings. This is how it could look:<pre>$(table).myPlugin({url: 'edit.htm', param: 'id'});<br /></pre> </li><li> <span style="font-weight: bold;">Elegance</span> </li> The code above surely looks better than a whole script, doesn't it?</ul> <p><br />Now it's time to show some real life example. I have been using a script, to make each row of a table clickable. </p><pre>$("table tr").click(function() {<br /> location.href = 'edit.html?id=' + $("td:first a", $(this)).html();<br />});<br /></pre> Whenever I wanted to make the rows clickable I copied the snippet and changed the url or parameter name. But with the plugin..<br /><pre>$.fn.clickable = function(settings) {<br /> defaults = {<br /> href: 'edit.htm',<br /> paramName: 'id'<br /> }<br /> <br /> settings = $.extend(defaults, settings); //overwrite the defaults with provided setings<br /> <br /> $this = $(this);<br /> <br /> $("tr", $this).click(function() {<br /> location.href = settings.href + '?' + settings.paramName + '=' + $("td:first", $(this)).html();<br /> });<br /> <br /> return $this;<br />}<br /></pre> ..I can use it: <pre>$("table").clickable();</pre> or when I am not confident with default settings, I can change them <pre>$("table").clickable({href: 'change.htm'});<br /></pre> <p> If you want to know more about plugins, read the official <a href="http://docs.jquery.com/Plugins/Authoring">plugin authoring guide</a> or Mike Alsup's excellent <a href="http://www.learningjquery.com/2007/10/a-plugin-development-pattern">plugin development pattern</a>.<br />I hope I inspired you.</p>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com2tag:blogger.com,1999:blog-8838158931136582952.post-58726116503941413952008-01-10T11:05:00.000+01:002008-02-03T20:36:20.660+01:00Else is evil<p>What is the purpose of the <span style="font-style:italic;">else</span> statement?<br />When you write <span style="font-style:italic;">if</span> statement, you are expressing explicit condition, which the code following <span style="font-style:italic;">if</span> will be executed under. You ensure that the code will run, only when the condition holds. What about <span style="font-style:italic;">else</span>? <span style="font-weight:bold;">By using the <span style="font-style:italic;">else</span>, you are stating, that you don't mind the condition, potentially grouping multiple conditions under one statement.</span> To illustrate the point, i will use the snippet of code <br /><pre>int deliveryType = order.getDeliveryType();<br /><br />if(deliveryType == Delivery.NORMAL) {<br /> orderQueue.placeOrder(order);<br />} else {<br /> orderQueue.placePriorityOrder(order);<br />}<br /></pre><p>What's wrong with this code? Everything will work fine, unless there are only two types of order. The code explicitly handles normal order and then <span style="font-weight:bold;">groups every other order and treats it the same</span>. As soon as there is new order type added this code would break.<p>I believe that as the <span style="font-style:italic;">if</span> expresses exactly one condition, the <span style="font-style:italic;">else</span> too should express exactly one condition, or if this is not the case, then it should serve as a guardian. A guardian before the inevitable changes.<br /><pre>int deliveryType = order.getDeliveryType();<br /><br />if(deliveryType == Delivery.NORMAL) {<br /> orderQueue.placeOrder(order);<br />} else if(deliveryType == Delivery.EXPRESS) {<br /> orderQueue.placePriorityOrder(order);<br />} else {<br /> throw new RuntimeException("Unknown delivery type.");<br />}<br /></pre><p>The code above illustrates much better approach. The <span style="font-style:italic;">else</span> serves here as a guardian. The application will work, and when there is new delivery type requested it will immediately break unit tests and signal the cause of problem.<br /><pre>if(order.isNew() == true) {<br /> getOrderDao().save(order);<br />} else {<br /> getOrderDao().update(order);<br />}<br /></pre><p>Using <span style="font-style:italic;">else</span> here is appropriate too, as it represents exactly one condition. A boolean can never be anything else than true, or false. True or false, two conditions, two branches and there is no way for third.Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com5tag:blogger.com,1999:blog-8838158931136582952.post-21914753734283071762008-01-06T22:46:00.000+01:002008-01-06T19:53:33.297+01:00I used to have a player<p><br />I used to have an mp3 player. It was an iPod Nano and it sucked. Everytime I wanted to push there some music, I had to go through extra slow and user-unfriendly iTunes. I don't have that player anymore, I threw it away. <br /><p><br />I have a new player now. I can manage my music using a file browser. I can watch videos, play games (half-life, doom, gameboy color games). I can choose how it will look like and how it will behave. It is still the same old iPod Nano.. <br/>That little shiny magic, that converted my iPod into a box full of fun is <a href="http://rockbox.org">RockBox</a><br /><br /><blockquote><br />Rockbox is an open source firmware replacement for a growing number of digital audio players. It has been in development since 2001 and receives new features, tweaks and fixes every day to provide you with the best possible music listening experience. Rockbox aims to be considerably more functional and efficient than your device's stock firmware while remaining easy to use and customizable. We believe that you should never need to go through a series of menus for an action you perform frequently. We also believe that you should be able to configure almost anything about Rockbox you could want, pertaining to functionality. It is written by users, for users.<br /></blockquote><br /><br /><h1>Features</h1><br /><br />So, what can you expect from it? Lot of things. <br /><br /><b>Although this post talks about iPod, RockBox runs on other players too, just check the <a href="http://www.rockbox.org/twiki/bin/view/Main/TargetStatus">official list</a></b><br /><br /><h2>No more database</h2><br />Rockbox is a file system based jukebox. Unlike iPod original firmware, it does not depend on any proprietary binary database. This means, that you no more need iTunes to access and manage your music. All you need is a file browser. With rockbox, iPod works just like any other USB device. You can organize your files whatever you like, they will be recognized by rockbox and ready to play. On figure 1, you can see a file tree view.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/R4EB3zQ-CSI/AAAAAAAAAHA/qQBUIPsiMDg/s1600-h/file-tree.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_GFNxMeHpbcw/R4EB3zQ-CSI/AAAAAAAAAHA/qQBUIPsiMDg/s400/file-tree.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5152401506854373666" /></a><br /><center><b>Fig. 1</b> File tree view</center><br /><br />It behaves exactly like you'd expect, like a normal file browser. You can find your files there, and they will be handled with the correct plugin (eg. opening an jpeg image will activate the image viewer plugin, opening .mpg file will play the video).<br /><br /><h2>Database</h2><br />Well, I lied in the previous section. You can have your database if you want. Rockbox can be set, such that it scans your files when it starts. All audio files are processed and the database is created from the id3 tags. You can then view your music in a similar way like with the original firmware (figure 2).<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R4EFEDQ-CTI/AAAAAAAAAHI/eIVqBNdGRdI/s1600-h/database.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R4EFEDQ-CTI/AAAAAAAAAHI/eIVqBNdGRdI/s400/database.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5152405015842654514" /></a><br /><center><b>Fig. 2</b> Database view</center><br /><br /><h2>Wide range of music formats and audio settings</h2><br />You can have your music encoded in one of the 15 audio codecs, including (mp3, ogg, wma, aac, wav and flac. see the <a href="http://www.rockbox.org/twiki/bin/view/Main/SoundCodecs#Current_status">full list</a>). RockBox provides a graphical equalizer, with a presets and gaples playback.<br /><br /><h2>Customizable screen themes</h2><br />You can choose from a <a href="http://www.rockbox-themes.org">range of themes</a>, or create your own. Figure 3 shows some themes I liked.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R4EHLjQ-CUI/AAAAAAAAAHQ/inHAOjLLlzI/s1600-h/backgrounds.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R4EHLjQ-CUI/AAAAAAAAAHQ/inHAOjLLlzI/s400/backgrounds.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5152407343714928962" /></a><br /><center><b>Fig. 3</b> Themes</center><br /><br /><h2>Comprehensive settings</h2><br />You can set almost everything. This might not mean much to you, but if you are like me, and you like to have control over your player, you will be pleased.<br /><br /><h2>Movies</h2><br />Yes, rockbox can play movies. But to make any use from it, you will need to reencode them in the mpeg2 format, and change the resolution. There are 3 examples on the <a href="http://www.rockbox.org/twiki/bin/view/Main/PluginMpegplayer">plugin page</a>, but only the one with mencode worked for me. Fortunately, all movies from <a href="http://www.pocketmovies.net/">pocketmovies.com</a> worked well without encoding.<br />The plugin page further states:<br /><blockquote><br />mpegplayer does all video and audio decoding using your device's main CPU. It does not use any special video decoding hardware such as the Broadcom Video Processor found in the ipod Video. mpegplayer therefore performs very badly on such devices in comparison with the manufacturer's original firmware.<br /></blockquote><br /><br /><h2>Games</h2><br />This is the best feature of rockbox for me. It comes bundled with a dozen of simple games, like chess, snake, winmines, solitaire.. and doom. Rockbox actually provides a doom engine, to play the game, you need to get the game wads. The wads provide the game graphics and level definitions. You can find some wads on <a href="http://www.doomworld.com/10years/bestwads/">doomworld</a>. I've even seen <a href="http://youtube.com/watch?v=WSk1aEayIGQ">half-life</a> and <a href="http://youtube.com/watch?v=pogDRvrq9Q4&feature=related">counterstrike</a> wads.<br />Another possibility for a game-thirsty rockboxer is the gameboy emulator, with which you can play gameboy color games, like Super Mario.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R4EOujQ-CVI/AAAAAAAAAHY/lmAyGeQ8bJc/s1600-h/doom.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R4EOujQ-CVI/AAAAAAAAAHY/lmAyGeQ8bJc/s400/doom.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5152415641591744850" /></a><br /><center><b>Fig. 4</b> Freedoom</center><br /><br /><h2>Applications and Demos</h2><br />Quite useless for me, I don't need text editors, paint tools, nor do I like to watch fire demos, or rotating cubes. They are a simple demonstration of power of rockbox.<br /><br /><h2>Image and text viewing</h2><br />The same as with original firmware, except that you can place your images anywhere in the player, and you don't need to use iTunes.<br /><br /><h2>Voice menus and multilingual support</h2><br />Great for people with limited abilities, and for those, who don't speak English.<br /><br /><h2>Last.Fm support</h2><br />Even if your player does not support <a href="http://last.fm">Last.Fm</a> directly, with RockBox, you can get a log of your music activity. This log can be then sent to Last.Fm using <a href="http://www.rockbox.org/twiki/bin/view/Main/LastFMLog">one of the tools</a> listed in RockBox wiki.<br /><br /><h2>Downsides</h2><br />The main disadvantage of all this is the battery life. iPod Nano is simply not prepared for a display backlight turned on for a long time, as is the case when playing videos, or games. According to my experience, batteries cannot take longer than one hour of playing, or watching videos. But this is not a blame of rockbox, but of the iPod's poor battery life. 8 hours of music playback with original firmware is not much I think. Rockbox can match the original firmware in this aspect, 8 hours of playback with a promise:<br /><br /><blockquote><br />Right now Rockbox is in development. The software currently requires more power to run than the original firmware, and so the battery life is shorter. With time this will improve. On other platforms Rockbox has actually surpassed the retail firmware in battery life, though of course we can't promise that will happen with Rockbox until we see what the limits are, but it will definitely be better than it is now.<br /></blockquote><br /><br />Another thing I noticed is no podcast support. Podcasts are treated as normal audio files. With the original firmware, I could resume the podcast where I stopped it, there is no such option in rockbox.<br /><br /><h1>Installation</h1><br /><br />Installation was a breeze. Actually, and there's a bit of irony in this, rockbox installation was far more simpler than loading my iPod with music using iTunes.<br />All what is needed is to unpack the rockbox archive to player and run the boot loader patcher. Patching was very convenient, I just ran the patcher and it did its job well, without asking me for help. I didn't even had to specify the mount point, everything was autodetected.<br /><br />Rockbox team provides a tool for automatic download, installation and patching called <a href="http://www.rockbox.org/twiki/bin/view/Main/RockboxUtility">RockBoxUtility</a>. Unfortunately it didn't work for me, but it might work for you.<br /><br /><b>Notice:</b> Installing rockbox will not destroy your original firmware, nor will it delete your music collection. Original firmware will be still available.<br /><br />After a week of using, I can say for myself, that I never want to see the original firmware again.<br /><br /><i>All images, except the fig. 3, were captured by myself, using the <a href="http://rasher.dk/rockbox/simulator/">rockbox simulator</a> - it is a nice utility which can run RockBox on a PC.</i>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com0tag:blogger.com,1999:blog-8838158931136582952.post-16388103093330411282007-12-31T16:41:00.000+01:002008-02-03T20:45:51.301+01:00Maven + Hibernate + Spring fun<p>Maven can be pain, indeed. Few days ago I put following dependency to my pom.xml:<br /><pre><dependency><br /> <groupId>org.hibernate</groupId><br /> <artifactId>hibernate-entitymanager</artifactId><br /> <version>3.3.1.ga</version><br /></dependency><br /></pre><br />but the build failed, saying that javax.transaction:jta:jar:1.0.1B cannot be resolved. After some googling I found a solution in a google cache of <a href="http://www.dhruba.name/"> Dhruba Bandopadhyay's</a> blog. The 1.0.1B can be found in a java.net repository. Actually, the poms of this version are available on ibiblio too, but the jars are missing.<br /><br />So simply add<br /><pre><repository><br /> <id>maven2-repository.dev.java.net</id><br /> <name>Java.net Maven 2 Repository</name><br /> <url>http://download.java.net/maven/2/</url><br /></repository><br /></pre><br />I ran maven again, only to come across <br /><br /><pre>java.lang.NoClassDefFoundError: EDU/oswego/cs/dl/util/concurrent/ConcurrentReaderHashMap<br /> at org.jboss.util.file.ArchiveBrowser.<clinit>(ArchiveBrowser.java:52) <br /></pre><br />I found an <a href="http://opensource.atlassian.com/projects/hibernate/browse/EJB-324?actionOrder=desc">opened bug</a> in hibernate issue tracker from November 07, but it was not fixed yet. After some additional search I found that the required dependency can be found at jboss's maven repository.<br /><br /><pre><dependencies><br /> <dependency><br /> <groupId>oswego-concurrent</groupId><br /> <artifactId>concurrent</artifactId><br /> <version>1.3.4</version><br /> </dependency><br /></dependencies><br /><br /><repository><br /> <id>jboss.org</id><br /> <name>Jboss Maven 2 Repository</name><br /> <url>http://repository.jboss.org/maven2/</url><br /></repository><br /></pre><br />But this piece of configuration just yielded another exception, this time it was a NoSuchMethodException, complaining about ClassValidator.<init> method missing. Although I saw the missing constructor in the hibernate jars, I was still getting this error. I spent hours searching the web, only to find many people having the same problem and trying various suggestions, but none of them worked.<br /><p><br />The solution came today, when I read this post from <a href="http://blog.krecan.net/2008/01/05/flushing-hibernate/">Lukas Krecan</a>. In his code I found the correct dependecies<br /><br /><pre><dependency><br /> <groupId>org.hibernate</groupId><br /> <artifactId>hibernate-entitymanager</artifactId><br /> <version>3.3.1.ga</version><br /> </dependency><br /><dependency><br /> <groupId>concurrent</groupId><br /> <artifactId>concurrent</artifactId><br /> <version>1.3.4</version><br /></dependency><br /></pre><br />and the correct Spring + JPA initialization<br /><br /><pre><bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"><br /> <property name="persistenceUnitName" value="Spring.Persistence" /><br /> <property name="dataSource" ref="dataSource" /><br /> <property name="jpaProperties"><br /> <props><br /> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop><br /> </props><br /> </property><br /></bean><br /><br /><bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"><br /> <property name="entityManagerFactory" ref="entityManagerFactory" /><br /></bean><br /></pre><br />In META-INF/persistence.xml put:<br /><br /><pre><?xml version="1.0" encoding="UTF-8"?><br /><br /><persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br /> xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0"><br /><br /> <persistence-unit name="Spring.Persistence" transaction-type="RESOURCE_LOCAL"><br /> <provider>org.hibernate.ejb.HibernatePersistence</provider><br /> </persistence-unit><br /> <br /></persistence><br /></pre><br />Thank you Lukas.<br/>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com1tag:blogger.com,1999:blog-8838158931136582952.post-41035739940307160692007-10-16T20:44:00.000+02:002007-12-21T09:42:52.685+01:00Effective Eclipse: III. Don't write the code, generate it<p><br />I hope that we will never be able to generate applications. I would be without job then and you probably too. But what we can generate are various repetitive and boring pieces of code.<br /><br /><p><br />The first thing that can be generated is class file. You are using it, but you have probably never realized how much time did it save you. If there was no class skeleton generation, you would have to: create new file in the proper directory (with respect to package (and create the folders too)) and place the package statement at the beginning of a class.<br />I noticed that all people generate their classes, but not all of them specify implemented interfaces and extended class. Surely, you can generate the class and write the extends and implements part afterwards, but it involves moving the cursor, writing and eventually generating abstract or implemented methods. I found it much easier to press ALT + E (<u>e</u>xtend) to add extended class and ALT + A (<u>a</u>dd interface) to add interfaces.<br /><br /><p><br />I you look at the Source menu you can find more "Generate" commands. But none of them is so valuable and useful as the Eclipse templates. They are the true gem in my daily work and its pity they are hidden out of sight. And they are hidden well.<br /><br /><p><br />What are they and how to get them? <br/><br />Templates serve as a shorthand for a snippet of code. You type the magical word and it will be transformed into the snippet.<br /><br />Some examples:<br /><br />Type sysout and press CTRL + SPACE (the autocompletion, in case you didn't know) and it will be automagically changed to System.out.println(); with the caret waiting right in the middle between the parenthesizes.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R2rmmTQ-COI/AAAAAAAAAGg/JxrQha-rzCk/s1600-h/sysout.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R2rmmTQ-COI/AAAAAAAAAGg/JxrQha-rzCk/s400/sysout.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5146179069905078498" /></a><br /><br />While we are here, let's explore the next interesting feature. Type "for" and press CTRL + SPACE to change it to a skeleton of a for loop. <br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/R2rmwDQ-CPI/AAAAAAAAAGo/bcuADEpQ0vY/s1600-h/caret.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp2.blogger.com/_GFNxMeHpbcw/R2rmwDQ-CPI/AAAAAAAAAGo/bcuADEpQ0vY/s400/caret.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5146179237408803058" /></a><br /><br />Notice the blue boxes around some of the commands. They represent the caret stop and you can move between them using the TAB key. Now, with the caret on "iterator", type the name of the variable representing the iterator. It's name will be changed in the whole loop as you type (the occurrences are marked with a light blue background). Now just two more TABs to change the collection variable and the type. Noticed the green line sitting in the empty line? It marks the position where the caret will jump when Enter key is pressed. So after changing the variable type you can just press Enter and the caret will jump to the empty line. Notice, that when you use autocompletion the green marker is always there, waiting for you to press Enter.<br /><br /><p><br />The templates are defined under: Window -> Preferences -> Java -> Editor -> Templates<br />where you can define your own templates.<br /><br /><p><br />That pesky CTL + SPACE shortcut offers some more surprises. If you get used to it, you will be hitting it often, even in situations where there is nothing to autocomplete. Or is it?<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R2ro2TQ-CQI/AAAAAAAAAGw/gPFBGgmvaX8/s1600-h/varname.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R2ro2TQ-CQI/AAAAAAAAAGw/gPFBGgmvaX8/s400/varname.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5146181543806241026" /></a><br /><br />Guess what is on the picture above? It is eclipse trying to autocomplete the name of a variable.<br /><br />It is pity it cannot read my mind. I often find myself hitting the shortcut in the middle of the string ever wondering why it doesn't complete the word :)<br /><br /><p><br />Never can remember the signature of a method you want to override? Never mind, hit CTRL + SPACE and you will get a list.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R2rrlzQ-CRI/AAAAAAAAAG4/Onpmat-ZDKM/s1600-h/override.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R2rrlzQ-CRI/AAAAAAAAAG4/Onpmat-ZDKM/s400/override.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5146184558873282834" /></a>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com7tag:blogger.com,1999:blog-8838158931136582952.post-60333288049264025752007-10-16T20:05:00.003+02:002008-02-16T12:36:12.404+01:00Effective Eclipse: II. Shortcut keys<h3>Use your hands to write code</h3><br />You should try to keep your hands on keyboard. The less you touch the mouse, the more code you can write. I am trying to keep the mouse laying still and control the IDE completely using keyboard. What do you think is faster: pressing <span style="font-style: italic;">ALT + C</span> or right clicking the project, selecting <span style="font-style: italic;">Team -> Commit</span>?<br /><p>It is said, that if a function does not have a key binding, it is useless. Below you will find a set of essential keyboard shortcuts that I love. These shortcuts are set up by default, they should all work.<br /></p><dl><dt><span style="font-weight: bold;">CTRL + D</span></dt><br /><dd>Delete row. Try it! You no more need to grab the mouse and select the line, no more Home, Shift + End, Delete. Quick and clean.</dd><br /><dt><span style="font-weight: bold;">ALT + Up/Down Arrow</span></dt><br /><dd>Move the row (or the entire selection) up or down. Very useful when rearranging code. You can even select more rows and move them all. Notice, that it will be always correctly indented.</dd><dt><br /></dt><dt><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_GFNxMeHpbcw/R7bIJuAFphI/AAAAAAAAAJg/sBbK3i86bgU/s1600-h/alt-arrow.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_GFNxMeHpbcw/R7bIJuAFphI/AAAAAAAAAJg/sBbK3i86bgU/s400/alt-arrow.png" alt="" id="BLOGGER_PHOTO_ID_5167537691747001874" border="0" /></a></dt><br /><dt><span style="font-weight: bold;">ALT + Left/Right Arrow</span></dt><br /><dd>Move to the last location you edited. Imagine you just created a class Foo, and now you are working on a class Boo. Now, if you need to look at the Foo class, just press Alt+Left Arrow. Alt+Right Arrow brings you back to Boo.</dd><br /><dt><span style="font-weight: bold;">CTRL+SHIFT+O</span></dt><br /><dd>Organize imports. What happens when you first use a class you have not yet imported? You will see an error. But when you press this magical combination, all your missing classes will be imported, and the unused imports will vanish.</dd><br /><dt><span style="font-weight: bold;">CTRL+1</span></dt><br /><dd>Probably the most useful one. It activates the quick fix. Imagine you create a class, which implements some interface. You will get an error, because the inherited methods are not yet implemented. While you are on line where the error occurs, press this combination to activate the quick fix. Now, select the "Add unimplemented methods" option. You can use the quick fix at every error you ever receive.<br /><br />Quick fix comes handy in other situations too. My favorite is the "Split variable declaration". Sometimes I need to broaden the scope of a variable. I activate the quick fix, split declaration, and use alt + arrow to put it where it belongs. You can find even more usages: Convert local variable to field, rename in file, Inline local variable..<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/RxUAZm2okoI/AAAAAAAAAFI/FEDfs4d2mGE/s1600-h/quickfix.png"><img style="cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/RxUAZm2okoI/AAAAAAAAAFI/FEDfs4d2mGE/s400/quickfix.png" alt="" id="BLOGGER_PHOTO_ID_5122000591130235522" border="0" /></a><br /><span style="font-size:78%;">You could use the "Split variable declaration" on the bar variable, and then move it with Alt+Arrows above the try block..</span><br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/RxUAq22okpI/AAAAAAAAAFQ/umsmSUHU80s/s1600-h/quickfix2.png"><img style="cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/RxUAq22okpI/AAAAAAAAAFQ/umsmSUHU80s/s400/quickfix2.png" alt="" id="BLOGGER_PHOTO_ID_5122000887482978962" border="0" /></a><br /><span style="font-size:78%;">Or you could use the "Add unimplemented methods" fix here.</span><br /><br />The best thing you can do if you see an error is to use the quick fix.<br /></dd><br /><dt><span style="font-weight: bold;">CTRL+SHIFT+T</span></dt><br /><dd>Open Type. Imagine, that you need to have a look at the Foo class. But, where is the Foo class? Is it in the Boo project and in the foo.bar package? Or somewhere else? With this shortcut, you don't need to know. Just press it, type Foo and you are in.</dd><dt><br /></dt><dt><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R7bIbOAFpiI/AAAAAAAAAJo/Yhj4X5xVHHw/s1600-h/open-type.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R7bIbOAFpiI/AAAAAAAAAJo/Yhj4X5xVHHw/s400/open-type.png" alt="" id="BLOGGER_PHOTO_ID_5167537992394712610" border="0" /></a></dt><br /><dt><span style="font-weight: bold;">CTRL+E</span></dt><br /><dd>Shows you a list of all open editors.</dd><dd><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/RxUBOW2okqI/AAAAAAAAAFY/TqPXyZ_7btA/s1600-h/ctrl-e.png"><img style="cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/RxUBOW2okqI/AAAAAAAAAFY/TqPXyZ_7btA/s400/ctrl-e.png" alt="" id="BLOGGER_PHOTO_ID_5122001497368335010" border="0" /></a><br /></dd><br /><dt><span style="font-weight: bold;">CTRL+F6</span></dt><br /><dd>Use to move between open editors. This is an slower alternative to Ctrl + E. Comes handy in a situation when you want to periodically switch between two editors, something, what is nearly impossible with Ctrl+E as it sorts entries quite randomly. Or you might just use Alt+Arrows..</dd><br /><dt><span style="font-weight: bold;">CTRL+F7</span></dt><br /><dd>Move between views. When in editor, press Ctrl+F7 to switch to the Package Explorer, or hold Ctrl and press F7 multiple times to switch to other views.</dd><dt><br /></dt><dt><span style="font-weight: bold;">CTRL+F8</span></dt><dd><br /></dd><dd>Move between perspectives. The same as previous.</dd><dt><br /></dt><dt><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/R7bIuOAFpjI/AAAAAAAAAJw/GGQOLb7k7wg/s1600-h/switching-trio.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/R7bIuOAFpjI/AAAAAAAAAJw/GGQOLb7k7wg/s400/switching-trio.png" alt="" id="BLOGGER_PHOTO_ID_5167538318812227122" border="0" /></a></dt><dt><span style="font-weight: bold;">CTRL + F11</span></dt><br /><dd>Runs the application. What gets launched depends on your settings. It will either launch the last launched class (my preffered way) or it will launch currently selected resource (the default way). If you want to change its behavior read the previous post.</dd><br /><dt><span style="font-weight: bold;">CTL + N</span></dt><br /><dd>Open new type wizard. This is not very quick because you have to select the wizard type (weather you want to create new class, jsp, xml or something else) in the next step. Much faster way would be if you could just hit the shortcut and invoke the particular wizard. It is possible, just keep reading..</dd><br /><dt><span style="font-weight: bold;">CTRL + M</span></dt><br /><dd>Maximize or umaximize current tab.</dd><br /><dt><span style="font-weight: bold;">CTRL + I</span></dt><br /><dd>Corrects indentation.</dd><br /><dt><span style="font-weight: bold;">CTRL + SHIFT + F</span></dt><br /><dd>Formats code. You can make a beautiful looking code out of a mess with this. It requires a bit of setup, but it is well worth it. You can find its settings under Window->Preferences->Java->Code style->Formatter</dd><br /><dt><span style="font-weight: bold;">CTRL + J</span></dt><br /><dd>Incremental search. Similar to the search in firefox. It shows you results as you type. Don't be surprised, if you hit this combination, nothing happens - at the first glance. Just start typing and eclipse will move your cursor to the first ocurence.</dd><br /><dt><span style="font-weight: bold;">CTRL + SHIFT + L</span></dt><br /><dd>Shows you a list of your currently defined shortcut keys.</dd></dl><h3>I don't like your shortcuts</h3>Such is life nowadays. Remember, you can always change those bindings to match your preferences. Open Windows->Preferences->General->Keys. Now you can use the filter to find your shortcut and change its binding.<br /><p>The real fun begins when you cannot find the command you are looking for. The key here, is to have the "Include unbounds commands" checkbox checked. It will show you all commands, even those, which have no keys bound.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_GFNxMeHpbcw/RxUBzW2oksI/AAAAAAAAAFo/qFEt6n3Y8V0/s1600-h/key-binding.png"><img style="cursor: pointer;" src="http://bp0.blogger.com/_GFNxMeHpbcw/RxUBzW2oksI/AAAAAAAAAFo/qFEt6n3Y8V0/s400/key-binding.png" alt="" id="BLOGGER_PHOTO_ID_5122002133023494850" border="0" /></a><br /><br />While you are here, I recommend to add the following bindings:<br /></p><dl><dt><span style="font-weight: bold;">CTRL+SHIFT+G</span></dt><br /><dd>Bind this to "Generate getters and setters". This is a "must have".</dd><br /><dt><span style="font-weight: bold;">ALT+C</span></dt><br /><dd>Bind this to SVN/CVS "Commit".</dd><br /><dt><span style="font-weight: bold;">ALT+U</span></dt><br /><dd>Bind this to SVN/CVS "Update".</dd></dl>Now, type "new" (without quotes) in the filter text. You should see a list of all new type wizards. Choose the most frequently used and assign them a shortcut. For example, the most used wizard for me is the new class wizard. Thus I assigned it the <span style="font-style: italic;">CTRL+SHIFT+N</span> keys.<br /><br /><br />Let me demonstrate a quick way to create new class now.<br /><br />Hit <span style="font-style: italic;">CTRL + SHIFT + N</span> (or the combination you assigned in the previous step). This should bring up new class wizard. Type in the name and press <span style="font-style: italic;">ALT+E</span>. You can now select a class which will be a superclass for the newly created class. Hit <span style="font-style: italic;">ALT+A</span> and select all implemented interfaces . Now hit ALT+F and your class will be generated. Eclipse will also provide the default implementation for all abstract and interface methods you inherited.<br /><p>Did you notice the weird underscores everywhere in the dialog? They give you a hint about the shortcut key. Hit <span style="font-style: italic;">ALT</span> and the underlined letter to press the button, check the checkbox or get focus for a textfield.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/RxUBg22okrI/AAAAAAAAAFg/5K2bopJ-6_Q/s1600-h/newtype.png"><img style="cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/RxUBg22okrI/AAAAAAAAAFg/5K2bopJ-6_Q/s400/newtype.png" alt="" id="BLOGGER_PHOTO_ID_5122001815195914930" border="0" /></a><br /></p><p><span style="font-size:78%;">Did you notice the underscores?</span><br /><br />I think that using shortcut keys is the fastest way to productivity and if not, then at least your wrists will say you a silent thanks. Now, don't wait, go on and assign keys to the features you use most.</p><p>One final tip from Andriy:</p><p></p><blockquote>The problem is that there are so many keyboard shortcuts. I used to keep a printout with all the shortcuts I wanted to use. Finally I wrote an Eclipse plugin <a rel="nofollow" href="http://www.mousefeed.com/">MouseFeed</a>, which reminds the keyboard shortcuts for the actions called with mouse. You can even tell it to enforce some shortcuts - the action will run only if called with a keyboard shortcut.<br /></blockquote><p></p><p>So if you are struggling with yourself, if you want to use shortcuts, but always subconsciously touch the mouse, install the plugin and let it enforce the shortcuts - the mouse will be useless and you will be forced to use keyboard.</p><p>What shortcuts do you use? </p>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com25tag:blogger.com,1999:blog-8838158931136582952.post-57861511154444009182007-10-15T19:46:00.000+02:002008-02-08T10:54:42.134+01:00Effective Eclipse: I. SetupToday, I was taught an important lesson. The lesson of effectivity. I was attending a presentation, called "Python Django: Advanced web application in 40 minutes". The guy was a geek, he was writing the code in a very basic vim installation. I bet, that if he used something better (no offense, it was really basic installation and he was apparently no vim master) he could crack it in half the time. It was an "oh, I made a typo here" presentation. It was then, when I realized that you really need a good editor if you want to be productive.<br /><br /><span style="font-weight: bold;"><span style="font-size:130%;">Choose your tool</span></span><br /><span style="font-size:100%;"><br /></span><span style="font-size:100%;">Just do it. Find what suits you best and use it. I found <a href="http://www.blogger.com/www.eclipse.org">Eclipse</a>. If you found something else, then I am sorry, but you probably wouldn't </span><span style="font-size:100%;">be inte</span><span style="font-size:100%;">rest</span><span style="font-size:100%;">ed in the res</span><span style="font-size:100%;">t of the article.</span><span style="font-weight: bold;"><span style="font-size:130%;"><br /></span></span><br /><span style="font-weight: bold;font-size:130%;" >Know your tool<br /><br /><span style="font-size:100%;"><span style="font-weight: bold;">Basic setup<br /><br /></span></span></span><span style="font-size:100%;">The first thing you should do, is to set up your </span><span style="font-size:100%;">font. If </span><span style="font-size:100%;">you are using Windows, you are lucky, as the font looks probably good and is well readable. If you are using Ubuntu like me, you might have less luck. When I first started </span><span style="font-size:100%;">e</span><span style="font-size:100%;">clipse, I was stunned. The font</span><span style="font-size:100%;"> was big and crappy.<br />But not for too long.<br />Open: <span style="font-weight: bold;">Window->Preferences->General->Appe</span></span><span style="font-size:100%;"><span style="font-weight: bold;">arance->Color and Fonts->Basic->Text Font </span></span><span style="font-size:100%;"><span style="font-size:100%;">and change the font size to 8. Much better now.<br />The font used is called Monospace, some people <a href="http://www.lowing.org/fonts/">recommend Bitstream Vera Sans Mono</a>. This is how it looked before and how it looks now.<br /><br />Before:<br /></span></span><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/Rw0qv22okhI/AAAAAAAAAD4/YGgL5u8Vaa4/s1600-h/ubuntu-eclipse-before.png"><img style="cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/Rw0qv22okhI/AAAAAAAAAD4/YGgL5u8Vaa4/s400/ubuntu-eclipse-before.png" alt="" id="BLOGGER_PHOTO_ID_5119795353057006098" border="0" /></a><br /><br />After:<br /><div style="text-align: left;"><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_GFNxMeHpbcw/Rw0qP22okgI/AAAAAAAAADw/T4bpKZKBOBc/s1600-h/ubuntu-eclipse-after.png"><img style="cursor: pointer;" src="http://bp2.blogger.com/_GFNxMeHpbcw/Rw0qP22okgI/AAAAAAAAADw/T4bpKZKBOBc/s400/ubuntu-eclipse-after.png" alt="" id="BLOGGER_PHOTO_ID_5119794803301192194" border="0" /></a><br /><br />I recommend lowering the font size for your whole desktop. You will be surprised how much more can you see now. You can<span style="font-size:100%;"><span style="font-size:100%;"> </span></span><span style="font-size:100%;"><span style="font-size:100%;"><a href="http://ubuntuforums.org/showthread.php?t=343670">improve the font rendering</a> too.</span></span><span style="font-size:100%;"><span style="font-size:100%;"><br /></span></span></div><span style="font-size:100%;"><span style="font-size:100%;"><br /><span style="font-weight: bold;"><span style="font-size:130%;">Don't be greedy<br /><br /></span></span><span style="font-size:100%;">Eclipse is running with very small memory by default, but there is really no reason to be greedy. Just give your toy what it needs. Fire up the text editor, open eclipse.ini and enter:<br /></span><pre>-vmargs -Xms512M -Xmx1024M -XX:PermSize=128M -XX:MaxPermSize=256M</pre>The -Xms option specifies the minimum and -Xmx the maximum heap size. The same holds for PermSize and MaxPermSize. Heap is that part of memory, where all your objects live. PermGen means "Permanent Generation" and it is a part of memory where all permanent objects are stored. By permanent, I mean those, which are not going to be garbage collected (for example Strings, classes etc.). Here you can find a better <a href="http://www.thesorensens.org/?p=14">explanation of what PermGen</a> is.<br />If you are running a linux box, you might experience <a href="http://java.sun.com/javase/6/docs/api/java/lang/OutOfMemoryError.html">OutOfMemoryError</a>-s if you do not adjust memory </span></span><span style="font-size:100%;">size. The values provided above are only for example, you should enter the values appropriate to your RAM size.<br /><br /></span>You can further tune the performance by providing additional arguments. In his article, Jim Bethancourt recommends using <a href="http://eclipse.dzone.com/news/what-java-ide-vm-arguments-do-you-use">Throughput garbage collector</a> (-XX:+UseParallelGC), Robi Sen recommends using <a href="http://www.robisen.com/index.cfm?mode=entry&entry=FD4BE2FC-55DC-F2B1-FED0717CC1C7E0AF">CMS Collector</a> (-XX:+UseConcMarkSweepGC) as more effective.<br /><span style="font-size:100%;"><br /><span style="font-weight: bold;">Help, I am giving the crap all my memory and it still keeps OutOfMemoryErroring!<br /><br /></span>The reason is that you are simply not giving it enough memory. But don't worry, you don't have to buy another memory module (well, unless you have 128MB RAM). It is possible that you have made a typo in eclipse.ini, or maybe you used wrong eclipse.ini or maybe it simply doesn't work. I cannot tell you how to fix it, but I can tell how much memory are you giving it.<br /><br />Open<span style="font-weight: bold;"> Window->Preferences->General </span>and check the "Show heap status" checkbox. You should now see the memory status in the bottom right corner.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_GFNxMeHpbcw/RxOySG2okmI/AAAAAAAAAE4/zfk4J_4wpho/s1600-h/Screenshot.png"><img style="cursor: pointer;" src="http://bp1.blogger.com/_GFNxMeHpbcw/RxOySG2okmI/AAAAAAAAAE4/zfk4J_4wpho/s400/Screenshot.png" alt="" id="BLOGGER_PHOTO_ID_5121633225397539426" border="0" /></a><br /></span><br />If you see values which correspond to the values you entered, everything should be fine.<span style="font-size:100%;"><br /></span><span style="font-size:100%;"><span style="font-size:100%;"><br /><span style="font-weight: bold;font-size:130%;" >Set it up<br /><br /></span><span style="font-size:100%;">You should really take a time to walk through all the options under Window -> Preferences and customize your eclipse installation. I am going to list few basic useful settings.<br /><br /><span style="font-weight: bold;">General<br /><br /></span><span style="font-style: italic;">Always run in background:</span> when eclipse is doing something time consuming it will bother you with a modal popup window showing you the progress of the task. I used to dismiss the popup with "run in background" button. I am usually not interested in watching the lazy progressbar. If you enable this option eclipse will no longer bother you, and all tasks will run in background by default. There is nothing worse than breaking your workflow with messages: Hey I am building, can you see?<br /><br /><span style="font-style: italic;">Appearance: </span>You can set various font related options here. If you are interested, you can change the position of tabs from top to bottom.<br /><br /><span style="font-style: italic;">Editors->File associations:</span> if you have some exotic extension you can map it to the appropriate editor here. If you have xml file called myfile.exotic you can map .exotic extension to the xml editor.<br /><br /><span style="font-style: italic;">Editors->Text Editors -> Show line numbers</span>: If you like, you can see line numbers. Very useful.<br /><br /><span style="font-style: italic;">Editors->Text Editors -> Spelling:</span> Eclipse comes bundled with a spell checking turned on by default. This is a good idea and I really liked it, until I opened localized messages for my web application. Every word in my file was marked as misspelled, I was looking at an yellow sea of warnings, editor became quickly unresponsive as it wasn't able to handle hundreds of spelling errors. I had to turn this feature off, at least until some kind of ignore list is implemented or some good folk creates dictionary for my language.<br /><br /><span style="font-weight: bold;">Java</span><br /><br /><span style="font-style: italic;">Java->Code style: </span>Under Cleanup and Formatter are code formatting settings which are applied everytime the file is saved. If you tune it, it is really a lifesaver.<br /><br /><span style="font-style: italic;">Java->Code style->Code templates:</span> Here you can find and edit various templates. The only thing I do here is changing the "new Type" template to show my real name as author instead of my operating system username.<br /><br /><span style="font-weight: bold;">Run/Debug</span><br /><br /><span style="font-style: italic;">Run/Debug->Launching:</span> In previous Eclipse releases if you hit the run button, the last launched application was started. In Eclipse 3.3 this behavior changed a bit, and the selected resource gets launched. I found it annoying as I usually have only one runnable class. You can switch to the old style by choosing the right option under Launch Operation fieldset.<br /><br /></span></span></span>I know I am repeating myself, but it is essential that you walk through the options and set it, such that it works with you, not against you.<br/><br/>Tomáš Kramárhttp://www.blogger.com/profile/12420015656795241246noreply@blogger.com3