Friday 18 October 2013

Simplifying the way to understand Dynamic Apex in Salesforce: Part - 3


Keeping the momentum with the previous two blog-posts Part - 1 and Part - 2 , here I would like to cover the way to write Dynamic SOQL/SOSL/DML.

Creation of SOQL/SOSL/SObjects at the runtime with Apex code is referred to as Dynamic SOQL/SOSL/DML which can be used to create more flexible applications like creating a search based on end user's input.

DYNAMIC SOQL

Database query methods are used to create a dynamic SOQL.

Example:

                  Return a single sObject when query comes back with one record
                   sObject s = Database.query(query_string_limit_1);

                  Return a list of sObjects when query comes back with more than one record
                   List listSObject = Database.query(query_string);

Points to remember(SOQL)

  • We can use simple bind variables in dynamic SOQL query strings.
          String sTestString = 'Test Name';          
          List listSObject = Database.query('Select Id from MyCustomObject__c where Name =: sTestString');

  • Unlike inline SOQL, Dynamic SOQL can't use bind variable fields in the query string.

          MyCustomObject__c oCustomObject = new MyCustomObject__c(field1__c = 'TestField');
          List listSObject = Database.query('Select Id from MyCustomObject__c  where field1__c =: oCustomObject.field1__c'); 


          MyCustomObject__c oCustomObject = new MyCustomObject__c(field1__c = 'TestField');
          String myField = oCustomObject.field1__c;
          List listSObject = Database.query('Select Id from MyCustomObject__c  where field1__c =' + myField'); 


DYNAMIC SOSL

Search query  methods are used to create a dynamic SOSL.

Example:

          List> myQuery = search.query(SOSL_search_string);

          String searchquery = 'FIND \'Edge*\' IN ALL FIELDS RETURNING Account(id,name),Contact, Lead';
          List> searchList = search.query(searchquery);


Points to remember(SOSL)

  • Dynamic SOSL statements evaluate to a list of lists of sObjects, where each list contains the search results for a particular sObject type.
  • The result lists are always returned in the same order as they were specified in the dynamic SOSL query.
  • From the example above, the results from Account are first, then Contact, then Lead.


DYNAMIC DML

We can also create sObjects dynamically and insert them into the database using DML.

Example

//Get a new Account
Account A = new Account();
//Get the token for that Account
Schema.sObjectType tokenA = oAccount.getSObjectType();
// Error because the token is a generic object, not ac Account
Account B = tokenA.newSObject(); 
//Correct way
Account B = (Account) tokenA.newSObject(); 


public class DynamicSObjectCreation{

     public static SObject createObject(String sObjectTypeName){
          Schema.SObjectType objectType = Schema.getGlobalDescribe().get(sObjectTypeName);
          if(objectType == null){
              // throw an exception
          }
         // instantiate an SObject with the type passed in as an argument at run time
          return objectType.newSObject();
     }
}

Points to remember(DML)

  • To create a new sObject of a given type, use the newSObject() method on an sObject token.
  • The token must be cast into a concrete sObject type (such as Account).

Wednesday 16 October 2013

Simplifying the way to understand Dynamic Apex in Salesforce: Part - 2

With reference to the knowledge sharing in my previous blog Simplifying the way to understand Dynamic Apex in Salesforce: Part - 1 I would like to cover the further concepts in a more simplified way.











Simplifying the way to understand Dynamic Apex in Salesforce: Part - 1

From the very beginning, Dynamic Apex had been difficult for me to understand. This time I thought of going slowly through it and thereby finding a simple way to understand its basic implementation first.
Since I do this now, it's worth sharing here. 

Dynamic Apex implementation in Salesforce focuses on four major areas:

  • Apex Describe Information
  • Dynamic SOQL
  • Dynamic SOSL
  • Dynamic DML

Image1: Showing different attributes constituting the Apex Describe Information




Image2: Showing two different ways to access token for sObject and Field separately





Image3: Showing two different ways to access Describe Result for sObject and Field separately



Thursday 10 October 2013

Generate/Parse XML content using the Apex DOM classes

Working on Order Capture has made me explore lots of new Salesforce concepts which were unknown to me. In one of the Apex classes, we were framing HTTP request and also parsing HTTP response using the DOM classes. I was unaware of it. It exhorted me to dive deep into it and share among the other people here on The Hub.. 

Introduction

The DOM represents an XML document as a hierarchy of nodes. Some nodes may be branch nodes and have child nodes, while others are leaf nodes with no children.Apex provides classes that enable you to work with XML content using the DOM (Document Object Model).DOM classes help you parse or generate XML content.
Common Usage of DOM:  to generate the body of a request created by HttpRequest or to parse a response accessed by HttpResponse.

  • Use the Document Class to process the content in the body of the XML document.
  • Use the XmlNode Class to work with a node in the XML document.

Take an example (Parsing an XML content)

Considering this as the XML response:



The following example illustrates how to use DOM classes to parse the above XML response returned in the body of a GET request:

public class DomDocument {

    // Pass in the URL for the request
    // For the purposes of this sample,assume that the URL
    // returns the XML shown above in the response body
    public void parseResponseDom(String url){
        Http h = new Http();
        HttpRequest req = new HttpRequest();
       // url that returns the XML in the response body
        req.setEndpoint(url);
        req.setMethod('GET');
        HttpResponse res = h.send(req);
        Dom.Document doc = res.getBodyDocument();

       //Retrieve the root element for this document.
        Dom.XMLNode address = doc.getRootElement();

        String name = address.getChildElement('name', null).getText();
        String state = address.getChildElement('state', null).getText();
        // print out specific elements
        System.debug('Name: ' + name);
        System.debug('State: ' + state);

        // Alternatively, loop through the child elements.
        // This prints out all the elements of the address
        for(Dom.XMLNode child : address.getChildElements()) {
           System.debug(child.getText());
        }
    }
}


Take an example (Generating an XML content)

public class DomNamespaceSample
{

    public void sendRequest(String endpoint)
    {

        String soapNS = 'http://schemas.xmlsoap.org/soap/envelope/';
       String servicePrefix ='glob';
        String serviceNS = 'http://www.myservice.com/services/MyService/';
     
       // Create the request envelope
        DOM.Document doc = new DOM.Document();
        dom.XmlNode envelope = doc.createRootElement('Envelope', soapNS, 'soapenv');
        envelope.setNamespace(servicePrefix, serviceNS);
     
        dom.XmlNode body = envelope.addChildElement('Body', soapNS, null);     
        body.addChildElement('echo', serviceNS, 'req').addChildElement('category', serviceNS, null).addTextNode('classifieds');
     
        System.debug('Request XML:' + doc.toXmlString());
     


        // Send the request
        HttpRequest req = new HttpRequest();
        req.setMethod('POST');
        req.setEndpoint(endpoint);
        req.setHeader('Content-Type', 'text/xml');      
        req.setBodyDocument(doc);
     
        Http http = new Http();
        HttpResponse res = http.send(req);
     
        System.assertEquals(200, res.getStatusCode());
     
        dom.Document resDoc = res.getBodyDocument();      
        envelope = resDoc.getRootElement();

        System.assertEquals('classifieds', envelope.getChildElement('Body', soapNS).getChildElement('echo', serviceNS).getChildElement('category', serviceNS).getText());
    }
}


Useful Quicklinks


Happy Apex Coding! 


Wednesday 9 October 2013

Understanding Inbound Email Services in Salesforce

Use of Inbound Email Service in one of my projects named Order Capture triggered my attention to know more deeply about this awesome process provided by Salesforce. So today I took some time to know about it and share it here.
As a part of Order Capture, in a nutshell, when we are creating/updating an Opportunity on a Prospect Account, the following steps happen:

     Workflow Rule --> Email Alert --> Inbound Email Service --> Execute an Apex Class --> Create a Prospect/Customer Account in SAP CRM

Moving forward, I would like to go through some of the basic steps which we follow while implementing Inbound Email Service in Salesforce.

An Introduction

Email services are one of the important Force.com processes that use Apex classes to process incoming email messages. When we set up an email service, we could generate a special email address on which Force.com will receive your emails. You also supply an Apex class adhering to a particular interface. The email services will then invoke a method on the Apex class whenever an email is received on the email address.Since they result in Apex logic being executed, the emails can be made to invoke any number of actions.

The rest of this section shows an example how to set up your inbound email service and write a simple Apex class to react to incoming email. Setting up an email service is simple:

  •   Build an inbound email handler Apex class for processing the email
  •   Configure the email service, binding it to the Apex class

Inbound Email Handler

An Apex class that acts as an inbound email handler simply needs to implement the Messaging.InboundEmailHandler interface.
The interface defines a single method: Messaging.InboundEmailResult handleInboundEmail(Messaging.inboundEmail email, Messaging.InboundEnvelope envelope)
The message contents are available through the email argument, and the envelope stores the to and from address.

  This example processes incoming email as follows:

  •        Create a new Account record with the email subject as the account name
  •        Save the text and binary attachments
  •        Store the email body as a note

First, the class implements the Messaging.InboundEmailHandler interface, and all the activity happens in the handleInboundEmail() method.

global class EmailDemoReceive implements Messaging.InboundEmailHandler {
  global Messaging.InboundEmailResult handleInboundEmail(Messaging.InboundEmail email, Messaging.Inboundenvelope envelope) {
     Account account;
     Messaging.InboundEmailResult result = new Messaging.InboundEmailResult();

          try {
          The email and envelope arguments have several public attributes you can access directly. First, let’s grab the email’s subject and create a new account record if it doesn’t already exist.
           // Look for account whose name is the subject and create it if necessary
                 if ([select count() from Account where Name =:email.subject] == 0) {
                       account = new Account();
                       account.Name = email.subject;
                       insert account;
                 } else {
                       account = [select Id from Account where Name =:email.subject];
                 }

       You can even access text and binary attachments:

       // Save attachments, if any
       for (Messaging.Inboundemail.TextAttachment tAttachment : email.textAttachments) {
             Attachment attachment = new Attachment(); 
             attachment.Name = tAttachment.fileName;
             attachment.Body = Blob.valueOf(tAttachment.body);
             attachment.ParentId = account.Id;
             insert attachment;
       }
       for (Messaging.Inboundemail.BinaryAttachment bAttachment : email.binaryAttachments) {
             Attachment attachment = new Attachment();
           attachment.Name = bAttachment.fileName;
            attachment.Body = bAttachment.body;
             attachment.ParentId = account.Id;
             insert attachment;
       }

       And of course, you can access the body of an email as well. In this case we’re assuming a plain email (not an HTML one) and use the plainTextBody field:

       // Turn email body into note
       Note note = new Note();
       note.Title = email.fromName + ' (' + DateTime.now() + ')';
       note.Body = email.plainTextBody;
       note.ParentId = account.Id;
       insert note;

       Here we explicitly indicate success or failure by setting the success field of our InboundEmailResult object.

      result.success = true;
     } catch (Exception e) {
           result.success = false;
           result.message = ‘Oops, I failed.’
    }

    return result;
  }
}


If a failure was indicated (if the success field is set to false) then the platform automatically rejects the inbound email and sends a reply email to the original sender containing the message specified in the message field.

Email Service

Next, you need to define the email service. This establishes an email address, which you can then tie to the Apex class that you’ve just written. Define the email service by logging into your environment:

  • Log into Force.com and select on Setup->App Setup->Develop->Email Services
  • Select New Email Service. You’ll see a screen:

          Give a name for Email Service Name, like say “EmailDemoReceive”
            For Apex Class, specify the Apex class you just built
            You can leave the rest of the fields at their default values for starters
            Hit Save

            That’s it, you’ve created your first email service. But you still need to generate an email address on which Force.com will listen for incoming emails. To do that, select New Email Address and fill as follows:

            Choose an id for Email address. This can be anything, like say "invoices" if you plan to process invoices with this address.
            Check Active.
            Set Context User – this specifies the context under which the Apex class will run. It defaults to you, but you’re free to pick another user from your organization.
            For Accept Emails From, give a comma-separated list of addresses (a@b.com) or domains (b.com) that Email Services can accept emails from. If you leave it blank, all addresses will work.
            Hit Save


  You will see a new email address that Force.com will monitor: emails received on this address will trigger the associated Apex code.

  That’s it! Any email sent to the above email address will now result in the Apex class being executed.

To Sum Up

In summary, to handle inbound emails all you have to do is:

  •      Create an Apex class that implements Messaging.InboundEmailHandler
  •      Create an email service that binds to that Apex class
  •      Create one or more email addresses, associated with the email service

In order to leverage the Inbound Email Service, for instance, we could create Contacts from the CC-ed part of Email. At that time, the following objects could be useful.


Happy Apex Coding!