<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>Blogs at Near Infinity</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/" />
    <link rel="self" type="application/atom+xml" href="http://www.nearinfinity.com/blogs/atom.xml" />
    <id>tag:www.nearinfinity.com,2007-12-20:/blogs/7</id>
    <updated>2009-05-20T13:35:33Z</updated>
    <subtitle>Employee Blogs</subtitle>
    <generator uri="http://www.sixapart.com/movabletype/">Movable Type 4.23-en</generator>

<entry>
    <title>Agile in School</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/chris_rohr/agile_in_school.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.743</id>

    <published>2009-05-20T19:33:24Z</published>
    <updated>2009-05-20T13:35:33Z</updated>

    <summary><![CDATA[I have recently been taking some graduate classes in the field of Information Technology Management.&nbsp; After the first few core classes, I have come to the conclusion that there are...]]></summary>
    <author>
        <name>Chris Rohr</name>
        
    </author>
    
        <category term="Agile Development" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="agile" label="agile" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="education" label="education" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[I have recently been taking some graduate classes in the field of Information Technology Management.&nbsp; After the first few core classes, I have come to the conclusion that there are WAY too many higher education institutions that are avoiding Agile methodologies when they begin teaching software development practices.<br /><br />To give some background on where I'm coming from, the program that I had started included a class on project management.&nbsp; The semester had a week or two going into detail about the standard software development life cycle (SDLC).&nbsp; The way they described it was exactly the way waterfall works.&nbsp; All work was done in phases, requirements, design, development, test, deployment, all of which revolves around mountains of documentation and paperwork.<br /><br />Seeing as I have been working on an Agile based project for over 3 years, I thought I would inject some of my thoughts for the class on how things could be better.&nbsp; I couldn't believe how much negativity I got from other students and even the professor.&nbsp; I was told numerous times how the Agile methodologies (in general, not specific implementations) wouldn't work for large projects and is only good for prototyping functionality.&nbsp; The professor even made the comment that Agile was too restrictive when it comes to the time constraints (this I had a good laugh at).<br /><br />To make matters worse, if I was to continue the program, the last 5 classes are all different steps in the waterfall process.&nbsp; There is a class on Requirements, there is a class on Design, etc., all leading up to a final course that puts it all together.&nbsp; I don't see a problem with teaching students different ways to gather requirements or how to go about thinking about and designing a system.&nbsp; What I do have a problem with is that these higher education institutions are still forcing a specific system down the throats of students when they should be training the students on how to be most effective in their jobs and provide them with as many tools to accomplish that goal.<br /><br />Agile isn't just a new fad, it has been around for quite a while now and has taken some of the best practices from years of experience and made those the focus.&nbsp; Furthering oneself through education should benefit the student not waste their time.&nbsp; My hope is that one day there will be a reform in the software development education programs so that new software development managers will have the necessary tools to be effective rather than being restricted out of the gate.&nbsp; If there isn't some change soon, the industry is going to pass the education system by and getting a masters isn't going to do anyone any good.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Secrets of SharePoint 2010 Exposed at TechEd 2009</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/lee_richardson/secrets_of_sharepoint_2010_exp.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.748</id>

    <published>2009-05-18T02:42:01Z</published>
    <updated>2009-06-12T14:21:49Z</updated>

    <summary> In case you aren&apos;t aware, the details of SharePoint 2010 are under tight wraps. If you asked any of the presenters at Tech Ed the typical response was &quot;No...</summary>
    <author>
        <name>Lee Richardson</name>
        
    </author>
    
        <category term=".NET" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="sharepoint" label="SharePoint" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[ <p>In case you aren't aware, the details of SharePoint 2010 are under tight wraps.  If you asked any of the presenters at Tech Ed the typical response was "No idea what you're talking about."  But that doesn't mean presenters didn't occasionally slip up or say more than they probably should have.</p>
<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/05/secrets-of-sharepoint-2010-exposed-at.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>

<p><b>Publically Stated SharePoint 2010 Info</b></p>
<p>Here's what has been publically stated about SharePoint 2010 thus far:</p>
<ul>
<li>Requires at least Windows Server 2008 64 bit</li>
<li>Requires SQL  Server 64 bit (2005 or 2008)</li>
<li>Will not support for IE 6</li>
<li>Public testing to occur first half of next year</li>
</ul>
<p>This was announced at TechEd by <a href=" http://blogs.msdn.com/thomriz/default.aspx">Tom Rizzo</a>, director of Microsoft SharePoint Server,  as posted in this <a href=" http://www.infoworld.com/d/applications/sharepoint-2010-will-require-64-bit-sql-server-141">InfoWorld</a> article and also on the <a href=" http://blogs.msdn.com/sharepoint/archive/2009/05/07/announcing-sharepoint-server-2010-preliminary-system-requirements.aspx">SharePoint blog</a>.</p>
<p><b>New SharePoint 2010 Secrets</b></p>
<p>An exciting slip up that has received no press thus far was from the presentation: <a href=" http://www.msteched.com/online/view.aspx?tid=5150ae0f-d6c6-4238-9637-93c7b7ca4054">Microsoft Visual Studio 2010 Overview for the Business Application Developer</a>.  If you check 1:00:33 of the presentation you'll see the first glimpse of a SharePoint 2010 Site Home Page:</p>

<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_gez10dNhuPk/ShDErv76MKI/AAAAAAAABpc/xri8sCxYnQY/s1600-h/SP2010-Home-Page.jpg"><img style="cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://3.bp.blogspot.com/_gez10dNhuPk/ShDErv76MKI/AAAAAAAABpc/xri8sCxYnQY/s400/SP2010-Home-Page.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5336981814315200674" /></a></p>

<p>I could tell something wasn't right when I saw this part of the demo, but fellow <a href=" http://www.nearinfinity.com/">Near Infinity</a> employee <a href="http://www.nearinfinity.com/blogs/joe_ferner/">Joe Ferner</a> put it together first when he saw the big red "Give Feedback" button in the top right.  He <a href=" http://twitter.com/joeferner">tweeted</a> about what came next: </p>

<p><b>"Sharepoint 2010 to have inline list ajaxy editing."</b></p>
<p>It looks really nice, and is very exciting since SharePoint is currently a little unwieldy.  Check out this screenshot from 1:01:08:</p>

<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/ShDEwEHvUOI/AAAAAAAABpk/f4XI7p4EHKU/s1600-h/SP2010-Ajax-Support.jpg"><img style="cursor:pointer; cursor:hand;width: 400px; height: 250px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/ShDEwEHvUOI/AAAAAAAABpk/f4XI7p4EHKU/s400/SP2010-Ajax-Support.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5336981888453005538" /></a></p>

<p>So that was the most exciting slip up.  Other exciting tidbits were:</p>
<p><b>SharePoint designer will support saving workflows to re-use for provisioning</b></p>
<p>I learned this one during the Q&A session of the "Automate Business Processes Using InfoPath Forms with Integrated SharePoint Designer Workflows... All without Coding!" talk.  It's currently a pain point that workflows developed in SharePoint designer can't be reused in the same way workflows developed in Visual Studio can, so this will be a wonderful new feature.</p>
<p><b>BDC will probably support updating and inserting data</b></p>
<p>Apparently MOSS only shipped without this feature because it hadn't been thoroughly tested.  That there has been plenty of time to test this feature by now, so it's a pretty reasonable assumption that it will be in the next version.</p>
<p>Finally this is pure speculation, but I'm guessing:</p>
<p><b>SharePoint 2010 to support ASP.Net Data Services API</b></p>
<p>Microsoft supports two AJAX approaches: client side and server side.  The server side uses the UpdatePanel control where you code as usual and everything magically gets AJAXized.  The client side version is part of the unreleased ASP.Net 4.0, but ties in tightly with JSON provided by the .Net Data Services API that was released in the .Net Framework 3.5 SP1.  </p>
<p>The SharePoint team could have used the server side approach, but why not use the latest technology available, speed up UI significantly, and simultaneously allow web part developers a fantastic level of client side AJAX support?  If they made the entire SharePoint API available via the .Net Data Services API it would enable some powerful fast AJAX web parts.  It would be awesome.</p>
<p>Finally, the only other tidbit isn't a secret at all, but what I consider to the most exciting feature of  Visual Studio 2010: it will support editing SharePoint solutions without editing XML.  I hate XML, so that will be wonderful.  So are you ready for SharePoint 2010 today?  I sure am.  Pity about the wait.</p>]]>
        
    </content>
</entry>

<entry>
    <title>How to add a custom action to a SharePoint list actions menu for a specific list or content type.</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/joe_ferner/how_to_add_a_custom_action_to.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.746</id>

    <published>2009-05-10T16:35:59Z</published>
    <updated>2009-05-10T16:51:26Z</updated>

    <summary> If you have ever tried adding a SharePoint custom action to the actions menu and tried using &quot;List&quot; or &quot;ContentType&quot; as the &quot;RegistrationType&quot; and then tried to specify a...</summary>
    <author>
        <name>Joe Ferner</name>
        
    </author>
    
        <category term=".NET" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="net" label=".net" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sharepoint" label="SharePoint" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>
If you have ever tried adding a SharePoint custom action to the actions menu and tried using "List" or "ContentType" as the "RegistrationType" and then tried to specify a specific list or content type in the "RegistrationId" you know that it doesn't work. SharePoint will silently not render your custom action. If you try and target a generic list using a "RegistrationId" of "100" you will see that SharePoint will gladly render your action on every list in the site. I have found a rather kludgy work around to the problem.

<a style="float:right;" href="http://www.dotnetkicks.com/kick/?url=http%3a%2f%2fwww.nearinfinity.com%2fblogs%2fjoe_ferner%2fhow_to_add_a_custom_action_to.html"><img src="http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=http%3a%2f%2fwww.nearinfinity.com%2fblogs%2fjoe_ferner%2fhow_to_add_a_custom_action_to.html" border="0" alt="kick it on DotNetKicks.com" /></a>
</p>
<p>
First off in your element manifest file you need to use the "ControlAssembly" and "ControlClass" attributes off of CustomAction. MSDN doesn't say a whole lot about these attributes but essentially they allow you to specify a web control class in your assembly which can render the action. (If you need to create hierarchical menus check out this <a href="http://weblogs.asp.net/jan/archive/2008/05/08/creating-hierarchical-menus-with-a-customaction-in-sharepoint.aspx">article</a>.) Here is the XML to get you started:
</p>
<pre class="prettyprint">
&lt;Elements xmlns="http://schemas.microsoft.com/sharepoint/"&gt;
  &lt;CustomAction
    Id="MyCustomAction"
    RegistrationType="List"
    GroupId="ActionsMenu"
    Location="Microsoft.SharePoint.StandardMenu"
    Sequence="1000"
    ControlAssembly="[Fully qualified assembly name]"
    ControlClass="MyNamespace.MyCustomAction"&gt;
  &lt;/CustomAction&gt;
&lt;/Elements&gt;
</pre>
<p>
Next you will need to create a web control class which renders the menu item, as seen below:
</p>
<pre class="prettyprint">
public class MyCustomAction : WebControl {
  private MenuItemTemplate _action;

  protected override void CreateChildControls() {
    SPWeb site = SPContext.Current.Web;

    _action = new MenuItemTemplate {
      Text = "My Action",
      Description = "My Action",
      ImageUrl = "/_layouts/images/NEWITEM.GIF",
      ClientOnClickNavigateUrl = "http://www.nearinfinity.com"
    };

    Controls.Add(_action);
  }
}
</pre>
<p>
Compile and deploy your solution. Oh and make sure to add your assembly and namespace to the safe control list or you will end up pulling your hair out because once again SharePoint will silently not render your menu item. You should now see the "My Action" on every list in the site. We have now reproduced what a standard CustomAction element in your element manifest would do normally. Now we need to find a way to determine which list our control is being added to. The best way I found for doing that is to traverse the control hierarchy up the parent chain until I found the containing ListViewWebPart. The code is quite simple and looks like this:
</p>
<pre class="prettyprint">
private ListViewWebPart GetParentListViewWebPart() {
  Control parent = Parent;
  while (parent != null) {
    if (parent is ListViewWebPart) {
      return (ListViewWebPart)parent;
    }
    parent = parent.Parent;
  }
  return null;
}
</pre>
<p>
You should know where I'm going with this now, but for completness I will show you the last piece of code below which restricts it to a single list instance:
</p>
<pre class="prettyprint">
private Guid TARGET_LIST_ID = new Guid ("0D9B9302-8599-4CE5-8695-1B95FE7378F1");

protected override void OnLoad(EventArgs e) {
  base.OnLoad(e);
  if (!Page.IsPostBack) {
    EnsureChildControls();
    _action.Visible = false;
    ListViewWebPart listView = GetParentListViewWebPart();
    if (listView != null) {
      Guid listGuid = new Guid(listView.ListName);
      if (TARGET_LIST_ID == listGuid) {
        _action.Visible = true;
      }
    }
  }
}
</pre>
<p>
Now that we have the list Guid that our control is being rendered for I will leave it as an exercise to the reader to restrict it to a given content type.
</p>
<p>
Why SharePoint doesn't provide this kind of functionality out of the box amazes me, but at least they provide a powerful API that you can get in there and work around it in a not so horribly kludgy way. Maybe SharePoint 2010 will include this :)
</p>]]>
        
    </content>
