SlideShare une entreprise Scribd logo
1  sur  22
Télécharger pour lire hors ligne
Process Orchestration using
           Streaming API and Heroku

Andrew Fawcett, FinancialForce.com, CTO
@andyinthecloud
Safe harbor
Safe harbor statement under the Private Securities Litigation Reform Act of 1995:

This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties
materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or
implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking,
including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements
regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded
services or technology developments and customer contracts or use of our services.

The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality
for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results
and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of intellectual property and other
litigation, risks associated with possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating
history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful
customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers.
Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10-
Q for the most recent fiscal quarter ended July 31, 2012. This documents and others containing important disclosures are available on the SEC
Filings section of the Investor Information section of our Web site.

Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available
and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features
that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.
All about FinancialForce.com
                 Leading Native ISV on Force.com

                 • #1 Accounting App on Force.com
                 • #1 Professional Services Automation App on Force.com


                 Backed by Salesforce.com & UNIT4

                 • UNIT4 - $600 million, 33 years building business apps


                 Growing Rapidly

                 • San Francisco HQ – 595 Market St.
                 • 145 Employees
                 • Customers in 23 countries
Andrew Fawcett
CTO
@andyinthecloud
Building declarative applications
Building applications that support Force.com declarative features is critical.
Building applications that consume Force.com declarative features to support your
  app is smart!
     Encourage users admins to use what they have already
         • Building their solution consisting of part your app and part platform features can be a powerful combo!

     Make sure you understand how to be dynamic…
         • Metadata API, Apex Describe
         • Dynamic SOQL, Dynamic Visualforce, Fieldsets
         • Reference Formulas, Rollup Summaries, List Views etc..

     Make your applications metadata portable between orgs!
Consultants love our declarative applications! 
Our user story
As A: System Applications Administrator
I want: To be able to link a series of HTTP / REST based API’s to data changes
   occurring in my organization, based on criteria I provide. Without resorting
   to Apex coding.
So that: I can harness the power of many HTTP / REST based services to
  further automate my companies business processes. And leverage my skills
  as a System Administrator.
Our user case : eBay Integration
     Invoice Number: INV-000001

                                                                                      Process Manager


        eBay Item: 12345678



                                                                                        Streaming API via
                                                                                         Bayeux Protocol
                Overview Salesforce Streaming API via Bayeux Protocol

1.   Create a Push Topic in Force.com
      •     Using the SOQL statement you provide. Salesforce servers will send JSON
            messages to listeners. When changes occur to record data that meet the
            criteria expressed by the SOQL query.Item: 12345678
                                              eBay

2.   Install a Bayeux Client Library
      •     Clients are available from http://cometd.org (none for Apex)
3.   Connect and start Listening!
      •     This sample uses the Java Bayeux library
Live Demonstration
PushTopic (Streaming API)         Name                       Query Select From
      Name                               processchanges             Process__c
      Query
      NotifyForOperations                processlogslinescreated    ProcessLogLine__c
      NotifyForFields                    {Proccess__c.Id}           {SourceObject__c}

               Process__c          /topic/processchanges                                           Process__c Listener
      Name                                                                               On Insert
      SourceObject__c                       ProcessStep__c
                                                                                         1.   Generate PushTopic Query
      When__c                         Name
                                                                                         2.   Create new PushTopic record
      ListViewName__c                 HTMLEndpoint__c
                                                                                         3.   Subscribe via Streaming API
                                      HTMLHeader__c
                                                                                         4.   Start {SourceObject__c} Listener
                                      HTMLMethod__c                     Admin creates
                                                                                         5.   Log to ProcessLogLineItem__c
                                      HTMLBody__c                         Process
ProcessLogLine__c Listener                 ProcessLogLine__c
  Live Log Viewer                     Message__c                                                {SourceObject__c} Listener
      “1. xxxx
       2. xxxx”
                                   /topic/processlogslinescreated
                                                                                         On Update
                                                                                         1.  Read ProcessSteps__c
                    Invoice__c          /topic/{Process__c.Id}                           2.  Read {SourceObject__c}
      Name                                                                               3.  Call {HTMLEndpoint__c} …
      Account__c                                                                         4.  Log to ProcessLogLineItem__c
      Amount__c
      eBayItemNumber__c
      eBayCompleteSaleRequest__c
                                                                        Invoice Clerk
                                                                       updates Invoice   HTTP POST:
                                                                                         <CompleteSaleRequest>
                                                                                           <Item>{!eBayItemNumber}</Item>
                                                                                         </CompleteSaleRequest>
Java Code : Heroku Worker Process
/**
 * Heroku Work Processes are simply Java classes with a main method!
 */

