# Tuesday, 01 January 2013

Note: Apex can now be called from workflows as Invocable Methods using the Process Builder.

Here is a simple hack to call Apex classes from workflow rules.

Problem: Salesforce has a magnificently declarative environment for creating point-and-click applications and workflows, but one area that gets particularly gnarly is executing business rules in response to changes in state.

Given a problem like "When Opportunity stage equals 'Closed-Won', send the order to the back office system for processing", the Business Analyst has a good idea of "when" the business process should be executed. The Developer knows "how" the process should be executed.

The result is often the development of a trigger that includes both the "when" and "how" logic merged into a single class. The trigger ultimately ends up containing code to detect state changes; a task otherwise best left to workflow rule conditions.

Future enhancements to the business rules require the BA to submit a change request to the Developer, impairing the overall agility of the system.

(Some discussions of detecting record state in trigger can be found here, here, and here.)

The Solution: Calling Apex From Outbound Messages
Empower the System Administrator/BA to create workflow rules that call Apex classes in response to declarative conditions.

Create a workflow rule with an outbound message action that calls a message handler (hosted on Heroku), that in turn calls back to a Salesforce REST resource.

Components of the Outbound Message:

  1. The endpoint URL is hosted on Heroku. The outbound message handler receives the message and issues a callback to Salesforce using the path provided after the root URL.
  2. Pass the session ID to the endpoint (Note: the 'User to send as' must have permissions to call and invoke the Apex REST web service)
  3. Pass only the Id of object meeting the workflow condition. This gets passed back to the REST service as an "oid" parameter (object id).

Getting Started:

Download the Heroku outbound message handler from Github (link).

git clone https://github.com/cubiccompass/sfdc-om-workflow
Build the solution and deploy to Heroku.
mvn package
git init
git commit -am "Initial commit"
heroku apps:create omhandler
git push heroku master
Create a workflow rule with an outbound message action that calls the Heroku hosted endpoint.
Create a Salesforce REST resource for handling the callback.

To see the workflow in action, view the Heroku web service logs while updating records in Salesforce that trigger the workflow rule.
heroku logs -tail

Errata:

IWorkflowTask: In the real world, I'm evolving this design pattern to include an IWorkflowTask interface to clearly distinguish which business objects handle workflow actions. The execute() method takes a WorkflowContext object that includes more details from the outbound message.

Daisy Chaining Workflows: It's important that workflow tasks record or modify some state after executing a task in order to allow for triggering follow-up workflow actions. For example, an OrderProcessor workflow task might update an Order__c status field to "Processed". This allows System Administrators to create follow-up workflow rules/actions, such as sending out emails.

Security: Use HTTPS/SSL endpoints to ensure session information is not subject to man in the middle attacks.

Idempotence: Salesforce does not guarantee that each outbound message will be sent only once (although it's mostly consistent with 1:1 messaging). REST resources should be developed to handle the rare instance where a message might be received twice. In the use case above, the code should be designed to defend against submitting the same order twice; possibly by checking a 'Processed' flag on a record before submitting to a back-office system.

Governor Limits: Workflow tasks are called asynchronously, so there's a decent amount of processing and execution freedom using this pattern.

Tuesday, 01 January 2013 11:57:10 (Pacific Standard Time, UTC-08:00)
# Saturday, 15 December 2012

Technical Architects make many tough decisions on a daily basis, often with incomplete information. Colin Powell's 40-70 rule is helpful when facing such situations.

He says that every time you face a tough decision you should have no less than forty percent and no more than seventy percent of the information you need to make the decision. If you make a decision with less than forty percent of the information you need, then you're shooting from the hip and will make too many mistakes.

The second part of the decision making rule is what surprises many leaders. They often think they need more than seventy percent of the information before they can make a decision. But in reality, if you get more than seventy percent of the information you need to make the decision, then the opportunity to add value has usually passed, or the competition has beaten you to the punch. And with today's agile development and continuous integration (CI) methodologies, you can afford to iterate on an architecture with incomplete information.

A key element that supports Powell’s rule is the notion that intuition is what separates great Technical Architects from average ones. Intuition is what allows us to make tough decisions well, but many of us ignore our gut. We want certainty that we are making the right decision, but that's not possible. People who want certainty in their decisions end up missing opportunities, not leading.

Making decisions with only 40%-70% of the information requires responsibly communicating the technical architecture + how changes will be implemented as more information becomes available.

Architecture + Continuous Integration Process = Agility.

Architecture alone is not a sufficient solution and can leave a solution inflexible to change. "Release early and often" is the new mantra in cloud development.

The best way to manage risk as a TA with 40-70% of the information is to constantly ask yourself 2 questions:
1) What is the simplest possible solution to the current problem?
2) How will future changes be implemented?