</entry>

<entry>
    <title>Code Access Security Cheat Sheet</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/lee_richardson/code_access_security_cheat_she.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.744</id>

    <published>2009-05-07T13:36:58Z</published>
    <updated>2009-05-07T13:39:58Z</updated>

    <summary>I did short presentation on Code Access Security (CAS) a while ago and put together a cheat sheet to help remember the terms and how they fit together. It includes...</summary>
    <author>
        <name>Lee Richardson</name>
        
    </author>
    
        <category term=".NET" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="reference" label="reference" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="security" label="security" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>I did short presentation on <a href="http://en.wikipedia.org/wiki/Code_Access_Security">Code Access Security (CAS)</a> a while ago and put together a cheat sheet to help remember the terms and how they fit together.  It includes screenshots of the .NET Framework 2.0 Configuration tool (in Control Panel\Administrative Tools) and uses <a href="http://rapidapplicationdevelopment.blogspot.com/2007/06/entity-relationship-diagram-example.html">Entity Relationship Diagram (ERD) Notation</a>.  I had to pull it up recently and figured others might also find it helplful.</p>

<div style='float:right; margin-left:10px;'>
<script type='text/javascript'>
        var currentPageUrl = 'http://rapidapplicationdevelopment.blogspot.com/2009/05/code-access-security-cheat-sheet.html';

        /* Digg */
        var diggIframe = document.createElement('iframe');
        diggIframe.setAttribute('src', 'http://digg.com/tools/diggthis.php?u=' + currentPageUrl);
        diggIframe.setAttribute('height', '80');
        diggIframe.setAttribute('width', '52');
        diggIframe.setAttribute('frameborder', '0');
        diggIframe.setAttribute('scrolling', 'no');
        diggIframe.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');

        /* DotNetKicks */
        var dotnetkicksLink = document.createElement('a');
        dotnetkicksLink.setAttribute('href', 'http://www.dotnetkicks.com/kick/?url=' + currentPageUrl);
        var dotnetkicksImg = document.createElement('img');
        dotnetkicksImg.setAttribute('src', 'http://www.dotnetkicks.com/Services/Images/KickItImageGenerator.ashx?url=' + currentPageUrl);
        dotnetkicksImg.setAttribute('alt', 'Kick this article (a good thing) on DotNetKicks');
        dotnetkicksImg.setAttribute('border', '0');
        dotnetkicksImg.setAttribute('style', 'margin-left:auto; margin-right:auto; display:block; text-align:center;');
        dotnetkicksLink.appendChild(dotnetkicksImg);

        var div = document.createElement('div');
        div.appendChild(dotnetkicksLink);
        div.appendChild(document.createElement('br'));
        div.appendChild(diggIframe);

        document.write(div.innerHTML);
    </script>
</div>

<p>It describes the following terms:</p>

<ul>
<li>Permission</li>
<li>PermissionSet</li>
<li>Code Group</li>
<li>Policy Level</li>
<li>Assembly Instance</li>
<li>Evidence; and</li>
<li>Evidence Type</li>
</ul>

<p>It should print to 8.5 x 11.  Click to enlarge:</p>

