It is 2010 now and SharePoint 2007 have been out forever, it feels like it anyways. The last two years has been about best practices in SharePoint both for developers and IT-pros and especially the Disposing of SharePoint objects has been discussed in absurdum. So I guess we should have to talk about it - but guess what - we certainly do!

The reason I bring this up today is that I was about to join a new WFE to a farm and it failed once it started to provision the web applications. Using the logs I found the source of the failure, it was some kind of component that threw an unhandled exception when it was created. See logs below (I have cropped it a bit)

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

01/19/2010 14:58:58  8  INF                            Openning configdb so that I can join it at server 01/19/2010 15:18:16  8  ERR                            Task configdb has failed with an unknown exception 
01/19/2010 15:18:16  8  ERR                            Exception: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: The Web application at http://SERVERXXX could not be found. Verify that you have typed the URL correctly. If the URL should be serving existing content, the system administrator may need to add a new request URL mapping to the intended application.
   at Microsoft.SharePoint.SPSite..ctor(SPFarm farm, Uri requestUri, Boolean contextSite, SPUserToken userToken)
   at Microsoft.SharePoint.SPSite..ctor(String requestUrl)
   at XXX.YYY.MyTimerJob.GetWeb()
   at XXX.YYY.MyTimerJob..ctor()
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle._InvokeConstructor(Object[] args, SignatureStruct& signature, IntPtr declaringType)
...
   at Microsoft.SharePoint.Administration.SPWebApplication.Provision()
   at Microsoft.SharePoint.Administration.SPWebServiceInstance.Provision()
   at Microsoft.SharePoint.Administration.SPFarm.Join()
   at Microsoft.SharePoint.PostSetupConfiguration.ConfigurationDatabaseTask.CreateOrConnectConfigDb()
   at Microsoft.SharePoint.PostSetupConfiguration.ConfigurationDatabaseTask.Run()
   at Microsoft.SharePoint.PostSetupConfiguration.TaskThread.ExecuteTask()
 

I opened up the source code to take a look what was going on in there. Fortunately this was no component that we have produced! This is what I found:

public class MyTimerJob: SPJobDefinition {
    static SPSite site = null;
    static SPWeb web = GetWeb();
    public static SPWeb GetWeb() {
        site = new SPSite("http://" + Environment.MachineName);   
        return site.RootWeb;
    }
...
}

So what is wring with this? Pretty obvious huh?

Not disposing objects!

This is a really bad example of not disposing objects. Both the SPSite and SPWeb are static members and are not getting disposed correctly and will hold the resources for as long as the object lives, in this case until the process terminates. You will likely not notice any degradation in performance if you have one of these objects but if you continue to build objects like this you will eventually trash the server.

SharePoint 2007 and SharePoint 2010, yup we are stuck with the same obstacles, have objects that are non-managed and uses connections to the database. These unmanaged are used by managed objects such as SPSite and SPWeb. The idea behind unmanaged code is that you should not have to care about object lifetime, destruction and garbage collecting but when we use unmanaged code we have to release these objects once we are finished with them and we should not use them any longer than we need to. Please do read through the Best Practices on MSDN before doing anything else!

Not testing the code!

This code had obviously not been tested thoroughly. The reason I got the exception was that during the web application provisioning objects like the timer jobs are being deserialized and that involves creating the object. Since the static objects are created the first time an object of that type is created and in this case it tries to attach to the web application that we are provisioning and not yet done with. So it will not find any web application and we get that exception.

Using the machine name!

The code tries to attach to the web application that has the address equal to the server name - that may be true on some occasions, but more often you have another address for your web application or use host headers etc.

What can we learn from all of this? I guess that we should all make sure that you and your colleagues know what to dispose and when to dispose it. If you are a trainer - please add an extra 10-15 minutes for this. Then test your code, not just on a single machine, but in a live environment resembling your production environment.

And by the way, since I had no control over the code causing the exception all I had to do was to deactivate the feature, install SharePoint and then activate it again.

For more bad practices head on over to Natalyas post.