<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>The Enforcer.net &#187; Apex</title>
	<atom:link href="http://theEnforcer.net/category/apex/feed/" rel="self" type="application/rss+xml" />
	<link>http://theEnforcer.net</link>
	<description>a force.com blog</description>
	<lastBuildDate>Fri, 30 Jul 2010 07:02:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.5</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using WhatId to find Opportunities associated with Activities</title>
		<link>http://theEnforcer.net/2010/07/using-whatid-to-find-opportunities-associated-with-activities/</link>
		<comments>http://theEnforcer.net/2010/07/using-whatid-to-find-opportunities-associated-with-activities/#comments</comments>
		<pubDate>Mon, 12 Jul 2010 02:56:05 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=252</guid>
		<description><![CDATA[We recently reassigned a heap of Opportunities between staff members. However, the previous Opportunity Owner had open Activities on the Opportunities. The new Opportunity owners couldn&#8217;t close those Activities since they belong to somebody else.
So, they asked me to find a way to bulk-close the Activities.
This sounded simple, but was made more difficult by the [...]]]></description>
			<content:encoded><![CDATA[<p>We recently reassigned a heap of Opportunities between staff members. However, the previous Opportunity Owner had open Activities on the Opportunities. The new Opportunity owners couldn&#8217;t close those Activities since they belong to somebody else.</p>
<p>So, they asked me to find a way to bulk-close the Activities.</p>
<p>This sounded simple, but was made more difficult by the fact that Activities can link to many different object types:  Account, Opportunity, Campaign, Case or Custom Object.</p>
<p>The connection is made via WhatID, which is the ID of the associated object. It can be accessed via SOQL like this:</p>
<p><code>SELECT Id, What.Name from Task</code></p>
<p>However, not all fields are available, so you can&#8217;t <code>SELECT What.OwnerId</code>.</p>
<p>Fortunately, I found a forum post called <a href="http://community.salesforce.com/t5/General-Development/Getting-Object-type-of-WhatId-WhoId-Task-Event-fields/td-p/2928" target="_blank">Getting Object type of WhatId/WhoId Task/Event fields</a> gave me a few hints, and I came up with this code:</p>
<pre class="brush: plain;">
// Get list of Opportunities owned by new person
Opportunity[] opps = [Select Id from Opportunity where OwnerId = '005200300014jeN'];

// Get incomplete Activities owned by previous person attached to the above Opportunities
Task[] tasks = [select Id, What.Name from Task where OwnerId = '00520000000tSOj' and Status != 'Completed' and WhatId in :opps];
for (Task t : tasks) {
  t.Status = 'Completed';
}
update tasks;
</pre>
<p>This grabs a list of &#8216;owned&#8217; Opportunities and checks for any Activities (which are actually Task objects) that have a <code>WhatId</code> matching those Opportunities.</p>
<p>Straight-forward and pretty simple. Almost makes up for not being able to traverse directly to the linked object.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Activities can link to multiple objects</li>
<li>They connect via WhatId, but only a limited number of fields are exposed, eg What.Name</li>
<li>Use an &#8216;IN&#8217; comparison to match the Activities with Opportunities</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/07/using-whatid-to-find-opportunities-associated-with-activities/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Manually-entered Date value in Apex SOQL query</title>
		<link>http://theEnforcer.net/2010/07/manually-entered-date-value-in-apex-soql-query/</link>
		<comments>http://theEnforcer.net/2010/07/manually-entered-date-value-in-apex-soql-query/#comments</comments>
		<pubDate>Fri, 02 Jul 2010 01:24:36 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=244</guid>
		<description><![CDATA[I run into this problem all the time.
I want to write a quite routine in the System Log window to Mass Update some records (eg my previous Mass Delete via System Log window blog post). I want to find all records before a certain date, but SOQL never likes my date format, eg:
select Id from [...]]]></description>
			<content:encoded><![CDATA[<p>I run into this problem all the time.</p>
<p>I want to write a quite routine in the System Log window to Mass Update some records (eg my previous <a href="http://theEnforcer.net/2009/01/mass-delete">Mass Delete via System Log window</a> blog post). I want to find all records before a certain date, but SOQL never likes my date format, eg:</p>
<p><code>select Id from Opportunity where Expiry_Date__c &lt; <span style="color: #ff0000;">2010-01-01</span></code></p>
<p>Yes, it is possible to convert it to Timezone format and do it this way:</p>
<p><code>select Id from Opportunity where Expiry_Date__c &lt; 2008-01-01<span style="color: #ff0000;">T00:00:00Z</span></code></p>
<p>but I&#8217;ve always thought that silly when comparing against a Date field.</p>
<p>So, I eventually figured out that I can do it this way:</p>
<p><code>select Id, Name, LastLoginDate from User where LastLoginDate &gt; <span style="color: #ff0000;">:Date.valueOf('2008-01-01')</span></code></p>
<p>Of course, this only works within the context of Apex, such as the System Log window. It won&#8217;t work in pure SOQL tools like <a href="http://www.pocketsoap.com/osx/soqlx/">SOQL Explorer</a>. Here&#8217;s an example:</p>
<pre class="brush: plain;">
Opportunity[] opps = [select Id from Opportunity where Expiry_Date__c &lt; :Date.valueOf('2010-01-01')];
System.Debug(opps.size());
</pre>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Date strings can&#8217;t be entered into SOQL</li>
<li>Option 1: Use Timezone format: 2010-01-01T00:00:00Z</li>
<li>Option 2: Convert from string: :Date.valueOf(&#8217;2010-01-01&#8242;)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/07/manually-entered-date-value-in-apex-soql-query/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Making Owner available in Formulas</title>
		<link>http://theEnforcer.net/2010/06/making-owner-available-in-formulas/</link>
		<comments>http://theEnforcer.net/2010/06/making-owner-available-in-formulas/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 07:37:26 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[Data Loader]]></category>
		<category><![CDATA[Force.com IDE]]></category>
		<category><![CDATA[formulas]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=228</guid>
		<description><![CDATA[I was configuring DataLoader to export a list of Opportunities, and I went to select the &#8220;Owner Name&#8221;. However, only OwnerID is available on an Opportunity.
&#8220;No problem!&#8221; I think to myself, as I go and create a Custom Field with a formula equal to Owner.Alias.
&#8220;What?&#8221; I say in surprise. &#8220;It won&#8217;t let me access a [...]]]></description>
			<content:encoded><![CDATA[<p>I was configuring DataLoader to export a list of Opportunities, and I went to select the &#8220;Owner Name&#8221;. However, only <code>OwnerID</code> is available on an Opportunity.</p>
<p>&#8220;No problem!&#8221; I think to myself, as I go and create a Custom Field with a formula equal to <code>Owner.Alias</code>.</p>
<p>&#8220;What?&#8221; I say in surprise. &#8220;It won&#8217;t let me access a field on the Owner object!&#8221;</p>
<p><img class="aligncenter size-full wp-image-229" title="NoLink" src="http://theEnforcer.net/wp-content/uploads/2010/06/NoLink.gif" alt="NoLink" width="302" height="136" /></p>
<p>Mmm. This is strange. Then a Google Search reveals an 18-month old Ideas request to <a href="http://sites.force.com/ideaexchange/apex/ideaview?id=08730000000BrqaAAC" target="_blank">Make &#8220;Owner Id&#8221; Look up fields available for formulas</a>.</p>
<p>Oh dear.</p>
<p>Well, that&#8217;s a shame, but it&#8217;s easily solved! I created:</p>
<ul>
<li>A field called <code>Owner_Link__c</code> of type <code>Lookup(User)</code></li>
<li>A Trigger to copy<code> OwnerId</code> to <code>Owner_Link__c</code> when the Owner is changed</li>
<li>A test for the Trigger</li>
</ul>
<p><strong>Trigger:</strong></p>
<pre class="brush: java;">
trigger Update_OwnerLink_on_Owner_Update on Opportunity (before update, before insert) {

  // When 'Owner' field is changed, update 'OwnerLink' too

	// Loop through the incoming records
	for (Opportunity o : Trigger.new) {

		// Has Owner chagned?
		if (o.OwnerID != o.Owner_Link__c) {
			o.Owner_Link__c = o.OwnerId;
		}
	}
}
</pre>
<p><strong>Test:</strong></p>
<pre class="brush: java;">
public with sharing class TriggerTest_OwnerLink {

	static TestMethod void testOwnerLink() {

		// Grab two Users
		User[] users = [select Id from User limit 2];
		User u1 = users[0];
		User u2 = users[1];

		// Create an Opportunity
		System.debug('Creating Opportunity');
		Opportunity o1 = new Opportunity(CloseDate = Date.newInstance(2008, 01, 01), Name = 'Test Opportunity', StageName = 'New', OwnerId = u1.Id);
		insert o1;

		// Test: Owner_Link should be set to user 1
		Opportunity o2 = [select id, OwnerId, Owner_Link__c from Opportunity where Id = &amp;#58o1.Id];
		System.assertEquals(u1.Id, o2.OwnerId);
		System.assertEquals(u1.Id, o2.Owner_Link__c);

		// Modify Owner
		o2.OwnerId = u2.Id;
		update o2;

		// Test: Owner_Link should be set to user 2
		Opportunity o3 = [select id, OwnerId, Owner_Link__c from Opportunity where Id = &amp;#58o2.Id];
		System.assertEquals(u2.Id, o3.OwnerId);
		System.assertEquals(u2.Id, o3.Owner_Link__c);
	}
}
</pre>
<p>This then gave me a new Owner object on my Opportunity on which I could create Formulas:</p>
<p><img src="http://theEnforcer.net/wp-content/uploads/2010/06/Result.png" alt="Result" title="Result" width="626" height="139" class="aligncenter size-full wp-image-234" /></p>
<p>I could also use it in the DataLoader by referring to <code>Owner_Link__r.Alias</code>.</p>
<p>Hooray!</p>
<p>Easy to solve, but it&#8217;s a shame it was necessary.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Formulas can&#8217;t access <code>Opportunity.Owner</code> fields</li>
<li>Create a &#8217;shadow&#8217; field to hold Owner and populate it via a Trigger</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/06/making-owner-available-in-formulas/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New System Log Console looks deliciously good!</title>
		<link>http://theEnforcer.net/2010/05/new-system-log-console-looks-deliciously-good/</link>
		<comments>http://theEnforcer.net/2010/05/new-system-log-console-looks-deliciously-good/#comments</comments>
		<pubDate>Tue, 11 May 2010 07:17:10 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=224</guid>
		<description><![CDATA[A new Salesforce blog post by Ümit Yalçinalp (whom I interviewed back at Dreamforce 2009) is showing some incredible new features for the System Log Console.

I first discovered the joys of the Console while trying to debug some Apex. I used it to call an Anonymous function to run my code, or sometimes I&#8217;d just [...]]]></description>
			<content:encoded><![CDATA[<p>A new <a href="http://blog.sforce.com/sforce/2010/05/sneak-peak-the-new-system-log-console.html">Salesforce blog post</a> by Ümit Yalçinalp (whom I <a href="http://theenforcer.net/2009/11/dreamforce-2009-day-0/">interviewed</a> back at Dreamforce 2009) is showing some incredible new features for the System Log Console.</p>
<p style="text-align: center;"><img class="aligncenter" src="http://blog.sforce.com/.a/6a00d8341cded353ef01348096977b970c-500wi" alt="" /></p>
<p>I first discovered the joys of the Console while trying to debug some Apex. I used it to call an Anonymous function to run my code, or sometimes I&#8217;d just paste my whole code into the debug window and run it from there. It&#8217;s also a great place to <a href="http://theenforcer.net/2009/01/mass-delete/">run some quick code</a> to update records.</p>
<p>However, it&#8217;s not that great. It&#8217;s very hard to do good debugging in a web-based, multi-tenant environment. Some <a href="http://theenforcer.net/2010/03/new-system-log-window-is-great/">recent improvements</a> were quite nice but they look decidedly antiquated compared to what&#8217;s going to be released.</p>
<p>It seems that we&#8217;ll be able to step-through already-executed code. So, rather than pausing the whole Salesforce system, waiting for us to hit a &#8217;step&#8217; button (not great for a multi-tenant system!), it captures very detailed information and allows us to play back the executed code while viewing the execution stack and the lines of Apex code.</p>
<p>Very clever indeed!</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>A new System Log Console is being piloted</li>
<li>It&#8217;s giving amazing capabilities for a cloud-based system</li>
<li>See the <a href="http://blog.sforce.com/sforce/2010/05/sneak-peak-the-new-system-log-console.html">full article</a> for more details</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/05/new-system-log-console-looks-deliciously-good/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New System Log window is great!</title>
		<link>http://theEnforcer.net/2010/03/new-system-log-window-is-great/</link>
		<comments>http://theEnforcer.net/2010/03/new-system-log-window-is-great/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 05:13:56 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=216</guid>
		<description><![CDATA[Wow, I just noticed the new System Log window in Salesforce.com:

The first big improvement is the provision of a Log History. When executing code in the top half, the log file appears in the bottom half. This also works when data is updated through other means, such as editing a record. Previous logs can be [...]]]></description>
			<content:encoded><![CDATA[<p>Wow, I just noticed the new System Log window in Salesforce.com:</p>
<p><img src="http://theEnforcer.net/wp-content/uploads/2010/03/System-Log.png" width="700" height="647" class="aligncenter size-full wp-image-217" border="1" /></p>
<p>The first big improvement is the provision of a Log History. When executing code in the top half, the log file appears in the bottom half. This also works when data is updated through other means, such as editing a record. Previous logs can be viewed by clicking. (I did, however, notice that it was a little slow when the log was large.)</p>
<p>Another little improvement is the way the &#8220;Execute&#8221; button changes to &#8220;Executing&#8230;&#8221; when clicked. I have always been confused over this, because the window appears to &#8216;hang&#8217; when executing time-intensive code (eg looping over many records) and I could never tell if the command was correctly transmitted.</p>
<p>Thank you, Salesforce development team!</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>The System Log window has been updated</li>
<li>Multiple log histories are available</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2010/03/new-system-log-window-is-great/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>List has no rows for assignment to SObject</title>
		<link>http://theEnforcer.net/2009/09/list-has-no-rows-for-assignment-to-sobject/</link>
		<comments>http://theEnforcer.net/2009/09/list-has-no-rows-for-assignment-to-sobject/#comments</comments>
		<pubDate>Sat, 12 Sep 2009 22:46:33 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[SOQL]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=122</guid>
		<description><![CDATA[Here&#8217;s a lesson I learned while making our Cloud Developer Challenge entry.
Take a look at these lines of code and tell me which ones are OK and which ones are dangerous:
integer count = [SELECT count() FROM Contact];
Contact c1 = [SELECT Id FROM Contact LIMIT 1];
Contact c2 = [SELECT Id FROM Contact LIMIT 1];
Id first = [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a lesson I learned while making our Cloud Developer Challenge entry.</p>
<p>Take a look at these lines of code and <strong>tell me which ones are OK and which ones are dangerous:</strong></p>
<pre class="brush: java; light: true;">integer count = [SELECT count() FROM Contact];
Contact c1 = [SELECT Id FROM Contact LIMIT 1];
Contact c2 = [SELECT Id FROM Contact LIMIT 1];
Id first = [SELECT Id FROM Contact LIMIT 1].Id;
Contact[] contacts = [SELECT Id FROM Contact LIMIT 1];
Contact[] allContacts = [SELECT Id FROM Contact];</pre>
<p>If you executed the above code on most systems, it will run just fine. However, there is a situation in which you&#8217;ll get the dreaded <code><span style="color: #ff0000;">List has no rows for assignment to SObject</span></code> error. Can you figure out which one?</p>
<p><strong>It&#8217;s when there&#8217;s no objects to return!</strong></p>
<p>For example, if you have a system with no Contracts, try running the above code with <code>Cont<strong><span style="color: #ff0000;">r</span></strong>act</code> in place of <code>Contact</code> and you&#8217;ll get:</p>
<p><code><span style="color: #ff0000;">ERROR - Evaluation error: System.QueryException: List has no rows for assignment to SObject<br />
ERROR - Evaluation error: AnonymousBlock: line 2, column 15</span></code></p>
<p>What happened? Well, these 3 lines will all give an error if there&#8217;s no row found:</p>
<pre class="brush: java; light: true;">Contact c1 = [SELECT Id FROM Contact LIMIT 1];
Contact c2 = [SELECT Id FROM Contact LIMIT 1];
Id first = [SELECT Id FROM Contact LIMIT 1].Id;
</pre>
<p>While a <code>SELECT</code> normally returns an array/list, these statements are using the shorthand syntax that assumes only one row is returned. What&#8217;s not obvious is that it also assumes that <strong><span style="text-decoration: underline;">exactly</span> one row is returned!</strong></p>
<p>While this is unlikely to occur for <code>Contact</code>, it is highly likely to occur for any custom objects you create, especially when a <code>WHERE</code> statement is used that might return zero rows, such as:</p>
<pre class="brush: java;">Player__c player = [SELECT Id from Player__c where Name = :username];
if (player != null)
    p = player.Id;</pre>
<p><strong>The above code will fail</strong> if there is no <code>Player__c</code> record with the matching username. It doesn&#8217;t actually return a <code>null</code>.</p>
<p>It would be safer to do the following:</p>
<pre class="brush: java;">Player__c[] players = [SELECT Id from Player__c where Name = :username];
if (players.size() &gt; 0)
    p = players[0].Id;</pre>
<p>It&#8217;s one of those situations for which you wouldn&#8217;t normally think of creating a test, so it&#8217;s safer to just avoid the possibility rather than making an assumption about your data.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>The shorthand syntax that expects one row to be returned from a <code>SELECT</code> statement is very handy</li>
<li>It&#8217;s also dangerous if no rows are found!</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2009/09/list-has-no-rows-for-assignment-to-sobject/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Cloud Challenge Entry: Daily Shinro</title>
		<link>http://theEnforcer.net/2009/09/cloud-challenge-entry-daily-shinro/</link>
		<comments>http://theEnforcer.net/2009/09/cloud-challenge-entry-daily-shinro/#comments</comments>
		<pubDate>Fri, 04 Sep 2009 22:46:03 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[Force.com Platform]]></category>
		<category><![CDATA[Sites]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=117</guid>
		<description><![CDATA[I&#8217;m pleased to announce my entry into the 2009 Force.com Cloud Developer Challenge .
The Challenge is designed to evangelize the Force.com platform, encouraging lots of people to discover, learn and use Force.com. The rules are wide open — just build something using Force.com, Visualforce and Sites (so that it is publicly accessible). It&#8217;s a very [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m pleased to announce my entry into the 2009 Force.com <a href="http://developer.force.com/events/cloud_coding_challenge">Cloud Developer Challenge</a> .</p>
<p>The Challenge is designed to evangelize the Force.com platform, encouraging lots of people to discover, learn and use Force.com. The rules are wide open — just build something using Force.com, Visualforce and Sites (so that it is publicly accessible). It&#8217;s a very clever idea — sort of a small version of the <a href="http://www.xprize.org/">X-Prize</a> , with the concept that offering prizes will encourage more people to do interesting than actually directly paying people to do it!</p>
<h3>Our Entry</h3>
<p>So, would you like to know about our entry?</p>
<p>Yes, I use the word &#8216;Our&#8217; rather than &#8216;My&#8217; because I&#8217;m happy to say that I teamed up with David Schach, author of the <a href="http://www.x2od.com/blog">X-Squared on Demand blog</a> . Previous readers will remember that I met David some time ago <a href="http://theenforcer.net/2008/11/x2od-the-enforcer/">when he visited Australia</a> . Well, it just so happened that David read <a href="http://theenforcer.net/2009/07/sites-visualforce-some-early-lessons/">my previous blog entry</a> about the Cloud Developer Challenge and dropped me an email to say he was visiting Australia again, and did I want some help?</p>
<p>This was a god-send, because I had been hitting lots of brick walls in my ramp-up of Visualforce and Sites knowledge, and David is an absolute expert in the subject. So, I did all the high-level UI, he did all the low-level &#8216;engine room&#8217; stuff and we worked in the middle to make a very exciting site.</p>
<h3>Introducing Daily Shinro</h3>
<p>The site we developed is a <strong>Social Gaming Website</strong> that we call <a href="http://www.dailyshinro.com">Daily Shinro</a> .</p>
<p style="text-align: center;"><img class="aligncenter" src="http://shinro-developer-edition.ap1.force.com/resource/1252098071000/Graphics/GamePic.png" alt="Daily Shinro" /></p>
<p>The idea for the site began with my work team at <a href="http://www.atlassian.com">Atlassian</a> , where we play a daily game of <a href="http://www.setgame.com/set/puzzle_frame.htm">SET</a> , a really fun logic puzzle that changes each day. To keep track of our scores, we created a shared Google Apps spreadsheet with our scores and we soon discovered that it was actually just as fun to analyze the scores as to play the game!</p>
<p>We had been looking around for another daily puzzle that we could all play, preferably something that only took a couple of minutes and which had a scoring element. Unfortunately, very few online games took our interest. However, around that time, I had become addicted to playing <a href="http://www.shinromines.com/">Shinro Mines</a> on the iPhone. Shinro is a little-known puzzle that has been described as a cross between Minesweeper and Sudoku.</p>
<p>So, once I put together the desire to enter the Cloud Developer Challenge, the need for another team puzzle with a social scoring element and my enjoyment of Shinro Mines, the choice of project became obvious!</p>
<h3>A Social Gaming Website</h3>
<p>There&#8217;s really two parts to Daily Shinro: the game and the social aspect.</p>
<p><strong>The Game</strong><br />
I created the game in JavaScript using the <a href="http://raphaeljs.com/">fantastic open-source Raphael JavaScript graphics library</a> that provides cross-browser graphics. It renders in XML for IE (boo!) and SVG for every other browser (yay!). It even supports animation.</p>
<p>Raphael was actually written by <a href="http://dmitry.baranovskiy.com/">Dmitry Baranovskiy</a> , a colleague of mine at Altassian. I highly recommend you look at the demo pages!</p>
<p>To provide a &#8216;daily&#8217; concept for the game, a new puzzle is made available each day. The background picture for the puzzle is a daily selection from flickr, selected with the help of the beautiful <a href="http://labs.ideeinc.com/multicolr">Idée Multicolr Search Lab</a> . It just adds a bit of spice and variety to the daily puzzle!</p>
<p><strong>Social Gaming</strong><br />
From the very beginning, my intention was to create a &#8217;social&#8217; gaming experience, based upon the spreadsheet developed by my work team. Basically, scores are calculated by how well each player beats the team average. Therefore, it needs at least two people to play the puzzle and all scores net-out to zero. This has the advantage that, if somebody doesn&#8217;t play one day, they aren&#8217;t penalized.</p>
<p>This scoring system is implemented at two levels in Daily Shinro — Public and &#8216;League&#8217;.</p>
<p>At the Public level, players&#8217; scores are compared to the public average. At the League level, scores are compared only amongst your friends or office co-workers who are members of the same League.</p>
<p>Leagues are all about comparisons <em>within</em> a team rather than <em>between</em> teams — sort of like a private gaming site for friends. Thus, everyone can create their own League and invite friends to join. The score graphs then reflect the scores amongst members of the League.</p>
<p style="text-align: center;"><img class="aligncenter" src="http://chart.apis.google.com/chart?chs=700x300&amp;chxt=x%2Cy%2Cx&amp;chco=cd5c5c&amp;chf=c%2Clg%2C30%2Cffffff%2C0%2Cf0e68c%2C1&amp;cht=lc&amp;chds=-578%2C1215&amp;chxr=1%2C-578%2C1215&amp;chg=10%2C3%2C2%2C2%2C0%2C2&amp;chco=5496ff%2C5a9e68%2Cbf6900%2C32cc85%2C804dff%2C8c7a77&amp;chxl=0%3A%7C1%7C2%7C3%7C4%7C5%7C6%7C7%7C8%7C9%7C10%7C11%7C12%7C13%7C14%7C15%7C16%7C17%7C18%7C19%7C20%7C21%7C22%7C23%7C24%7C25%7C26%7C27%7C28%7C29%7C30%7C2%3A%7CAugust%7CAugust&amp;chd=s%3ATTTTTTVVVVVVVVVVVVVVVVVVVVVVaa%2CTTTTTTVXXXXafikkkkkkolot058655%2CTTTTTRRUUUUUUUVQPRPQQTTTTPNMMM%2CTTTTTZVRRRRQRTSVTTVWTTPOLKLMMM%2CTTTTTSRRRRROKKKLONLMLMKHHHGKII%2CTTTTTRRRRRRRQLKKKJJIGGJIEDCABB&amp;chdl=Vernon%7CSteve%7CRyan%7COrson%7CParker%7CNeil" alt="League Score sample" /></p>
<p>The charts are generated with some magical Apex code that gathers up League scores, compares players to game averages and then outputs the results into a Google Charts URL.</p>
<p>I invite you all to visit <a href="http://www.dailyshinro.com/">www.dailyshinro.com</a> and play the game!</p>
<p>If you find any bugs or strange behaviors, please let us know!</p>
<h3>Will we win?</h3>
<p>Ah, that&#8217;s the big question! My personal goal is to have the site &#8216;mentioned&#8217; in the results pages of the Cloud Developer Challenge. That way, we&#8217;ll feel rewarded for the long hours that were put into the site.</p>
<p>We&#8217;ve done several things to give us an <strong>advantage </strong> in the competition:</p>
<ul>
<li>We made a fun site that is <strong>attractive and enjoyable to use.</strong></li>
<li>We utilized <strong>lots of different technologies </strong> to showcase how Force.com can &#8216;pull together&#8217; capabilities from across the web to build an even richer application environment.</li>
<li>We added <strong>lots of pages of explanations</strong> , showing how we used Force.com technology. I&#8217;m hoping that this will help the folks at Salesforce.com promote the Force.com platform, which means that they&#8217;ll want lots of people visiting our site to help promote their technology. And what better way to do this than mentioning us in the final results?! (Clever, eh!)</li>
<li>Finally, there&#8217;s this blog, which I know is read by about 1000 people per month (including some legendary Salesforce staff!). Throw in David&#8217;s blog and we&#8217;re hoping to get the attention of enough people in Salesforce that we&#8217;ll get on the short-list.</li>
</ul>
<p>Oh, one word to the judges &mdash; we fixed a few bugs in the last couple of days. So, if you visited the site already, please visit again and see it in its fully-working glory!</p>
<p>It&#8217;s been a tough Challenge, but it was great fun and an utterly fantastic way to learn Visualforce and Sites. I started with zero knowledge and now consider myself a competent user of those technologies. I&#8217;d also like to thank David Schach whose knowledge of Visualforce and Sites is just incredible. I couldn&#8217;t have done this site without him.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Visualforce and Sites are mature and capable technologies for building websites on Force.com technology</li>
<li>The Cloud Developer Challenge was an excellent way to &#8217;spread the word&#8217; and get people to use the technologies</li>
<li>You&#8217;ve got to visit <a href="http://www.dailyshinro.com/">Daily Shinro</a>!</li>
<li>If you know the judges, please tell them how great we are! :)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2009/09/cloud-challenge-entry-daily-shinro/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Sites &amp; Visualforce: Some early lessons</title>
		<link>http://theEnforcer.net/2009/07/sites-visualforce-some-early-lessons/</link>
		<comments>http://theEnforcer.net/2009/07/sites-visualforce-some-early-lessons/#comments</comments>
		<pubDate>Tue, 28 Jul 2009 12:10:00 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>
		<category><![CDATA[Sites]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://theEnforcer.net/?p=103</guid>
		<description><![CDATA[I&#8217;ve bitten bullet! I&#8217;m currently working on an entry for the Force.com Cloud Developer Challenge, which fortunately was extended to the end of August 2009.
I started a bit late because I couldn&#8217;t think of anything fun to make. Then, a few cool ideas came together and I&#8217;m spending whatever time I can on the effort. [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve bitten bullet! I&#8217;m currently working on an entry for the <a href="http://developer.force.com/events/cloud_coding_challenge">Force.com Cloud Developer Challenge</a>, which fortunately was extended to the end of August 2009.</p>
<p>I started a bit late because I couldn&#8217;t think of anything fun to make. Then, a few cool ideas came together and I&#8217;m spending whatever time I can on the effort. I&#8217;ll talk more about the entry in a later post, but thought it worthwhile posting my learnings as part of the process.</p>
<h3>Visualforce</h3>
<p>The Challenge wants something built using <a href="http://www.salesforce.com/platform/cloud-platform/sites.jsp">Force.com Sites</a> (<a href="http://developer.force.com/sites">technical stuff</a>) and that mostly uses <a href="http://www.salesforce.com/platform/application-development/visualforce/">Visualforce</a> (<a href="http://wiki.developerforce.com/index.php/Visualforce">technical stuff</a> ).</p>
<p>To date, I haven&#8217;t had a business need to justify my learning Visualforce so it remained a mystery. However, that has changed with my need to crash-learn Sites and Visualforce.</p>
<p>The first thing I realised was how reliant Visualforce is on the Apex programming language. I had <a href="http://theenforcer.net/2008/09/the-forcecom-hierarchy-of-skills/">earlier postulated</a> that Apex was at the top of the Force.com skillset, being the hardest to learn. I&#8217;m now thinking that Visualforce should be at the top, because it relies so much on Apex to add useful functionality. Using Visualforce without knowing Apex would be difficult, indeed. So, at least I did things in the &#8216;right&#8217; order.</p>
<h3>Frustration</h3>
<p>As with developing any new application, and even moreso when trying to use a new technology, there are things that take a while to figure out. Here&#8217;s some things I learned:</p>
<p><strong>Field-level security</strong> also impacts Sites. I was trying to figure out why a page wasn&#8217;t displaying some fields (they came up as blank) and why I was getting occasional &quot;unauthorized access&quot; errors. Yep, turned out to be field-level security settings for my Sites Guest Profile. I managed to debug it using the <strong>Field Accessibility</strong> function under <strong>Security Controls</strong>. It appears that &quot;Guest&quot; profiles used by Sites don&#8217;t appear in the selection set when adding a field (unless it&#8217;s a Required Field), so after creating a new field I had to go back to the Guest Profile and add access permissions. Argh!</p>
<p><em>Update:</em> In fact, it could be a bug. The Sites and Portal profiles don&#8217;t appear when creating a custom field, but if I hit &#8216;Previous&#8217; to go back to the Profiles selection screen while creating the field, the additional profiles appear. I&#8217;ve logged it as a potential bug.</p>
<p><strong>The <code>&lt;apex:page&gt;</code> tag doesn&#8217;t show the page title</strong> if <code>showHeader=&quot;false&quot;</code>. I found it <a href="http://community.salesforce.com/sforce/board/message?board.id=Visualforce&amp;message.id=15176">mentioned on a discussion board</a> and mention it here in case it frustrates you, also.</p>
<p><strong>Governor limitations are still our enemy</strong> but it&#8217;s slightly better under Visualforce. According to Apex documentation, the &quot;Total number of records retrieved by SOQL queries&quot; is <code>1000 x batch size</code> for Triggers and 10,000 for Visualforce. This becomes a real stinker when used with the <code>count()</code> function on a SOQL query since every row is counted even though the function is only returning an integer. Thus, <code>SELECT Count() from Contact</code> will fail if there are more rows than allowed by the limit. This is really, really stupid. If you agree, vote for this idea to <a href="http://ideas.salesforce.com/article/show/10089055/Count_the_SOQL_count_query_as_a_single_row_query">Count the SOQL count() query as a single row query</a>.</p>
<p><strong>Instant Apex in the System Log window is fantastic!</strong> I used it to test the Governor Limit with code like this:</p>
<pre class="brush: jscript;">
List ls = new List();
for (integer i = 0; i &lt; 1000; i++) {
  ls.add(new Test__c());
}
insert ls;
integer c = [select count() from Test__c];
System.Debug(c);
</pre>
<p><strong>The Salesforce UI was really slow.</strong> Really, really slow. I used the Net tab in Firebug to see what was slowing things down, and it was continually reloading JavaScript files that should have been cached and the wholepage was taking 15+ seconds to load. Here&#8217;s a picture of the time taken after clicking the &#8216;New&#8217; button to add a Custom Field:</p>
<p style="text-align: center;"><img class="aligncenter" src="http://theenforcer.net/wp-content/uploads/2009/07/nettime.png" border="1" alt="" /></p>
<p>Well, I eventually discovered that Firefox was not caching SSL pages. I turned it on (enter the address <code>about:config</code> then set <code>browser.cache.disk_cache_ssl</code> to <code>true</code>  and now the pages load at a screaming pace!</p>
<p><strong>To trigger field updates via a link</strong>, look at Scott Hemmeter&#8217;s article on how to <a href="http://sfdc.arrowpointe.com/2009/01/08/invoke-apex-from-a-custom-button-using-a-visualforce-page/">Invoke Apex from a Custom Button using a Visualforce Page</a>.</p>
<p><strong>Stylesheets are always a pain</strong> but the Salesforce Unearthed blog has a good article <a href="http://salesforceexperts.blogspot.com/2009/06/style-your-visualforce-pages-for.html">Style your VisualForce Pages -for newbies</a> that was very helpful, especially the bit about <code>standardstylesheets=&quot;false&quot;</code>. I also found a good article about <a href="http://www.devarticles.com/c/a/Web-Style-Sheets/DIV-Based-Layout-with-CSS/">DIV Based Layout with CSS</a> that explains the basics of formatting a page using DIVs. Also, be sure to read the bit in the Visualforce manual that mentions how to match style <code>id</code>.</p>
<p>Static Resources have to be public. I&#8217;ll admit, I got some strange variations on this, but <a href="http://salesforceexperts.blogspot.com/2009/07/visualforce-page-with-css.html">lots</a> of <a href="http://wiki.developerforce.com/index.php/Force.com_Sites_Best_Practices">documentation</a> give this advice.</p>
<p>In fact, Salesforce Unearthed has an excellent example of <a href="http://salesforceexperts.blogspot.com/2009/07/zip-file-as-static-resource.html">how to use a Zip file as Static Resource</a>. It lets you put your stylesheet and images in a single zip file. Fascinating!</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>There&#8217;s a lot to learn to get Sites and Visualforce doing what you envisage</li>
<li>You&#8217;ll need Apex and HTML skills (preferably CSS, too)</li>
<li>All time for the standard frustration of coding in new systems</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2009/07/sites-visualforce-some-early-lessons/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Beware Trigger batches over 100 records</title>
		<link>http://theEnforcer.net/2009/02/beware-trigger-batches-over-100-records/</link>
		<comments>http://theEnforcer.net/2009/02/beware-trigger-batches-over-100-records/#comments</comments>
		<pubDate>Mon, 09 Feb 2009 00:04:49 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>

		<guid isPermaLink="false">http://theenforcer.net/?p=67</guid>
		<description><![CDATA[I came across a thread about Dataload batch size and triggers in the Salesforce Developer Community.
Several people are reporting strange behaviour in their Triggers, such that a batch of 200 records actually calls the Trigger twice, but variables are not reset. Apparently it&#8217;s an intended behaviour and not a bug, but it&#8217;s not documented.
As a [...]]]></description>
			<content:encoded><![CDATA[<p>I came across a thread about <a href="http://community.salesforce.com/sforce/board/message?board.id=general_development&amp;message.id=23983" target="_blank">Dataload batch size and triggers</a> in the Salesforce Developer Community.</p>
<p>Several people are reporting strange behaviour in their Triggers, such that a batch of 200 records actually calls the Trigger twice, but variables are not reset. Apparently it&#8217;s an intended behaviour and not a bug, but it&#8217;s not documented.</p>
<p>As a result, I&#8217;ve reduced all my batch sizes to 100 to avoid any potential problems. You might want to do the same.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Beware of Triggers with batches of over 100 records</li>
<li>The online <a href="http://community.salesforce.com/sforce/?category.id=developers">Developer Community</a> is great for finding answers to strange situations</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2009/02/beware-trigger-batches-over-100-records/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Mass Delete via System Log window</title>
		<link>http://theEnforcer.net/2009/01/mass-delete/</link>
		<comments>http://theEnforcer.net/2009/01/mass-delete/#comments</comments>
		<pubDate>Tue, 06 Jan 2009 23:27:23 +0000</pubDate>
		<dc:creator>The Enforcer</dc:creator>
				<category><![CDATA[Apex]]></category>

		<guid isPermaLink="false">http://theenforcer.net/?p=64</guid>
		<description><![CDATA[I had been keeping an eye on our Storage Quota and suddenly noticed that we had passed 100%. We don&#8217;t store documents on our Salesforce instance — just object data, most of which is imported from our legacy system. Unfortunately, this had been filling up and we exceeded our 1GB quote (20 users).
First, I used [...]]]></description>
			<content:encoded><![CDATA[<p>I had been keeping an eye on our Storage Quota and suddenly noticed that we had passed 100%. We don&#8217;t store documents on our Salesforce instance — just object data, most of which is imported from our legacy system. Unfortunately, this had been filling up and we exceeded our 1GB quote (20 users).</p>
<p>First, I used <a href="http://wiki.apexdevnet.com/index.php/Mass_Update_Anything">Mass Update Anything</a> (available for both Mac and Windows) with a query to find some old data records. I could then delete those records and re-query. Unfortunately, it only processes about 1000 records at a time.</p>
<p>Then, I saw a Custom Object that I could do without. It was taking 80MB, so I deleted the object. Unfortunately, the 80MB remained allocated — perhaps because the Recycle Bin only empties after 30 days, but I&#8217;m not sure. Also, Mass Update Anything didn&#8217;t like querying that object, so I was stuck.</p>
<p>Then I remembered a post I had read that morning from MK Partners about <a href="http://www.mkpartners.com/apex-code/my-new-best-friend">using the Salesforce System Log window to mass-update some data</a>. Matt had written some quick Apex that executes in the System Log window. So, I modified it to do a mass delete.</p>
<p style="text-align: center;"><img class="aligncenter" title="mass-delete" src="http://theenforcer.net/wp-content/uploads/2009/01/mass-delete.png" alt="" width="550" height="415" /></p>
<p>Two points to note:</p>
<ul>
<li>The <code>SELECT</code> statement can only return 1000 records, lest you receive the error &#8220;<code>System.QueryException: Inline query has too many rows for direct assignment, use FOR loop</code>&#8220;</li>
<li>The whole Apex block can only use 10,000 query rows (hence the 10x loop)</li>
</ul>
<p>So, I had to run it a few times to delete all my records. It all worked very well.</p>
<p>Oh, one more point. When a custom object is deleted and brought back to life, it gets renamed (eg my_obj_del__c), so take a look at the object page to find the correct API name.</p>
<h3>The Bottom Line</h3>
<ul class="nomargin">
<li>Apex can execute in the System Log window</li>
<li>Apex governor limits can be mostly avoided</li>
<li>It pays to read blogs!</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://theEnforcer.net/2009/01/mass-delete/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>