<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/SgLivNex9qI/AAAAAAAABpU/gnOSJYssXeE/s1600-h/CAS_Cheat_Sheet.gif"><img style="cursor:pointer; cursor:hand;width: 291px; height: 400px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/SgLivNex9qI/AAAAAAAABpU/gnOSJYssXeE/s400/CAS_Cheat_Sheet.gif" border="0" alt=""id="BLOGGER_PHOTO_ID_5333074209460582050" /></a></p>

<p>Hope you find it useful.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Groovification</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/scott_leberknight/groovification.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.742</id>

    <published>2009-05-04T21:22:38Z</published>
    <updated>2009-05-04T21:25:52Z</updated>

    <summary> Last week I tweeted about groovification, which is defined thusly: groovification. noun. the process of converting java source code into groovy source code (usually done to make development more...</summary>
    <author>
        <name>Scott Leberknight</name>
        
    </author>
    
        <category term="Groovy" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Java" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="gmaven" label="gmaven" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="groovy" label="groovy" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="java" label="java" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[ <p>Last week I tweeted about groovification, which is defined thusly:</p>

<p><i>groovification.</i> noun. the process of converting java source code into groovy source code (usually done to make development more fun)</p>

<p>On my main day-to-day project, we've been writing unit tests in Groovy for quite a while now, and recently we decided to start implementing new code in Groovy rather than Java. The reason for doing this is to gain more flexibility in development, to make testing easier (i.e. in terms of the ability to mock dependencies in a trivial fashion), to eliminate a lot of Java boilerplate code and thus write less code, and of course to make developing more fun. It's not that I hate Java so much as I feel Java simply isn't innovating anymore and hasn't for a while, and isn't adding features that I simply don't want to live without anymore such as closures and the ability to do metaprogramming when I need to. In addition, it isn't removing features that I don't want, such as checked exceptions. If I know, for a fact, that I can handle an exception, I'll handle it appropriately. Otherwise, when there's nothing I can do anyway, I want to let the damn thing propagate up and just show a generic error message to the user, log the error, and send the admin team an email with the problem details.</p>

<p>This being, for better or worse, a Maven project, we've had some interesting issues with mixed compilation of Java and Groovy code. The <a href="http://groovy.codehaus.org/">GMaven plugin</a> is easy to install and works well but currently has some outstanding issues related to Groovy stub generation, specifically it cannot handle <a href="http://jira.codehaus.org/browse/MGROOVY-108">generics</a> or <a href="http://jira.codehaus.org/browse/MGROOVY-109">enums</a> properly right now. (Maybe someone will be less lazy than me and help them fix it instead of complaining about it.) Since many of our classes use generics, e.g. in service classes that return domain objects, we currently are not generating stubs. We'll convert existing classes and any other necessary dependencies to Groovy as we make updates to Java classes, and we are implementing new code in Groovy. Especially in the web controller code, this becomes trivial since the controllers generally depend on other Java and/or Groovy code, but no other classes depend on the controllers. So starting in the web tier seems to be a good choice. Groovy combined with implementing controllers using the Spring @MVC annotation-based controller configuration style (i.e. no XML configuration), is making the controllers <i>really</i> thin, lightweight, and easy to read, implement, and test.</p>

<p>I estimate it will take a while to fully convert all the existing Java code to Groovy code. The point here is that we are doing it piecemeal rather than trying to do it all at once. Also, whenever we convert a Java file to a Groovy one, there are a few basics to make the classes Groovier without going totally overboard and spending loads of time. First, once you've used <a href="http://www.jetbrains.com/idea/">IntelliJ's</a> move refactoring to move the .java file to the Groovy source tree (since we have src/main/java and src/main/groovy) you can then use IntelliJ's handy-dandy "Rename to Groovy" refactoring. In IntelliJ 8.1 you need to use the "Search - Find Action" menu option or keystroke and type "Rename to..." and select "Rename to Groovy" since they goofed in version 8 and that option was left off a menu somehow. Once that's done you can do a few simple things to make the class a bit more groovy. First, get rid of all the semi-colons. Next, replace getter/setter code with direct property access. Third, replace for loops with "each"-style internal iterators when you don't need the loop index and "eachWithIndex" where you do. You can also get rid of some of the redundant modifiers like "public class" since that is the Groovy default. That's not too much at once, doesn't take long, and makes your code Groovier. Over time you can do more groovification if you like.</p>

<p>The most common gotchas I've found have to do with code that uses anonymous or inner classes since Groovy doesn't support those Java language features. In that case you can either make a non-public named class (and it's OK to put it in the same Groovy file unlike Java as long as it's not public) or you can refactor the code some other way (using your creativity and expertise since we are not <a href="http://www.nearinfinity.com/blogs/scott_leberknight/thinking_matters.html">monkeys</a>, right?). This can sometimes be a pain, especially if you are using a lot of them. So it goes. (And yes, that is a <a href="http://en.wikipedia.org/wiki/Slaughterhouse-Five">Slaughterhouse Five</a> reference.)</p>

<p>Happy groovification!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Thinking Matters</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/scott_leberknight/thinking_matters.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.740</id>

    <published>2009-04-30T19:59:04Z</published>
    <updated>2009-04-30T20:11:18Z</updated>

    <summary> Aside from the fact that Oracle&apos;s Java Problem contains all kinds of factual and other errors (see the comments on the post) this sentence caught my eye in particular...</summary>
    <author>
        <name>Scott Leberknight</name>
        
    </author>
    
        <category term="General" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Java" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="cylon" label="cylon" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="logic" label="logic" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="programming" label="programming" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="thinking" label="thinking" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[ <p>Aside from the fact that <a href="http://www.forbes.com/2009/04/29/java-oracle-sun-technology-internet-infrastructure-java.html">Oracle's Java Problem</a> contains all kinds of factual and other errors (see the comments on the post) this sentence caught my eye in particular when referring to Java being "quite hard to work with" - "Then, as now, you needed to be a highly trained programmer to make heads or tails of the language."</p>

<p>What's the issue here? That Java is hard to work with? Perhaps more specifically, not just Java but perhaps the artificial complexity in developing "Enterprise" applications in Java? Nope. The problem is that this type of thinking epitomizes the attitude that business people and other "professionals" tend to have about software development in general, in that they believe it is or should be easy and that it is always the tools and rogue programmers that are the problem. Thus, with more and better tools, they reason, there won't be a need for skilled developers and the monkey-work of actually programming could be done by, well, <a href="http://www.newtechusa.com/PPI/main.asp">monkeys</a>.</p>

<p>I believe software development is one of the hardest activities humans currently do, and yes I suppose I do have some bias since I am a developer. Also contrary to what many people think, there is both art and engineering involved, and any given problem can be solved in an almost infinite variety of ways. Unlike more established disciplines that have literally been around for hundreds or thousands of years (law, medicine, accounting, architecture, certain branches of engineering like civil, etc.), the software industry hasn't even reached the century mark yet! As a result there isn't any kind of consensus whatsoever about a completely standardized "body of knowledge" and thus there isn't an industy-recognized set of standard exams and boards like you find in the medical and law professions for example. (That topic is for a future post.)</p>

<p>One thing that is certain is that software development involves logic, and thus people who can solve problems using logic will always be needed, whether the primary medium stays in textual format (source code) or whether it evolves into some different representation like <a href="http://martinfowler.com/bliki/IntentionalSoftware.html">Intentional Software</a> is trying to do. So the statement from the article that "you needed to be a highly trained programmer to make heads or tails of the language" is always going to be true in software development. More generally, highly skilled people are needed in any complex endeavor, and attempts to dumb dumb complex things will likely not succeed in any area, not just software development. Would you trust someone to perform surgery on you so long as they have a "Dummies Guide to Surgery" book? Or someone to represent you in court who stayed at a Holiday Inn Express last night?</p>

<p>I hypothesize that things are becoming more complex as time moves on, not less. I also propose that unless we actually succeed in building <a href="http://www.scifi.com/battlestar/">Cylons</a> who end up wiping us all out or enslaving us, we will never reach a point where we don't need people to actually think and use logic to solve problems. So even though many business-types would love to be able to hire a bunch of monkeys and pay them $0.01 per day to develop software, those who actually realize that highly skilled people are an asset and help their bottom line, and treat them as such, are the ones who will come out on top, because they will smash their competitors who think of software/IT purely as a cost center and not a profit center.</p>]]>
        
    </content>
</entry>

<entry>
    <title>Making SharePoint Title a Calculated Column</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/lee_richardson/making_sharepoint_title_a_calc.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.738</id>

    <published>2009-04-27T12:55:54Z</published>
    <updated>2009-04-27T13:01:02Z</updated>

    <summary>All SharePoint lists start with a user editable &quot;Title&quot; column that ECB menu&apos;s hang off of and that is the default field to display in associated child tables. This works...</summary>
    <author>
        <name>Lee Richardson</name>
        
    </author>
    
        <category term=".NET" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="howto" label="How-To" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="sharepoint" label="SharePoint" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>All SharePoint lists start with a user editable "Title" column that ECB menu's hang off of and that is the default field to display in associated child tables.  This works well most of the time.  For example if you have a list like Company, you can change the display name of Title to "Company Name," and then Employee records display that field for their parent relationship.</p>

<p><a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_gez10dNhuPk/SfUP1O5aPEI/AAAAAAAABpM/GjPbprracyE/s1600-h/employee-sharepoint-list.jpg"><img style="cursor:pointer; cursor:hand;width: 400px; height: 291px;" src="http://2.bp.blogspot.com/_gez10dNhuPk/SfUP1O5aPEI/AAAAAAAABpM/GjPbprracyE/s400/employee-sharepoint-list.jpg" border="0" alt=""id="BLOGGER_PHOTO_ID_5329183141269224514" /></a></p>

<p>Where this doesn't work well is lists like Employee, where there is no single column that uniquely identifies a row to an end user.  You could create a new "Full Name" calculated column and delete the Title column, but making Title a calculated column just feels like a cleaner solution.</p>

<p>I looked into making Title calculated where it is defined in CAML, but it looked pretty messy, and a true calculated column additionally suffers from the limitation that you can't pull from other lists.  The solution I settled on was to populate it in ItemAdding and ItemUpdating.  Of course you tie into those methods with something like:</p>

    <p>
        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;
mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:#2B91AF;
mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;
mso-no-proof:yes">SPList</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;
mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:
EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes"> employeeList 
        = site.Lists[<span style="color:#A31515">&quot;Employee List&quot;</span>];<br />
        employeeList.EventReceivers.Add(<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">
        SPEventReceiverType</span>.ItemUpdating,
        <br />
        <span style="color:#A31515"><span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>&quot;[four 
        part assembly name]&quot;</span>,
        <br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:#A31515">
        &quot;Namespace.EmployeeEventReceiver&quot;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span>);<br />
        employeeList.EventReceivers.Add(<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:#2B91AF">
        SPEventReceiverType</span>.ItemAdding,
        <br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:#A31515">&quot;[four 
        part assembly name]&quot;</span>,
        <br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:#A31515">
        &quot;Namespace.EmployeeEventReceiver&quot;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span></span>);</span></p>