01: public class WorkerProcess
02: {
03: // Salesforce API's
04: private static final String SALESFORCE_API = "25.0";
05: private static final String LOGIN_ENDPOINT = "https://login.salesforce.com/services/Soap/u/" + SALESFORCE_API;
06: private static final String REST_ENDPOINT_URI = "/services/data/v" + SALESFORCE_API + "/";
07: private static final String STREAMING_ENDPOINT_URI = "/cometd/" + SALESFORCE_API;
08:
09: /**
10:   * Main entry point for the Heroku Worker Process
11:   * @param args
12:   * @throws Exception
13:   */
14: public static void main(String[] args) throws Exception
15: {
16:           // Startup and assignment of listeners to Salesforce Streaming API topics…
17: }
Java Code : Process__c Listener
/**
 * Listener : Process__c
 * Comment : Bayeux Client used connect to Streaming API and implement MessageListener interface
 * @see          makeStreamingAPIConnection method
 * @see       JSON class from Jetty
 * @see       processInsert method
 */
01: // Connect to Salesforce Streaming API
02: final BayeuxClient client = makeStreamingAPIConnection(loginResult);
03:
04: // Subscribe to the Process__c topic to listen for new or updated Processes
05: client.getChannel("/topic/processchanges").subscribe(new MessageListener()
06: {
07:          public void onMessage(ClientSessionChannel channel, Message message)
08:          {
09:            HashMap<String, Object> data = (HashMap<String, Object>) JSON.parse(message.toString());
10:            HashMap<String, Object> record = (HashMap<String, Object>) data.get("data");
11:            HashMap<String, Object> sobject = (HashMap<String, Object>) record.get("sobject");
12:            HashMap<String, Object> event = (HashMap<String, Object>) record.get("event");
13:            // Event type, insert or update?
14:            String type = (String) event.get("type");
15:            if(type.equals("created"))
16:                       processInsert(loginResult, client, sobject);
17:          }
18: });
Java Code : Process__c Listener
  Java Code : Process__c                                                                                  Listener
  /**
   * Listener : Process__c
   * Step : Connect and Listen
   *       API connections and message data, used WSC manual login to obtain Metadata API base URL from
   *       LoginResult (not normally exposed by the standard connector classes)
   * @see      makeRestConnection method (Rest URL helper)
   */
  01: // Connection configuration
  02: ConnectorConfig metadataConfig = new ConnectorConfig();
  03: metadataConfig.setSessionId(loginResult.getSessionId());
  04: metadataConfig.setServiceEndpoint(loginResult.getMetadataServerUrl());
  05: MetadataConnection metadataConnection =
  06:          com.sforce.soap.metadata.Connector.newConnection(metadataConfig);
  07:
  08: // Make a REST connection
  09: RestConnection restConnection = makeRestConnection(loginResult);
  10:
  11: // Message data from Proccess__c
  12: String processId = (String) sObject.get("Id");
  13: String processName = (String) sObject.get("Name");
  14: String sourceObject = (String) sObject.get("SourceObject__c");
  15: String listViewName = (String) sObject.get("ListViewName__c");
Java Code : Process__c Listener
  Java Code : Process__c                                                                              Listener
   /**
    * Listener : Process__c
    * Step : Generate PushTopic Query
    * Comment : Retrieve via Metadata API custom object definition to get at the List View
    *       definition for generating PushTopic Query
   */
   01: // Retrieve Custom Object Meta data (and thus List View definition) for Source Object
   02: RetrieveRequest retrieveRequest = new RetrieveRequest();
   03: retrieveRequest.setSinglePackage(true);
   04: com.sforce.soap.metadata.Package packageManifest = new com.sforce.soap.metadata.Package();
   05: ArrayList<PackageTypeMembers> types = new ArrayList<PackageTypeMembers>();
   06: PackageTypeMembers packageTypeMember = new PackageTypeMembers();
   07: packageTypeMember.setName("CustomObject");
   08: packageTypeMember.setMembers(new String[] { sourceObject });
   09: types.add(packageTypeMember);
   10: packageManifest.setTypes((PackageTypeMembers[]) types.toArray(new PackageTypeMembers[] {}));
   11: retrieveRequest.setUnpackaged(packageManifest);
   12: AsyncResult response = metadataConnection.retrieve(retrieveRequest);
   13: while(!response.isDone())
   14: {
   15:          Thread.sleep(1000);
   16:          response = metadataConnection.checkStatus(new String[] { response.getId()} )[0];
   17: }
   18: RetrieveResult retrieveResult = metadataConnection.checkRetrieveStatus(response.getId());
Java Code : Process__c Listener
  Java Code : Process__c                                                                                   Listener
  /**
   * Listener : Process__c
   * Step : Generate PushTopic Query
   * Comment : Uses the WSC TypeMapper to deserialise the Custom Object definition from the
   *         package zip returned by „retrieve‟
   */
  01: // Parse Custom Object metadata for Process Source Object
  02: CustomObject customObject = new CustomObject();
  03: byte[] zipBytes = retrieveResult.getZipFile();
  04: ZipInputStream zipis = new ZipInputStream(new ByteArrayInputStream(zipBytes, 0, zipBytes.length));
  05: ZipEntry zipEntry = null;
  06: while((zipEntry = zipis.getNextEntry()) != null) {
  07:          if(zipEntry.getName().endsWith(sourceObject + ".object")) / Process Source Object?
  08:          {
  09:                       TypeMapper typeMapper = new TypeMapper();
  10:                       XmlInputStream xmlis = new XmlInputStream();
  11:                       xmlis.setInput(zipis, "UTF-8");
  12:                       customObject.load(xmlis, typeMapper);
  13:                       zipis.closeEntry();
  14:                       break;
  15:          }
  16: }
  17: // Find the List View indicated on the Process to define query for Streaming API Push Topic
  18: ListView processlistView = null;
  19: for(ListView listView : customObject.getListViews()) { ... }
Java Code : Process__c Listener
  Java Code : Process__c                                                                            Listener
   /**
    * Listener : Process__c
    * Step : Generate PushTopic Query
    * Comment : Parse List View definition to construct SOQL Query for Push Topic. Code shortened
    *       for this slide.
    */
  01: // Generate SOQL statement for PushTopic based on List View definition
  02: StringBuilder fieldList = new StringBuilder("Id");
  03: for(String field : processlistView.getColumns())
  04:          fieldList.append(", " + field);
  05: // Simple version assumes AND‟s, ignores processListView.getBooleanFilter()
  06: StringBuilder whereClause = new StringBuilder();
  07: for(ListViewFilter lvFilter : processlistView.getFilters())
  08: {
  09:          switch (lvFilter.getOperation())
  10:          {
  11:                       case equals:
  12:                       // ...
  13:          }
  14: }
  15: // Construct SOQL query statement
  16: StringBuilder soql = new StringBuilder()
  17:          .append("select ”) .append(fieldList.toString())
  18:          .append("from ”)          .append(sourceObject + " ")
  19:          .append("where ”)          .append(whereClause.toString());
Java Code : Process__c Listener
  Java Code : Process__c                                                                              Listener
  /**
   * Listener : Process__c
   * Step      : Create PushTopic and subscribe
   * Comment        : PushTopic Name has to be unique thus we used the Process__c.Id.
   *         It is possible to immediately subscribe once the Push Topic has been created!
   * @see         SourceObjectListener class implements MessageListener interface!
   */
  01: // Create PushTopic
  02: PushTopic pushTopic = new PushTopic();
  03: pushTopic.Name = processId;
  04: pushTopic.Query = soql.toString();
  05: pushTopic.ApiVersion = SALESFORCE_API;
  06: pushTopic.NotifyForOperations = "All"; // TODO: Interpret the 'When__c' field from Process__c
  07: pushTopic.NotifyForFields = "Referenced";
  08: restConnection.create(pushTopic);
  09:
  10: // Update Process with Push Topic Name (so that if the worker restarts it can reconnect)
  11: Process__c process = new Process__c();
  12: process.PushTopicName__c = pushTopic.Name;
  13: restConnection.update(process, processId);
  14:
  15: // Start listening on the new Push Topic immediately!
  16: client.getChannel("/topic/"+pushTopic.Name).subscribe(
  17:           new SourceObjectListener(loginResult, processId, sourceObject));
Java Code {SourceObject__c} Listener
 Java Code : : {SourceObject__c} Listener
 /**
  * Listener : {SourceObject__c}
  * Step 1    : Parse Source Object Id from message and read current process steps. Determine what HTTP call
  *         information will be provided by the source object record fields.
  */

 01: public static class SourceObjectListener implements MessageListener
 02: {
 03:         public void onMessage(ClientSessionChannel channel, Message message)
 04:         {
 05:                      // Source Object Message
 06:                      HashMap<String, Object> data = (HashMap<String, Object>) JSON.parse(message.toString());
 07:                      HashMap<String, Object> record = (HashMap<String, Object>) data.get("data");
 08:                      HashMap<String, Object> sobject = (HashMap<String, Object>) record.get("sobject");
 09:                      String sourceId = (String) sobject.get("Id")
 10:                      // Query Process Steps
 11:                QueryResult processStepsResult = m_partnerConnection.query(
 12:                      “select Id, Name, " +
 13:                                              "HTTPEndPoint__c, HTTPEndPointFrom__c, " +
 14:                                   "HTTPMethod__c, HTTPMethodFrom__c, " +
 15:                                   "HTTPHeader__c, HTTPHeaderFrom__c, " +
 16:                                   "HTTPBody__c, HTTPBodyFrom__c " +
 17:                      ”from ProcessStep__c " +
 18:                      "where Process__c = '" + m_processId + "'");
Java Code {SourceObject__c} Listener
 Java Code : : {SourceObject__c} Listener
 /**
  * Listener : {SourceObject__c}
  * Step 2    : Dynamically build query for source object to include fields required
  *         to make HTTP callout contextual
  */
  01: // Construct Source Object SOQL (query formula fields)
  02: StringBuilder fieldList = new StringBuilder();
  03: fieldList.append("Id, Name");
  04: for(String field : sourceFields)
  05:          fieldList.append(", " + field);
  06: StringBuilder soql = new StringBuilder()
  07:          .append("select ")
  08:          .append(fieldList.toString() + " ")
  09:          .append("from ")
  10:          .append(m_sourceObject + " ")
  11:          .append("where ")
  12:          .append("id = '%s'");
  13: String sourceObjectQuery = soql.toString();
  14:
  15: // Query Source Object record
  16: String query = String.format(sourceObjectQuery, sourceId);
  17: QueryResult sourceObjectResult = m_partnerConnection.query(query);
  18: SObject sourceRecord = sourceObjectResult.getRecords()[0];
Java Code {SourceObject__c} Listener
 Java Code : : {SourceObject__c} Listener
  /**
   * Listener : {SourceObject__c}
   * Step 3   : Use Jetty HTTP Client to make callout. HTTP call out details are taken from literals on the step
   *         or from formula fields on the source record
   */
  01: // Create the HTTP client
  02: HttpClient httpClient = new HttpClient();
  03: httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
  04: httpClient.start();
  05: // HTTP parameters
  06: String httpEndpoint = ...
  07: String httpHeader = ...
  08: String httpMethod = ...
  09: String httpBody = ...
  10:         processStep.HTTPBodyFrom__c.equals("Literal") ?
  11:         processStep.HTTPBody__c : (String) sourceRecord.getField(processStep.HTTPBody__c);
  12: // Construct HTTP request
  13: ContentExchange contentExchange = new ContentExchange(true);
  14: contentExchange.setMethod(httpMethod);
  15: contentExchange.setURL(httpEndpoint);
  16: contentExchange.setRequestHeader(...);
  17: contentExchange.setRequestContent(new ByteArrayBuffer(httpBody));
  18: httpClient.send(contentExchange);
  19: contentExchange.waitForDone();
Resources
Java Code : {SourceObject__c} Listener
    • Other // TODO:’s and Ideas?! 
      – Record Types for Process Steps?
      – State / Variables between Steps?
    • Source Code and Contact Details
      GitHub:
      https://github.com/financialforcedev
      Heroku App (Clone):
      https://api.heroku.com/myapps/df12-processmanager/clone
      Twitter: andyinthecloud
DF12 - Process Orchestration using Streaming API and Heroku
DF12 - Process Orchestration using Streaming API and Heroku

Contenu connexe

Tendances

Adapters db-104-informixstoredprocedure
Adapters db-104-informixstoredprocedureAdapters db-104-informixstoredprocedure
Adapters db-104-informixstoredprocedureprathap kumar
 
Java Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application SecurityJava Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application SecurityIMC Institute
 
Integrating dialog flow (api.ai) into qiscus sdk chat application
Integrating dialog flow (api.ai) into qiscus sdk chat applicationIntegrating dialog flow (api.ai) into qiscus sdk chat application
Integrating dialog flow (api.ai) into qiscus sdk chat applicationErick Ranes Akbar Mawuntu
 
Harmony API developers documentation (version 2.2)
Harmony API developers documentation (version 2.2)Harmony API developers documentation (version 2.2)
Harmony API developers documentation (version 2.2)112Motion
 
Apache Aries Blog Sample
Apache Aries Blog SampleApache Aries Blog Sample
Apache Aries Blog SampleSkills Matter
 
Orchard Dynamic Class Extensions
Orchard Dynamic Class ExtensionsOrchard Dynamic Class Extensions
Orchard Dynamic Class Extensionsmarkdolar
 
Java Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAXJava Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAXIMC Institute
 
OrchardCMS module development
OrchardCMS module developmentOrchardCMS module development
OrchardCMS module developmentJay Harris
 

Tendances (10)

JSP Error handling
JSP Error handlingJSP Error handling
JSP Error handling
 
Adapters db-104-informixstoredprocedure
Adapters db-104-informixstoredprocedureAdapters db-104-informixstoredprocedure
Adapters db-104-informixstoredprocedure
 
Java Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application SecurityJava Web Programming [9/9] : Web Application Security
Java Web Programming [9/9] : Web Application Security
 
Intro to flask2
Intro to flask2Intro to flask2
Intro to flask2
 
Integrating dialog flow (api.ai) into qiscus sdk chat application
Integrating dialog flow (api.ai) into qiscus sdk chat applicationIntegrating dialog flow (api.ai) into qiscus sdk chat application
Integrating dialog flow (api.ai) into qiscus sdk chat application
 
Harmony API developers documentation (version 2.2)
Harmony API developers documentation (version 2.2)Harmony API developers documentation (version 2.2)
Harmony API developers documentation (version 2.2)
 
Apache Aries Blog Sample
Apache Aries Blog SampleApache Aries Blog Sample
Apache Aries Blog Sample
 
Orchard Dynamic Class Extensions
Orchard Dynamic Class ExtensionsOrchard Dynamic Class Extensions
Orchard Dynamic Class Extensions
 
Java Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAXJava Web Programming [8/9] : JSF and AJAX
Java Web Programming [8/9] : JSF and AJAX
 
OrchardCMS module development
OrchardCMS module developmentOrchardCMS module development
OrchardCMS module development
 

Similaire à DF12 - Process Orchestration using Streaming API and Heroku

SoftLayer API 12032015
SoftLayer API  12032015SoftLayer API  12032015
SoftLayer API 12032015Nacho Daza
 
Best Practices for Architecting a Pragmatic Web API.
Best Practices for Architecting a Pragmatic Web API.Best Practices for Architecting a Pragmatic Web API.
Best Practices for Architecting a Pragmatic Web API.Mario Cardinal
 
Get things done with Yii - quickly build webapplications
Get things done with Yii - quickly build webapplicationsGet things done with Yii - quickly build webapplications
Get things done with Yii - quickly build webapplicationsGiuliano Iacobelli
 
Creating a World-Class RESTful Web Services API
Creating a World-Class RESTful Web Services APICreating a World-Class RESTful Web Services API
Creating a World-Class RESTful Web Services APIDavid Keener
 
Online Bank Hack
Online Bank HackOnline Bank Hack
Online Bank HackCaleb Sima
 
WSO2Con EU 2015: Extending and Customizing WSO2 API Manager
WSO2Con EU 2015: Extending and Customizing WSO2 API ManagerWSO2Con EU 2015: Extending and Customizing WSO2 API Manager
WSO2Con EU 2015: Extending and Customizing WSO2 API ManagerWSO2
 
InterConnect 2016 Java EE 7 Overview (PEJ-5296)
InterConnect 2016 Java EE 7 Overview (PEJ-5296)InterConnect 2016 Java EE 7 Overview (PEJ-5296)
InterConnect 2016 Java EE 7 Overview (PEJ-5296)Kevin Sutter
 
AspMVC4 start101
AspMVC4 start101AspMVC4 start101
AspMVC4 start101Rich Helton
 
Php and web forms
Php and web formsPhp and web forms
Php and web formssana mateen
 
Yii Framework Security
Yii Framework SecurityYii Framework Security
Yii Framework SecurityIlko Kacharov
 
Repository Pattern in MVC3 Application with Entity Framework
Repository Pattern in MVC3 Application with Entity FrameworkRepository Pattern in MVC3 Application with Entity Framework
Repository Pattern in MVC3 Application with Entity FrameworkAkhil Mittal
 
Introduction to the Client OM in SharePoint 2010
Introduction to the Client OM in SharePoint 2010Introduction to the Client OM in SharePoint 2010
Introduction to the Client OM in SharePoint 2010Ben Robb
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfonyFrancois Zaninotto
 
Bt0083 server side programing
Bt0083 server side programing Bt0083 server side programing
Bt0083 server side programing Techglyphs
 

Similaire à DF12 - Process Orchestration using Streaming API and Heroku (20)

SoftLayer API 12032015
SoftLayer API  12032015SoftLayer API  12032015
SoftLayer API 12032015
 
Best Practices for Architecting a Pragmatic Web API.
Best Practices for Architecting a Pragmatic Web API.Best Practices for Architecting a Pragmatic Web API.
Best Practices for Architecting a Pragmatic Web API.
 
contentDM
contentDMcontentDM
contentDM
 
1z0 591
1z0 5911z0 591
1z0 591
 
Get things done with Yii - quickly build webapplications
Get things done with Yii - quickly build webapplicationsGet things done with Yii - quickly build webapplications
Get things done with Yii - quickly build webapplications
 
Creating a World-Class RESTful Web Services API
Creating a World-Class RESTful Web Services APICreating a World-Class RESTful Web Services API
Creating a World-Class RESTful Web Services API
 
Development withforce
Development withforceDevelopment withforce
Development withforce
 
Online Bank Hack
Online Bank HackOnline Bank Hack
Online Bank Hack
 
WSO2Con EU 2015: Extending and Customizing WSO2 API Manager
WSO2Con EU 2015: Extending and Customizing WSO2 API ManagerWSO2Con EU 2015: Extending and Customizing WSO2 API Manager
WSO2Con EU 2015: Extending and Customizing WSO2 API Manager
 
InterConnect 2016 Java EE 7 Overview (PEJ-5296)
InterConnect 2016 Java EE 7 Overview (PEJ-5296)InterConnect 2016 Java EE 7 Overview (PEJ-5296)
InterConnect 2016 Java EE 7 Overview (PEJ-5296)
 
AspMVC4 start101
AspMVC4 start101AspMVC4 start101
AspMVC4 start101
 
Fwdtechseminars
FwdtechseminarsFwdtechseminars
Fwdtechseminars
 
ELEVATE Paris
ELEVATE ParisELEVATE Paris
ELEVATE Paris
 
flask.pptx
flask.pptxflask.pptx
flask.pptx
 
Php and web forms
Php and web formsPhp and web forms
Php and web forms
 
Yii Framework Security
Yii Framework SecurityYii Framework Security
Yii Framework Security
 
Repository Pattern in MVC3 Application with Entity Framework
Repository Pattern in MVC3 Application with Entity FrameworkRepository Pattern in MVC3 Application with Entity Framework
Repository Pattern in MVC3 Application with Entity Framework
 
Introduction to the Client OM in SharePoint 2010
Introduction to the Client OM in SharePoint 2010Introduction to the Client OM in SharePoint 2010
Introduction to the Client OM in SharePoint 2010
 
Simplify your professional web development with symfony
Simplify your professional web development with symfonySimplify your professional web development with symfony
Simplify your professional web development with symfony
 
Bt0083 server side programing
Bt0083 server side programing Bt0083 server side programing
Bt0083 server side programing
 

Dernier

COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureEric D. Schabell
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemAsko Soukka
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXTarek Kalaji
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfJamie (Taka) Wang
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationIES VE
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Commit University
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6DianaGray10
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Adtran
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-pyJamie (Taka) Wang
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfinfogdgmi
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostMatt Ray
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...DianaGray10
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8DianaGray10
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7DianaGray10
 

Dernier (20)

20150722 - AGV
20150722 - AGV20150722 - AGV
20150722 - AGV
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
OpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability AdventureOpenShift Commons Paris - Choose Your Own Observability Adventure
OpenShift Commons Paris - Choose Your Own Observability Adventure
 
201610817 - edge part1
201610817 - edge part1201610817 - edge part1
201610817 - edge part1
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
Bird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystemBird eye's view on Camunda open source ecosystem
Bird eye's view on Camunda open source ecosystem
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 
VoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBXVoIP Service and Marketing using Odoo and Asterisk PBX
VoIP Service and Marketing using Odoo and Asterisk PBX
 
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
activity_diagram_combine_v4_20190827.pdfactivity_diagram_combine_v4_20190827.pdf
 
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve DecarbonizationUsing IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
Using IESVE for Loads, Sizing and Heat Pump Modeling to Achieve Decarbonization
 
Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)Crea il tuo assistente AI con lo Stregatto (open source python framework)
Crea il tuo assistente AI con lo Stregatto (open source python framework)
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6UiPath Studio Web workshop series - Day 6
UiPath Studio Web workshop series - Day 6
 
Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™Meet the new FSP 3000 M-Flex800™
Meet the new FSP 3000 M-Flex800™
 
20230202 - Introduction to tis-py
20230202 - Introduction to tis-py20230202 - Introduction to tis-py
20230202 - Introduction to tis-py
 
Videogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdfVideogame localization & technology_ how to enhance the power of translation.pdf
Videogame localization & technology_ how to enhance the power of translation.pdf
 
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCostKubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
KubeConEU24-Monitoring Kubernetes and Cloud Spend with OpenCost
 
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
Connector Corner: Extending LLM automation use cases with UiPath GenAI connec...
 
UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8UiPath Studio Web workshop series - Day 8
UiPath Studio Web workshop series - Day 8
 
UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7UiPath Studio Web workshop series - Day 7
UiPath Studio Web workshop series - Day 7
 

DF12 - Process Orchestration using Streaming API and Heroku

  • 1. Process Orchestration using Streaming API and Heroku Andrew Fawcett, FinancialForce.com, CTO @andyinthecloud
  • 2. Safe harbor Safe harbor statement under the Private Securities Litigation Reform Act of 1995: This presentation may contain forward-looking statements that involve risks, uncertainties, and assumptions. If any such uncertainties materialize or if any of the assumptions proves incorrect, the results of salesforce.com, inc. could differ materially from the results expressed or implied by the forward-looking statements we make. All statements other than statements of historical fact could be deemed forward-looking, including any projections of product or service availability, subscriber growth, earnings, revenues, or other financial items and any statements regarding strategies or plans of management for future operations, statements of belief, any statements concerning new, planned, or upgraded services or technology developments and customer contracts or use of our services. The risks and uncertainties referred to above include – but are not limited to – risks associated with developing and delivering new functionality for our service, new products and services, our new business model, our past operating losses, possible fluctuations in our operating results and rate of growth, interruptions or delays in our Web hosting, breach of our security measures, the outcome of intellectual property and other litigation, risks associated with possible mergers and acquisitions, the immature market in which we operate, our relatively limited operating history, our ability to expand, retain, and motivate our employees and manage our growth, new releases of our service and successful customer deployment, our limited history reselling non-salesforce.com products, and utilization and selling to larger enterprise customers. Further information on potential factors that could affect the financial results of salesforce.com, inc. is included in our annual report on Form 10- Q for the most recent fiscal quarter ended July 31, 2012. This documents and others containing important disclosures are available on the SEC Filings section of the Investor Information section of our Web site. Any unreleased services or features referenced in this or other presentations, press releases or public statements are not currently available and may not be delivered on time or at all. Customers who purchase our services should make the purchase decisions based upon features that are currently available. Salesforce.com, inc. assumes no obligation and does not intend to update these forward-looking statements.
  • 3. All about FinancialForce.com Leading Native ISV on Force.com • #1 Accounting App on Force.com • #1 Professional Services Automation App on Force.com Backed by Salesforce.com & UNIT4 • UNIT4 - $600 million, 33 years building business apps Growing Rapidly • San Francisco HQ – 595 Market St. • 145 Employees • Customers in 23 countries
  • 5. Building declarative applications Building applications that support Force.com declarative features is critical. Building applications that consume Force.com declarative features to support your app is smart!  Encourage users admins to use what they have already • Building their solution consisting of part your app and part platform features can be a powerful combo!  Make sure you understand how to be dynamic… • Metadata API, Apex Describe • Dynamic SOQL, Dynamic Visualforce, Fieldsets • Reference Formulas, Rollup Summaries, List Views etc..  Make your applications metadata portable between orgs! Consultants love our declarative applications! 
  • 6. Our user story As A: System Applications Administrator I want: To be able to link a series of HTTP / REST based API’s to data changes occurring in my organization, based on criteria I provide. Without resorting to Apex coding. So that: I can harness the power of many HTTP / REST based services to further automate my companies business processes. And leverage my skills as a System Administrator.
  • 7. Our user case : eBay Integration Invoice Number: INV-000001 Process Manager eBay Item: 12345678 Streaming API via Bayeux Protocol Overview Salesforce Streaming API via Bayeux Protocol 1. Create a Push Topic in Force.com • Using the SOQL statement you provide. Salesforce servers will send JSON messages to listeners. When changes occur to record data that meet the criteria expressed by the SOQL query.Item: 12345678 eBay 2. Install a Bayeux Client Library • Clients are available from http://cometd.org (none for Apex) 3. Connect and start Listening! • This sample uses the Java Bayeux library
  • 9. PushTopic (Streaming API) Name Query Select From Name processchanges Process__c Query NotifyForOperations processlogslinescreated ProcessLogLine__c NotifyForFields {Proccess__c.Id} {SourceObject__c} Process__c /topic/processchanges Process__c Listener Name On Insert SourceObject__c ProcessStep__c 1. Generate PushTopic Query When__c Name 2. Create new PushTopic record ListViewName__c HTMLEndpoint__c 3. Subscribe via Streaming API HTMLHeader__c 4. Start {SourceObject__c} Listener HTMLMethod__c Admin creates 5. Log to ProcessLogLineItem__c HTMLBody__c Process ProcessLogLine__c Listener ProcessLogLine__c Live Log Viewer Message__c {SourceObject__c} Listener “1. xxxx 2. xxxx” /topic/processlogslinescreated On Update 1. Read ProcessSteps__c Invoice__c /topic/{Process__c.Id} 2. Read {SourceObject__c} Name 3. Call {HTMLEndpoint__c} … Account__c 4. Log to ProcessLogLineItem__c Amount__c eBayItemNumber__c eBayCompleteSaleRequest__c Invoice Clerk updates Invoice HTTP POST: <CompleteSaleRequest> <Item>{!eBayItemNumber}</Item> </CompleteSaleRequest>
  • 10. Java Code : Heroku Worker Process /** * Heroku Work Processes are simply Java classes with a main method! */ 01: public class WorkerProcess 02: { 03: // Salesforce API's 04: private static final String SALESFORCE_API = "25.0"; 05: private static final String LOGIN_ENDPOINT = "https://login.salesforce.com/services/Soap/u/" + SALESFORCE_API; 06: private static final String REST_ENDPOINT_URI = "/services/data/v" + SALESFORCE_API + "/"; 07: private static final String STREAMING_ENDPOINT_URI = "/cometd/" + SALESFORCE_API; 08: 09: /** 10: * Main entry point for the Heroku Worker Process 11: * @param args 12: * @throws Exception 13: */ 14: public static void main(String[] args) throws Exception 15: { 16: // Startup and assignment of listeners to Salesforce Streaming API topics… 17: }
  • 11. Java Code : Process__c Listener /** * Listener : Process__c * Comment : Bayeux Client used connect to Streaming API and implement MessageListener interface * @see makeStreamingAPIConnection method * @see JSON class from Jetty * @see processInsert method */ 01: // Connect to Salesforce Streaming API 02: final BayeuxClient client = makeStreamingAPIConnection(loginResult); 03: 04: // Subscribe to the Process__c topic to listen for new or updated Processes 05: client.getChannel("/topic/processchanges").subscribe(new MessageListener() 06: { 07: public void onMessage(ClientSessionChannel channel, Message message) 08: { 09: HashMap<String, Object> data = (HashMap<String, Object>) JSON.parse(message.toString()); 10: HashMap<String, Object> record = (HashMap<String, Object>) data.get("data"); 11: HashMap<String, Object> sobject = (HashMap<String, Object>) record.get("sobject"); 12: HashMap<String, Object> event = (HashMap<String, Object>) record.get("event"); 13: // Event type, insert or update? 14: String type = (String) event.get("type"); 15: if(type.equals("created")) 16: processInsert(loginResult, client, sobject); 17: } 18: });
  • 12. Java Code : Process__c Listener Java Code : Process__c Listener /** * Listener : Process__c * Step : Connect and Listen * API connections and message data, used WSC manual login to obtain Metadata API base URL from * LoginResult (not normally exposed by the standard connector classes) * @see makeRestConnection method (Rest URL helper) */ 01: // Connection configuration 02: ConnectorConfig metadataConfig = new ConnectorConfig(); 03: metadataConfig.setSessionId(loginResult.getSessionId()); 04: metadataConfig.setServiceEndpoint(loginResult.getMetadataServerUrl()); 05: MetadataConnection metadataConnection = 06: com.sforce.soap.metadata.Connector.newConnection(metadataConfig); 07: 08: // Make a REST connection 09: RestConnection restConnection = makeRestConnection(loginResult); 10: 11: // Message data from Proccess__c 12: String processId = (String) sObject.get("Id"); 13: String processName = (String) sObject.get("Name"); 14: String sourceObject = (String) sObject.get("SourceObject__c"); 15: String listViewName = (String) sObject.get("ListViewName__c");
  • 13. Java Code : Process__c Listener Java Code : Process__c Listener /** * Listener : Process__c * Step : Generate PushTopic Query * Comment : Retrieve via Metadata API custom object definition to get at the List View * definition for generating PushTopic Query */ 01: // Retrieve Custom Object Meta data (and thus List View definition) for Source Object 02: RetrieveRequest retrieveRequest = new RetrieveRequest(); 03: retrieveRequest.setSinglePackage(true); 04: com.sforce.soap.metadata.Package packageManifest = new com.sforce.soap.metadata.Package(); 05: ArrayList<PackageTypeMembers> types = new ArrayList<PackageTypeMembers>(); 06: PackageTypeMembers packageTypeMember = new PackageTypeMembers(); 07: packageTypeMember.setName("CustomObject"); 08: packageTypeMember.setMembers(new String[] { sourceObject }); 09: types.add(packageTypeMember); 10: packageManifest.setTypes((PackageTypeMembers[]) types.toArray(new PackageTypeMembers[] {})); 11: retrieveRequest.setUnpackaged(packageManifest); 12: AsyncResult response = metadataConnection.retrieve(retrieveRequest); 13: while(!response.isDone()) 14: { 15: Thread.sleep(1000); 16: response = metadataConnection.checkStatus(new String[] { response.getId()} )[0]; 17: } 18: RetrieveResult retrieveResult = metadataConnection.checkRetrieveStatus(response.getId());
  • 14. Java Code : Process__c Listener Java Code : Process__c Listener /** * Listener : Process__c * Step : Generate PushTopic Query * Comment : Uses the WSC TypeMapper to deserialise the Custom Object definition from the * package zip returned by „retrieve‟ */ 01: // Parse Custom Object metadata for Process Source Object 02: CustomObject customObject = new CustomObject(); 03: byte[] zipBytes = retrieveResult.getZipFile(); 04: ZipInputStream zipis = new ZipInputStream(new ByteArrayInputStream(zipBytes, 0, zipBytes.length)); 05: ZipEntry zipEntry = null; 06: while((zipEntry = zipis.getNextEntry()) != null) { 07: if(zipEntry.getName().endsWith(sourceObject + ".object")) / Process Source Object? 08: { 09: TypeMapper typeMapper = new TypeMapper(); 10: XmlInputStream xmlis = new XmlInputStream(); 11: xmlis.setInput(zipis, "UTF-8"); 12: customObject.load(xmlis, typeMapper); 13: zipis.closeEntry(); 14: break; 15: } 16: } 17: // Find the List View indicated on the Process to define query for Streaming API Push Topic 18: ListView processlistView = null; 19: for(ListView listView : customObject.getListViews()) { ... }
  • 15. Java Code : Process__c Listener Java Code : Process__c Listener /** * Listener : Process__c * Step : Generate PushTopic Query * Comment : Parse List View definition to construct SOQL Query for Push Topic. Code shortened * for this slide. */ 01: // Generate SOQL statement for PushTopic based on List View definition 02: StringBuilder fieldList = new StringBuilder("Id"); 03: for(String field : processlistView.getColumns()) 04: fieldList.append(", " + field); 05: // Simple version assumes AND‟s, ignores processListView.getBooleanFilter() 06: StringBuilder whereClause = new StringBuilder(); 07: for(ListViewFilter lvFilter : processlistView.getFilters()) 08: { 09: switch (lvFilter.getOperation()) 10: { 11: case equals: 12: // ... 13: } 14: } 15: // Construct SOQL query statement 16: StringBuilder soql = new StringBuilder() 17: .append("select ”) .append(fieldList.toString()) 18: .append("from ”) .append(sourceObject + " ") 19: .append("where ”) .append(whereClause.toString());
  • 16. Java Code : Process__c Listener Java Code : Process__c Listener /** * Listener : Process__c * Step : Create PushTopic and subscribe * Comment : PushTopic Name has to be unique thus we used the Process__c.Id. * It is possible to immediately subscribe once the Push Topic has been created! * @see SourceObjectListener class implements MessageListener interface! */ 01: // Create PushTopic 02: PushTopic pushTopic = new PushTopic(); 03: pushTopic.Name = processId; 04: pushTopic.Query = soql.toString(); 05: pushTopic.ApiVersion = SALESFORCE_API; 06: pushTopic.NotifyForOperations = "All"; // TODO: Interpret the 'When__c' field from Process__c 07: pushTopic.NotifyForFields = "Referenced"; 08: restConnection.create(pushTopic); 09: 10: // Update Process with Push Topic Name (so that if the worker restarts it can reconnect) 11: Process__c process = new Process__c(); 12: process.PushTopicName__c = pushTopic.Name; 13: restConnection.update(process, processId); 14: 15: // Start listening on the new Push Topic immediately! 16: client.getChannel("/topic/"+pushTopic.Name).subscribe( 17: new SourceObjectListener(loginResult, processId, sourceObject));
  • 17. Java Code {SourceObject__c} Listener Java Code : : {SourceObject__c} Listener /** * Listener : {SourceObject__c} * Step 1 : Parse Source Object Id from message and read current process steps. Determine what HTTP call * information will be provided by the source object record fields. */ 01: public static class SourceObjectListener implements MessageListener 02: { 03: public void onMessage(ClientSessionChannel channel, Message message) 04: { 05: // Source Object Message 06: HashMap<String, Object> data = (HashMap<String, Object>) JSON.parse(message.toString()); 07: HashMap<String, Object> record = (HashMap<String, Object>) data.get("data"); 08: HashMap<String, Object> sobject = (HashMap<String, Object>) record.get("sobject"); 09: String sourceId = (String) sobject.get("Id") 10: // Query Process Steps 11: QueryResult processStepsResult = m_partnerConnection.query( 12: “select Id, Name, " + 13: "HTTPEndPoint__c, HTTPEndPointFrom__c, " + 14: "HTTPMethod__c, HTTPMethodFrom__c, " + 15: "HTTPHeader__c, HTTPHeaderFrom__c, " + 16: "HTTPBody__c, HTTPBodyFrom__c " + 17: ”from ProcessStep__c " + 18: "where Process__c = '" + m_processId + "'");
  • 18. Java Code {SourceObject__c} Listener Java Code : : {SourceObject__c} Listener /** * Listener : {SourceObject__c} * Step 2 : Dynamically build query for source object to include fields required * to make HTTP callout contextual */ 01: // Construct Source Object SOQL (query formula fields) 02: StringBuilder fieldList = new StringBuilder(); 03: fieldList.append("Id, Name"); 04: for(String field : sourceFields) 05: fieldList.append(", " + field); 06: StringBuilder soql = new StringBuilder() 07: .append("select ") 08: .append(fieldList.toString() + " ") 09: .append("from ") 10: .append(m_sourceObject + " ") 11: .append("where ") 12: .append("id = '%s'"); 13: String sourceObjectQuery = soql.toString(); 14: 15: // Query Source Object record 16: String query = String.format(sourceObjectQuery, sourceId); 17: QueryResult sourceObjectResult = m_partnerConnection.query(query); 18: SObject sourceRecord = sourceObjectResult.getRecords()[0];
  • 19. Java Code {SourceObject__c} Listener Java Code : : {SourceObject__c} Listener /** * Listener : {SourceObject__c} * Step 3 : Use Jetty HTTP Client to make callout. HTTP call out details are taken from literals on the step * or from formula fields on the source record */ 01: // Create the HTTP client 02: HttpClient httpClient = new HttpClient(); 03: httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); 04: httpClient.start(); 05: // HTTP parameters 06: String httpEndpoint = ... 07: String httpHeader = ... 08: String httpMethod = ... 09: String httpBody = ... 10: processStep.HTTPBodyFrom__c.equals("Literal") ? 11: processStep.HTTPBody__c : (String) sourceRecord.getField(processStep.HTTPBody__c); 12: // Construct HTTP request 13: ContentExchange contentExchange = new ContentExchange(true); 14: contentExchange.setMethod(httpMethod); 15: contentExchange.setURL(httpEndpoint); 16: contentExchange.setRequestHeader(...); 17: contentExchange.setRequestContent(new ByteArrayBuffer(httpBody)); 18: httpClient.send(contentExchange); 19: contentExchange.waitForDone();
  • 20. Resources Java Code : {SourceObject__c} Listener • Other // TODO:’s and Ideas?!  – Record Types for Process Steps? – State / Variables between Steps? • Source Code and Contact Details GitHub: https://github.com/financialforcedev Heroku App (Clone): https://api.heroku.com/myapps/df12-processmanager/clone Twitter: andyinthecloud

Notes de l'éditeur

  1. Rehab Breakfast on Friday, talking to people in the area for roles we have open, come along even if your tired! ;-)Expanding Development Group, adding Development Team in SFIndustrial Strength Applications
  2. - Mention platform Flow and Workflow differences and capabilities vs this solution.
  3. Timing: 6 minutes
  4. Timing: 2 minutes
  5. Timing: Code Walkthrough 8 minutes
  6. Timing: Code Walkthrough 8 minutes
  7. Timing: Code Walkthrough 8 minutes
  8. Timing: Code Walkthrough 8 minutes
  9. Timing: Code Walkthrough 8 minutes
  10. Timing: Code Walkthrough 8 minutes
  11. Timing: Code Walkthrough 8 minutes
  12. Timing: Code Walkthrough 8 minutes
  13. Timing: Code Walkthrough 8 minutes
  14. Timing: Code Walkthrough 8 minutes
  15. Timing: Code Walkthrough 8 minutes