Tuesday, July 15, 2008

Workflow updating current item - infinite loop

I added a dead simple workflow to a calendar list today to try something out. It copies the value from a hidden column (Email To) to a column I added (Attendees). I set the workflow to run when when a new item is added or an item is changed. I didn't think too much but during testing, the page becomes very sluggish and eventually it errors out:

"Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries. "

I eventually came across this post that's exactly the same as my problem. The direct cause of the error is that the CAML query statement gets really big. But why? Then it suddenly hit me, it's because that the workflow is set to run when an item is changed too. Since the workflow updates a column in the current list item, this creates an infinite loop where a new workflow instance is created after another.

This appears to me like a bug. There should be a difference between item changes inside a workflow vs outside of the workflow.

Tuesday, July 8, 2008

stsadm -o Deploysolution, to force or not to force?

There have been many discussions about this error that occurs when running stsadm -o deploysolution to deploy a solution:

The Execute method of job definition "SPSolutionDeploymentJobDefinition" (id "65274d73-2174-417e-b0fa-a63130953ee3") threw an exception. Failed to create feature receiver object from assembly "MyFeaturePack, Version=1.0.0.0, Culture=neutral, PublicKeyToken=9f4da00116c38ec5", type "MyFeaturePack.FeatureReceiverApplyRootUI" for feature 0f9127e3-a930-41a3-8cda-21ded77d996d: System.ArgumentNullException: Value cannot be null.

Parameter name: type
at System.Activator.CreateInstance(Type type, Boolean nonPublic)
at System.Activator.CreateInstance(Type type)
at Microsoft.SharePoint.Administration.SPFeatureDefinition.get_ReceiverObject()

Common causes of the problem include that (1) the assembly not being deployed to GAC, thereby having code access issue; (2) the signing key is somehow wrong; (3) the class name is not what's defined in feature.xml.

However, this error occurred for a different reason. Actually I still don't know the reason but managed to figure out a solution. Somehow adding the "-force" parameter on stsadm -o deploysolution made it to work for me:

stsadm -o deploysolution -url http://mossdev/ -name MyUI.wsp -immediate -allowgacdeployment -force

Maybe -force wipes out some caching somewhere. Oh well.

Tuesday, July 1, 2008

Custom theme in a feature does not get applied

People have written about deploying various customizations and custom functionalities as features via SharePoint Solution packages. I'm not going to go through it step by step here. As usual, I want to focus on the 'unusual' or 'gotcha' stuff when it comes to SharePoint.

Assuming you already have your custom theme, feature.xml, and the solution packaging files (manifest.xml and the ddf) ready, you can deploy the theme via the solution package, which adds your custom theme to /12/TEMPLATES/THEMES. Then you need to tell your site collection or web to actually use this new custom theme. This is typically accomplished in the FeatureReceiver class so when you activate the feature, the theme is applied. There are of course other ways to do this. For example, you can write a simple console application to run on the SharePoint WFE server to apply the theme.

SPWeb has a method ApplyTheme() that allows you to change the web theme in the code.

public override void FeatureActivated(SPFeatureReceiverProperties properties) {
SPSite site = properties.Feature.Parent as SPSite;
if (site == null) {
throw new SPException("This feature should only be activated on a Site Collection");
}
SPWeb rootweb = site.RootWeb;
rootweb.MasterUrl = "MyNewUI.master";
rootweb.ApplyTheme("MyCustomTheme");
rootweb.Update();
}

The code works without any error and the master page is correctly applied to the root web when you activate the feature. However, the custom theme is not applied. What is wrong?

The problem is with the order of the last two methods on SPWeb. It is necessary to call SPWeb.Update() to commit the changes when you assign new values to many of the pulbic properties of SPWeb. However, calling Update() AFTER ApplyTheme() somehow wipes out the change ApplyTheme() makes. So in order for this to work, there cannot be an Update() call after ApplyTheme() is called on the same instance of SPWeb. The above code would work perfectly by simply switch the order of the two method calls:

................
rootweb.Update();

rootweb.ApplyTheme("MyCustomTheme");
...............


Some folks have mentioned that in order to apply a custom theme from feature activation, there can not be an entry in \12\TEMPLATE\LAYOUTS\1033\SPTHEMES.XML for the theme. I found this to be not true. SPTHEMES.XML is for displaying the available themes on _layouts/themeweb.aspx for user to select. It has bearing on how a theme works or how it's applied. Therefore, you can either modify SPTHEMES.XML in your FeatureReceiver class or you don't have to. Adding an entry would allow user to see the theme applied listed on on _layouts/themeweb.aspx. That's all.


.