<p>The only reason this is worth documenting is because setting title is a little messy in the event receivers and there is very little documentation on how to do it.</p>

    <p>
        <span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;
mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;color:blue;
mso-ansi-language:EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;
mso-no-proof:yes">public</span><span style="font-size:10.0pt;font-family:&quot;Courier New&quot;;
mso-fareast-font-family:Calibri;mso-fareast-theme-font:minor-latin;mso-ansi-language:
EN-US;mso-fareast-language:EN-US;mso-bidi-language:AR-SA;mso-no-proof:yes">
        <span style="color:blue">class</span> <span style="color:#2B91AF">
        EmployeeEventReceiver</span> : <span style="color:#2B91AF">SPItemEventReceiver</span> 
        {<br />
        <br />
        <span style="mso-spacerun:yes">&nbsp; </span><span style="color:blue">public</span>
        <span style="color:blue">override</span> <span style="color:blue">void</span> 
        ItemAdding(<span style="color:#2B91AF">SPItemEventProperties</span> properties) 
        {<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span> 
        fullName = GetFullName(properties);<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>properties.AfterProperties[<span 
            style="color:#A31515">&quot;Title&quot;</span>] = fullName;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">base</span>.ItemAdding(properties);<br />
        <span style="mso-spacerun:yes">&nbsp; </span>}<br />
        <br />
        <span style="mso-spacerun:yes">&nbsp; </span><span style="color:blue">private</span>
        <span style="color:blue">static</span> <span style="color:blue">string</span> 
        GetFullName(<span style="color:#2B91AF">SPItemEventProperties</span> properties) 
        {<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span> 
        firstName = properties.AfterProperties[<span style="color:#A31515">&quot;First_Name&quot;</span>].ToString();<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span> 
        middleName = properties.AfterProperties[<span style="color:#A31515">&quot;Middle_Name&quot;</span>].ToString();<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span> 
        lastName = properties.AfterProperties[<span style="color:#A31515">&quot;Last_Name&quot;</span>].ToString();<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">return</span>
        <span style="color:#2B91AF">Employee</span>.GetFullName(firstName, middleName, 
        lastName);<br />
        <span style="mso-spacerun:yes">&nbsp; </span>}<br />
        <br />
        <span style="mso-spacerun:yes">&nbsp; </span><span style="color:blue">public</span>
        <span style="color:blue">override</span> <span style="color:blue">void</span> 
        ItemUpdating(<span style="color:#2B91AF">SPItemEventProperties</span> 
        properties) {<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span> 
        fullName = GetFullName(properties);<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">string</span> 
        internalTitleName = properties.ListItem<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>.Fields[<span 
            style="color:#A31515">&quot;Title&quot;</span>].InternalName;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span>
        properties.AfterProperties[internalTitleName] = fullName;<br />
        <span style="mso-spacerun:yes">&nbsp;&nbsp;&nbsp; </span><span style="color:blue">base</span>.ItemUpdating(properties);<br />
        <span style="mso-spacerun:yes">&nbsp; </span>}<br />
        }</span></p>

<p>The tricky part is getting the title field by internal name in ItemUpdating vs. getting it normally in ItemAdding.  It's pretty easy once you work through it, but it took me longer than it should have.  So hopefully this helps someone somewhere. </p>]]>
        
    </content>
</entry>

