<?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>Perspectives on Salesforce.com &#187; APEX Code</title>
	<atom:link href="http://sfdc.arrowpointe.com/taxonomy/category/APEX%20Code/feed/" rel="self" type="application/rss+xml" />
	<link>http://sfdc.arrowpointe.com</link>
	<description>Authored by Scott Hemmeter of Arrowpointe Corp, this blog is written from the perspective of a Salesforce.com solution provider and contains information on Arrowpointe's AppExchange products as well as tips, findings, sample code, functionality wishes, etc.</description>
	<lastBuildDate>Thu, 24 Jun 2010 06:02:39 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Endpoint for Debugging HTTP Callouts</title>
		<link>http://sfdc.arrowpointe.com/2010/02/16/endpoint-for-debugging-http-callouts/</link>
		<comments>http://sfdc.arrowpointe.com/2010/02/16/endpoint-for-debugging-http-callouts/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 16:39:05 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=743</guid>
		<description><![CDATA[When I use Apex to make HTTP callouts to other web services (e.g. Google Checkout, PayPal, Shopify, MapQuest, etc), it is often a game of trial and error to get things right.  Oftentimes, I get errors from the recipient that my request is invalid and, for the life of me, I cannot see the [...]]]></description>
			<content:encoded><![CDATA[<p>When I use Apex to make HTTP callouts to other web services (e.g. Google Checkout, PayPal, Shopify, MapQuest, etc), it is often a game of trial and error to get things right.  Oftentimes, I get errors from the recipient that my request is invalid and, for the life of me, I cannot see the problem.</p>
<p>To help me debug, I keep a test endpoint in my DE orgs that I make callouts to in order to get a good look at what I am sending.  It&#8217;s a simple Visualforce page that I expose over Sites to act as a fake endpoint while I do development.  When developing a callout, I will often use this endpoint in the beginning to organize the parameters and then periodically throughout development to debug.</p>
<p>The page is simple.</p>
<pre class="brush: java">
&lt;apex:page controller=&quot;Endpoint_Controller&quot; cache=&quot;false&quot; showHeader=&quot;false&quot; sidebar=&quot;false&quot; action=&quot;{!init}&quot;&gt;
&lt;pre&gt;
&lt;apex:outputText escape=&quot;false&quot; value=&quot;{!debugInfo}&quot;&gt;&lt;/apex:outputText&gt;
&lt;/pre&gt;
&lt;/apex:page&gt;
</pre>
<p>Depending upon my need, I will add/remove the action=&#8221;{!init}&#8221; parameter from the page because I have it in there to write the {!debugInfo} variable to a Task for later review (kind of like using a task as a mini-debug log).  I don&#8217;t always need it turned on, so that parameter comes and goes.</p>
<p>My controller, with test method, is:</p>
<pre class="brush: java">
public without sharing class Endpoint_Controller {

public String debugInfo {get; set;}{

debugInfo = &#039;&#039;;

if (ApexPages.currentPage() != null){
// Incoming Headers
debugInfo += &#039;\n***ALL INCOMING HEADERS ***\n&#039;;
for (string key: ApexPages.currentPage().getHeaders().keySet()){
if (ApexPages.currentPage().getHeaders().get(key) != null){
debugInfo += key + &#039; = &#039; + ApexPages.currentPage().getHeaders().get(key) + &#039;\n&#039;;
}
}

// Incoming Parameters
debugInfo += &#039;\n***ALL INCOMING PARAMETERS ***\n&#039;;
for (string key: ApexPages.currentPage().getParameters().keySet()){
if (ApexPages.currentPage().getParameters().get(key) != null){
debugInfo += key + &#039; = &#039; + ApexPages.currentPage().getParameters().get(key) + &#039;\n&#039;;
}
}

// Other Page Reference Stuff
debugInfo += &#039;\n***OTHER PAGE REFERENCE INFO ***\n&#039;;
debugInfo += &#039;Anchor: &#039; + ApexPages.currentPage().getAnchor() + &#039;\n&#039;;
debugInfo += &#039;URL: &#039; + ApexPages.currentPage().getUrl() + &#039;\n&#039;;
}

}

public Endpoint_Controller(){}

public PageReference init() {

Task t = new Task();
t.Subject = &#039;Endpoint Invoked&#039;;
t.Description = debugInfo;
t.ActivityDate = Date.Today();
insert t;

return null;

}

static testMethod void Endpoint_Controller_test() {

// Set the page reference and pass through some parameters
PageReference thePage = Page.Endpoint;
thePage.getParameters().put(&#039;param1&#039;,&#039;1&#039;);
thePage.getParameters().put(&#039;param2&#039;,&#039;2&#039;);
Test.setCurrentPage(thePage);

// Run the init function to have it handle the web to lead submission
Endpoint_Controller ep = new Endpoint_Controller();
ep.init();
}
}
</pre>
<p>What does it do?  Well, it simply gathers up all the headers, page parameters and other useful info and outputs it in a readable way.  I sent a test request to one of my pages and this is what the page produced (and logged to a task in that org):</p>
<blockquote><p>
***ALL INCOMING HEADERS ***<br />
Accept = application/xml;charset=UTF-8<br />
Cache-Control = no-cache, max-age=0<br />
CipherSuite = RC4-MD5 TLSv1 128-bits<br />
Content-Type = application/xml;charset=UTF-8<br />
Host = testorg.secure.force.com<br />
Pragma = no-cache<br />
SFDC_STACK_DEPTH = 1<br />
User-Agent = SFDC-Callout/18.0<br />
X-Forwarded-For = 10.226.8.134<br />
X-Salesforce-Forwarded-To = na7.salesforce.com<br />
X-Salesforce-SIP = 204.14.234.8</p>
<p>***ALL INCOMING PARAMETERS ***<br />
param1 = value1<br />
param2 = value2<br />
param3 = value3</p>
<p>***OTHER PAGE REFERENCE INFO ***<br />
Anchor: null<br />
URL: /apex/Endpoint?param1=value1&#038;param2=value2&#038;param3=value3
</p></blockquote>
<p>I also construct debugInfo variables in my Production system to capture the receipt of incoming calls to Sites pages I have exposed (e.g. Google Checkout talks to my Salesforce org via a Sites page).  I will usually have a custom setting that I can turn on/off so I have an easy way to turn off the creation of those activities.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=743&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2010/02/16/endpoint-for-debugging-http-callouts/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Using Aggregate Functions</title>
		<link>http://sfdc.arrowpointe.com/2010/02/10/using-aggregate-functions/</link>
		<comments>http://sfdc.arrowpointe.com/2010/02/10/using-aggregate-functions/#comments</comments>
		<pubDate>Wed, 10 Feb 2010 17:51:05 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Releases]]></category>
		<category><![CDATA[Spring '10]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=732</guid>
		<description><![CDATA[In Spring &#8216;10 Salesforce released new Apex functionality for aggregate functions.  Prior to this feature being available, one would have to perform a large query, loop through it and perform calculations themselves to do things like count records, sum values, get the max value, etc.  Now, you can do it in one simple, fast query!
The [...]]]></description>
			<content:encoded><![CDATA[<p>In <a href="http://sites.force.com/features/ideaHome?c=09a30000000DCUV" target="_blank">Spring &#8216;10</a> Salesforce released new Apex functionality for <a href="http://sites.force.com/ideaexchange/ideaView?c=09a30000000D9xt&amp;id=08730000000BrorAAC" target="_blank">aggregate functions</a>.  Prior to this feature being available, one would have to perform a large query, loop through it and perform calculations themselves to do things like count records, sum values, get the max value, etc.  Now, you can do it in one simple, fast query!</p>
<p>The <a href="http://www.salesforce.com/us/developer/docs/api/index_Left.htm#StartTopic=Content%2Fsforce_api_calls_soql_select_agg_functions.htm|SkinName=webhelp" target="_blank">API Guide</a> has all the details about how to perform aggregate functions in SOQL, but at a high-level, they (along with the GROUP BY clause) let you do things like:</p>
<ul>
<li>Get a <strong>count</strong> of Accounts grouped by Industry &amp; State</li>
<li>Get the <strong>avg</strong> Opportunity amount grouped by Calendar Month</li>
<li>Get the <strong>sum</strong> of Custom Object $ field grouped by Account</li>
<li>etc.</li>
</ul>
<p>Get the idea?  The functions you have available are COUNT(), COUNT_DISTINCT(), AVG(), SUM(), MIN(), MAX().  Think of these like you would the Columns To Total in a summary report.</p>
<p>You can also use the GROUP BY clause in your query to summarize your data by other fields.  Think of it like a Summary Report grouping.</p>
<p>The best way to learn it is to put it into practice.  To do so, I am going to &#8220;upgrade&#8221; the code from my <a href="http://sfdc.arrowpointe.com/2008/10/31/campaign-member-summary-using-google-charts/" target="_blank">Campaign Member Summary using Google Charts</a> post.  The goal is to create a chart that looks like below:</p>
<p><img class="aligncenter size-full wp-image-462" title="vfcampaignchart" src="http://sfdc.arrowpointe.com/wp-content/images/vfcampaignchart.png" alt="" width="457" height="238" /></p>
<p>The <strong>original controller</strong> used the following code to build the count of records per Campaign Member Status:</p>
<pre class="brush: java">
// List of valid Campaign Member Statuses for the Campaign
List&lt;CampaignMemberStatus&gt; list_cms = [select Id, Label from CampaignMemberStatus where CampaignId = :camp.id];

// Loop through each Campaign Member Status, get a count of Campaign Members and add it to the items list
for (CampaignMemberStatus cms:list_cms) {
integer Count = [select count() from CampaignMember where CampaignId = :camp.id AND Status = :cms.Label];
if (Count &gt; 0) {
items.add(new ChartDataItem(cms.Label, Count.format()));
}
}
</pre>
<p>The code above works just fine, but has some issues.  The main issue is that we are performing a query inside a for() loop.  Bad!  If a Campaign had more than 20 statuses, the code would fail. Also, this is a performance hit because we have to perform as many queries as there are member statuses.  Enter aggregate functions.</p>
<p>The <strong>improved controller</strong> changes the query to work like this.</p>
<pre class="brush: java">
// Get all the data in one query
AggregateResult[] groupedResults = [select Status, count(Id) from CampaignMember where CampaignId = :camp.id group by status];

// Loop through the query and add chart items
for (AggregateResult ar : groupedResults) {
     items.add(new ChartDataItem( String.valueOf(ar.get(&#039;Status&#039;)), String.valueOf(ar.get(&#039;expr0&#039;))));
}
</pre>
<p>Now we are doing everything we need in 1 query.  Even if we had 1000 different member statuses, it wouldn&#8217;t matter.  We should never hit a governor limit with this code and performance has also been improved.  Some important things to note in making this change and in understanding aggregate functions:</p>
<ul>
<li>Your controller class should be on API version 18.0 or higher.  18.0 is the Spring &#8216;10 release and that&#8217;s when these functions were introduced.</li>
<li>The results of a query with aggregate functions should result in a AggregateResult[] collection.</li>
<li>The get() method is used to retrieve data from an AggregateResult object (used inside the loop when looking at a single result)</li>
<li>To get the value from a field your are grouping by (i.e. doesn&#8217;t have a function for it), use .get(&#8216;fieldName&#8217;).  In the above example, I use this to get the Status value I am grouping by.</li>
<li>To get the value from a field that has an aggregate function, use .get(&#8216;expr#&#8217;), where # is the index number for that field.  A query can have multiple functions in it so you need to specify which function you are grabbing and you do so by its index number.  For you non-programmers out there, remember that <strong>counting starts at 0</strong>.   In the above example, I use this to get the count(id) value.  Since I only have 1 aggregate function in my query, i get it using .get(&#8216;expr0&#8242;) where 0 is the index number for my function result.</li>
<li>The get() method returns an Object type so you will need to use the appropriate valueOf() method to put it into the data type you need.</li>
</ul>
<p><strong>NOTE</strong>: As of writing this post, the IDE was not yet upgraded to 18.0 so I had to do this work inside the browser and I used the new-ish Deploy functionality from inside Salesforce to migrate the change from Sandbox to Production.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=732&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2010/02/10/using-aggregate-functions/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Associate Email to Salesforce Task to Opportunity</title>
		<link>http://sfdc.arrowpointe.com/2009/10/06/associate-email-to-salesforce-task-to-opportunity/</link>
		<comments>http://sfdc.arrowpointe.com/2009/10/06/associate-email-to-salesforce-task-to-opportunity/#comments</comments>
		<pubDate>Tue, 06 Oct 2009 23:32:48 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=714</guid>
		<description><![CDATA[I use the Email to Salesforce functionality every single day.  This feature allows you to get a random email address similar to emailtosalesforce@0235ffdsdfsad98dvfj4i549540njh3.in.salesforce.com (this is just a sample) that you bcc on emails and Tasks get created in your system that are auto-associated to your Leads/Contacts.
There is an option to associate the Task to Opportunities, [...]]]></description>
			<content:encoded><![CDATA[<p>I use the Email to Salesforce functionality every single day.  This feature allows you to get a random email address similar to <em>emailtosalesforce@0235ffdsdfsad98dvfj4i549540njh3.in.salesforce.com</em> (this is just a sample) that you bcc on emails and Tasks get created in your system that are auto-associated to your Leads/Contacts.</p>
<p>There is an option to associate the Task to Opportunities, but instead of creating a Task and associating it to the Lead/Contact AND the Opportunity, 2 tasks are created: one against the Lead/Contact and another against the Opportunity.  I have no idea why it was designed this way, but it was.  Given that, I don&#8217;t use the option to associate the Task to Opportunities.</p>
<p>After months of manually assigning to Opportunities after I send the email, I got fed up and wrote a trigger that senses an email to salesforce record and auto associates it to the nearest Open Opportunity.  I thought I&#8217;d share it with y&#8217;all.</p>
<p>This code assumes the following:</p>
<ul>
<li>You are using Email to Salesforce</li>
<li>You have the Email to Salesforce option for Leads &#038; Contacts enabled and the one for Opportunities disabled</li>
<li>You associate Contacts to your Opportunities via the OpportunityContactRole object</li>
</ul>
<p><strong>Trigger</strong></p>
<pre class="brush: java">
trigger Tasks on Task (before insert) {

	// BEFORE INSERT
	if(Trigger.isBefore &amp;&amp; Trigger.isInsert){
		Tasks t = new Tasks();
        t.AssociateOpportunity(Trigger.new);
    }

}
</pre>
<p><strong>Class</strong></p>
<pre class="brush: java">
public class Tasks {

    // Default Constructor
    public Tasks()
    {
    }

    // Associates a new Task generated by Email to Salesforce to an open opportunity, if one exists for the Account
    public void AssociateOpportunity(Task[] tasks)
    {

    	/***************
        * Variables
        ***************/
		list&lt;Task&gt; l_Tasks = new list&lt;Task&gt;(); // Tasks we&#039;ll be updating
		set&lt;ID&gt; s_ContactIDs = new set&lt;ID&gt;(); // Set of Contact IDs

		/***************
        * Initial Loop
        ***************/
		for(Task t:tasks) {

			// Add Task to working list and collect the Contact ID
			if (t.WhatId == null &amp;&amp; t.Subject.startsWith(&#039;Email:&#039;) &amp;&amp; t.WhoId != null) {
				// only for Contacts
				if (String.valueOf(t.WhoId).startsWith(&#039;003&#039;)){
					l_Tasks.add(t);
					s_ContactIDs.add(t.WhoId);
				}
			}

		}

		/***************
        * Create Maps
        ***************/
        // Maps Contact ID to an Opportunity ID
		map&lt;ID, ID&gt; map_cID_to_oID = new map&lt;ID, ID&gt;();
			// Query for the Contact&#039;s Open Opportunities. Sort by CloseDate DESC so the Task gets assigned to the earliest Opportunity as it loops
			for (OpportunityContactRole ocr:[select Id, OpportunityId, ContactId
											 from OpportunityContactRole
											 where ContactId in :s_ContactIDs
											 AND Opportunity.IsClosed = false
											 order by Opportunity.CloseDate DESC
											 ]) {
				map_cID_to_oID.put(ocr.ContactId, ocr.OpportunityId);
			}

		/***************
        * Process Records
        ***************/
		for (Task t:l_Tasks) {

			// If the Contact has an Opportunity mapped to it, update the Task with that Opportunity
			if (map_cID_to_oID.get(t.WhoId) != null) {
				t.WhatId = map_cID_to_oID.get(t.WhoId);
			}

		}
    }

}
</pre>
<p><strong>Test Class</strong></p>
<pre class="brush: java">
@isTest
private class Tasks_Test {

    static testMethod void AssociateOpportunity_Test() {

        // Create a Lead
        Lead l = new Lead();
	        l.FirstName = &#039;Test&#039;;
	        l.LastName = &#039;Lead&#039;;
	        l.Company = &#039;Test Company&#039;;
	        l.Email = &#039;leademail@example.com&#039;;
        insert l;

        // Create an Account
        Account a = new Account();
        	a.Name = &#039;Test Account&#039;;
        insert a;

        // Create a Contact
        Contact c = new Contact();
	        c.FirstName = &#039;Test&#039;;
	        c.LastName = &#039;Contact&#039;;
	        c.AccountId = a.Id;
	        c.Email = &#039;contactemail@example.com&#039;;
        insert c;

        // Create Opportunities
        list&lt;Opportunity&gt; l_Opps = new list&lt;Opportunity&gt;();
        Opportunity o = new Opportunity();
        	o.AccountId = a.id;
        	o.Name = &#039;Test Opportunity&#039;;
        	o.CloseDate = date.today();
        	o.StageName = &#039;Qualified&#039;;
        	o.Description = &#039;Test Opportunity Description&#039;;
        l_Opps.add(o);

        Opportunity o2 = new Opportunity();
        	o2.AccountId = a.id;
        	o2.Name = &#039;Test Opportunity&#039;;
        	o2.CloseDate = date.today().addDays(30);
        	o2.StageName = &#039;Qualified&#039;;
        	o2.Description = &#039;Test Opportunity Description&#039;;
        l_Opps.add(o2);

        Opportunity o3 = new Opportunity();
        	o3.AccountId = a.id;
        	o3.Name = &#039;Test Opportunity&#039;;
        	o3.CloseDate = date.today().addDays(60);
        	o3.StageName = &#039;Closed Won&#039;;
        	o3.Description = &#039;Test Opportunity Description&#039;;
        l_Opps.add(o3);

        insert l_Opps;

        // Create Opportunity Contact Roles
        list&lt;OpportunityContactRole&gt; l_Ocr = new list&lt;OpportunityContactRole&gt;();
    	OpportunityContactRole ocr1 = new OpportunityContactRole();
    		ocr1.ContactId = c.id;
    		ocr1.OpportunityId = o.id;
			ocr1.IsPrimary = true;
			ocr1.Role = &#039;Decision Maker&#039;;
		l_Ocr.add(ocr1);

		OpportunityContactRole ocr2 = new OpportunityContactRole();
    		ocr2.ContactId = c.id;
    		ocr2.OpportunityId = o2.id;
			ocr2.IsPrimary = true;
			ocr2.Role = &#039;Decision Maker&#039;;
		l_Ocr.add(ocr2);

		insert l_Ocr;

        /* Create Tasks for Test Cases */
        list&lt;Task&gt; l_Tasks = new list&lt;Task&gt;();

        // Task associated to Lead, not Contact
        Task t1 = new Task();
        	t1.Subject = &#039;Email: something&#039;;
        	t1.Status = &#039;Completed&#039;;
        	t1.WhoId = l.id;
        	t1.ActivityDate = Date.today();
    	l_Tasks.add(t1);

    	// Task with wrong subject
    	Task t2 = new Task();
        	t2.Subject = &#039;something&#039;;
        	t2.Status = &#039;Completed&#039;;
        	t2.WhoId = c.id;
        	t2.ActivityDate = Date.today();
    	l_Tasks.add(t2);

    	// Task with no WhoId
    	Task t3 = new Task();
        	t3.Subject = &#039;something&#039;;
        	t3.Status = &#039;Completed&#039;;
        	t3.ActivityDate = Date.today();
    	l_Tasks.add(t3);

    	// Task with a What ID already
    	Task t4 = new Task();
        	t4.Subject = &#039;something&#039;;
        	t4.Status = &#039;Completed&#039;;
        	t4.WhoId = c.id;
        	t4.WhatId = o2.id;
        	t4.ActivityDate = Date.today();
    	l_Tasks.add(t4);

    	// Task that should get triggered fully
    	Task t5 = new Task();
        	t5.Subject = &#039;Email: something&#039;;
        	t5.Status = &#039;Completed&#039;;
        	t5.WhoId = c.id;
        	t5.ActivityDate = Date.today();
    	l_Tasks.add(t5);

    	insert l_Tasks;

 		/* Asserts */

 		// Task 1 should not have a What ID populated
 		Task t = [select Id, WhoId, WhatId from Task where Id = :t1.id limit 1];
 		system.assertEquals(t.WhatId, null);

 		// Task 2 should not have a What ID populated
 		t = [select Id, WhoId, WhatId from Task where Id = :t2.id limit 1];
 		system.assertEquals(t.WhatId, null);

 		// Task 3 should not have a What ID populated
 		t = [select Id, WhoId, WhatId from Task where Id = :t3.id limit 1];
 		system.assertEquals(t.WhatId, null);

 		// Task 4 should have the same What ID it had originally populated
 		t = [select Id, WhoId, WhatId from Task where Id = :t4.id limit 1];
 		system.assertEquals(t.WhatId, o2.id);

 		// Task 5 is the one that should&#039;ve had the Opportunity ID auto populated
 		t = [select Id, WhoId, WhatId from Task where Id = :t5.id limit 1];
 		system.assertEquals(t.WhatId, o.id);

    }
}
</pre>
<p>Let me know if you have any suggestions.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=714&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2009/10/06/associate-email-to-salesforce-task-to-opportunity/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Invoking Apex from a Button (JS &#8211;&gt; Apex Web Service)</title>
		<link>http://sfdc.arrowpointe.com/2009/07/13/invoking-apex-from-a-button-js-apex-web-service/</link>
		<comments>http://sfdc.arrowpointe.com/2009/07/13/invoking-apex-from-a-button-js-apex-web-service/#comments</comments>
		<pubDate>Mon, 13 Jul 2009 16:54:13 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[The Community]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=652</guid>
		<description><![CDATA[In January I posted about how to invoke Apex from a Custom Button using a Visualforce Page.  It has been a popular post and is a topic which is of interest to many developers.  I wanted to draw your attention to another post.  Sam Arjmandi, from Salesforce Source, posted about how to invoke Apex from [...]]]></description>
			<content:encoded><![CDATA[<p>In January I posted about how to <a href="http://sfdc.arrowpointe.com/2009/01/08/invoke-apex-from-a-custom-button-using-a-visualforce-page/" target="_blank">invoke Apex from a Custom Button using a Visualforce Page</a>.  It has been a popular post and is a topic which is of interest to many developers.  I wanted to draw your attention to another post.  Sam Arjmandi, from <a href="http://salesforcesource.blogspot.com/" target="_blank">Salesforce Source</a>, posted about how to <a href="http://salesforcesource.blogspot.com/2009/06/triggering-apex-method-with-custom.html" target="_blank">invoke Apex from a button</a> by calling the Apex directly from JavaScript whereby the Apex must be available as a web service.</p>
<p>Both methods work just fine and there is a choice of approach.  Recently, my personal choice for implementing this kind of functionality is to use Sam&#8217;s approach and it&#8217;s mostly due to the user experience.  Using this approach, the code is called directly and there is no time spent by the browser needing to load a new blank page only to return to the same page.  It works much more seamlessly.  You also get the benefit of having less objects to develop (no VF page) and tie together.  The only real downside (outside of requirement-specific ones) is that Salesforce won&#8217;t bark at you if you delete the web service class because it doesn&#8217;t know that the web service is tied to JavaScript.  If your Apex Code is a controller for your VF page, Salesforce will protect you from deleting it accidentally.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=652&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2009/07/13/invoking-apex-from-a-button-js-apex-web-service/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Force.com Debug Log Parser</title>
		<link>http://sfdc.arrowpointe.com/2009/06/04/forcecom-debug-log-parser/</link>
		<comments>http://sfdc.arrowpointe.com/2009/06/04/forcecom-debug-log-parser/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 16:45:51 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Innovations]]></category>
		<category><![CDATA[The Community]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=636</guid>
		<description><![CDATA[Kyle Peterson has released the Force.com Debug Log Parser, a nifty little .NET app for parsing the mess of a debug log you get from Salesforce when executing Apex code.   You can see a video demonstration here.
Great work, Kyle!
P.S. The comments to the post suggest an interest by Salesforce to include this into the IDE.  [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://codebit.wordpress.com/about/" target="_blank">Kyle Peterson</a> has released the <a href="http://codebit.wordpress.com/2009/06/04/force-com-debug-log-parser/" target="_blank">Force.com Debug Log Parser</a>, a nifty little .NET app for parsing the mess of a debug log you get from Salesforce when executing Apex code.   You can see a video demonstration <a href="http://home.comcast.net/~kpeterson85/ForceDebugLogParser.swf" target="_blank">here</a>.</p>
<p>Great work, Kyle!</p>
<p>P.S. The comments to the post suggest an interest by Salesforce to include this into the IDE.  Hopefully that happens.  Until then, I&#8217;ll install this version and use it regularly.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=636&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2009/06/04/forcecom-debug-log-parser/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Testing HTTP Callouts</title>
		<link>http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/</link>
		<comments>http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/#comments</comments>
		<pubDate>Fri, 01 May 2009 16:45:53 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=616</guid>
		<description><![CDATA[When writing Apex Code, there are some things that simply cannot be tested, namely HTTP callouts.  The Intro to Apex Code Test Methods has one solution to testing as much of an HTTP callout as possible.  That is to break the HTTP callout into 3 methods: 1) Build Request, 2) Make Request, 3) Handle Response.  [...]]]></description>
			<content:encoded><![CDATA[<p>When writing Apex Code, there are some things that simply cannot be tested, <strong>namely HTTP callouts</strong>.  The <a href="http://wiki.developerforce.com/index.php/An_Introduction_to_Apex_Code_Test_Methods" target="_blank">Intro to Apex Code Test Methods</a> has one solution to testing as much of an HTTP callout as possible.  That is to break the HTTP callout into 3 methods: 1) Build Request, 2) Make Request, 3) Handle Response.  In the test method, you are only calling the Build Request and Handle Response methods.</p>
<p>I have another approach.  My main reason for not using the approach mentioned above is that I didn&#8217;t read that post until after I developed something.  However, my approach accomplishes the same thing, but also <strong>adds a variable to your class so that you can know whether or not a test is running</strong>.  Knowing this may be useful in other situations too.</p>
<p>Here&#8217;s is a <strong>class</strong> that uses my technique.</p>
<pre class="brush: java">
public class sample {

	// Static variable that assumes a test is not running
	public static boolean isApexTest = false;

	public String main(){

	    // Do a whole bunch of stuff

		// Build the http request
		Http h = new Http();
		HttpRequest req = new HttpRequest();
	    req.setEndpoint(&#039;http://local.yahooapis.com/MapsService/V1/geocode?appid=YD-9G7bey8_JXxQP6rxl.fBFGgCdNjoDMACQA--&amp;street=701+First+Ave&amp;city=Sunnyvale&amp;state=CA&#039;);
	    req.setMethod(&#039;GET&#039;);

		// Invoke web service call
		String result = &#039;&#039;;
		if (!isApexTest){
			// Make a real callout since we are not running a test
			HttpResponse res = h.send(req);
			result = res.getBody();
		} else {
			// A test is running
			result = &#039;&lt;?xml version=&quot;1.0&quot;?&gt;&lt;ResultSet xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns=&quot;urn:yahoo:maps&quot; xsi:schemaLocation=&quot;urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd&quot;&gt;&lt;Result precision=&quot;address&quot;&gt;&lt;Latitude&gt;37.416397&lt;/Latitude&gt;&lt;Longitude&gt;-122.025055&lt;/Longitude&gt;&lt;Address&gt;701 1st Ave&lt;/Address&gt;&lt;City&gt;Sunnyvale&lt;/City&gt;&lt;State&gt;CA&lt;/State&gt;&lt;Zip&gt;94089-1019&lt;/Zip&gt;&lt;Country&gt;US&lt;/Country&gt;&lt;/Result&gt;&lt;/ResultSet&gt;&#039;;
		}

		// Do whole bunch of stuff

	    return result;
	}

	// Wrapper method for &quot;main&quot; that we will call in the Test Class
	public String mainForTest(){
		isApexTest = true;
		return main();
	}
}
</pre>
<p>I have a static variable called <strong>isApexTest</strong> that I set to false by default so the code assumes a test is not running.  For testing purposes, I created a &#8220;wrapper&#8221; method (called &#8220;mainForTest()&#8221;) that I will call in my test class in order to test the main() method.  This wrapper method sets the isApexTest variable to true, calls the main() method and then passes back the result from the main() method.  mainForTest() is merely a way to get the isApexTest variable set to true.</p>
<p>My test class is below.</p>
<pre class="brush: java">
@isTest
private class sample_test {

    static testMethod void main_test() {

		// Establish sample class
		sample s = new sample();

		// Call the mainForTest wrapper method so we can set the variable indicating that a test is running
		String retVal = s.mainForTest();

	 	// Add asserts for validation
	 	String expectedResult = &#039;&lt;?xml version=&quot;1.0&quot;?&gt;&lt;ResultSet xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns=&quot;urn:yahoo:maps&quot; xsi:schemaLocation=&quot;urn:yahoo:maps http://api.local.yahoo.com/MapsService/V1/GeocodeResponse.xsd&quot;&gt;&lt;Result precision=&quot;address&quot;&gt;&lt;Latitude&gt;37.416397&lt;/Latitude&gt;&lt;Longitude&gt;-122.025055&lt;/Longitude&gt;&lt;Address&gt;701 1st Ave&lt;/Address&gt;&lt;City&gt;Sunnyvale&lt;/City&gt;&lt;State&gt;CA&lt;/State&gt;&lt;Zip&gt;94089-1019&lt;/Zip&gt;&lt;Country&gt;US&lt;/Country&gt;&lt;/Result&gt;&lt;/ResultSet&gt;&#039;;
	 	System.assertEquals(retVal, expectedResult);

	 }

}
</pre>
<p>In case you are wondering why I use a static variable for isApexTest instead of a class property, it is because I originally developed this technique to test an Apex Web Service.  Since all web service methods are static, I couldn&#8217;t create an instance of a class to set the property to true and then call the web service method.  Web service methods must be invoked directly and not through an instance of a class.  That&#8217;s where the wrapper method idea came from.</p>
<p>Another approach than a wrapper method would be to have an input variable to my main() method that accepts true/false whether a test was running.  I did not go with this approach because I might have many methods performing callouts and I preferred to have 1 public variable accessible throughout the entire class than a local variable in each method.  If I used a local variable, I would need to keep passing it around to other methods.</p>
<p>Comment with your thoughts and alternative approaches.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=616&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2009/05/01/testing-http-callouts/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Set Defaults for Opportunity Contact Roles (when converting)</title>
		<link>http://sfdc.arrowpointe.com/2009/02/06/set-defaults-for-opportunity-contact-roles-when-converting/</link>
		<comments>http://sfdc.arrowpointe.com/2009/02/06/set-defaults-for-opportunity-contact-roles-when-converting/#comments</comments>
		<pubDate>Fri, 06 Feb 2009 20:24:46 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=587</guid>
		<description><![CDATA[It&#8217;s always bugged me that the Primary flag and a Role are not set on Opportunity Contact Roles when converting a Lead.  After every convert, I manually set these.  Typically, I set the Role to &#8220;Decision Maker&#8221;and the Primary Flag to True.  I got sick of doing this manually, so I wrote a trigger for [...]]]></description>
			<content:encoded><![CDATA[<p>It&#8217;s always bugged me that the Primary flag and a Role are not set on Opportunity Contact Roles when converting a Lead.  After every convert, I manually set these.  Typically, I set the Role to &#8220;Decision Maker&#8221;and the Primary Flag to True.  I got sick of doing this manually, so I wrote a trigger for it and I am sharing it with you all.</p>
<p><strong>Trigger</strong></p>
<pre class="brush: java">
trigger Opportunities on Opportunity (after insert) {

	Opportunities o = new Opportunities();
	o.SetContactRoleDefaults(Trigger.new);

}
</pre>
<p><strong>Class</strong></p>
<pre class="brush: java">
public class Opportunities {

    // Default Constructor
    public Opportunities()
    {
    }

    // Sets default values on the Contact Role record created during Conversion. Called on AFTER INSERT
    public void SetContactRoleDefaults(Opportunity[] opptys)
    {
    	/***************
        * Variables
        ***************/
		set&lt;ID&gt; set_opptyIDs = new set&lt;ID&gt;();

		/***************
        * Initial Loop
        ***************/
        // Get a set of the Opportunity IDs being affected.
		for(Opportunity o:opptys) {
			set_opptyIDs.add(o.id);
		}

		/***************
        * Process Records
        ***************/
        // Update the Contact Role record to be Primary and the Decision Maker
        list&lt;OpportunityContactRole&gt; list_opptyContactRolesToUpdate = new list&lt;OpportunityContactRole&gt;();
		for(OpportunityContactRole ocr:[select Id,IsPrimary,Role from OpportunityContactRole where OpportunityId in :set_opptyIDs]) {
			ocr.IsPrimary = true;
			ocr.Role = &#039;Decision Maker&#039;;
			list_opptyContactRolesToUpdate.add(ocr);
		}

		if (list_opptyContactRolesToUpdate.size() &gt; 0) {
			update list_opptyContactRolesToUpdate;
		}

    }
}
</pre>
<p><strong>Test Class</strong></p>
<pre class="brush: java">
@isTest
private class Opportunities_Test {

    static testMethod void SetContactRoleDefaults_Test() {

        // Create a Lead
        Lead l = new Lead();
        l.lastname = &#039;Lastname&#039;;
        l.firstname = &#039;FirstName&#039;;
        l.company = &#039;Company&#039;;
        insert l;

        // Convert the Lead
        Database.LeadConvert lc = new database.LeadConvert();
		lc.setLeadId(l.id);

		LeadStatus convertStatus = [Select Id, MasterLabel from LeadStatus where IsConverted=true limit 1];
		lc.setConvertedStatus(convertStatus.MasterLabel);

		Database.LeadConvertResult lcr = Database.convertLead(lc);
		System.assert(lcr.isSuccess());

		// Query Contact Role Records and Asserts all was set correctly.
		for (OpportunityContactRole ocr:[select Id,IsPrimary,Role from OpportunityContactRole where OpportunityId = :lcr.getOpportunityId()]) {
			system.AssertEquals(&#039;Decision Maker&#039;, ocr.Role);
			system.AssertEquals(true, ocr.IsPrimary);
		} 

    }

}
</pre>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=587&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2009/02/06/set-defaults-for-opportunity-contact-roles-when-converting/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>Invoke Apex from a Custom Button using a Visualforce Page</title>
		<link>http://sfdc.arrowpointe.com/2009/01/08/invoke-apex-from-a-custom-button-using-a-visualforce-page/</link>
		<comments>http://sfdc.arrowpointe.com/2009/01/08/invoke-apex-from-a-custom-button-using-a-visualforce-page/#comments</comments>
		<pubDate>Thu, 08 Jan 2009 23:45:36 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=525</guid>
		<description><![CDATA[I have had a few occasions where I wanted to invoke Apex Code by clicking a button on a Page Layout.  Everywhere I looked, it always said I needed to have the button call an s-Control, which would then invoke Apex Code that&#8217;s written as a Web Service.  I am doing my best to avoid [...]]]></description>
			<content:encoded><![CDATA[<p>I have had a few occasions where I wanted to invoke Apex Code by clicking a button on a Page Layout.  Everywhere I looked, it always said I needed to have the button call an s-Control, which would then invoke Apex Code that&#8217;s written as a Web Service.  I am doing my best to avoid using s-Controls and figured there had to be a way using Visualforce instead of an s-Control.  The key was the <em>action</em> attribute on the &lt;apex:page tag.</p>
<p>Suppose you wanted to add a button on your Opportunity page that automatically did something when you pushed the button.  You can&#8217;t execute Apex Code directly from a button.  You need something in the middle.  Let&#8217;s try to do it with a Visualforce page instead of an s-Control.</p>
<h6>Controller</h6>
<p>The controller has the main method in it to be executed.  This method returns a PageReference (very important).  Note that the method does not need to be a webservice.</p>
<pre class="brush: java">

public class VFController {

	// Constructor - this only really matters if the autoRun function doesn&#039;t work right
	private final Opportunity o;
	public VFController(ApexPages.StandardController stdController) {
		this.o = (Opportunity)stdController.getRecord();
	}

	// Code we will invoke on page load.
	public PageReference autoRun() {

		String theId = ApexPages.currentPage().getParameters().get(&#039;id&#039;);

		if (theId == null) {
			// Display the Visualforce page&#039;s content if no Id is passed over
			return null;
		}

		for (Opportunity o:[select id, name, etc from Opportunity where id =:theId]) {
			// Do all the dirty work we need the code to do
		}

		// Redirect the user back to the original page
		PageReference pageRef = new PageReference(&#039;/&#039; + theId);
		pageRef.setRedirect(true);
		return pageRef;

	}

}
</pre>
<h6>Visualforce </h6>
<p>The Visualforce page is very simple.  You really don&#8217;t need anything in there except the <apex:page tag.  I added a bit of content into it to tell a user that something went wrong if they see the page in the browser.</p>
<p>The expected behavior is that the <em>action</em> parameter invokes code (the autoRun method) that runs before the page is initialized.  That method returns a Page Reference that redirects the user back to the original page.</p>
<pre class="brush: html">

&lt;apex:page standardController=&quot;Opportunity&quot;
 extensions=&quot;VFController&quot;
 action=&quot;{!autoRun}&quot;
&gt;
  &lt;apex:sectionHeader title=&quot;Auto-Running Apex Code&quot;/&gt;
  &lt;apex:outputPanel &gt;
      You tried calling Apex Code from a button.  If you see this page, something went wrong.  You should have
      been redirected back to the record you clicked the button from.
  &lt;/apex:outputPanel&gt;
&lt;/apex:page&gt;
</pre>
<h6>Custom Button</h6>
<p>All we need now is a custom Opportunity button.  Because we used the Opportunity standard controller in the Visualforce page, we can simply have the button point to a the page we created.</p>
<p>Add that button to your Page Layout and all should work swimmingly.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=525&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2009/01/08/invoke-apex-from-a-custom-button-using-a-visualforce-page/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>Calling Apex Web Services from PHP</title>
		<link>http://sfdc.arrowpointe.com/2008/12/05/calling-apex-web-services-from-php/</link>
		<comments>http://sfdc.arrowpointe.com/2008/12/05/calling-apex-web-services-from-php/#comments</comments>
		<pubDate>Fri, 05 Dec 2008 21:31:07 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=475</guid>
		<description><![CDATA[Apex Code can be exposed as a Web Service and made available outside of your Salesforce environment (e.g. from a PHP page).  This approach essentially lets you build a personal API into your Salesforce org and eliminates the need for calling standard API methods in PHP code where it is vulnerable to your configuration [...]]]></description>
			<content:encoded><![CDATA[<p>Apex Code can be exposed as a Web Service and made available outside of your Salesforce environment (e.g. from a PHP page).  This approach essentially lets you build a personal API into your Salesforce org and eliminates the need for calling standard API methods in PHP code where it is vulnerable to your configuration changes.</p>
<p>Working with the folks over at <a href="http://www.mkpartners.com" target="_blank">MK Partners</a> on some recent projects, I&#8217;ve learned how to call into Apex Web Services from PHP.  It&#8217;s actually pretty easy.  Special thanks for <a href="http://www.pocketsoap.com" target=_blank>Simon Fell</a> for helping me through a particularly tricky part.</p>
<h6>Apex Web Service Class</h6>
<p>A simple web service class is below.  The method we call from PHP is <strong>myMethod</strong>.  There are 2 inner classes that are used to capture inputs and send back outputs to PHP.</p>
<pre class="brush: java">
global class MyWebService {

    // A class to accept an array of input records (e.g. product/amount combinations)
    global class myInputs{
        webservice Id productId;
        webservice Double amount;
    }

    // A class to send back as an output to PHP
    global class myOutputs{
        webservice String errorMessage;
        webservice Boolean success;
        webservice List&lt;myInputs&gt; inputs;
        webservice Id contactId;
    }

    // The actual web service method we will call
    webservice static myOutputs myMethod(Id contactId, List&lt;myInputs&gt; inputs){

        /*
        * Write a bunch of code here to do all kinds of stuff.
        */

        myOutputs output = new myOutputs();
            output.errorMessage = &#039;No errors here.&#039;;
            output.success = true;
            output.inputs = inputs;
            output.contactId = contactId;
        return output;

    }
}
</pre>
<h6>PHP</h6>
<p>Login like you normally would using the PHP toolkit.  Nothing new here.  The final part is defining some constants for use later when we call the web service.</p>
<pre class="brush: php">
// Include the PHP Toolkit
require_once(&#039;salesforceAPI/SforcePartnerClient.php&#039;);
require_once(&#039;salesforceAPI/SforceHeaderOptions.php&#039;);

// Login
$sfdc = new SforcePartnerClient();
$SoapClient = $sfdc-&gt;createConnection(&#039;salesforceAPI/wsdl.xml&#039;);
$loginResult = false;
$loginResult = $sfdc-&gt;login(&#039;user@domain.com&#039;, &#039;password&#039; . &#039;securitytoken&#039;);

// Define constants for the web service. We&#039;ll use these later
$parsedURL = parse_url($sfdc-&gt;getLocation());
define (&quot;_SFDC_SERVER_&quot;, substr($parsedURL[&#039;host&#039;],0,strpos($parsedURL[&#039;host&#039;], &#039;.&#039;)));
define (&quot;_WS_NAME_&quot;, &#039;MyWebService&#039;);
define (&quot;_WS_WSDL_&quot;, _WS_NAME_ . &#039;.xml&#039;);
define (&quot;_WS_ENDPOINT_&quot;, &#039;https://&#039; . _SFDC_SERVER_ . &#039;.salesforce.com/services/wsdl/class/&#039; . _WS_NAME_);
define (&quot;_WS_NAMESPACE_&quot;, &#039;http://soap.sforce.com/schemas/class/&#039; . _WS_NAME_);
</pre>
<p>Next we will call the web service.  First thing to do is setup a Soap Client and modify the headers.  Then we are setting up some fake data that maps to the expected inputs of the myMethod method in the web service.  Then we actually call the web service.</p>
<pre class="brush: php">
// SOAP Client for Web Service
$client = new SoapClient(_WS_WSDL_);
$sforce_header = new SoapHeader(_WS_NAMESPACE_, &quot;SessionHeader&quot;, array(&quot;sessionId&quot; =&gt; $sfdc-&gt;getSessionId()));
$client-&gt;__setSoapHeaders(array($sforce_header));

// Setup fake data to send into the web service
$prodAmtArray = array();
	$prodAmtArray[] = array(&#039;productId&#039;=&gt;&#039;01t60000000lvBN&#039;,&#039;amount&#039;=&gt;100);
	$prodAmtArray[] = array(&#039;productId&#039;=&gt;&#039;01t60000000lvBS&#039;,&#039;amount&#039;=&gt;200);

$wrkArray = array(
				&#039;contactId&#039;=&gt;&#039;0036000000nVtpT&#039;,
				&#039;inputs&#039;=&gt;$prodAmtArray
				);

// Call the web service
$response = $client-&gt;myMethod($wrkArray);

// Output results to browser
echo &quot;&lt;p&gt;&lt;pre&gt;&quot; . print_r($response, true) . &quot;&lt;/pre&gt;&lt;/p&gt;&quot;;
echo &quot;Contact Id is &quot; . $response-&gt;result-&gt;contactId;
</pre>
<h6>Results</h6>
<p>Below displays what those 2 echo statements output.</p>
<pre style='line-height:1.2em; font-size: 1.3em;'>
stdClass Object
(
    [result] => stdClass Object
        (
            [contactId] => 0036000000nVtpTAAS
            [errorMessage] => No errors here.
            [inputs] => Array
                (
                    [0] => stdClass Object
                        (
                            [amount] => 100
                            [productId] => 01t60000000lvBNAAY
                        )
                    [1] => stdClass Object
                        (
                            [amount] => 200
                            [productId] => 01t60000000lvBSAAY
                        )
                )
            [success] => 1
        )
)
Contact Id is 0036000000nVtpTAAS
</pre>
<h6>One last little trick</h6>
<p>One annoyance during the development of Apex Web Services is having to continually generate a WSDL for the web service.  When testing, I would find that I would continually need to put a new WSDL on the web server.  I decided to automate this where I could add a variable to the queryString and have PHP refresh the WSDL on my web server.  You need the cURL module for this, but most PHP installs have it.</p>
<pre class="brush: php">
$ch = curl_init();
	$fp = fopen(_WS_WSDL_, &quot;w&quot;);
	curl_setopt($ch, CURLOPT_URL, _WS_ENDPOINT_);
	curl_setopt($ch, CURLOPT_FILE, $fp);
	curl_setopt($ch, CURLOPT_HEADER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
	curl_setopt($ch, CURLOPT_COOKIE, &#039;sid=&#039;.$sfdc-&gt;getSessionId());
	setcookie(&quot;sid&quot;, $sfdc-&gt;getSessionId(), 0, &quot;/&quot;, &quot;.salesforce.com&quot;, 0);
	curl_setopt($ch, CURLOPT_TIMEOUT, 30);
	curl_exec($ch);
	fclose($fp);
curl_close($ch);
</pre>
<p>If you have experience with this kind of integration, please comment here on other tips &#038; tricks.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=475&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2008/12/05/calling-apex-web-services-from-php/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
		<item>
		<title>Campaign Member Summary using Google Charts</title>
		<link>http://sfdc.arrowpointe.com/2008/10/31/campaign-member-summary-using-google-charts/</link>
		<comments>http://sfdc.arrowpointe.com/2008/10/31/campaign-member-summary-using-google-charts/#comments</comments>
		<pubDate>Fri, 31 Oct 2008 20:15:16 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=461</guid>
		<description><![CDATA[I was inspired by Sam Arjmandi&#8217;s post about embedding Google Charts into VisualForce pages.  I have a use case that requires a little different approach.  I needed to get a quick view of the Campaign Member Statuses for a Campaign.  I went ahead and started with Sam&#8217;s example and tweaked it for my purpose.  Here&#8217;s [...]]]></description>
			<content:encoded><![CDATA[<p>I was inspired by <a href="http://salesforcesource.blogspot.com/2008/10/how-to-easily-bring-graphical-charts.html" target="_blank">Sam Arjmandi&#8217;s post</a> about embedding Google Charts into VisualForce pages.  I have a use case that requires a little different approach.  I needed to get a quick view of the Campaign Member Statuses for a Campaign.  I went ahead and started with Sam&#8217;s example and tweaked it for my purpose.  Here&#8217;s the result!</p>
<p><img class="aligncenter size-full wp-image-462" title="vfcampaignchart" src="http://sfdc.arrowpointe.com/wp-content/images/vfcampaignchart.png" alt="" width="457" height="238" /></p>
<p>It&#8217;s an embedded VisualForce component in the Results section of my Campaign page.  It shows a quick count for each Member Status that is being used.  To get it going in your org, here&#8217;s what you need.</p>
<p><strong>VisualForce Page</strong></p>
<p>It&#8217;s a simple page containing 1 DIV so that I can set the background color to match that of a Page Layout.  Other than that it&#8217;s just an image returned from <a href="http://code.google.com/apis/chart/">Google Charts</a>.  There is a lot of flexibility with Google Charts.  Therefore, I made it so most of the URL can be tweaked in VisualForce. Only the data values and its labels come from the controller.  This is nice because you can edit VF in a production org, but you can&#8217;t edit Apex.  This will let you change things like width, height, chart colors, chart type, etc.</p>
<pre class="brush: html">

&lt;apex:page standardController=&quot;Campaign&quot; extensions=&quot;VFController_CampaignMemberStatusChart&quot;&gt;
    &lt;style&gt;
        #DIV_Container{padding: 0; margin: 0; background-color: #F3F3EC;}
    &lt;/style&gt;
    &lt;div id=&quot;DIV_Container&quot;&gt;
        &lt;!-- See http://code.google.com/apis/chart/ for more info on customizing the chart --&gt;
        &lt;apex:image url=&quot;http://chart.apis.google.com/chart?cht=p3&amp;chs=1000x125&amp;chf=bg,s,F3F3EC&amp;chco=CC9933{!chartData}&quot;&gt;&lt;/apex:image&gt;
    &lt;/div&gt;
&lt;/apex:page&gt;
</pre>
<p><strong>Apex Controller</strong><br />
The controller is an extension of the Campaign standard controller.  This is so the VisualForce page becomes an option to include on a Campaign Page Layout.  The method that does all the work is getChartData.  It gets the available Campaign Member Statuses and then queries the Campaign Member object for that Campaign and adds a data/label value for each one.  It then returns a query string that you include into the Image src on the Visual Force page.</p>
<p>I am bad at Test classes, but there is 1 in there that passes and should be good enough.  This functionality is pretty harmless.</p>
<pre class="brush: java">
public class VFController_CampaignMemberStatusChart {

	private final Campaign camp;

	public VFController_CampaignMemberStatusChart(ApexPages.StandardController stdController) {
		this.camp = (Campaign)stdController.getRecord();
	}

	public String getChartData() {

		// The list of chart items
		List&lt;ChartDataItem&gt; items = new List&lt;ChartDataItem&gt;();

		// List of valid Campaign Member Statuses for the Campaign
		List&lt;CampaignMemberStatus&gt; list_cms = [select Id, Label from CampaignMemberStatus where CampaignId = :camp.id];

		// Loop through each Campaign Member Status, get a count of Campaign Members and add it to the items list
		for (CampaignMemberStatus cms:list_cms) {
			integer Count = [select count() from CampaignMember where CampaignId = :camp.id AND Status = :cms.Label];
			if (Count &gt; 0) {
				items.add(new ChartDataItem(cms.Label, Count.format()));
			}
		}

		// Initialize Strings
		String chd = &#039;&#039;; // Data
		String chl = &#039;&#039;; // Labels

		for(ChartDataItem citem : items) {
			chd += citem.ItemValue + &#039;,&#039;;
			chl += citem.Label + &#039; (&#039; + citem.ItemValue + &#039;)|&#039;;
		}

		//remove the last comma or pipe
		if (items.size() &gt; 0) {
			chd = chd.substring(0, chd.length() -1);
			chl = chl.substring(0, chl.length() -1);
		}

		// We are only returning the values and labels. The rest of the URL string is in the VF page
		String result = &#039;&amp;chd=t:&#039; + chd + &#039;&amp;chl=&#039; + chl; // &amp;chl returns with labels pointing to pie pieces
		//String result = &#039;&amp;chd=t:&#039; + chd + &#039;&amp;chdl=&#039; + chl; // &amp;chdl returns with labels in a legend

		return result;
	}

	// Class holding each chart data item
	public class ChartDataItem {
		public String ItemValue {get; set;}
		public String Label {get; set;}

		public ChartDataItem(String Label, String Value)
		{
			this.Label = Label;
			this.ItemValue = Value;
		}
	}

	static testMethod void testVFController_Sidebar_Summary() {

		// Create Campaign
        Campaign c = new Campaign();
        c.Name = &#039;Test Campaign&#039;;
        insert c;

        // Create Lead
        Lead l = new Lead();
        l.LastName = &#039;Last Name&#039;;
        l.Company = &#039;Company&#039;;
        insert l;

        // Create Campaign Member
        CampaignMember cms = new CampaignMember();
        cms.CampaignId = c.id;
        cms.LeadId = l.id;
        insert cms;

		test.startTest();

		ApexPages.StandardController sc = new ApexPages.StandardController(c);
		VFController_CampaignMemberStatusChart controller = new VFController_CampaignMemberStatusChart(sc);
		String s1 = controller.getChartData();

		test.stopTest();
	}

}
</pre>
<p><strong>Page Layout</strong><br />
When you add it to the Page Layout, make the height of the component the same as the height you specified in the VF page&#8217;s image src for Google Charts.  In this example, it&#8217;s 125.  Doing this will ensure the background colors match your Page Layout.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=461&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2008/10/31/campaign-member-summary-using-google-charts/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sidebar Summary using Visualforce</title>
		<link>http://sfdc.arrowpointe.com/2008/09/17/sidebar-summary-using-visualforce/</link>
		<comments>http://sfdc.arrowpointe.com/2008/09/17/sidebar-summary-using-visualforce/#comments</comments>
		<pubDate>Thu, 18 Sep 2008 06:11:41 +0000</pubDate>
		<dc:creator>Scott Hemmeter</dc:creator>
				<category><![CDATA[APEX Code]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Arrowpointe Products]]></category>
		<category><![CDATA[Configuration]]></category>
		<category><![CDATA[Sidebar Summary]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Visualforce]]></category>

		<guid isPermaLink="false">http://sfdc.arrowpointe.com/?p=395</guid>
		<description><![CDATA[About a year ago, I posted about the Sidebar Summary.  The Sidebar Summary exists in the Salesforce.com sidebar and displays the counts of some important queries.  The counts are also hyperlinks to a view or report representing that query.  It&#8217;s a very handy thing to have in your sidebar and I use it all the [...]]]></description>
			<content:encoded><![CDATA[<p>About a year ago, I posted about the <a href="http://sfdc.arrowpointe.com/2007/08/28/sidebar-summary/" target="_self">Sidebar Summary</a>.  The Sidebar Summary exists in the Salesforce.com sidebar and displays the counts of some important queries.  The counts are also hyperlinks to a view or report representing that query.  It&#8217;s a very handy thing to have in your sidebar and I use it all the time for my own work.  However, because it&#8217;s an s-Control, it runs a little slow.  In fact, it ran slow enough to make me uncheck the user interface option &#8220;Show Custom Sidebar Components on All Pages&#8221;.</p>
<p style="text-align: center;"><img class="size-full wp-image-398 aligncenter" title="sidebarsummary" src="http://sfdc.arrowpointe.com/wp-content/images/sidebarsummary.png" alt="" width="353" height="310" /></p>
<p>I changed it into a Visualforce page with a custom Apex controller and now it runs super fast and I am able to keep the &#8220;Show Custom Sidebar Components on All Pages&#8221; option turned on and see it on every page I go to.  There&#8217;s a bit of hardcoding in here, but it gets the job done pretty well.  Bye bye s-Control.</p>
<p><span style="text-decoration: underline;"><strong>Visualforce</strong></span></p>
<p>The Page is almost all raw HTML.  The only dynamic thing in there are the count values.  Each one retrieves the value from a specific &#8220;get&#8221; method in the controller.  If you like the queries I use, then the only thing you&#8217;ll need to confirm are the URLs that get linked to.  The first 2 go to Views in my Org and the last 2 go to Reports in my Org.  You&#8217;ll need to change those URLs.</p>
<p>I named the VF Page &#8220;<span id="j_id0:theTemplate:j_id7:j_id8:j_id16:j_id17">SidebarSummary&#8221;.</span></p>
<pre class="brush: html">

&lt;apex:page controller=&quot;VFController_Sidebar_Summary&quot; sidebar=&quot;false&quot; showHeader=&quot;false&quot; standardStylesheets=&quot;true&quot;&gt;
&lt;style type=&quot;text/css&quot; media=&quot;all&quot;&gt;
body{margin: 0; padding: 0; color: #000000; background-color: #E8E8E8;}
#DIV_Container {background-color: #F3F3EC;}
&lt;/style&gt;
&lt;div id=&quot;DIV_Container&quot;&gt;
&lt;table&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;Unread Leads&lt;/em&gt;:  &lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/00Q?fcf=00B30000005JhsT&quot; target=&quot;_parent&quot;&gt;&lt;b&gt;{!UnreadLeads}&lt;/b&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;Leads - Not Contacted&lt;/em&gt;:  &lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/00Q?fcf=00B30000005Jhru&quot; target=&quot;_parent&quot;&gt;&lt;b&gt;{!NotContactedLeads}&lt;/b&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;Oppty - Next 30 Days&lt;/em&gt;:  &lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/00O30000001aEHV&quot; target=&quot;_parent&quot;&gt;&lt;b&gt;{!Next30DayOppty}&lt;/b&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;em&gt;Oppty - Past Due&lt;/em&gt;:  &lt;/td&gt;&lt;td&gt;&lt;a href=&quot;/00O30000001aEHV&quot; target=&quot;_parent&quot;&gt;&lt;b&gt;{!PastDueOppty}&lt;/b&gt;&lt;/a&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;/apex:page&gt;
</pre>
<p><span style="text-decoration: underline;"><strong>Apex</strong></span></p>
<p>The controller has a method for each query to be run.  Each query is a count() query and returns an Integer.  At the end is a really lame Test method, but it does get 100% of the code covered.  I am certain the code works, so I didn&#8217;t do too much with the Test method.  Salesforce just requires the code to be tested.</p>
<pre class="brush: java">

public class VFController_Sidebar_Summary {

public Integer getUnreadLeads() {
return [
select count() from Lead
where IsConverted = False
AND IsUnreadByOwner = TRUE
];
}

public Integer getNotContactedLeads() {
return [
select count() from Lead
where IsConverted = False
AND Status = &#039;Open - Not Contacted&#039;
];
}

public Integer getNext30DayOppty() {
return [
select count() from Opportunity
where IsClosed = False
AND (CloseDate = Next_N_DAYS:30 OR CloseDate = TODAY)
];
}

public Integer getPastDueOppty() {
return [
select count() from Opportunity
where IsClosed = False
AND CloseDate &lt; TODAY
];
}

static testMethod void testVFController_Sidebar_Summary() {
Test.setCurrentPageReference(new PageReference(&#039;Page.SidebarSummary&#039;));
VFController_Sidebar_Summary controller = new VFController_Sidebar_Summary();
Integer i1 = controller.getUnreadLeads();
Integer i2 = controller.getNotContactedLeads();
Integer i3 = controller.getNext30DayOppty();
Integer i4 = controller.getPastDueOppty();
}

}
</pre>
<p><span style="text-decoration: underline;"><strong>Homepage HTML Component</strong></span></p>
<p>I created a component for the Narrow side and put the following HTML into the editor.  Essentially, you create an IFRAME and embed the VF page into it.  I found a (unsupported) trick on the forums to remove the developer bar from a page.  Just add <strong>?core.apexpages.devmode.url=1</strong> to the URL.  This will turn off development mode when that page is rendered.  This is important for this little iFrame page on the sidebar.  From what I&#8217;ve gathered, this hack is not supported and could change at any time.</p>
<p>The code below should work for you.  The only thing you might need to change is the Page URL if you didn&#8217;t name your page SidebarSummary and the height of it.</p>
<pre class="brush: html">

&lt;iframe src=&quot;/apex/SidebarSummary?core.apexpages.devmode.url=1&quot; frameborder=&quot;0&quot; height=&quot;100&quot; width=&quot;100%&quot;&gt;&lt;/iframe&gt;
</pre>
<p>Let me know what you think.</p>
<img src="http://sfdc.arrowpointe.com/?ak_action=api_record_view&id=395&type=feed" alt="" />]]></content:encoded>
			<wfw:commentRss>http://sfdc.arrowpointe.com/2008/09/17/sidebar-summary-using-visualforce/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
	</channel>
</rss>