Within the realm of Salesforce, a Technical Architecture conducive to CI is achieved primarily through 3 design patterns:
* Declarative configuration
* Custom Settings
* Hybrid apps / Web Tabs / Canvas

1) Declarative configuration. First and foremost, it's the obligation of a TA to maximize the point-and-click configuration of any solution. This is done by using as many out of box features as possible.
2) Custom settings: When coding is required, externalizing the behaviors and conditional branches to custom settings gives System Admins and Business Analysts the ability to fine tune a solution as more information becomes available. For example, rather than hardcoding a callout URL in a trigger, move the URL to a custom setting.
3) Hybrid / Web Tabs / Canvas: For ISVs and custom application development, an IFRAME wrapper to an app hosted on Heroku provides the greatest agility to pivot on a solution. Code changes can be pushed several times per day without having to go through the AppExchange package and review process. Matching the look and feel of Salesforce within a Hybrid or canvas app can provide the best of both worlds; a native Salesforce business application with code managed on a separate platform.

Saturday, 15 December 2012 13:44:55 (Pacific Standard Time, UTC-08:00)
# Wednesday, 28 November 2012

I've published an example of a self-documenting REST API to Github (source).

Why a self-documenting REST API?

A typical REST API sample is hosted at http://restdoc-sample.herokuapp.com/hello, using Heroku's embedded Tomcat Java example.

As a Developer, your initial questions may be:

  • "What does the 'hello' endpoint do?"
  • "Does the endpoint support GET, POST, PUT, DELETE?"
  • "What headers and message body payloads does this endpoint support?"

Fortunately, the RESTDoc project has already defined a specification for documenting REST APIs. The intent of RESTDocs is for each endpoint to support the OPTIONS method and return a structured RESTDoc for the particular API endpoint.

Getting back to the Heroku hosted sample, submitting a curl request for the 'hello' endpoint using the OPTIONS method returns the sample RESTDoc below.

curl -X OPTIONS http://restdoc-sample.herokuapp.com/hello

In addition to supporting the OPTIONS method, the github sample also supports appending '/describe' to any API endpoint to view RESTDocs in web browser. Example: http://restdoc-sample.herokuapp.com/hello/describe.

Standardizing on RESTDocs opens up a number of interesting possibilities. Since transitioning away from SOAP, the web development community has lost the ability to auto-generate object proxies for calling web services. Webhook and Enterprise Service Bus (ESB) platforms have lost the ability to auto-discover web service endpoints and their supported messages.