<entry>
    <title>Tuning the IBM JVM for large heaps</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/aaron_mccurry/tuning_the_ibm_jvm_for_large_h.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.737</id>

    <published>2009-04-25T00:53:36Z</published>
    <updated>2009-04-25T02:04:07Z</updated>

    <summary><![CDATA[ Recently I have been rewriting a lot of our lucene search engine code for a web application that I'm currently supporting.&nbsp; Our physical environment is a little different than...]]></summary>
    <author>
        <name>Aaron McCurry</name>
        
    </author>
    
        <category term="General" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Java" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Lucene" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[
 
 
 
Recently I have been rewriting a lot of our lucene search engine code
for a web application that I'm currently supporting.&nbsp; Our physical
environment is a little different than most, we have a single very
large computer (a left over from a previous project) running several
virtual machines.&nbsp; The virtual machine that we are currently using for
our searching duties is a 64 cpu 128G box.<br />

<br />
Before I go into the tuning saga, I would like to say that in a
previous version of the search engine we ran many more (16), smaller
jvms all on the same box.&nbsp; They work together through a main controller
module that coordinates calls to all the searching jvms.&nbsp; After the
rewrite of the
searchers, there was a lot of pressure to get the new code out the
door.&nbsp; The new code partitions the data and searching duties in a very
similar way to the previous version, however I haven't had time to
focus
on getting all the parts broken up across all the jvms.&nbsp; It's very
doable, but do to customer priorities it hasn't been developed.&nbsp; But I
was in
luck (kinda), our environment was a single computer, so I thought I
will just run one large jvm.&nbsp; I knew going in that garbage collection
(GC) was going to be a
problem, I just didn't realize how much.<br />

<br />
Currently, we are running the 64-bit IBM java 6 jvm, the IBM jvm is very
different from the Sun jvm, but no more so than in the GC tuning
department.&nbsp; In the Sun jvm you have all kinds of settings to tweak,
algorithms to use etc.&nbsp; The IBM jvm just isn't as advanced, you have 4
different GC policies, and sizing for various parts of the internals.&nbsp;
And that's it!&nbsp; Great, it should be simple right?&nbsp; Well sorta.<br />

<br />

First try, bring the system online with a 50G (yes that's gigabytes)
heap, with all the default settings.&nbsp; Run some load tests and see where
we are.<br />

<br />

Everything is running great right up to the first full GC, 25 seconds
doesn't sound that long but when you are waiting for a computer to
return results, it's an eternity.&nbsp; For those that don't know, when a
full GC occurs (some of the newer Sun algorithms are different) it
stops the world (STW).&nbsp; This means the JVM is frozen until the GC is
complete.&nbsp; No good.<br />

<br />

So the default policy is the optthruput policy (-Xgcpolicy:optthruput).&nbsp; After digging through the IBM documentation,
this type of policy should be used for maximum throughput, but at the
expense of pauses during GC.&nbsp; They also mention that this should be
used for batch processing when pauses are really a problem.<br />

<br />

Next I tried the optavgpause policy (-Xgcpolicy:optavgpause), this is
suppose to smooth out the GCs by kicking off the mark phase early.&nbsp; I'm
not going to talk about mark, sweep, and compaction, you can find it
here (<a href="http://www.ibm.com/developerworks/ibm/library/i-incrcomp/">http://www.ibm.com/developerworks/ibm/library/i-incrcomp/</a>).&nbsp; But
basically it's suppose to run a concurrent parallel mark phase before
the jvm runs out of heap space and performs a full GC that STW.&nbsp; This did help,
got us down in the 10-15 second range on average, but the problem was
that the mark phase was too slow to start under heavy load and didn't
give us a whole lot of concurrent marking before the STW.&nbsp; I found this
out by adding -verbose:gc, this adds a lot of debugging information to the
standard out.&nbsp; You should just run this all the time, it provides a lot
of useful information about your application.<br />

<br />

Next I tried subpool (-Xgcpolicy:subpool), it worked fine but was
plagued by the same problem, slow full GCs.&nbsp; Subpool is suppose to work
better on large SMP machines like ours, but in the end it was more of
the same.&nbsp; It's full GCs were in the 10-12 second range, plus the application seemed
to run slower, by about 10%.<br />

<br />
And last I tried gencon (-Xgcpolicy:gencon), the newest of all
their
policies.&nbsp; Gencon is suppose to be used on "transactional systems",
systems that create a lot of short lived objects.&nbsp; Isn't that what most
java applications do?&nbsp; When I started it up, it seemed to be faster,
and our load test confirmed that, 30% more throughput.&nbsp; But the amazing
thing was that the full GCs were fast, really fast, in the 200-400ms
range, for a 50G heap!&nbsp; But wait, it wasn't using most of the heap, and
it was GCing all the time.&nbsp; Back to the verbose:gc log, AHA!&nbsp; The
nursery was too small, it was about 10% of the heap, and because our
application is almost all short lived objects I decided to increase the
size of the nursery.&nbsp; I gave it 50% of the heap, and the time between
GCs slowed down, but the time to perform the GC was still in the 350ms
range.&nbsp; Awesome!<br />

<br />

I finally settled on 100G heap with 50% a nursery, and the full GCs are
now in the 400-600ms range.&nbsp; I can live with that, because this gives
us a huge ceiling for load, and capacity.<br />

<br />

So to summarize, if you application needs to run a huge heap size, and
you are using the IBM jvm, I would start by using the gencon policy.&nbsp;
It seems to be the most modern of all their policies, and it seems to
work the best.<br /><br />Good luck!<br />

]]>
        
    </content>
</entry>

<entry>
    <title>Groovy&apos;s Safe Navigation Operator Not as Safe as I Thought</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/jeff_kunkle/groovys_safe_navigation_operat.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.716</id>

    <published>2009-04-14T10:50:00Z</published>
    <updated>2009-04-14T12:47:58Z</updated>

    <summary>The safe navigation operator is almost certainly my favorite operator in Groovy. It allows you to guard against NullPointerException(s) much more cleanly than defining a nasty if/else mess. Consider the...</summary>
    <author>
        <name>Jeff Kunkle</name>
        
    </author>
    
        <category term="Groovy" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>The safe navigation operator is almost certainly my favorite operator in Groovy. It allows you to guard against <code>NullPointerException</code>(s) much more cleanly than defining a nasty if/else mess. Consider the following example.</p>

<pre name="code" class="prettyprint lang-groovy">
class Book {
    String title
    Author author
}

class Author {
    String firstName
    String lastName
}

def author = new Author(firstName:'Jason')
def book = new Book(title:'Say no to NPEs', author:author)

println book.author?.lastName
</pre>

<p>Did you see that <code>?.</code> operator on the last line of the code sample? That's the safe navigation operator, and it's the equivalent of writing the following if statement (although it's much more readable).</p>

<pre name="code" class="prettyprint lang-groovy">
if (book.author != null) {
    println book.author.lastName
}
</pre>

<p>The safe navigation operator essentially checks to see if the object you're about to invoke a method on is <code>null</code>. If it is <code>null</code>, it simply skips the method invocation and returns <code>null</code>. If it isn't <code>null</code>, it proceeds as usual. It works for method chaining too, so if you're worried about <code>book</code> being <code>null</code>, you could write</p>

<pre name="code" class="prettyprint lang-groovy">
println book?.author?.lastName
</pre>

<p>This way, if either <code>book</code> or <code>author</code> are <code>null</code>, you simply print out <code>null</code> instead of causing a NullPointerException.</p>

<p>Since learning about the safe navigation operator, I've used it successfully in dozens of classes without any problem. Until last week. Consider the following line of code .</p>

<pre name="code" class="prettyprint lang-groovy">
println book?.author?.firstName?.trim().concat(" is great.")
</pre>

<p>Thanks to the safe navigation operator we can write this concatenation of <code>firstName</code> and a sentence fragment without worrying about <code>NullPointerException</code>(s) and ugly if blocks. Or so I thought.</p>

<p>Looking at this line of code, I thought for sure I was safe from any sneaky <code>NullPointerException</code>. If <code>book</code>, <code>author</code> or <code>firstName</code> are <code>null</code> I'll simply end up printing <code>null</code> and not have to worry about the <code>concat()</code> method. After all, if the <code>trim()</code> method succeeds, there's no sense in guarding it's result for <code>null</code>. And that's where I was wrong.</p>

<p>I naively assumed the method chain would stop once the safe navigation operator encountered a <code>null</code> when in fact it does not. While the <code>trim()</code> method is safe from being called on a <code>null</code> <code>firstName</code> object, it will return <code>null</code>, upon which the <code>concat()</code> method is called. Oops!</p>
]]>
        

    </content>
</entry>

<entry>
    <title>A little tuning can go a long way...</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/aaron_mccurry/a_little_tuning_can_go_a_long.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.714</id>

    <published>2009-04-03T01:50:52Z</published>
    <updated>2009-04-03T14:51:35Z</updated>

    <summary><![CDATA[The application that I'm current developing uses Lucene for searching and data retrieval.&nbsp; We recently had a rather special need to use one of the utility classes in Lucene, OpenBitSet.&nbsp;...]]></summary>
    <author>
        <name>Aaron McCurry</name>
        
    </author>
    
        <category term="Java" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Lucene" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="openbitsetlucenejavaperformance" label="openbitset lucene java performance" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[The application that I'm current developing uses Lucene for searching
and data retrieval.&nbsp; We recently had a rather special need to use one
of the utility classes in Lucene, OpenBitSet.&nbsp; OpenBitSet is not unlike
the regular BitSet provided by the java.util package.&nbsp; The biggest
difference is that the class is NOT final.&nbsp; So for someone like me,
that tinkers and optimizes to get every last bit of performance out of
my application, final classes are a major PITA.<br /><br />The problem:<br /><br />OpenBitSet
provides an optimized "find the next set bit starting here" method
called nextSetBit(long index).&nbsp; However I needed to find the previous
set bit, so naturally I started by using the built-in api.&nbsp; Iterate backwards over each bit starting at given position until a bit that it is set to true is found.&nbsp; Probably not the fastest way, but it
works.&nbsp; I thought that if I wrote my own "find the previous
set bit starting here" method it could be potently a lot faster.&nbsp; And because the class is not final and the internals are not private I can extend it, YAY!<br /><br />So after some work and some tests I came up with this:<br /><br />
<pre class="prettyprint">&nbsp;&nbsp;&nbsp; /**<br />&nbsp;&nbsp;&nbsp; &nbsp;* Finds the previous set bit in the bitset, start looking at the index position.<br />&nbsp;&nbsp;&nbsp; &nbsp;* @param index the index to start looking.<br />&nbsp;&nbsp;&nbsp; &nbsp;* @return the previous position in the bitset that is set.<br />&nbsp;&nbsp;&nbsp; &nbsp;*/<br />&nbsp;&nbsp;&nbsp; public long prevSetBit(long index) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //get index of the word to start with<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i = (int) (index &gt;&gt;&gt; 6); //div by 64<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (i &gt;= wlen) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //if the index requested is greater than the actual<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //max word, just start with the last word<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i = wlen - 1;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //loop backwards over the bits[] until a non-zero word is found<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (i &gt;= 0) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long word = bits[i];<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (word != 0) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //find the position of the most significant bit<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int pomsb = getPositionOfMostSigBit(word);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //multiply by 64<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long l = ((long) i) &lt;&lt; 6;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; //add together to find the actual position<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return l + pomsb;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i--;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; /**<br />&nbsp;&nbsp;&nbsp; &nbsp;* The word passed in, should not be 0.<br />&nbsp;&nbsp;&nbsp; &nbsp;* @param word the word to find the position of the most significant bit.<br />&nbsp;&nbsp;&nbsp; &nbsp;* @return the position in the word.<br />&nbsp;&nbsp;&nbsp; &nbsp;*/<br />&nbsp;&nbsp;&nbsp; private int getPositionOfMostSigBit(long word) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (word == 1l) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int i = 0;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (word != 1) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; word = word &gt;&gt;&gt; 1;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i++;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return i;<br />&nbsp;&nbsp;&nbsp; }<br /><br /></pre>
And of course I had to write a performance test to make sure that my work had produced something useful.&nbsp; Here's the test:<br /><br />

<pre class="prettyprint">&nbsp;&nbsp;&nbsp; public static void main(String[] args) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; CustomOpenBitSet bitSet = new CustomOpenBitSet(Integer.MAX_VALUE);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int maxCount = 1000000;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; fillBitSet(bitSet, maxCount);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; 10; i++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double s1 = System.nanoTime();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int slow = runSlowReverseSeeksToSetBits(bitSet, maxCount);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double e1 = System.nanoTime();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double s2 = System.nanoTime();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int fast = runFastReverseSeeksToSetBits(bitSet, maxCount);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; double e2 = System.nanoTime();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; assert (slow == fast);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("The slow time took " + ((e1-s1) / ONE_BILLION) + " seconds");<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; System.out.println("The fast time took " + ((e2-s2) / ONE_BILLION) + " seconds");<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; private static int runFastReverseSeeksToSetBits(CustomOpenBitSet bitSet, int maxCount) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int count = 0;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long start = Integer.MAX_VALUE;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (count &lt; maxCount - 1) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long position = bitSet.prevSetBit(start);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; count++;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; start = position - 1;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return count;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; private static int runSlowReverseSeeksToSetBits(CustomOpenBitSet bitSet, int maxCount) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int count = 0;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long start = Integer.MAX_VALUE;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (count &lt; maxCount - 1) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; long position = slowSeek(bitSet,start);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; count++;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; start = position - 1;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return count;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; private static long slowSeek(CustomOpenBitSet bitSet, long position) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (!bitSet.get(position)) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; position--;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (position &lt; 0) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return -1;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return position;<br />&nbsp;&nbsp;&nbsp; }<br /><br />&nbsp;&nbsp;&nbsp; private static void fillBitSet(CustomOpenBitSet bitSet, int numberOfBitsToSet) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Random random = new Random();<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int nextInt = -1;<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; numberOfBitsToSet; i++) {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; do {<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; nextInt = random.nextInt(Integer.MAX_VALUE);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } while (bitSet.fastGet(nextInt));<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; bitSet.set(nextInt);<br />&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp; }
</pre>
The
test creates a BitSet that is Integer.MAX_VALUE long and randomly
populates it with 1 million bits set to true.&nbsp; Then starting at
Integer.MAX_VALUE, find all the bits that are set to true, moving from
the greatest position to the smallest position.&nbsp; Do this 10 times and
print off the time taken to perform both algorithms. <br /><br />
<pre class="prettyprint">Pass [0], the slow time took 7.867899136 seconds<br />Pass [0], the fast time took 0.059851008 seconds<br />Pass [1], the slow time took 7.84461184 seconds<br />Pass [1], the fast time took 0.051954944 seconds<br />Pass [2], the slow time took 7.820731904 seconds<br />Pass [2], the fast time took 0.07801088 seconds<br />Pass [3], the slow time took 7.81953408 seconds<br />Pass [3], the fast time took 0.074951168 seconds<br />Pass [4], the slow time took 7.798106112 seconds<br />Pass [4], the fast time took 0.07792384 seconds<br />Pass [5], the slow time took 7.742498048 seconds<br />Pass [5], the fast time took 0.067644928 seconds<br />Pass [6], the slow time took 7.664754944 seconds<br />Pass [6], the fast time took 0.07476992 seconds<br />Pass [7], the slow time took 7.841472768 seconds<br />Pass [7], the fast time took 0.073187072 seconds<br />Pass [8], the slow time took 7.927188992 seconds<br />Pass [8], the fast time took 0.07574912 seconds<br />Pass [9], the slow time took 7.85273088 seconds<br />Pass [9], the fast time took 0.076514048 seconds
</pre>So as you can see the new method is about 100 times faster than just iterating backwards over the bitset, given this sample data.&nbsp; I would assume that if the sample size of 1 million were to increase, the gap between the 2 methods would narrow.<br />]]>
        
    </content>
