tag:blogger.com,1999:blog-64065937503279459502008-07-18T20:30:51.938-07:00Igor Minar's BlogIgor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comBlogger88125tag:blogger.com,1999:blog-6406593750327945950.post-84320667241910378932008-06-30T07:00:00.000-07:002008-06-30T07:00:01.568-07:00Enough with the Flash AlreadyIt often bothers me when Flash is being misused for small visual effects on home pages of websites. Not just that it slows things down, but it also usually breaks these websites terribly when I want to copy&paste stuff or when one doesn't have the Flash plugin installed.<br /><br /><a href="http://www.fgslovakia.com/author">Margarete</a>, has recently bugged me quite a bit about making the front page of her website a bit more "visual". She started with an idea of adding some flash to her website, which I dismissed quickly.<br /><br />Fortunately I was able to come up with a neat little CSS code, which is way better than Flash for what she was trying to achieve. Don't be mistaken, I didn't even need JavaScript to do all the subtle movements and eager image loading, it's all pure CSS.<br /><br />The front page:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_p64VvtgZDp4/SGhRpu8FyAI/AAAAAAAAAIY/MEVYelCBiPU/s1600-h/home_page_FGSlovakia_web.jpg"><img style="border: medium none ; margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_p64VvtgZDp4/SGhRpu8FyAI/AAAAAAAAAIY/MEVYelCBiPU/s400/home_page_FGSlovakia_web.jpg" alt="" id="BLOGGER_PHOTO_ID_5217509945725274114" border="0" /></a><br /><br />A small "visual" effect when one mouses over the "Blog" element:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_p64VvtgZDp4/SGhXl5TxzQI/AAAAAAAAAIg/2m4CguTknsA/s1600-h/home_page_FGSlovakia_focus.jpg"><img style="border: medium none ; margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_p64VvtgZDp4/SGhXl5TxzQI/AAAAAAAAAIg/2m4CguTknsA/s400/home_page_FGSlovakia_focus.jpg" alt="" id="BLOGGER_PHOTO_ID_5217516476859272450" border="0" /></a><br /><br />I still plan to enhance the code a bit more to make it faster to load by decreasing the number of HTTP requests needed to load the asset files as well as size of the images, but I'm quite happy with what it looks and feels like already. Check out the live version at <a href="http://www.fgslovakia.com/">www.fgslovakia.com</a>.<br /><br />A good technical article describing a technique very similar to the one that I used can be found the <a href="http://alistapart.com/articles/sprites">A List Apart</a> website.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-22321987498158308462008-06-25T07:00:00.000-07:002008-06-25T13:57:05.856-07:00BTrace == DTrace for Java<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_p64VvtgZDp4/SGHbC6E0jJI/AAAAAAAAAIQ/DM5QTFYGvYA/s1600-h/BTrace.png"><img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand; border: 0px solid black;" src="http://bp2.blogger.com/_p64VvtgZDp4/SGHbC6E0jJI/AAAAAAAAAIQ/DM5QTFYGvYA/s400/BTrace.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5215690686467443858" /></a>Last week, I was trying to nail down a bug in <a href="http://wikis.sun.com/">SunWikis</a> that was triggered by some kind of race condition. These kinds of issues are pretty nasty, especially if the application in question is a pretty complex beast, something that <a href="http://www.blogger.com/www.atlassian.com/software/confluence">Confluence</a> definitely qualifies as.<br /><br />The debugger was no help because the timing had to be very precise for the issue to occur, and logging was totally useless because of zillions lines of logs that would be difficult to safely filter out. In many cases the information I needed was not present in logs anyway and since my guess was that the bug was coming from 3rd party code, logged data couldn't be easily expanded. <a href="http://www.sun.com/bigadmin/content/dtrace/">DTrace</a>, which I blogged about in <a href="http://blog.igorminar.com/2008/06/dtrace-and-java-observations-and-docs.html">my previous post</a>, could have revealed some information, but I think that it would be very difficult to write a good D script that could give me some clues.<br /><br />While waiting for my dev server to restart, I came across an <a href="http://blogs.sun.com/theaquarium/entry/btrace_showing_promises">interesting blog post</a> that caught my eye. It mentioned this thing called <a href="https://btrace.dev.java.net/">BTrace</a>, that I hadn't heard about before. It promised it to be a DTrace aimed at Java apps. With a fair amount of skepticism, I navigated to the BTrace website and started reading. Four things about BTrace earned my interest:<ul><li>It's based on same or very similar principals as DTrace, but specialized for Java apps</li><li>No restarts necessary, you can observe a running app by connecting to a JVM identified by a PID</li><li>The BTrace programs are written in a language that is a subset of Java, and heavily based on annotations. This was a bit of a turnoff for me at first, until I found out that the programs don't need to be compiled manually but <code>btrace</code> takes care of that for me. Bravo!</li><li>I can call DTrace from my BTrace programs if I need to instrument native code or the OS</li></ul><br /><br />Armed with all this info and my eyes sparking, I wrote my first BTrace program and it worked as advertised! No restarts, no compilation, no hassle.<br /><br />A few hours later, I had a program that was observing exactly those parts of Confluence that I needed. All of this while the application was running uninterrupted. I was able to snoop on how my code was interacting with Confluence and Confluence was in turn interacting with Hibernate in a way that I would have never dreamed of. All of this while concurrent events aimed at triggering the bug were happening.<br /><br />Running BTrace programs is as easy as this:<br /><pre><br />$ ./bin/btrace \<br /> -classpath hibernate-2.1.8-atlassian.jar:spring-hibernate2-2.0.6.jar \<br /> 6266 HibernateSessions.java<br /></pre><br />Where 6266 is the PID of my app/web server and <code>HibernateSessions.java</code> is my BTrace program.<br /><br />Parts of the program looks like this (check out the javadoc comments for explanation of the code):<br /><pre><br />import com.sun.btrace.annotations.*;<br />import static com.sun.btrace.BTraceUtils.*;<br />import net.sf.hibernate.HibernateException;<br />import net.sf.hibernate.collection.PersistentCollection;<br />import net.sf.hibernate.engine.SessionImplementor;<br />import org.springframework.orm.hibernate.support.OpenSessionInViewFilter;<br /><br />@BTrace<br />public class HibernateSessions {<br /> /**<br /> * A thread local variable used to filter out all the events that we<br /> * are not interested it.<br /> */<br /> @TLS private static boolean viaSso = false;<br /> private static boolean printStack = false;<br /><br /> /** print a message when a thread enters doFilter method of SsoFilter */<br /> @OnMethod(<br /> clazz="com.sun.dse.wikis.auth.SsoFilter",<br /> method="doFilter"<br /> )<br /> public static void enableProbing() {<br /> println(str(currentThread(), " - Entered SSO Filter"));<br /> viaSso = true;<br /> }<br /><br /> /** print a message when exiting the doFilter method of SsoFilter */<br /> @OnMethod(<br /> clazz="com.sun.dse.wikis.auth.SsoFilter",<br /> method="doFilter",<br /> location=@Location(Kind.RETURN)<br /> ) <br /> public static void disableProbing() {<br /> println(str(currentThread(), " - Exited SSO Filter"));<br /> viaSso = false;<br /> }<br /><br /> /**<br /> * print an message with a HibernateException is thrown, with detailed <br /> * info about the current context<br /> */<br /> @OnMethod(<br /> clazz="net.sf.hibernate.HibernateException",<br /> method="<init>"<br /> )<br /> public static void onthrowreturn(HibernateException self, String s) {<br /> println(str(currentThread(), <br /> strcat(" - HibernateException was thrown: ",<br /> strcat(s, strcat(" | collection: ", str(collection))))));<br /> }<br /><br /> /**<br /> * Print a message when Hibernate is attaching a collection to a session.<br /> * This was crucial info for me to get in order to resolve the issue<br /> */<br /> @OnMethod(<br /> clazz="net.sf.hibernate.collection.PersistentCollection",<br /> method="setCurrentSession",<br /> location = @Location(Kind.RETURN)<br /> )<br /> public static void setSessionForCollection(boolean returnValue) {<br /> if (returnValue == true) {<br /> println(str(currentThread(),<br /> strcat(" - a collection was attached to a session. Collection:",<br /> str(collection))));<br /> }<br />}<br /></init></pre><br /><br />The result of this was a workaround for my code as well as a pretty <a href="http://jira.atlassian.com/browse/CONF-12201">detailed bug report</a> that Atlassian confirmed to be a very similar to a confirmed bug that was reported recently. I could hardly achieve this without BTrace or without an in-depth knowledge of how all the Confluence code works.<br /><br />As great as BTrace is, it is still a beta. If you decide to use it in production environment you should keep that in mind. During the several hours I spent working with BTrace, I experienced one JVM crash/lockup caused by BTrace. I bet that this kind of issues will be ironed out soon, and often this kind of risk is worth undertaking in order to resolve otherwise untraceable bugs.<br /><br />Since last week, BTrace is part of my toolkit and I already have other mysteries on my ToDo list that I want to shine some light on with BTrace. I applaud the BTrace team for giving us this amazing tool!Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-32669802077768818152008-06-24T22:30:00.000-07:002008-06-24T22:30:06.423-07:00DTrace and Java - Observations and DocsFor a long time I've been hearing about <a href="http://www.sun.com/bigadmin/content/dtrace/">DTrace</a> and how cool it was. I read a lot about it and saw some presentation on observing Java apps with DTrace, but only recently have I found enough free time to extensively play with it. And oh boy, it really is cool. But even with all this coolness, dtracing Java apps feels a bit awkward.<br /><br />I think there are two reasons for that. The <a href="http://wikis.sun.com/display/DTrace/D+Program+Structure">D language</a>, which looks like C, but has a few fundamental differences, is pretty far from what Java developers are used to. And the second reason is the fact that DTrace is in reality instrumenting JVM and not the application running in the JVM. This means that dtracing Java is limited by abilities of the <a href="http://java.sun.com/javase/6/docs/technotes/guides/vm/dtrace.html">Java DTrace provider</a> and also that the transition between the different layers of the stack can add some awkwardness.<br /><br />Having said that, DTrace is really awesome and can be enormously helpful in many cases when developing or troubleshooting (Java) apps.<br /><br />One thing I <b>really</b> miss in DTrace is regex support in any part of D scripts. There is a limited <a href="http://wikis.sun.com/display/DTrace/D+Program+Structure">globbing support</a> and <a href="http://mail.opensolaris.org/pipermail/dtrace-discuss/2007-May/003953.html">some workarounds</a>, but they ain't pretty.<br /><br />Here are some DTrace resources that I found useful:<ul><li><a href="http://wikis.sun.com/display/DTrace/Documentation">DTrace Wiki Docs</a> - the complete documentation (I love to see cool docs like this at our <a href="http://wikis.sun.com/">SunWikis</a>)</li><li><a href="http://www.sun.com/software/solaris/howtoguides/dtracehowto.jsp">a DTrace HowTo</a></li><li><a href="http://www.solarisinternals.com/wiki/index.php/DTrace_Topics_Java">DTrace for Java at Solaris Internals</a></li><li><a href="http://opensolaris.org/os/community/dtrace/dtracetoolkit/">DTrace Toolkit</a> - a compilation of DTrace scripts written by DTrace pros</li></ul>Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-21000587812905227322008-05-26T11:30:00.000-07:002008-05-26T11:30:00.759-07:00Catching StackOverflowError and a Bug in Regex Implementation in JavaShortly after we launched <a href="http://wikis.sun.com">SunWikis</a> almost a year ago, we started having an issue with <a href="http://java.sun.com/javase/6/docs/api/">StackOverflowError</a>, which was occurring when the content of certain wiki pages was being parsed and URLs where being extracted. I documented the issue in <a href="http://jira.atlassian.com/browse/CONF-9392">CONF-9392</a>.<br /><br />The problem is not really a bug in Confluence (even though using an overly-complex regular expressions doesn't help the case), but it's a problem in JDK. After a brief search at <a href="http://bugs.sun.com">bugs.sun.com</a> I found the root cause of our StackOverflowError documented as bug <a href="http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6337993">6337993</a>.<br /><br />Originally I tried to mitigate the situation by increasing the memory reserved for the stack data via the <code>-Xss</code> JVM parameter. This helped a little bit, but wasn't good enough in most cases.<br /><br />Last week I decided to go against everything I've been taught, and wrote a patch for Confluence that wraps the part of code that results in the StackOverflowError into a try/catch block. I know that any throwables that extend from Error <a href="http://java.sun.com/javase/6/docs/api/java/lang/Error.html">should not be caught</a> by a client code because they usually indicate a failure that only JVM should try to recover from, but IMO in the case of StackOverflowError, the situation is a bit different. That is mainly because before throwing the StackOverflowError, JVM pops the stack, so by the time the code execution gets to the catch block, JVM has already recovered from the error.<br /><br />I don't claim this to be a solution to the problem, it's just a workaround that works better than increasing the stack size in this particular case. The fact that Confluence doesn't find all the URLs in wiki pages (used mainly to list outgoing links in the page info view) is just a small sacrifice, compared to inability to save or copy the page.<br /><br />As for the solution, it seems that reimplementing Java's regular expressions library would be the most suitable one. I tried to run a code that fails in Java in JRuby, which uses a port of <a href="http://www.geocities.jp/kosako3/oniguruma/">Oniguruma</a> regex engine for Java and things worked flawlessly and as I read it also gives JRuby a <a href="http://www.infoq.com/news/2007/11/oniguruma-joni-jruby">performance boost over java.util.regex</a>.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-76259003664163501102008-02-08T11:00:00.000-08:002008-02-08T10:54:31.876-08:00Mediacast Deployment DiagramDuring our last meeting, <a href="http://weblogs.java.net/blog/arungupta/">Arun</a> suggested that I publish the high-level deployment diagram of <a href="http://mediacast.sun.com">mediacast.sun.com</a>. So here it is:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_p64VvtgZDp4/R6yhC1RzzpI/AAAAAAAAAII/5mRZxbxi8f0/s1600-h/Mediacast_Deployment_Diagram.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_p64VvtgZDp4/R6yhC1RzzpI/AAAAAAAAAII/5mRZxbxi8f0/s400/Mediacast_Deployment_Diagram.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5164679942720704146" /></a><br /><br />I described everything in textual form in my previous <a href="http://blog.igorminar.com/2008/01/jruby-on-rails-rewrite-of.html">blog entry about mediacast</a>.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-2493860737516272702008-01-27T20:16:00.000-08:002008-01-28T17:33:57.902-08:00JRuby on Rails Rewrite of mediacast.sun.com LaunchedA few days ago, we finally released <a href="http://mediacast.sun.com/">Mediacast 2.0</a> - a complete rewrite of the old Mediacast application.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_p64VvtgZDp4/R50181RzzoI/AAAAAAAAAIA/0zBAagWqj10/s1600-h/Picture+4.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_p64VvtgZDp4/R50181RzzoI/AAAAAAAAAIA/0zBAagWqj10/s400/Picture+4.png" alt="" id="BLOGGER_PHOTO_ID_5160340067246657154" border="0" /></a><br /><br />The original application was based on a few servlets, filters, and a lot of JSPs. It was all put together in hurry a few of years ago, when one of those fire-drill requests came to provide Sun employees with a site where they could publish files. The old code was hard to maintain and extend, and that's why we decided to EOL the old code base and write something better from scratch.<br /><br />I'm a fan of <a href="http://www.rubyonrails.org/">Rails</a> and for the past year I've been amazed by the great progress of the <a href="http://jruby.codehaus.org/">JRuby</a> project. This was one of the reasons why I suggested that we could try to rewrite the app in Rails and deploy it in a regular Java web container, thanks to JRuby and <a href="http://wiki.jruby.org/wiki/Goldspike">Goldspike</a>. It took some time for <a href="http://blogs.sun.com/rama/">Rama</a> to give us a go-ahead, but finally in late September, two other colleagues (with no Rails or JRuby experience) and I started to work on the rewrite alongside our other projects (<a href="http://forums.sun.com/">forums.sun.com</a> and <a href="http://wikis.sun.com/">wikis.sun.com</a>).<br /><br />Many people asked us why JRuby on Rails was picked for this project. Here is an incomplete list of reasons:<ul><li>we were starting from scratch, so we were not tied to any legacy code, and could pick any web framework that runs on Java</li><li>proof of concept project to evaluate the technology for other uses across our organization</li><li>verify that Rails really delivers the rapid development promise</li><li>something new/fun for the team to help balance out the not-so-fun stuff :)</li></ul><br />Here is my experience:<br /><br /><h2>Rails and JRuby Learning Curve</h2><br />I worked on my first Rails project in the summer of 2006 and since then I worked on a few other (internal) Rails projects. But having to teach others and deploy an application externally using JRuby was a new experience for me.<br /><br />As far as teaching goes, I can't critique myself, but what I can say is that I had a lot of good help thanks to some <a href="http://www.pragprog.com/titles/rails2">Rails</a>, <a href="http://www.pragprog.com/titles/ruby">Ruby</a> and <a href="http://www.apress.com/book/view/9781590598818">JRuby</a> books, and many websites and blogs that have sprung up on the Internet in the last couple of years.<br /><br />Learning JRuby (with previous Ruby and Java experience) is easy, because most of the time "it just works" and very rarely is the developer aware that the C-based MRI Ruby interpreter is not being used. The ability to access and seamlessly integrate with existing or new Java code is a huge plus without which we would not have been able to launch this project successfully (more on this later).<br /><br />The deployment part was a different story. The Ruby on Rails application can be deployed in many different ways and JRuby offers a new alternative approach to all of them. Instead of e.g. having Apache webserver reverse-proxy requests to an army of Mongrels, JRuby and <a href="http://wiki.jruby.org/wiki/Goldspike">Goldspike</a> make it possible to deploy Rails applications in a JavaEE web container. IMO this is much cleaner than anything else that is available in the non-JRuby Rails world. The downside is that this deployment method is quite new and there isn't a lot of documentation and community knowledge about it.<br /><br /><h2>Application Architecture</h2><br />Our app is a simple database-driven Rails application consisting of a handful of models, 4 controllers, and a bunch of view templates. The only piece of data that is not stored in the database are the actual files, which are stored on the file system.<br /><br />To be on the safe side when it comes to performance, we employed quite a lot of fragment caching, which sped up our application quite a bit.<br /><br /><h2>Development Environment</h2><br />Our development environment is based on a self-contained<a href="#1"><sup>1</sup></a> JRuby (1.0.3) on Rails (1.2.6) application stored in a <a href="http://www.selenic.com/mercurial">Mercurial</a> repository. The IDE we use is <a href="http://www.netbeans.org/">NetBeans 6</a> with Ruby support and <a href="http://wiki.netbeans.org/MercurialVersionControl">Mercurial plugin</a>. The DB of our choice is MySQL and servers we use during development are <a href="http://wiki.rubyonrails.org/rails/pages/WEBrick">WEBrick</a> and <a href="https://glassfish.dev.java.net/">Glassfish v2ur1</a>.<br /><br />NetBeans makes it super easy to write the Ruby code and offers a lot of neat features for Rails application development. I have to say that <a href="https://blogs.sun.com/tor">Tor</a> and the gang did a great job. In fact I switched from Eclipse to NetBeans thanks to its great Ruby support.<br /><br />Because the application runs in the JVM we can use JConsole to monitor the app while load testing which comes in really handy!<br /><br />So all is good here, except for one thing. I got used to using the amazing <a href="https://rubyforge.org/projects/ruby-debug/">ruby-debug</a> debugger for debugging my Ruby on Rails applications. This debugger is not yet available for JRuby on Rails application (unless you <a href="http://mysterycoder.blogspot.com/2007/10/debugging-jruby-on-rails-app-with-jruby.html">hack your way through</a>). I read somewhere that jruby-debug should be available with NetBeans 6.1. Once that is done, the JRoR dev environment will be on par with RoR (in fact thanks to tools like JConsole it will be superior).<br /><br /><h2>Production Environment</h2><br />We use a pair of load-balanced <a href="http://www.sun.com/servers/coolthreads/t2000/">T2000</a> with <a href="http://www.blogger.com/www.sun.com/software/solaris">Solaris 10</a>, <a href="https://jdk6.dev.java.net/">JDK6</a> and <a href="http://www.sun.com/software/products/appsrvr/index.xml">SJSAS 9.1u1</a>. These two servers share a nfs NAS drive used for file storage and fragment cache storage. The DB backend is a MySQL database server, which we access through a connection pool set up in the app server.<br /><br />All of this was fairly easy to set up. As you can see there were no special requirements when comparing this environment to a usual JavaEE production environment.<br /><br /><h2>The Good</h2><br />Once my colleagues grasped some RoR basics, we got the core of the application up and running fairly fast. Sometimes it still amazes even me how much one can do with Rails in a short amount of time. Thanks to a small amount of code one needs to write, the code review process is fast as well, and fixing a bug often means changing only a few lines of code.<br /><br /><h2>The Bad</h2><br />Since most of the C-based gems are not compatible out-of-box with JRuby (at the moment), the <a href="https://rubyforge.org/projects/jruby-extras/">jruby-extras</a> project aims to deliver JRuby compatible versions of these libraries. One of these libraries - JRuby-OpenSSL - was needed for me to integrate our app with our authentication webservice. I soon found out that JRuby-OpenSSL was not completely implemented yet and parts of functionality that I needed were missing. I'm sure that it is just a matter of time when problems like this will go away (if it hasn't happened already) as these libraries will mature.<br /><br /><h2>The Ugly</h2><br />The Goldspike project provides a bridge between the JavaEE and RoR world. It does this by dispatching the incoming HTTP requests into Rails running in a JRuby runtime.<br /><br />This works great for all requests that take little time to process, but if you have long-running requests like large file uploads or downloads, these requests will occupy your JRuby runtimes and you soon realize that you are running out of runtimes in your small pool, at which point your application becomes unresponsive for any new requests.<br /><br />This was the biggest problem we hit, but thanks to the possibility to seamlessly integrate Java code into our JRoR app and a great idea that my colleague Peter had, we solved this issue quite elegantly.<br /><br /><h2>JRuby and Java Come to the Rescue</h2><br />The two main issues we faced and that consumed most of my time on this project were related to the immaturity of the libraries around JRuby and application characteristics specific to JRoR deployment. Both of these issues can be resolved thanks to years of long Java and JavaEE history, and their libraries.<br /><br />The problem with reliable connection to our SOAP-over-HTTPS based authentication webservice was resolved by generating a client Java webservice stub and using that instead of <a href="http://dev.ctor.org/soap4r">SOAP4R</a> which didn't work properly because of the problems with JRuby-OpenSSL.<br /><br />The second problem with the long-running processes occupying our precious JRuby runtimes, we solved by using a servlet filter and a fake HttpServletResponse (that we sent to Goldspike instead of the original one) and streaming the data from the filter instead from the runtime. I'll write a separate blog entry on this.<br /><br /><h2>Overall Impression</h2><br />This project was/is fun to work on. We experimented with quite a few new (for us) technologies and learned a lot along the way. To be honest, I expected to deploy the app much sooner but at that time I was not aware of the two above mentioned issues which consumed a lot of my time.<br /><br />I was a bit worried about the performance of the application, but that turned out to be a non issue once we had the download servlet filter in place, and with the performance improvements in JRuby 1.1 things will be even better in the future.<br /><br />Overall I'm happy with the outcome of our project and I look forward to adding more functionality to the application.<br /><br /><h2>Our Future Plans</h2><br />From the infrastructure perspective:<ul><li>upgrade to JRuby 1.1 and Rails 2.0</li><li>start using <a href="http://wiki.jruby.org/wiki/Warbler">Warbler</a>, which looks to be superior to Goldspike's Rails plugin, for building the war file</li><li>experiment with in-memory session state replication in Glassfish</li></ul><br />From the feature perspective:<ul><li>better categorization of media items</li><li>search functionality via integration with <a href="http://search.sun.com">search.sun.com</a></li><li>previews of media items</li><li>new UI design</li><li>and the toughest one - audio and video streaming</li></ul><br /><br /><h2>JRuby/Goldspike/Glassfish Things I Would Like to See Improved</h2><br /><ul><li>I'm not sure if it is us and our (mis)configuration, Goldspike, JRuby or Glassfish, but right now we need quite a <b>big JVM heap</b> to keep things running. With 8 JRuby instances in the pool and Http thread count set to 512, we need -Xmx set to 2-2.5GB. This is a bit too much I think. We'll have to look into this and find the culprit.</li><li>The <b>application startup is quite slow</b>, especially on a machine like T2000, which doesn't perform well for heavy-weighted single-threaded operations. I don't see a reason, why Goldspike couldn't initialize the JRuby runtime pool concurrently cutting down the startup time significantly.</li><li><b>Offload JRuby runtimes as much as possible</b>. Currently operations like file upload or file download (via Rails' send_file) are handled by JRuby runtimes. I think that it should be possible to take care of these operations outside of the runtime, allowing the runtime to process other rails requests in the meantime.</li></ul><br /><br /><br /><a name="1"><sup>1</sup></a> - Rails and all the other gems and jars are frozen into the projectIgor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-38452491182653504392008-01-21T23:59:00.000-08:002008-01-26T14:37:18.683-08:00On the Move (Away from Blogger)Today was a big day for my blog. I started a "big" move that was hanging over my mind for a few months.<br /><br />I got my own domain <a href="http://igorminar.com/">igorminar.com</a> and changed the blogger.com settings so that the domain name <a href="http://blog.igorminar.com/">blog.igorminar.com</a> is being used instead of <a href="http://net3x.blogspot.com/">net3x.blogspot.com</a>.<br /><br />Except for a small hick-up with DNS cache and a weird 404 Server not Found error (described <a href="http://bloggerstatusforreal.blogspot.com/2007/11/custom-domain-publishing-and-404-error.html">in this blog post</a>) everything went smoothly. My plan is to keep on using Blogger's custom domain feature for a few weeks and then migrate all the content over to my own blogging engine. I'll most likely end up using <a href="http://mephistoblog.com/">Mephisto</a>, <a href="http://jruby.codehaus.org/">JRuby</a>, <a href="https://glassfish.dev.java.net/">Glassfish</a> and <a href="http://www.mysql.com/">MySQL</a>, but things can still change.<br /><br />The reason why I'm moving in two phases is to keep all the referring links that point to the old urls as well as most of the search engine ranking. The Blogger's custom domain feature now redirects everything to the new urls via 301 Permanent Redirect, so hopefully the transition will be close to painless. I'm not SEO expert, but this for sure is an interesting experiment.<br /><br />And for those SEO "experts" that were claiming that getting Blogger to do proper redirects after a blog move was impossible here is a little proof:<pre><br />$ wget --spider net3x.blogspot.com<br />--16:34:30-- http://net3x.blogspot.com/<br /> => `index.html.2'<br />Resolving net3x.blogspot.com... 72.14.207.191<br />Connecting to net3x.blogspot.com|72.14.207.191|:80... connected.<br />HTTP request sent, awaiting response... 301 Moved Permanently<br />Location: http://blog.igorminar.com/ [following]<br />--16:34:30-- http://blog.igorminar.com/<br /> => `index.html.2'<br />Resolving blog.igorminar.com... 66.249.81.121<br />Connecting to blog.igorminar.com|66.249.81.121|:80... connected.<br />HTTP request sent, awaiting response... 200 OK<br />Length: 0 [text/html]<br />200 OK<br /></pre>Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-15480089032691263792008-01-20T23:20:00.000-08:002008-01-20T23:12:07.690-08:00My Custom Prompt for Leopard's TerminalAs I mentioned in <a href="http://net3x.blogspot.com/2008/01/leopards-terminal-tabs.html">my previous post</a>, even though it is not perfect, I settled on using Terminal as my terminal application.<br /><br />The default prompt that comes with MacOS is not very useful, so I configured my own by adding this line to my <code>.bashrc</code> file:<br /><pre>export PS1="\[\033]0;\u@\h:\w\007\]\u@\h:\W\\$ "</pre><br />This results in a prompt that looks like this:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp2.blogger.com/_p64VvtgZDp4/R5RBR5lhkxI/AAAAAAAAAHk/AbnH-YzsnEQ/s1600-h/Terminal3.png"><img style="border: medium none ; margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp2.blogger.com/_p64VvtgZDp4/R5RBR5lhkxI/AAAAAAAAAHk/AbnH-YzsnEQ/s400/Terminal3.png" alt="" id="BLOGGER_PHOTO_ID_5157819249017852690" border="0" /></a><br />This prompt displays the prompt as <code>username@hostname:currentdir$</code> and in addition to that it sets the window title to <code>username@hostname:pwd</code>.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-5304416946434576312008-01-20T22:55:00.000-08:002008-01-20T22:59:08.486-08:00Leopard's Terminal TabsAs I shared yesterday, <a href="http://net3x.blogspot.com/2008/01/im-obsesed-with-tabs.html">I love tabs</a>. One of the few good things that MacOS 10.5 Leopard brought, was enhanced Terminal application. A basic feature - Tab support - that was missing in Terminal for way too long, was finally added, and Terminal app became finally usable for anyone who spends a great time of the day working on the command line.<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_p64VvtgZDp4/R5Qs-ZlhkvI/AAAAAAAAAHU/PNEd6H8SBXg/s1600-h/Terminal.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; border:none;" src="http://bp0.blogger.com/_p64VvtgZDp4/R5Qs-ZlhkvI/AAAAAAAAAHU/PNEd6H8SBXg/s400/Terminal.png" alt="" id="BLOGGER_PHOTO_ID_5157796923777848050" /></a><br />Before Leopard, I used <a href="http://iterm.sourceforge.net/">iTerm</a>, but there was just something about it that I didn't like, but the availability of tabs made me get over it. Now with Leopard there is no need for iTerm any more.<br /><br />Just to point out that Apple seems to be unable to get anything 100% right these days, there are two flaws in the Terminal's tab implementation.<br /><br />The first flaw is that you can't easily switch between tabs using keyboard shortcut. All you can do is to use <code>cmd+{</code> and <code>cmd+}</code> to switch to previous or next tab respectively. What a "wonderful" choice of keys that require use of right hand or both hands. Most importantly, one can't use the handy <code>cmd+1</code>, <code>cmd+2</code>, ..., <code>cmd+9</code> shortcuts (or anything similar) to switch to one of the first nine tabs. Maybe Apple doesn't want to overload us with new features and is planning to add this to Terminal in MacOS 10.6. :-) Fortunately, the <code>cmd+{</code> and <code>cmd+}</code> shortcuts can be remapped via System Preferences.<br /><br />The second flaw is that Terminal doesn't let you name the tabs or configure how the tabs should be named. This is a useful feature that many other terminal applications have, but Apple decided that using the name of the program of the currently running process is good enough. Well, this is what it looks like:<br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_p64VvtgZDp4/R5Q5JJlhkwI/AAAAAAAAAHc/52vurVDrhcc/s1600-h/Terminal2.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; border: none;" src="http://bp3.blogger.com/_p64VvtgZDp4/R5Q5JJlhkwI/AAAAAAAAAHc/52vurVDrhcc/s400/Terminal2.png" alt="" id="BLOGGER_PHOTO_ID_5157810302600975106" border="0" /></a><br />People are doing all kinds of crazy things to work around this issue. Including using <a href="http://www.allthepages.org/archives/2007/10/specify_tab_names_in_terminal.html">hardlinks to change names of programs</a> or creating <a href="http://pseudogreen.org/blog/set_tab_names_in_leopard_terminal.html">dummy processes that carry the tab name</a>.<br /><br />I would be very happy if Apple did something similar to what xterm does - <a href="http://www.faqs.org/docs/Linux-mini/Xterm-Title.html">using an environmental variable to set name of the tab dynamically</a>. But I have a feeling that we'll see MacOSX Trash go 3D sooner than properly working Terminal tabs. :(Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-71063554795279556572008-01-20T16:15:00.000-08:002008-01-20T16:06:45.203-08:00Mac Applications That I UseI've been meaning to write this entry on applications installed on my computer for a few months now, but never found time to do it. Hopefully none of those new Mac users that I told to check out my blog "in a few days", several months ago, got angry at me. If nothing else, my promise helped me to get more regular readers :).<br /><br />Anyway, here is the list of apps installed on my Mac (all these apps work with Leopard, unless I noted otherwise):<br /><h2>Essentials</h2>A Mac without these apps would never be the same:<br /><ul><li><a href="http://download.blacktree.com/download.php?id=com.blacktree.Quicksilver&type=dmg&new=yes">Quicksilver</a> - an app that helps you find things on your computer and execute actions on these things. I use it to launch apps, pause iTunes, find contacts in the AddressBook, and many many many other things. Most of the cool functionality is added via plugins, so don't forget to checkout the plugin section of preferences. This app is a must have. Here are <a href="http://docs.blacktree.com/quicksilver/what_is_quicksilver">Some docs</a> and a <a href="http://video.google.com/videoplay?docid=8493378861634507068">good video</a>.</li><br /><li><a href="http://www.adiumx.com/">Adium</a> - a really handy IM client that can handle all the popular IM protocols. Definitely a must have. (it's much better than iChat when it comes to IM-ing).</li><br /><li><a href="http://growl.info/downloads.php">Growl</a> - Growl is a notification system for Mac OS X: it allows applications that support Growl to send you notifications. Notifications include Adium or Skype messages, network up/down events, volume mount/unmount events, currently played iTunes song and many others. <a href="http://growl.info/about.php">More info</a> - One extension that I found to be incompatible with Leopard is GrowlMail for Mail.app notifications, when I received many new messages at once this extension would cause the Mail.app to crash.</li><br /><li><a href="http://www.macports.org/">MacPorts</a> - This is a geeky one: The MacPorts Project is an open-source community initiative to design an easy-to-use system for compiling, installing, and upgrading either command-line, X11 or Aqua based open-source software on the Mac OS X operating system.</li><br /><li><a href="http://www.mozilla.com/en-US/firefox/">Firefox</a> - no description needed :)</li></ul><br /><h2>Nice to Have</h2><ul><li><a href="http://www.islayer.com/index.php?op=item&id=28">iStat menus</a> - a nifty app that displays stats about cpu load, cpu temperature, memory and network utilization, and a lot of other interesting data about your Mac. I use it as a replacement of <a href="http://www.ragingmenace.com/software/menumeters/">MenuMeters</a> which I couldn't get to run reliably on Leopard.</li><br /><li><a href="http://perian.org/">Perian</a> - Perian is a free, open source QuickTime component that adds native support for many popular video formats.</li><br /><li><a href="http://caminobrowser.org/download/releases/">Camino</a> - yeah, as if the fact that <a href="http://net3x.blogspot.com/2008/01/im-obsesed-with-tabs.html">I'm obsessed with tabs</a> was not enough, I usually run 2 or 3 browsers at the same time to be able to take advantage of their unique features, or more often, while developing webapps, I need to be able to have more than one session open.</li><br /><li><a href="http://sourceforge.net/projects/cotvnc/">Chicken of the VNC</a> - A handy VNC client</li><br /><li><a href="http://code.google.com/p/macfuse/">MacFUSE + sshfs</a> - MacOS X implementation of <a href="http://fuse.sourceforge.net/">FUSE</a>, which makes it possible to painlessly mount all kinds of different filesystems e.g. sshfs.</li><br /><li><a href="http://code.google.com/p/macfusion/downloads/list">MacFusion</a> - GUI frontend for MacFUSE</li><br /><li><a href="http://www.videolan.org/vlc/">VLC</a> - alternative to QuickTime video player with build-in support for all kinds of video and audio codes, subtitle support and many other features</li><br /><li><a href="http://sourceforge.net/projects/osxvnc/">Vine Server (OSXvnc)</a> - a good VNC server in case you need a bit more control than the Leopard's built-in server offers</li><br /><li><a href="http://skype.com/">Skype</a> - I have a love-hate relationship with Skype. As soon as I find an alternative crossplatform communication tool with audio and video support and cheap calls to Slovakia, I'll switch. Maybe <a href="http://www.blogger.com/www.gizmoproject.com">Gizmo</a> will become that tool one day<br /></li><br /><li><a href="http://www.neooffice.org/neojava/en/maindownload.php">NeoOffice</a> - don't forget to install the latest <a href="http://www.neooffice.org/neojava/en/patch.php">Patch</a>. I have big hopes for <a href="http://porting.openoffice.org/mac/faq/aqua-prerelease/index.html">OpenOffice Aqua</a> to be released soon. <a href="http://net3x.blogspot.com/2007/06/openofficeorg-aqua-development-snapshot.html">My initial experiments</a> revealed some very good performance results.</li><br /><li><a href="http://www.shinywhitebox.com/home/home.html">iShowU</a> - a cool app for creating screencasts. This is the only paid-for app on my list. But it's well worth it.</li><br /><li><a href="http://lightheadsw.com/caffeine/">Caffeine</a> - Caffeine is a tiny program that prevents your Mac from automatically going to sleep, dimming the screen or starting screen savers. Very useful during video calls, while reading PDFs or watching movies.</li><br /><li><a href="http://iconfactory.com/software/twitterrific">Twitterrific</a> - a Twitter client</li><br /><li><a href="http://azureus.sourceforge.net/download.php">Azureus</a> - Java BitTorrent client</li><br /><li><a href="http://www.orange-carb.org/SkeyCalc/">SkeyCalc - An OTP (S/Key) calculator</a></li><br /><li>Cisco VPN Client</li></ul><h2>Development</h2><ul><li><a href="http://download.netbeans.org/netbeans/6.0/final/">NetBeans</a> - there is a lot of controversy in the community when it comes to the Eclipse vs NetBeans question. I used Eclipse for a really long time, but ever since I tried NB6 Milestone 8 or so, I started liking NB more than Eclipse. I'll give Eclipse another shot in a few weeks, but for now NetBeans is my default IDE. And as far as Ruby/JRuby development is concerned, I don't think that this is going to change for a long time.<br /></li><br /><li><a href="http://dist.codehaus.org/jruby/">JRuby</a> - a pure Java-based Ruby interpreter</li><br /><li><a href="https://glassfish.dev.java.net/">GlassFish</a> - JavaEE 5.0 compliant application server</li></ul><br /><h2>Other Stuff</h2><ul><li><a href="http://www.siliconimage.com/docs/SiI3132_1.1.9u_Sil_Pkg.zip">Drivers for my Vydeo eSATA 34: Dual Port 34mm Express Card</a> - More info in <a href="http://net3x.blogspot.com/2007/03/500gb-esata-external-storage-with.html">my older blog entry</a></li></ul><br /><br /><h2>Other Lists</h2><a href="http://blogs.sun.com/rama/entry/what_to_install_on_your">Rama</a> and <a href="http://blogs.sun.com/martin/entry/things_you_can_t_live">Martin</a> composed similar lists some time ago, so you might want to check those out as well.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-24227644677555992692008-01-20T01:00:00.000-08:002008-01-20T01:38:02.101-08:00I'm Obsessed with TabsThis is a screenshot I took during a regular development/research day:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_p64VvtgZDp4/R5MK1ZlhktI/AAAAAAAAAHE/GE4hpvzW5do/s1600-h/FirefoxTabs.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand; border: none;" src="http://bp3.blogger.com/_p64VvtgZDp4/R5MK1ZlhktI/AAAAAAAAAHE/GE4hpvzW5do/s400/FirefoxTabs.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5157477910786970322" /></a><br /><br />What is your average number of browser tabs opened at once?Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-45015702246747674582008-01-18T11:45:00.000-08:002008-01-20T15:16:57.977-08:00MultiSudokuSolver - A fun project I worked on during the Xmas breakWhile I was visiting my family in Slovakia during the winter 2005/2006 I found a <a href="http://en.wikipedia.org/wiki/Sudoku">sudoku</a> magazine in my dad's apartment. I like this kind of stuff, so I mediately started solving one puzzle after another, until I got to a "Speciality MultiSudoku" puzzle:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_p64VvtgZDp4/R5EAAJlhkrI/AAAAAAAAAG0/IaSZEI871gM/s1600-h/sudoku.jpg"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp0.blogger.com/_p64VvtgZDp4/R5EAAJlhkrI/AAAAAAAAAG0/IaSZEI871gM/s400/sudoku.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5156903050889237170" /></a><br /><br />This puzzle is composed of five regular 9x9 puzzles that are interconnected and you can't solve either of them alone, meaning that you need to be solving all five of them at the same time and use intermediate results from one puzzle to get an intermediate result for another puzzle that this puzzle is connected with. It sounded like a good challenge so I started working on it. After two or three nights I realized that I made a mistake!! Ughhh. I erased everything I had solved and started from scratch. After another few nights I found another problem, got turned off by this puzzle and put it away.<br /><br />I came across the puzzle once again when my wife and I returned to Slovakia this winter. I found the puzzle in the apartment and, being a person who likes challenges and doesn't get turned off my failures for too long, I decided to erase everything and this time be very careful and solve the puzzle once and for all.<br /><br />After about two evenings I found something I didn't want to see. An error!!! It was hard to believe it, but there it was. I tried to fix it, but if you don't spot an error in a sudoku puzzle early enough, you'll spend more time fixing it than if you started from scratch.<br /><br />Do you think I felt like starting from scratch? No! But I couldn't let this be. So since I had 10 or so days off during the Christmas break (thanks Sun!!!), I decided to use my brain in a more productive way and to write a small program that would solve the puzzle for me.<br /><br />Given my interest in Ruby and JRuby and the type of problem I was about to solve, the language choice was an easy one to make.<br /><br />A few days later I had a script that solved the puzzle for me within 1.07 seconds. Ya! You heard right! Solved not in a few evenings but in just a little more than one second.<br /><br /><pre><br />Top Left:<br />718|956|324<br />452|387|619<br />936|142|587<br />-----------<br />341|528|796<br />695|713|842<br />287|694|153<br />-----------<br />523|461|978<br />869|275|431<br />174|839|265<br /><br />Top Right:<br />635|428|971<br />214|679|853<br />897|531|426<br />-----------<br />976|382|514<br />152|764|389<br />348|915|267<br />-----------<br />463|857|192<br />529|146|738<br />781|293|645<br /><br />Bottom Left:<br />728|154|396<br />194|836|752<br />653|279|184<br />-----------<br />519|368|427<br />346|725|918<br />872|491|563<br />-----------<br />231|987|645<br />467|512|839<br />985|643|271<br /><br />Bottom Right:<br />215|849|637<br />348|627|591<br />976|153|824<br />-----------<br />869|431|752<br />154|972|368<br />732|568|149<br />-----------<br />521|796|483<br />483|215|976<br />697|384|215<br /><br />Center:<br />978|215|463<br />431|678|529<br />265|439|781<br />-----------<br />813|754|692<br />649|382|157<br />527|961|834<br />-----------<br />396|847|215<br />752|196|348<br />184|523|976<br /></pre><br /><br /><b>Lessons learned: "automate automate automate!" and "Don't work hard, but work smart!" :)</b><br /><br />The algorithm is very simple. The model is based on the simplest unit - a cell which is part of a row, column and a square. Each puzzle consists of 9 columns, 9 rows and 9 squares. Cells are flexible enough to be part of more than one square, row or a column at a time, so I can have cells that are present in more than one puzzle at a time. With a flexible model like this, all that the program needs to do is to use some basic rules to eliminate candidates and determine cell values. This type of solver is often referred to as human-style solver, because it uses the same techniques used by humans.<br /><br />If anyone is interested in having a look at the source code it can be downloaded from here: <a href="http://mediacast.sun.com/users/IgorMinar/media/multi_sudoku_solver.rb/details">multi_sudoku_solver.rb</a>. A word of warning - the code is not cleaned up nor documented. This was just a fun project that I worked on, and the fact that I achieved what I set out to achieve was a good enough milestone to call this project done.<br /><br />After this experience I don't feel like solving sudoku puzzles any more. They are just a repetitious problems that are well suited for automated solution. Most importantly - I actually had more fun writing the program than I had with solving the puzzle :).Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-60661527471859304542007-11-23T19:20:00.000-08:002007-11-23T20:18:16.504-08:00Shure SE210 Earphones (upgrade from E2c)When I bought my <a href="http://www.shure.com/PersonalAudio/Products/Earphones/ESeries/us_pa_E2c_content">Shure E2c</a> earphones two years ago, I was blown away by the sound quality. I never spend more than $50 for earphones before and after buying the E2c model I would never consider downgrading to anything less. Shure really knows how to create addictive high quality products. The quality of the sound produced by my old E2c earphones was so good that I had to get rid of some albums that I ripped into mp3s long time ago when hard drive space was measured in megabytes rather than in gigabytes.<br /><br />After two years of slave-like everyday service my Shure E2c earphones started to show signs of wear and it became apparent that they were going to retire soon.<br /><br />Afraid of being without a good pair of earphones during my upcoming transatlantic flight, I got a new pair of <a href="http://www.shure.com/PersonalAudio/Products/Earphones/SEModels/us_pa_SE210_content">Shure SE210</a>. The design has change slightly compared to the older model, but it still preserves the main features that I loved so much.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_p64VvtgZDp4/R0eTfr1wcUI/AAAAAAAAAGI/gdKXHGafCUU/s1600-h/shure_se210.jpg"><img style="border: medium none ; margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp3.blogger.com/_p64VvtgZDp4/R0eTfr1wcUI/AAAAAAAAAGI/gdKXHGafCUU/s400/shure_se210.jpg" alt="" id="BLOGGER_PHOTO_ID_5136236072592765250" border="0" /></a><br /><br />I've been listening to some music via these earphones for only an hour or so, but I can already tell that SE210 brings "great sound" to a brand new level. I don't consider myself to be an audiophile, but even my untrained ear can hear the big difference between the two. The new pair fits better as well as feels more comfortable in my ears.<br /><br /><a href="http://j0ni.livejournal.com/">J</a>, lost his mind a couple of weeks ago and bought a pair of the high-end <a href="http://www.shure.com/PersonalAudio/Products/Earphones/SEModels/us_pa_se530_content">SE530</a>. I don't even want to know what those sound like. I know that if I tried them, I would be tempted to pay an insane amount of money for them, so I better say away :)Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-39776366666448782662007-10-29T09:30:00.000-07:002007-10-29T09:19:38.866-07:00Inflector/environment.rb Bug in RailsToday I needed to get Rails to grok an uncountable noun "media". Easy you think, right? Just add an inflection rule.<br /><br />So I went to <code>config/environment.rb</code>, uncommented the Inflection example and modified it with my "media" noun, just like this:<pre>Rails::Initializer.run do |config|<br /> ...<br /> ...<br /> ...<br /> <br /> Inflector.inflections do |inflect|<br /> inflect.uncountable %w( media )<br /> end<br /><br /> # See Rails::Configuration for more options<br />end<br /><br /># Add new mime types for use in respond_to blocks:<br /># Mime::Type.register "text/richtext", :rtf<br /># Mime::Type.register "application/x-mobile", :mobile</pre><br /><br />When I tried to run rails console or tests I saw an error like this:<pre style="overflow: auto;"><br />me@Xbook:testapp$ ./script/console <br />Loading development environment.<br />./script/../config/../config/environment.rb:55:NameError: uninitialized constant Inflector<br />/opt/local/lib/ruby/gems/1.8/gems/actionpack-1.13.5/lib/action_controller/assertions/selector_assertions.rb:525:NoMethodError: undefined method `camelize' for "top":String<br />/Users/me3x/Development/DSE/mediacast2/apps/testapp/app/controllers/application.rb:4:NameError: uninitialized constant ActionController::Base</pre><br /><br />The problem turned out to be in the commented-out rails example in <code>environment.rb</code>. The <code>Inflector.inflections</code> block must not be nested within the <code>Initializer.run</code> block.<br /><br />This fixes the problem:<pre><br />Rails::Initializer.run do |config|<br /> ...<br /> ...<br /> ...<br /><br /> # See Rails::Configuration for more options<br />end<br /><br />Inflector.inflections do |inflect|<br /> inflect.uncountable %w( media )<br />end<br /><br /># Add new mime types for use in respond_to blocks:<br /># Mime::Type.register "text/richtext", :rtf<br /># Mime::Type.register "application/x-mobile", :mobile</pre>Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-32296624388321153432007-10-29T09:05:00.000-07:002007-10-29T10:30:07.841-07:0010 Things I Hate About MacOS X LeopardAlmost everyone is hyped about the new release of MacOS. All those <a href="http://www.apple.com/macosx/features/">great new features</a>. Auweeeeee! I'm a an Apple fan, for now - I'm starting to struggle to justify it. Leopard does have a lot of nice features, but it is missing a lot as well. Considering the delay of the OS, I'm disappointed mainly about these ten things:<br /><br /><ol><li><a href="http://blogs.sun.com/roumen/entry/no_jdk_6_on_macs">JDK6 is missing</a> - WTF Apple!?!?!?</li><li>Only read-only support for ZFS, unless you count the developer preview version at ADC</li><li><strike>Where is Xray? - The neat DTrace GUI that used to be <a href="http://flickr.com/photo_zoom.gne?id=541077688&context=photostream&size=l">promoted on Apple.com website a few weeks ago</a></strike> Update: The app is now called <a href="http://www.apple.com/macosx/features/300.html#instruments">Instruments</a> and is part of developer tools. Thanks Ron and Barry for pointing this out to me</li><li>JDK6 is missing!!!!! Are you kidding me? Even James Gosling who <a href="http://blogs.sun.com/jag/entry/the_new_macintoshes">liked to work on Macs</a>, <a href="http://blogs.sun.com/jag/entry/solaris_and_os_x">left Mac for Solaris</a></li><li><a href="http://www.macports.org/">MacPorts</a> break here and there - This might not sound like Apple's fault, but considering that Fink and MacPorts are the two main ways to get unix apps installed on Mac, Apple should have cared more about making sure that "things will just work"</li><li>Case sensitive FS is still only a second class citizen - I'm sick of all the dupes that iTunes and iPhoto creates, I'll be migrating to case insensitive FS soon</li><li>Mac Mini and possibly some other Macs, currently come with "upgrade only" Leopard DVDs - this means that if my Mac goes fubared, I'll have to install Tiger and only then I can install Leopard. Lame!</li><li>Why are <a href="http://www.apple.com/macosx/features/spaces.html">Spaces</a> one of the major features of Leopard? If I were Steve Jobs, I'd have added it long time ago, or if I added it only now, I'd be quiet and try not to attract too much attention to my past failures</li><li><a href="http://blog.refactor.se/2007/10/26/no-jdk6-with-os-x-105-leopard/">JDK6 is still missing!</a> - Seriously how much longer do we have to wait?!?!?</li><li>Why did Apple bothered to include built-in Ruby on Rails? Or should I say broken Ruby on Rails!?!? There was nothing wrong with installing Rails via MacPorts, but the one from Apple is already outdated and when I tried to upgrade it, it broke</li></ol><br /><br />MacOS X Leopard is "the most impressive Mac OS X version yet"? It's pretty good but hardly the most impressive without the latest Java.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-86258318519538541182007-10-24T13:20:00.000-07:002007-10-24T13:17:43.839-07:00SunWikis Used for San Diego Fire Emergency CoordinationI guess today is one of those days when I can really feel that what we do at <a href="http://wikis.sun.com">wikis.sun.com</a> is of great value - potentially life saving value. <br /><br />As almost everyone in the world knows there are big fires in San Diego right now - even my family from Slovakia contacted me yesterday to check that my wife's family in San Diego is ok.<br /><br />Today I noticed that SunWikis are being used for an emergency coordinations at Sun's San Diego campus: <a href="http://wikis.sun.com/display/Fires">http://wikis.sun.com/display/Fires</a>.<br /><br />I'm glad that we could help the guys in SD and I hope that everyone is fine over there.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-51978342191132233942007-10-17T18:00:00.000-07:002007-10-20T10:30:23.154-07:00How to Install Mercurial Support in NetBeans<a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_p64VvtgZDp4/RxZmraGuflI/AAAAAAAAAGA/UMxbAM6ELDw/s1600-h/mercurial-logo-small.jpg"><img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; border: none;" src="http://bp3.blogger.com/_p64VvtgZDp4/RxZmraGuflI/AAAAAAAAAGA/UMxbAM6ELDw/s400/mercurial-logo-small.jpg" alt="" id="BLOGGER_PHOTO_ID_5122394522108460626" border="0" /></a>Getting <a href="http://netbeans.org/">NetBeans</a> to grok <a href="http://www.selenic.com/mercurial">Mercurial</a> is pretty simple when you know all the gotchas. I already got stuck on the installation twice so I decided to turn this into a blog entry, so that I know what to do when I see the problem again. :)<br /><br />To install Mercurial support in NetBeans, do the following:<br /><ol><li>Get <a href="http://www.selenic.com/mercurial">Mercurial</a> and install it. On Mac you can install it via <a href="http://www.macports.org/">MacPorts</a></li><li>Get <a href="http://www.netbeans.org/community/releases/60/index.html">NetBeans 6</a> and install it</li><li>Install the Mercurial plugin via <code>Tools->Plugins->Available Plugins->Mercurial</code></li><li>Restart the IDE</li><li>If <code>Versioning->Mercurials</code> in the menu bar is disabled, go to <code>Tools->Options->Miscelanious->Mercurial</code> (on Mac <code>NetBeans->Preferences->Miscelanious->Mercurial</code>) and verify that <code>Mercurial executable path</code> is set up correctly - in my case, since I installed Mercurial via <a href="http://www.macports.org/">MacPorts</a>, the path should be <code>/opt/local/bin</code></li><li>Restart the IDE</li></ol><br />The problem, I encountered already twice, is that if the <code>Mercurial executable path</code> is not set up properly, the <code>Versioning->Mercurials</code> menu item is disabled and NetBeans doesn't give you any hint as to what went wrong. For some reason the path on my Mac is by default pointing to my python directory, which is not correct. Once the path is corrected and the IDE is restarted, everything works as expected.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_p64VvtgZDp4/RxZkz6GufjI/AAAAAAAAAFw/92xI-w7RKmw/s1600-h/netbeans-mercurial-path.png"><img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://bp1.blogger.com/_p64VvtgZDp4/RxZkz6GufjI/AAAAAAAAAFw/92xI-w7RKmw/s400/netbeans-mercurial-path.png" alt="" id="BLOGGER_PHOTO_ID_5122392469114093106" border="0" /></a>Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-14844134078381243232007-10-17T10:33:00.000-07:002007-10-17T10:30:34.489-07:00Apple to Bundle a Wiki Server with MacOS X Leopard Server<img src="http://mediacast.sun.com/share/igorminar/apple-wiki-server.png" style="float: left; margin: 10px 15px; border: none;"/> <br />Now that Apple finally released <a href="http://www.apple.com/macosx/features/">information about MacOS X Leopard</a>, I learned that a <a href="http://www.apple.com/server/macosx/features/wikis.html">wiki server</a> will be part of Leopard Server OS.<br /><blockquote>Mac OS X [Leopard] Server makes it easy for groups to collaborate and communicate through their own wiki-powered intranet website complete with group calendar, blog, and mailing list. Users can create and edit wiki pages, tag and cross-reference material, upload files and images, add comments, and search content with point-and-click ease. (<a href="http://www.apple.com/server/macosx/features/wikis.html">Source</a>)</blockquote><br />Pretty interesting, right? I wonder how the wiki server is implemented. I'd expect to see a lot of eye candy, seamless integration with other Apple offerings, but I'm not holding my breath for too many features. <br /><br />The website doesn't offer many details, but it seems that the wiki server is intended mainly for team collaboration and not for external facing sites like <a href="http://wikis.sun.com">wikis.sun.com</a>. I hope that I'll get more information soon. MacOS Server is not that easy to see around here. No wonder, after all, we have our cool <a href="http://www.sun.com/software/solaris/">Solaris</a> everywhere. :)Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-37378021357988577992007-10-11T13:25:00.000-07:002007-10-11T13:26:49.312-07:00SunWikis Update: 1000+ Wiki Pages in 10 Weeks!Today it happened! <b>We</b> made it! Let's go and celebrate! The <a href="http://wikis.sun.com">wikis.sun.com</a> community created altogether more than 1000 unique wiki pages in just 10 weeks since <a href="http://net3x.blogspot.com/2007/08/wikissuncom-is-live-engineering.html">our launch</a>.<br /><br /><pre><br />Number of users 1144<br />Number of spaces 94<br />Number of pages 1006<br />Number of page revisions 6362<br /></pre><br /><br />These are just number, but numbers that mean great adoption of this fairly young project.<br /><br />A big thank you to everyone who <a href="http://wikis.sun.com/display/About/Plant+a+Seed+-+Sun+Wikification+Video">planted the seed</a>!Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-47516186229161274522007-10-08T01:09:00.000-07:002007-10-08T12:31:33.778-07:00Adding the OpenSearch Descriptors to Confluence or Other WebSitesEarlier today I blogged about <a href="http://net3x.blogspot.com/2007/10/browser-search-plugins-for-sunwikis-and.html">the browser search plugins for SunWikis and Confluence</a>.<br /><br />This is how it all works:<br /><br /><h3>1. Create the descriptor file</h3><br />Create an <a href="http://www.opensearch.org/Specifications/OpenSearch">OpenSearch descriptor</a> (OSD) file:<br /><pre style="overflow: auto;"><br /><?xml version="1.0" encoding="UTF-8"?><br /><OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"><br /> <ShortName>SunWikis</ShortName><br /> <Description>SunWikis (wikis.sun.com) Search</Description><br /> <InputEncoding>UTF-8</InputEncoding><br /> <OutputEncoding>UTF-8</OutputEncoding><br /> <Image width="16" height="16" type="image/x-icon">http://wikis.sun.com/favicon.ico</Image><br /> <Url type="text/html" method="GET"<br />template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=conf_global&searchQuery.lastModified="/><br /></OpenSearchDescription><!-- <?xml version="1.0" encoding="UTF-8"?><br /><opensearchdescription xmlns="http://a9.com/-/spec/opensearch/1.1/"><br /> <shortname>SunWikis</shortname><br /> <description>SunWikis (wikis.sun.com) Search</description><br /> <inputencoding>UTF-8</inputencoding> <br /> <outputencoding>UTF-8</outputencoding><br /> <image width="16" height="16" type="image/x-icon">http://wikis.sun.com/favicon.ico</image><br /> <url type="text/html" method="GET" template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=conf_global&searchQuery.lastModified="><br /></opensearchdescription>--></pre><a href="http://mediacast.sun.com/share/igorminar/sunwikis-osd.xml">Download</a><br /><br />Check out the <code>template</code> attribute - the <code>{searchTerms}</code> will get replaced with the keyword typed into browser's search box. Keep in mind that if your template url contains an <code>"&"</code> character, it needs to be escaped as <code>&amp;</code>, otherwise your XML will not be well formated.<br /><br /><h3>2. Host the descriptor file</h3><br />Once you have the file ready, host it on your server e.g. as <code>wikis.sun.com/search/wikis-osd.xml</code><br /><br /><h3>3. Expose the descriptor file</h3><br />Now you need to let browsers know about the descriptor. You can do this by placing a snippet like this somewhere between the <code>head</code> HTML tags.<br /><pre style="overflow: auto;"><br /><link rel="search" type="application/opensearchdescription+xml"<br /> title="SunWikis" href="$req.contextPath/search/osd.xml"><br /></pre><br />In the case of using Confluence, you can do this by editing your template.<br /><br />The <code>$req.contextPath</code> part is Confluence specific. Replace it with a piece of code that retrieves the context path or replace it with static context path e.g. <code>/myapplication</code>.<br /><br /><h3>4. Bonus: Click-to-install link</h3><br />Firefox and IE support the installation of search engines via JavaScript, which can be handy if you want to provide an "install" link.<br /><br />As usual, both browsers use a different approach, and to be fair IE is ahead of Firefox in this one. :-/<br /><br />Here is a JavaScript I put together based on <a href="http://www.hunlock.com/blogs/Integrating_Site_Search_Into_Firefox_and_IE7">some</a> <a href="http://mycroft.mozdev.org/deepdocs/installing.html#server">resources</a><br /><pre style="overflow: auto;"><br />function addEngine(srcUrl, osdUrl, faviconUrl, fullName, category)<br />{<br /> if ((typeof window.sidebar == "object") && (typeof window.sidebar.addSearchEngine == "function")) /* Firefox */<br /> {<br /> window.sidebar.addSearchEngine(<br /> srcUrl, /* engine URL */<br /> faviconUrl, /* icon URL */<br /> fullName, /* engine name */<br /> category); /* category name */<br /> } else { /* IE */<br /> if (window.external.AddSearchProvider) {<br /> window.external.AddSearchProvider(osdUrl);<br /> }<br /> }<br />}<br /></pre><a href="http://mediacast.sun.com/share/igorminar/add-search-engine.js">Download</a><br /><br />For some weird reason (legacy?), Firefox uses <a href="http://mycroft.mozdev.org/deepdocs/deepdocs.html">Apple's Sherlock format</a> for JavaScript installation instead of OpenSearch descriptors. For this reason you need to create a Shrelock descriptor based on your OpenSearch descriptor. Keep in mind that the Shrelock descriptor filename must end with a <code>.src</code> extension.<br /><br />In my case, my sherlock.src looks like this:<br /><pre style="overflow: auto;"><br /><search<br />version="1.0"<br />name="SunWikis"<br />description="SunWikis (wikis.sun.com) Search"<br />action="http://wikis.sun.com/dosearchsite.action"<br />searchForm="http://wikis.sun.com/dosearchsite.action"<br />queryCharset="UTF-8"<br />method="GET"><br /><br /><input name="searchQuery.queryString" user><br /><input name="searchQuery.spaceKey" value="conf_global"><br /><input name="searchQuery.lastModified" value="&"><br /><br /></search><br /></pre><br /><br />It's not perfect because it is deliberately missing the <code><a href="http://mycroft.mozdev.org/deepdocs/browsertag.html">browser</a></code> element, but it will do. :)<br /><br />The <code>user</code> attribute is an equivalent of the <code>{searchTerms}</code> variable in OpenSearch specification.<br /><br />Once the file is created, upload it to your site, e.g. <code>wikis.sun.com/search/sherlock.src</code>.<br /><br />And now you can create the link on a page that contains the JavaScript code mentioned above:<br /><pre style="overflow: auto;"><br /><a onclick="addEngine('/search/sherlock.src', <br /> '/search/osd.xml', '/favicon.ico', 'SunWikis Search', 'Wiki')" <br /> href="#">Install<br /></a><br /></pre><br /><br />For more information on this topic check out <a href="http://www.hunlock.com/blogs/Integrating_Site_Search_Into_Firefox_and_IE7">this blog</a>, but watch out for an <a href="http://en.wikipedia.org/wiki/Cross-site_scripting">XSS</a> hole - the <code>searchTerms</code> variable in the JavaScript snippet in the section "Step 3: The Search" must be url-encoded before it is used later in the script.<br /><br /><h3>Some extra Confluece-specific stuff</h3><br />You can create OSD files that search in all the spaces of your Confluence instance or in one space only. You can specify this via the <code>Url</code> attribute in the OSD file.<br /><pre style="overflow: auto;"><br /><Url type="text/html" method="GET"<br />template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=conf_global&searchQuery.lastModified="/><br /></pre><br /><br />The <code>searchQuery.spaceKey=conf_global</code> part means - search in all Confluence spaces (with the exception of personal spaces IIRC).<br /><br />You can replace <code>conf_global</code> with a space key and you get a descriptor for space specific search.<br /><br />For example, the url for a descriptor for our <a href="http://wikis.sun.com/display/About">About</a> space would look like this:<br /><pre style="overflow: auto;"><br /><Url type="text/html" method="GET"<br />template="http://wikis.sun.com/dosearchsite.action?searchQuery.queryString={searchTerms}&searchQuery.spaceKey=About&searchQuery.lastModified="/><br /></pre><br /><br />If you want to get really fancy you can use the power of the <a href="http://lucene.apache.org/">Lucene</a> search engine (used in Confluence) to craft all kinds of interesting descriptors. For example this one that searches all the Confluence related spaces (the <a href="http://confluence.atlassian.com/display/DOC">DOC</a>, <a href="http://confluence.atlassian.com/display/DISC">DISC</a>, and <a href="http://confluence.atlassian.com/display/CONFEXT">CONFEXT</a>) at <a href="http://confluence.atlassian.com/">confluence.atlassian.com</a> by specifying the spaces in the <code>earchQuery.queryString</code> parameter instead of the <code>searchQuery.spaceKey</code>, which accepts only one space key.<br /><pre style="overflow: auto;"><br /><?xml version="1.0" encoding="UTF-8"?><br /><OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/"><br /> <ShortName>Confluence Extras</ShortName><br /> <Description>Documentation for the latest version of Confluence and Confluence Community + Confluence Extension Docs</Description><br /> <InputEncoding>UTF-8</InputEncoding><br /> <OutputEncoding>UTF-8</OutputEncoding><br /> <Image width="16" height="16" type="image/x-icon">http://confluence.atlassian.com/favicon.ico</Image><br /> <Url type="text/html" method="GET"<br /> template="http://confluence.atlassian.com/dosearchsite.action?searchQuery.queryString=spacekey%3A%28DOC+OR+DISC+OR+CONFEXT%29+AND+%28{searchTerms}%29&searchQuery.lastModified="/><br /></OpenSearchDescription><br /></pre><a href="http://mediacast.sun.com/share/igorminar/confluence-extra-osd.xml">Download</a><br /><br />This OSD is based on a wicked Lucene search query that looks like this:<br /><pre>spacekey:(DOC OR DISC OR CONFEXT) AND({searchTerms})<br /></pre>You can find out more about Lucene goodies <a href="http://lucene.apache.org/java/2_2_0/queryparsersyntax.html">here</a>.<br /><br />The last word of advice - instead of creating n+1 descriptors, one for each space + one for the search in all the spaces, use a JSP page to dynamically render the OSD file - that's how I implemented it for SunWikis.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-39312703579898983802007-10-06T22:00:00.000-07:002007-10-08T01:28:39.077-07:00Browser Search Plugins for SunWikis and Confluence<script type="text/javascript" src="http://mediacast.sun.com/share/igorminar/add-search-engine.js"></script>One of the small but useful features of the next release of <a href="http://wikis.sun.com/">SunWikis</a>, due some time next week, will be support for <a href="http://www.opensearch.org/Specifications/OpenSearch">Open Search descriptors</a>.<br /><br />Open Search descriptors (OSD) help browsers (and other clients) to discover ways to search content of a website. If you go to a site that supports OSD and you are using an Open Search enabled browser, the browser will notify you about the possibility of adding the current site's search among the browser's search plugins (Firefox does this by glowing the down arrow in the search box).<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_p64VvtgZDp4/Rwm12KGufgI/AAAAAAAAAFU/H4ZtUNc2fSM/s1600-h/sunwikis-osd-discovery.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_p64VvtgZDp4/Rwm12KGufgI/AAAAAAAAAFU/H4ZtUNc2fSM/s400/sunwikis-osd-discovery.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5118822393513410050" /></a><br /><br />Once the search plugin is installed, you can search SunWikis directly from your browser's search box.<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp3.blogger.com/_p64VvtgZDp4/RwmjyqGuffI/AAAAAAAAAFM/iY3uoqUrowE/s1600-h/sunwikis-search.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp3.blogger.com/_p64VvtgZDp4/RwmjyqGuffI/AAAAAAAAAFM/iY3uoqUrowE/s400/sunwikis-search.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5118802542174567922" /></a><br /><br />While I was at it, I created this descriptor for Confluence documentation located in the <a href="http://confluence.atlassian.com/display/DOC">DOC</a> wiki space at confluence.atlassian.com and a second descriptor that searches the DOC, <a href="http://confluence.atlassian.com/display/DISC">DISC</a> (Confluence Community), and <a href="http://confluence.atlassian.com/display/CONFEXT">CONFEXT</a> (Confluence Extensions) wiki spaces at the same time.<br /><br />So now I can search SunWikis and Confluence docs with ease:<br /><br /><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp1.blogger.com/_p64VvtgZDp4/Rwm4QKGufhI/AAAAAAAAAFc/tDPpX-evXB8/s1600-h/sunwikis-search2.png"><img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://bp1.blogger.com/_p64VvtgZDp4/Rwm4QKGufhI/AAAAAAAAAFc/tDPpX-evXB8/s400/sunwikis-search2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5118825039213264402" /></a><br /><br />If you are interested in installing these plugins as well (even before we make them available at wikis.sun.com), click on the links below:<br /><br /><b>Warning: As for SunWikis, you can install the search plugin now, but once the next SunWikis release is out, you should probably reinstall it just in case we tweak and enhance it.</b><br /><br /><table border="1"><tbody><tr><th>Name</th><th>Content</th><th>Click to Install<sup><a href="#1">1</a></sup></th><th>Download OSD<sup><a href="#2">2</a></sup></th></tr><tr><td>SunWikis</td><br /><td><a href="http://wikis.sun.com/">wikis.sun.com</a><br/>all spaces</td><td><a href="#" onclick="addEngine('http://mediacast.sun.com/share/igorminar/sunwikis-sherlock.src', 'http://mediacast.sun.com/share/igorminar/sunwikis-osd.xml', 'http://wikis.sun.com/favicon.ico', 'SunWikis Search', 'Wiki')">Install</a></td><td><a href="http://mediacast.sun.com/details.jsp?id=3740">Download</a></td></tr><tr><td>Confluence</td><td><a href="http://confluence.atlassian.com/">confluence.atlassian.com</a><br/>the <a href="http://confluence.atlassian.com/display/DOC">DOC</a> space</td><td><a href="#" onclick="addEngine('http://mediacast.sun.com/share/igorminar/confluence-sherlock.src', 'http://mediacast.sun.com/share/igorminar/confluence-osd.xml', 'http://confluence.atlassian.com/favicon.ico', 'Confluence Docs Search', 'Wiki')">Install</a></td><td><a href="http://mediacast.sun.com/details.jsp?id=3742">Download</a></td></tr><tr><td>Confluence+Extras</td><td><a href="http://confluence.atlassian.com/">confluence.atlassian.com</a><br/>the <a href="http://confluence.atlassian.com/display/DOC">DOC</a>, <a href="http://confluence.atlassian.com/display/DISC">DISC</a>, and <a href="http://confluence.atlassian.com/display/CONFEXT">CONFEXT</a> spaces</td><td>N/A<sup><a href="#3">3</a></sup></td><td><a href="http://mediacast.sun.com/details.jsp?id=3748">Download</a></td></tr></tbody></table><br /><br />Who knows, maybe Atlassian will use my code and officially support these search descriptors on their site - they have my full support.<br /><br />As for technical details, I <strike>plan to write</strike> wrote another entry just about <a href="http://net3x.blogspot.com/2007/10/adding-opensearch-descriptors-to.html">how I created and added these descriptors to Confluence</a>.<br /><br /><br /><a name="1"></a><sup>1</sup> Might or might not work for your browser. Click and sit tight :)<br /><a name="2"></a><sup>2</sup> The OSD file can be used for an alternative installation method - If you have Firefox and Mac you can place the file into <code>/Users/[yourname]/Library/Application\ Support/Firefox/Profiles/[the profile name]/searchplugins/</code> and restart Firefox, for other platforms, check out <a href="http://mycroft.mozdev.org/deepdocs/installing.html#manual">this doc</a><br /><a name="3"></a><sup>3</sup> Due to limitations of the <a href="http://mycroft.mozdev.org/deepdocs/deepdocs.html">Sherlock format</a>, it is not possible to craft a "click-to-install" file for the 3rd plugin, however you can still install it using the alternative<sup><a href="#2">2</a></sup> installation method.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-82018053721551709522007-10-06T14:05:00.000-07:002007-10-06T14:00:51.792-07:00AT&T's Language Mix-up in the "Philawarepragueacago" TV AdLast night I saw a new TV commercial for AT&T called “Philawarepragueacago”. In this ad a, guy studying and living in Prague says "How are you, brother?" supposedly in Czech. The problem is that he doesn't say it in Czech at all. He says it in Slovak! :)<br /><br />After I heard it the first time I wasn't sure if I heard it correctly or not, but after a quick Google search I found the <a href="http://www.commerciallygreen.com/">commercialy green</a> blog <a href="http://www.commerciallygreen.com/2007/10/03/att-philaware-commercial-philawarepragueacago/">dissecting and analyzing the commercial</a>.<br /><br />Commercially green was not able to transcribe the supposedly Czech line, so here it is:<blockquote>Jak sa máš, brácho?</blockquote><br />Which in casually spoken Slovak means:<blockquote>How are you, brother?</blockquote><br />The same thing in Czech would be:<blockquote>Jak <b>se</b> máš, brácho?</blockquote><br />It might be a small difference for Americans but I caught the difference right away.<br /><br />Maybe if the director of the commercial read the book, <a href="http://www.fgslovakia.com/the-book">The Foreigner's Guide to Living In Slovakia</a>, he'd know that there is a difference between the Czech and Slovak languages.<br /><br />The only explanation that AT&T can get away with is that there are a lot of Slovaks studying at Prague's universities, so it's possible that the "brother" has Slovak room-mates from which he picked up some Slovak. :)<br /><br /><a style="left: 539px ! important; top: 0px ! important;" title="Click here to block this object with Adblock Plus" class="abp-objtab-013411137612420032 visible ontop" href="http://www.commerciallygreen.com/wp-content/plugins/wordtube/mediaplayer.swf"></a><a style="left: 539px ! important; top: 0px ! important;" title="Click here to block this object with Adblock Plus" class="abp-objtab-013411137612420032 visible ontop" href="http://www.commerciallygreen.com/wp-content/plugins/wordtube/mediaplayer.swf"></a><embed flashvars="file=http://www.commerciallygreen.com/commercials/philaware.flv&image=http://www.commerciallygreen.com/commercials/philaware.jpg&id=5&overstretch=true&showdigits=true&callback=http://www.commerciallygreen.com/wp-content/plugins/wordtube/wordtube-statistics.php&backcolor=0xFFFFFF&frontcolor=0x000000&lightcolor=0x000000&volume=100&bufferlength=5&width=400&height=300&showfsbutton=false" wmode="transparent" quality="high" bgcolor="#FFFFFF" name="5" id="5" style="margin: 0px auto; display: block;" src="http://www.commerciallygreen.com/wp-content/plugins/wordtube/mediaplayer.swf" type="application/x-shockwave-flash" height="300" width="400"></embed>Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-65477463295291788542007-10-04T12:20:00.000-07:002007-10-04T12:10:16.288-07:00What Would You Do with SunWikis Remote API?As I mentioned <a href="http://net3x.blogspot.com/2007/09/sunwikis-v106-released-embedded-videos.html">previously</a>, one of the features for <a href="http://wikis.sun.com/">wikis.sun.com</a> that I'm working on is opening up the remote API. Before we do so, we need to customize the current behavior in order to make it a bit more secure. Before the feature is in production, I'd like to know how you would like to use it, so that we can factor that in, while customizing it.<br /><br />The main problem with the remote API right now is that it is either on or off. There is nothing in between. Because the remote API is very powerful (you can do everything that you could do via the browser and more), we'd like to limit who can use it in order to avoid having to clean up the mess created by reckless or malicious clients. Right now we are thinking about limiting the client IP addresses that can connect to the remote API, and/or limit the access to the service based on user's group memberships or user account permissions.<br /><br />I'd like to get a better understanding of if and how would you use the remote API for <a href="http://wikis.sun.com/">wikis.sun.com</a>, so that we can provide you with the best solution that fits needs of the majority.<br /><br />Some use cases that come to mind are:<ul><li>use an <a href="http://confluence.atlassian.com/display/CONFEXT/Confluence+SOAP+Client+in+Java">existing command line client</a> to access SunWikis</li><li>a (command line) tool that takes your data in some (XML) format, transforms it to our wiki markup and uploads it to your space</li><li>an application that creates an XYZ report from your database, build server, or other data source and publishes it in a wiki space every night at 3am</li><li>wikification of an existing application a la <a href="http://www.jdocs.com/javaee/5.0.0/javax/servlet/http/HttpServletRequest.html">JDocs</a> </li></ul>Feel free to come up with another (crazy) idea and let me know about it (leave a comment on my blog or send an email to our <a href="http://wikis.sun.com/display/Help/Aliases+%28Sun+Internal+Only%29">mailing list</a> (internal only)).<br /><br />For those who want the technical details:<br /><br />Each approach of limiting the access that I mentioned above has it's pros and cons. IP address restrictions are suitable for the integration of SunWikis with another web application or web service. On the other hand, it won't work well if the remote API is being accessed from your notebook or desktop that doesn't have a stable IP address.<br /><br />The restrictions based on group memberships (e.g. only Sun employees can access the API) are very well suited for personal use (e.g. the uploading multiple wiki pages or the renaming of wiki pages in batches), but won't work for web application integration, because employees would have to include <b>their</b> passwords in these applications, which is not a smart thing.<br /><br />Another problem with both of the previous approaches is that a bug in a client could affect content in all the wiki spaces, because Sun employees have write access to all spaces <a href="http://wikis.sun.com/display/Help/Default+Space+Permissions">by default</a>.<br /><br />A compromise might be to:<ol><li>let a user create special account used only for remote access</li><li>add this account to a special group (would be automated)</li><li>grant write access to this account on a per-space basis (requires space admin intervention - the same as <a href="http://wikis.sun.com/display/Help/Granting+Write+Access+by+Modifying+Space+Permissions">how permissions are being granted to external users</a>)</li></ol><br />This way a space admin (a Sun employee), has to endorse such an account (by granting it the write permission). In addition to that, this account will have access only to this space or maybe a few other spaces (if it is granted access to more spaces), which limits the potential damage.<br /><br />Maybe there is another way to let trust-worthy folks use the remote API - if you know about something, let me now. ;-)<br /><br />If you can't wait to start using or even writing clients for SunWikis, Atlassian has some good Confluence documentation that might be interesting for you if you have big remote API plans. Most importantly check out the <a href="http://confluence.atlassian.com/display/DOC/Remote+API+Specification+2.4">Remote API Specification</a>. Other interesting stuff: <a href="http://confluence.atlassian.com/display/DISC/Remote+API+examples">Remote API Examples</a>, <a href="http://confluence.atlassian.com/display/CONFEXT/Confluence+SOAP+Client+in+Java">Confluence SOAP Client in Java</a>Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-36984282856506951352007-09-22T22:30:00.000-07:002007-09-22T22:18:01.711-07:00API Design - A Lesson LearnedIn <a href="http://net3x.blogspot.com/2007/09/api-design-and-jsr-310-replacing-java.html">one of my older posts</a>, I mentioned that I watched an excellent video of Joshua Bloch's presentation on API design.<br /><br />Joshua mentioned that these days, developers are API designers and often don't even realize that. It's very easy to create a bad API when you don't realize that you're actually creating an API. And that's exactly what happened to me this week.<br /><br />One of the new features for SunWikis, <a href="http://net3x.blogspot.com/2007/09/sunwikis-v106-released-embedded-videos.html">we released with v1.0.6</a>, was a macro for embedding YouTube and Google videos. A simple features implemented via <a href="http://confluence.atlassian.com/display/CONF25/User+Macros">Confluence's user macros</a> - it was so simple that I actually managed to make it more complicated than it needed to be. All of that just because I wasn't aware of all the options that Confluence had to offer.<br /><br />My original macro sytax for this feature was:<pre>{video:youtube}<insert the youtube id here>{video}</pre><br /><br />Only later this week I realized that I could have made the syntax simpler by creating a user macro without a body. The syntax of the video macro without body looks like this: <pre>{video:youtube|<insert the youtube id here>}</pre><br /><br />This makes the macro code shorter, and as my friend J commented, it helps to make the macro syntax look less like an ugly version of XML.<br /><br />Compare the old and the new code used to embed <a href="http://net3x.blogspot.com/2007/08/wikification-of-sun-video.html">our promo video</a>:<pre>{video:youtube}tpR_6y-OoRc{video}<br />{video:youtube|tpR_6y-OoRc}</pre>The second one is obviously shorter and a bit simpler.<br /><br />I was lucky enough that I realized this soon enough to be able to fix it before it started to be used at <a href="http://wikis.sun.com/">wikis.sun.com</a>. So yesterday I changed the macro code, updated the documentation and fixed all the few pages that already were using the old clunky syntax.<br /><br />This made me realize that Joshua missed one point in his presentation:<br /><br /><b>Be more than familiar with the language, protocol or libraries you use to create the API.</b><br /><br />In the Java language this means use all the nice features that can make the lives of your users easier (e.g. annotations, generics, ..). In Ruby there are plenty of great idioms one can follow, and the same applies to Confluence's user macros - learn how they work, what they can do, and how you can leverage that.<br /><br />Lesson learned! Next time I'll think twice and read more docs before I design any API.Igor Minarhttp://www.blogger.com/profile/03520548417275543432noreply@blogger.comtag:blogger.com,1999:blog-6406593750327945950.post-82100825347936376642007-09-18T21:02:00.000-07:002007-09-18T20:46:20.879-07:00Are You a Right Clicka or an iBook Flippa?This video made me laugh hard today:<br /><br /><object width="425" height="353" style="margin-left: auto; margin-right: auto; display: block;"><param name="movie" value="http://www.youtube.com/v/Jkrn6ecxthM"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/Jkrn6ecxthM" type="application/x-shockwave-flash" wmode="transparent" width="425" height="353"></embed></object>