Self-describing REST APIs, using RESTDocs and the OPTIONS method, are a compelling solution for enabling the service oriented enterprise and integrating the cloud.

	{
	  "schemas" : {
	    "http://some.json/msg" : {
	      "type" : "inline",
	      "schema" : {
	        "type" : "object",
	        "properties" : {
	          "id" : {
	            "type" : "string"
	          },
	          "content" : {
	            "type" : "string"
	          }
	        }
	      }
	    }
	  },
	  // Headers can be described at the server level and/or per-method
	  "headers": {
	    "request": {
	      "Authorization": {
	        "description": "This server uses a custom authentication scheme. See http://myapi.com/docs/auth",
	        "required": true
	      }
	    },
	    "response": {
	      "X-RateLimit-Total": {
	        "description": "The number of API calls allowed per-hour"
	      },
	      "X-RateLimit-Remaining": {
	        "description": "Number of requests remaining until next refill"
	      },
	      "X-RateLimit-Reset": {
	        "description": "The time at which X-RateLimit-Remaining will be reset back to X-RateLimit-Total"
	      }
	    }
	  },
	  "resources": [
	    {
	      "id": "HelloMessage",
	      "description": "An example hello message",
	      "path": "/{locale}/{messageId}{?seasonal}", // representing query params with L3 URI templates
	      "params": { // URI parameters descriptions
	        "locale": {
	          "description": "A standard locale string, e.g. \"en_US.utf-8\"",
	          "validations": [ { "type": "match", "pattern": "[a-z]+(_[A-Z]+)?(\\\\.[a-z-]+)?" } ]
	        },
	        "messageId": {
	          "description": "A free-form message string",
	          "validations": [ { "type": "match", "pattern": "[a-z_]+" } ]
	        },
	        "seasonal": {
	          "description": "Whether the message is seasonal.",
	          "validations": [ { "type": "match", "pattern": "^(true|false|yes|no)$" } ]
	        }
	      },
	      "methods": {
	        "PUT": {
	          "description": "Update or create a message",
	          "statusCodes": { "201": "Created" },
	          "accepts": [   // Representations accepted by the method on this resource.
	            { "type": "text/plain" },
	            { "type": "application/json", "schema": "http://some.json/msg" }
	          ],
	          "headers": { // Request headers only, response headers are defined under 'response'
	            "X-User-Token": {
	              "description": "Used to identify the user creating the message"
	            }
	          },
	          "response": { // Response representations this resource/method provides
	            "types": [
	              { "type": "text/plain" },
	              { "type": "application/json", "schema": "http://some.json/msg" },
	            ],
	            "headers": {
	              "Location": {
	                "description": "The URL of the created message"
	              }
	            }
	          },
	          "examples": [
	            {
	              "path": "/en_US/greeting",
	              "body": "Hello, world!"
	            },
	            {
	              "path": "/en_US/greeting",
	              "headers": {"Content-Type": "application/json"},
	              "body": "{\"id\":\"greeting\",\"content\":\"Hello, world!\"}!"
	            }
	          ]
	        },
	        "GET": {
	          "description": "Retrieve a message",
	          "statusCodes": { 
	             "200": "Message retrieved successfully", 
	             "404": "Message not found"
	          }
	        }
	      }
	    },
	    {
	      // This resource has no human-readable documentation, but still provides some info on how to use it.
	      "id": "FallbackLocale",
	      "path": "/fallback/{locale}",
	      "params": {
	        "locale": { 
	          "validations": [ { "type": "match", "pattern": "[a-z]+(_[A-Z]+)?(\\\\.[a-z-]+)?" } ]
	        }
	      },
	      "methods": {
	        "GET": { "statusCodes": { "200": "OK" } },
	        "PUT": { "statusCodes": { "201": "Created" } }
	      }
	    }
	  ]
	}	
Wednesday, 28 November 2012 09:29:03 (Pacific Standard Time, UTC-08:00)
# Monday, 09 July 2012

Heroku supports running non-web Java processes called "workers". Heroku Workers are an economical solution for executing long running processes, such as waiting for events in a messaging queue.

A worker is basically a Java class that sits in a while loop.

public class WorkerProcess 
{
	public static void main(String[] args)
	{
		while(true) {
			try { 
				Thread.sleep(1000);
			} catch(InterruptedException e) {}            
			System.out.println("Worker process woke up");        
		}
	}    
}

The worker process utilizes its dyno (virtual machine) 100%, therefore is billed at the full rate.

For processes that make asynchronous calls and wait for a response, a single threaded worker can be wasteful. The examples below demonstrate how to spawn several threads within a Heroku Java worker.

public class WorkerProcess
{
	public static void main(String[] args)
	{
		final int MAX_THREADS = 100;
		
		for(int i = 0; i < MAX_THREADS; i++){
			WorkerThread t = new WorkerThread (i);
			new Thread(t).start();
		}
	}
}
public class WorkerThread implements Runnable 
{
	final private int thread_id;

	WorkerThread(int n) 
    {    	
		this.thread_id = n; 
    }
    
    public void run() 
    {
    	while(true){
    		try{
    			System.out.println("Thread " + this.thread_id);
    			//Do something here
    		}
    		catch(Exception e){
    			
    		}
    	}
    }
}
This example of 100 threads runs fine on the Heroku cedar stack. At the time of this writing, Heroku worker threads were bound by memory and not a fixed number of threads.

Resources:
Run non-web Java processes on Heroku
Git repository of Heroku demo (replace the demo classes with the code above in this article)
Monday, 09 July 2012 22:20:59 (Pacific Daylight Time, UTC-07:00)