</entry>

<entry>
    <title>Running VisualVM on a 32-bit Macbook Pro</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/scott_leberknight/running_visualvm_on_a_32-bit_m.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.713</id>

    <published>2009-04-01T14:08:23Z</published>
    <updated>2009-04-07T14:53:26Z</updated>

    <summary>If you want/need to run VisualVM on a 32-bit Macbook Pro you&apos;ll need to do a couple of things. First, download and install Soy Latte, using these instructions - this...</summary>
    <author>
        <name>Scott Leberknight</name>
        
    </author>
    
        <category term="Java" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Mac OS X" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="java" label="java" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="macbook" label="macbook" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="osx" label="os x" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="visualvm" label="visualvm" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>If you want/need to run <a href="https://visualvm.dev.java.net/">VisualVM</a> on a <i>32-bit</i> Macbook Pro you'll need to do a couple of things. First, download and install Soy Latte, using <a href="http://landonf.bikemonkey.org/static/soylatte/">these instructions</a> - this gets you a Java 6 JDK/JRE on your 32-bit Macbook Pro. Second, download VisualVM and extract it wherever, e.g. /usr/local/visualvm. If you now try to run VisualVM you'll get the following error message:</p>

<pre class="prettyprint">
$ ./visualvm
./..//platform9/lib/nbexec: line 489: /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home/bin/java: Bad CPU type in executable
</pre>

<p>Oops. After looking at the bin/visualvm script I noticed it is looking for an environment variable named "jdkhome." So the third step is to export an environment variable named 'jdkhome' that points to wherever you installed Soy Latte:

<pre class="prettyprint">
export jdkhome=/usr/local/soylatte16-i386-1.0.3
</pre>

<p>Now run the bin/visualvm script from the command line. Oh, almost forgot to mention that you should also have <a href="http://developer.apple.com/opensource/tools/X11.html">X11</a> installed, which it will be by default on Mac OS X Leopard. Now if all went well, you should have VisualVM up and running!</p>]]>
        
    </content>
</entry>

<entry>
    <title>Micro-optimization</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/joe_ferner/micro-optimization.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.706</id>

    <published>2009-01-30T14:34:35Z</published>
    <updated>2009-01-30T17:56:59Z</updated>

    <summary>This is my attempt at micro-optimizing code that Jeff Atwood posted about micro-optimization. To summarize Jeff talks about 5 ways to do string concatenation and how the difference between them...</summary>
    <author>
        <name>Joe Ferner</name>
        
    </author>
    
        <category term=".NET" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="performance" label="performance" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>This is my attempt at micro-optimizing code that Jeff Atwood posted about <a href="http://www.codinghorror.com/blog/archives/001218.html#comments">micro-optimization</a>. To summarize Jeff talks about 5 ways to do string concatenation and how the difference between them is negligible compared to the readability trade-offs. I agree with him 100%, unless you are faced with the need to optimize to that level make it readable first and fast second. I did on the other hand want to know why string.Concat was the fastest.</p>

<p>I&#8217;m going to ignore samples 2 (String.Format) and 4 (String.Replace) because those are obviously going to be slow. They require parsing the string to find tokens.</p>

<p>Sample 5 (StringBuilder) is a little more interesting. Looking at the StringBuilder in <a href="http://www.red-gate.com/products/reflector/">Reflector</a> you&#8217;ll see it&#8217;s doing some tricks under the cover to handle multi-threaded access to the StringBuilder object. Which from what I can deduce causes performance degradations. Not to mention the need to make 10 method calls (Append) and one object allocation (StringBuilder) from my code.</p>

<p>Sample 1 (Simple Concatenation) and 3 (string.Concat) are actually identical when viewed in <a href="http://www.red-gate.com/products/reflector/">Reflector</a> (other than the minor difference of new lines, but that is caused by the difference in the code).

<table border="1">
    <tr>
        <td>
            1. Simple Concatenation
            <pre class="prettyprint" style="width: 250px;">
.maxstack 3
.locals init (
    [0] string s,
    [1] string CS$1$0000,
    [2] string[] CS$0$0001)
L_0000: nop 
L_0001: ldc.i4.s 10
L_0003: newarr string
L_0008: stloc.2 
L_0009: ldloc.2 
L_000a: ldc.i4.0 
L_000b: ldstr "&lt;div class=\"user-action-time\">"
L_0010: stelem.ref 
L_0011: ldloc.2 
L_0012: ldc.i4.1 
L_0013: call string perftest.Program::st()
L_0018: stelem.ref 
L_0019: ldloc.2 
L_001a: ldc.i4.2 
L_001b: call string perftest.Program::st()
L_0020: stelem.ref 
L_0021: ldloc.2 
L_0022: ldc.i4.3 
L_0023: ldstr "&lt;/div>\r\n&lt;div class=\"user-gravatar32\">"
L_0028: stelem.ref 
L_0029: ldloc.2 
L_002a: ldc.i4.4 
L_002b: call string perftest.Program::st()
L_0030: stelem.ref 
L_0031: ldloc.2 
L_0032: ldc.i4.5 
L_0033: ldstr "&lt;/div>\r\n&lt;div class=\"user-details\">"
L_0038: stelem.ref 
L_0039: ldloc.2 
L_003a: ldc.i4.6 
L_003b: call string perftest.Program::st()
L_0040: stelem.ref 
L_0041: ldloc.2 
L_0042: ldc.i4.7 
L_0043: ldstr "&lt;br/>"
L_0048: stelem.ref 
L_0049: ldloc.2 
L_004a: ldc.i4.8 
L_004b: call string perftest.Program::st()
L_0050: stelem.ref 
L_0051: ldloc.2 
L_0052: ldc.i4.s 9
L_0054: ldstr "&lt;/div>"
L_0059: stelem.ref 
L_005a: ldloc.2 
L_005b: call string [mscorlib]System.String::Concat(string[])
L_0060: stloc.0 
L_0061: ldloc.0 
L_0062: stloc.1 
L_0063: br.s L_0065
L_0065: ldloc.1 
L_0066: ret</pre>
            </td>
            <td>
                3. string.Concat
                <pre class="prettyprint" style="width: 250px;">.maxstack 3
.locals init (
    [0] string s,
    [1] string CS$1$0000,
    [2] string[] CS$0$0001)
L_0000: nop 
L_0001: ldc.i4.s 10
L_0003: newarr string
L_0008: stloc.2 
L_0009: ldloc.2 
L_000a: ldc.i4.0 
L_000b: ldstr "&lt;div class=\"user-action-time\">"
L_0010: stelem.ref 
L_0011: ldloc.2 
L_0012: ldc.i4.1 
L_0013: call string perftest.Program::st()
L_0018: stelem.ref 
L_0019: ldloc.2 
L_001a: ldc.i4.2 
L_001b: call string perftest.Program::st()
L_0020: stelem.ref 
L_0021: ldloc.2 
L_0022: ldc.i4.3 
L_0023: ldstr "&lt;/div>&lt;div class=\"user-gravatar32\">"
L_0028: stelem.ref 
L_0029: ldloc.2 
L_002a: ldc.i4.4 
L_002b: call string perftest.Program::st()
L_0030: stelem.ref 
L_0031: ldloc.2 
L_0032: ldc.i4.5 
L_0033: ldstr "&lt;/div>&lt;div class=\"user-details\">"
L_0038: stelem.ref 
L_0039: ldloc.2 
L_003a: ldc.i4.6 
L_003b: call string perftest.Program::st()
L_0040: stelem.ref 
L_0041: ldloc.2 
L_0042: ldc.i4.7 
L_0043: ldstr "&lt;br/>"
L_0048: stelem.ref 
L_0049: ldloc.2 
L_004a: ldc.i4.8 
L_004b: call string perftest.Program::st()
L_0050: stelem.ref 
L_0051: ldloc.2 
L_0052: ldc.i4.s 9
L_0054: ldstr "&lt;/div>"
L_0059: stelem.ref 
L_005a: ldloc.2 
L_005b: call string [mscorlib]System.String::Concat(string[])
L_0060: stloc.0 
L_0061: ldloc.0 
L_0062: stloc.1 
L_0063: br.s L_0065
L_0065: ldloc.1 
L_0066: ret</pre>
            </td>
        </tr>
    </table>
</p>

<p> So now lets get to why I&#8217;m writing this post. Trying to micro-optimize code that is already micro-optimized. So lets start by looking at what string.Concat is doing inside.
<pre class="prettyprint">public static string Concat(params string[] values)
{
    int totalLength = 0;
    if (values == null)
    {
        throw new ArgumentNullException("values");
    }
    string[] strArray = new string[values.Length];
    for (int i = 0; i < values.Length; i++)
    {
        string str = values[i];
        strArray[i] = (str == null) ? Empty : str;
        totalLength += strArray[i].Length;
        if (totalLength < 0)
        {
            throw new OutOfMemoryException();
        }
    }
    return ConcatArray(strArray, totalLength);
}</pre>
Allocating a new array, that's got to take some time, and in fact it does, not much but it does take time. So do we have an alternative? Sure by using "string.Concat(string str0, string str1, string str2, string str3)". Looking at it's code it does essentially the same thing as "string.Concat(params string[] values)" but without the new array. So without further ado here is my over micro-optimized code.
<pre class="prettyprint">string s =
string.Concat(
    string.Concat(@"&lt;div class=""user-action-time"">", st(), st()),
    string.Concat(@"&lt;/div>&lt;div class=&#8221;&#8220;user-gravatar32&#8221;&#8220;>&#8221;, st(), @&#8221;&lt;/div>&lt;div class=&#8221;&#8220;user-details&#8221;&#8220;>&#8221;, st()),
    string.Concat(&#8220;&lt;br/>&#8221;, st(), &#8220;&lt;/div>&#8221;));
return s;</pre>
This code makes sure to only use the string.Concat that takes 4 arguments instead of the variable number of arguments. This speeds up the code by a whopping 2-3% on my machine. Sure it makes the code even more unreadable but if you are doing this 10 trillion times that might be necessary.
</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Finding Holes in Rcov and JRuby</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/brian_montgomery/finding_holes_in_rcov_and_jrub.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.705</id>

    <published>2009-01-27T22:40:42Z</published>
    <updated>2009-01-28T00:57:25Z</updated>

    <summary>&quot;We&apos;re missing some coverage...&quot; While creating coverage reports for a fairly new JRuby on Rails project, we noticed that our coverage numbers weren&apos;t quite right: certain classes were missing from...</summary>
    <author>
        <name>Brian Montgomery</name>
        
    </author>
    
        <category term="JRuby" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Ruby" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Testing" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<h2>"We're missing some coverage..."</h2>

<p>While creating coverage reports for a fairly new JRuby on Rails project, we noticed that our coverage numbers weren't <em>quite</em> right: certain classes were missing from the coverage reports. Rcov doesn't know about classes unless they are required: not a problem for models, but we were missing tests for some controllers and libraries.</p>

<p>Oops.</p>

<p>To properly correct this problem, I wrote the <code>coverage_helper</code> (to live alongside the <code>test_helper</code>).  Basically, this causes all of the classes to be required so that rcov knows about them.</p>

<h4>test\coverage_helper.rb</h4>

<pre><code>require 'test/unit'
require 'test_helper'

class CoverageHelper &lt; Test::Unit::TestCase
  def test_coverage
    ['app', 'lib'].each {|path| Dir.glob("#{path}/**/*.rb") {|file| 
      require File.expand_path(file.chomp('.rb'))
    }}
    assert true
  end
end
</code></pre>

<p>Simply include this test in your rcov builds and the problem is solved.  </p>

<p>Because of how rcov counts lines and the way Ruby class loading works, you'll never see files with 0% coverage.  However, at least you <em>will</em> see all of your classes listed and those that aren't covered will have a low percentage.</p>

<h4>Is this really necessary?</h4>

<p>First, the <code>File.expand_path</code> makes sure that your files are only required once.  I hate random warning messages because constants are initialized twice (among other issues).</p>

<p>Second, no, I didn't need to make this a test, but it just seemed nicer to.  I added the  <code>assert true</code> simply because I didn't feel right about not asserting <em>something</em> in the test.  </p>

<p>Third, as long as one uses the Rails scripts to generate the skeletons for your code, this scenario <em>should</em> never happen (because Rails will create all of the appropriate tests).  However, there is the tendency not to use the generated scripts when they don't output what you want, which is what we have discovered (Rails and Legacy Database Schemas aren't a perfect fit).  Also, sometimes I just forget to use them.</p>

<h2>What if you can't run rcov?</h2>

<p>One minor glitch of running JRuby on Windows is that the <code>File.separator</code> is technically incorrect (it's '<code>/</code>' instead of '<code>\</code>').  This usually isn't an issue... except when using rcov.  Since rcov executes from the shell, the arguments requiring file names and/or directories won't work because the separator is the wrong direction from what Windows is expecting.</p>

<p>The fix is to add a couple of methods to the File class to address the problem.</p>

<h4>Windows Separator Fix</h4>

<pre><code>class File
  @@is_windows = ENV['OS'] &amp;&amp; 
    (not ENV['OS'].downcase.match(/^windows/).nil?)

  def self.fix_name(name)
    @@is_windows ? name.tr(File::SEPARATOR, File::ALT_SEPARATOR) : name
  end

  def self.fixed_join(*files)
    self.fix_name(self.join files)
  end
end
</code></pre>

<p>The reason to do the <code>ENV['OS']</code> truth check first is that in JRuby on Solaris (where our CI is), that property doesn't exist. We couldn't use the <code>RUBY_PLATFORM</code> variable either, as in JRuby it's always assigned to '<code>java</code>'.</p>

<p>I should note that I've only use these fixed separator methods when necessary (in my rcov rake task).  The 'normal' separator has worked in every other situation I've run into.</p>
]]>
        

    </content>
</entry>

<entry>
    <title>Use DNS Search Domains for Shorter URLs</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/jeff_kunkle/use_dns_search_domains_for_sho.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.704</id>

    <published>2009-01-25T01:01:37Z</published>
    <updated>2009-01-25T01:41:28Z</updated>

    <summary>While I was reading through some Apple documentation on Bonjour I stumbled across a discussion on link-local addressing and DNS search domains. While the details of link-local addressing aren&apos;t that...</summary>
    <author>
        <name>Jeff Kunkle</name>
        
    </author>
    
        <category term="General" scheme="http://www.sixapart.com/ns/types#category" />
    
        <category term="Mac OS X" scheme="http://www.sixapart.com/ns/types#category" />
    
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[While I was reading through some Apple documentation on Bonjour I stumbled across a discussion on link-local addressing and DNS search domains. While the details of link-local addressing aren't that important here, the discussion on DNS search domains triggered a little light bulb in my brain.<div><br /></div><div>You see, DNS search domains are used as a guide to help your computer lookup an IP address when something simple like "blogs" is typed into your browser's URL. If you setup a DNS search domain of "nearinfinity.com", typing "blogs" will force your computer to first check if there's an address for "blogs.nearinfinity.com". If not it falls back to its default behavior.</div><div><br /></div><div>If you're a person that spends a lot of time on a small number of websites, you could use DNS search domains to your advantage to make navigating to those sites a snap. For instance, I just setup "nearinfinity.com" as an entry in my DNS search domains on my Mac. Simply go to the network preferences pane, click the advanced button at the bottom left, and then the DNS tab on the resulting popup.</div><div><br /></div><div><span class="mt-enclosure mt-enclosure-image" style="display: inline;"><img alt="dns_search_domains_osx.jpg" src="http://www.nearinfinity.com/blogs/assets/jkunkle/dns_search_domains_osx.jpg" width="600" height="450" class="mt-image-none" style="" /></span></div><div><br /></div><div>So now, whenever I type "blogs" in my URL I get "blogs.nearinfinity.com". Whenever I type "support" I get "support.nearinfinity.com". I think you probably get the idea. I know I'm no genius for discovering this since it's precisely the reason for having search domains. I just never thought to use them before.</div>]]>
        
    </content>
</entry>

<entry>
    <title>Missing aop &apos;target&apos; packages in Spring 3.0.0.M1 zip file</title>
    <link rel="alternate" type="text/html" href="http://www.nearinfinity.com/blogs/scott_leberknight/missing_aop_target_packages_in.html" />
    <id>tag:www.nearinfinity.com,2009:/blogs//7.703</id>

    <published>2009-01-15T23:06:22Z</published>
    <updated>2009-01-15T23:29:32Z</updated>

    <summary>Today I was mucking around with the Spring 3.0.0.M1 source release I downloaded as a ZIP file. I wanted to simply get the sample PetClinic up and running and be...</summary>
    <author>
        <name>Scott Leberknight</name>
        
    </author>
    
        <category term="Java" scheme="http://www.sixapart.com/ns/types#category" />
    
    <category term="ivy" label="ivy" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="openjdk" label="openjdk" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="soylatte" label="soylatte" scheme="http://www.sixapart.com/ns/types#tag" />
    <category term="spring" label="spring" scheme="http://www.sixapart.com/ns/types#tag" />
    
    <content type="html" xml:lang="en" xml:base="http://www.nearinfinity.com/blogs/">
        <![CDATA[<p>Today I was mucking around with the Spring 3.0.0.M1 source release I downloaded as a ZIP file. I wanted to simply get the sample PetClinic up and running and be able to load Spring as a project in IntelliJ. Note Spring now requires Java 6 to build, so if you're using an older 32-bit Macbook Pro you'll need to install JDK 6. I used <a href="http://landonf.bikemonkey.org/static/soylatte/">these instructions</a> generously provided by Landon Fuller to install Soy Latte, which is a Java 6 port for Mac OS X (Tiger and Leopard). So I went to run the "ant jar package" command (after first setting up <a href="http://ant.apache.org/ivy/">Ivy</a> since that is how Spring now manages dependencies) and everything went well until I got a compilation exception. There unfortunately wasn't any nice error message about why the compile failed.</p>

<p>So next I loaded up the Spring project in IntelliJ and tried to compile from there. Aha! It tells me that the org.springframework.aop.target package is missing as well as the org.springframework.aop.framework.autoproxy.target package, and of course all the classes in those packages were also missing. I was fairly sure I didn't accidentally delete those two packages in the source code, so I checked the spring-framework-3.0.0.M1.zip file to be sure. Sure enough those two 'target' packages are not present in the source code in the zip file. The resolution is to go grab the missing files from the Spring 3.0.0.M1 subversion <a href="https://src.springframework.org/svn/spring-framework/tags/spring-framework-3.0.0.M1/">repository</a> and put them in the correct place in the source tree. The better resolution is to do an export of the 3.0.0.M1 tag from the Subversion repo directly, rather than be lazy like I was and download the zip file.</p>

<p>I still am wondering why the 'target' packages were missing, however. My guess is that whatever build process builds the zip file for distribution excluded directories named 'target' since 'target' is a common output directory name in build systems like Ant and Maven and usually should be excluded since it contains generated artifacts. If that assumption is correct and <i>all</i> directories named 'target' were excluded, then unfortunately the two aop subpackages named 'target' got mistakenly excluded which caused a bit of head-scratching as to why Spring wouldn't compile.</p>]]>
        
    </content>
</entry>

</feed>
