Wednesday, June 6, 2012

How to Schedule job from Schedule Job

Salesforce only adds the process to the queue at the scheduled time. Actual execution may be delayed based on service availability.

You can only have 25 classes scheduled at one time. You can evaluate your current count by viewing the Scheduled Jobs page in Salesforce or programmatically using SOAP API to query the CronTrigger object.

When we schedule a class, cron expression plays an important role to decide the next scheduled time of the class. Please refer the following link for more details about cron expression. http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_scheduler.htm

In the below code sample the cron expression is built in such a way so that it will not schedule the job in future.I have used the year parameter in cron expression which will not schedule the same class again.

global class scheduledJobController implements Schedulable{
   global void execute(SchedulableContext SC) {
       try {
         // TO DO LOGIC
       }
       catch(Exception e) {
         // TO DO Log error
       }
       finally {
            Datetime currentTime = datetime.now();
            Datetime newTime = currentTime.addSeconds(20);
            // build cron expression
            String sch= String.valueOf(newtime.second()) +' ' + String.valueOf(newtime.minute()) + ' ' + String.valueOf(newTime.hour()) + ' ' + String.valueOf(newTime.day()) + ' ' + String.valueOf(newTime.month()) + ' ? ' +  String.valueOf(newTime.year());
            scheduledJobController scheduleObject = new scheduledJobController();
            Id sId = system.schedule('scheduledJobController'+newTime , sch, scheduleObject );  
       }
   }
}

Monday, June 4, 2012

Apex Describe support for Fieldsets

Visualforce dynamic bindings have supported field sets for some time. In Summer ’12, Apex provides describe support for field sets, which makes it possible to dynamically generate the SOQL necessary to load all fields in a field set. This makes field sets easier to use in Visualforce pages that use custom controllers.

This sample uses Schema.FieldSet and Schema.FieldSetMember methods to dynamically get all the fields in the ContactInfo field set for the Contact object. The list of fields is then used to construct a SOQL query that ensures those fields are available for display. The Visualforce page uses this class as its controller.

public class ContactDetails{
    public Contact con { get; set; }
    public ContactDetails() {
        this.con = getContactDetails();
    }
    public List getFields() {
        return SObjectType.Contact.FieldSets.ContactInfo.getFields();
    }
    private Contact getContactDetails() {
        String query = 'SELECT ';
        for(Schema.FieldSetMember f : this.getFields()) {
            query += f.getFieldPath() + ', ';
        }
        query += 'Id, Name FROM Contact LIMIT 1';
        return Database.query(query);
    }
}
The Visualforce page using the above controller is simple:

   
       
           
               
           
           
               
                   
               
           
      
   


Wednesday, November 9, 2011

How to parse JSON string using JSONParser class in Salesforce

Sample JSON String -
[ {  "Id" : "003U0000002kq41IAA", "FirstName" : "Rose", "LastName" : "Gonzalez", "Email" : "rose@edge.com", "Title" : "SVP, Procurement" }, {  "Id" : "003U0000002kq42IAA", "FirstName" : "Sean", "LastName" : "Forbes", "Email" : "sean@edge.com", "Title" : "CFO" }, {  "Id" : "003U0000002kq43IAA", "FirstName" : "Jack", "LastName" : "Rogers", "Email" : "jrogers@burlington.com", "Title" : "VP, Facilities" }, {  "Id" : "003U0000002kq44IAA", "FirstName" : "Pat", "LastName" : "Stumuller", "Email" : "pat@pyramid.net", "Title" : "SVP, Administration and Finance" }, {  "Id" : "003U0000002kq45IAA", "FirstName" : "Andy", "LastName" : "Young", "Email" : "a_young@dickenson.com", "Title" : "SVP, Operations" } ] 
Apex Class to parse JSON String -
public class JSONParserController{
    
    public List<ContactInfo> lstContactInfo{get;set;}
    public JSONParserController(){
        try{
            String jsonString = '[ {  "Id" : "003U0000002kq41IAA", "FirstName" : "Rose", "LastName" : "Gonzalez", "Email" : "rose@edge.com", "Title" : "SVP, Procurement" }, {  "Id" : "003U0000002kq42IAA", "FirstName" : "Sean", "LastName" : "Forbes", "Email" : "sean@edge.com", "Title" : "CFO" }, {  "Id" : "003U0000002kq43IAA", "FirstName" : "Jack", "LastName" : "Rogers", "Email" : "jrogers@burlington.com", "Title" : "VP, Facilities" }, {  "Id" : "003U0000002kq44IAA", "FirstName" : "Pat", "LastName" : "Stumuller", "Email" : "pat@pyramid.net", "Title" : "SVP, Administration and Finance" }, {  "Id" : "003U0000002kq45IAA", "FirstName" : "Andy", "LastName" : "Young", "Email" : "a_young@dickenson.com", "Title" : "SVP, Operations" } ] ';
            parseJSON(jsonString);
        }
        catch(Exception e ){
            Apexpages.addMessages(e);
        }
    }
    
    public void parseJSON(String jsonstr){
        if (jsonstr != null){
        lstContactInfo= new List<ContactInfo>();   
        JSONParser parser = JSON.createParser(jsonstr);
        while (parser.nextToken() != null)
        {
            if (parser.getCurrentToken() == JSONToken.START_ARRAY)
            {
             
                while (parser.nextToken() !=  JSONToken.END_ARRAY)
                {
                    if (parser.getCurrentToken() == JSONToken.START_OBJECT)
                    {
                        
                        ContactInfo ci = new ContactInfo();
                        while (parser.nextToken() !=  JSONToken.END_OBJECT)
                        {
                            
                                if((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&(parser.getText().tolowercase() == 'title'))
                                {
                                    parser.nextToken() ;    
                                    ci.title = parser.getText();
                                }
                                if((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&(parser.getText().tolowercase() == 'firstname'))
                                {
                                    parser.nextToken()     ;
                                    ci.firstname = parser.getText();
                                }
                                if((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&(parser.getText().tolowercase() == 'lastname'))
                                {
                                    parser.nextToken()     ;
                                    ci.lastname = parser.getText();
                                }
                                if((parser.getCurrentToken() == JSONToken.FIELD_NAME) &&(parser.getText().tolowercase() == 'email'))
                                {
                                    parser.nextToken()     ;
                                    ci.email = parser.getText();
                                }
                           
                            
                        }
                        lstContactInfo.add(ci);
                    }
                }
            }
        }
      }   
    }
    
    public class ContactInfo{
        public string title{get;set;}
        public string firstName{get;set;}
        public string lastName{get;set;}
        public string email{get;set;}
        public ContactInfo(){
        
        }
    }
}

Show response on VF Page -
<apex:page controller="JSONParserController">
  <apex:form >
      <apex:pageBlock >
      
          <apex:pageBlockSection >
              <apex:pageBlockTable value="{!lstContactInfo}" var="item">
                  <apex:column value="{!item.title}" headerValue="Title"/>
                  <apex:column value="{!item.firstname}" headerValue="First Name"/>
                  <apex:column value="{!item.lastname}" headerValue="Last Name"/>
                  <apex:column value="{!item.email}" headerValue="Email"/>
              </apex:pageBlockTable>
          </apex:pageBlockSection>
      </apex:pageBlock>
  </apex:form>
</apex:page>

Please refer the following link to complete documentation for JSONParser class methods.
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_jsonparser.htm

Sunday, October 9, 2011

Winter 12 New Feature - JSON Support

Hello,

Earlier I used an open source library called JSONObject to parse the json string. It works fine to parse the google json but in some case I was having the following error messaage while parsing the JSON string.

“FATAL_ERROR|superpat.JSONObject.JSONException: Expected a , or }”

You can find solutions of the following error here.

Now in winter 12 release, Salesforce is providing a native support for JSON parsing.

As per the winter 12 release notes -
JSON Support
JavaScript Object Notation (JSON) support has been added. Using JSON classes, you can now parse JSON content and
serialize Apex objects into the JSON format. The following classes have been added for JSON support:
• System.JSON: Contains methods for serializing Apex objects into JSON format and deserializing JSON content that
was serialized using the serialize method in this class.
• System.JSONGenerator: Contains methods used to serialize Apex objects into JSON content using the standard JSON
encoding.
• System.JSONParser: Represents a parser for JSON-encoded content.

You can also find the another cool article on JSON parser here

Thanks,



Wednesday, July 20, 2011

DOM Classes in salesforce

DOM (Document Object Model) classes help you to parse or generate XML content. The DOM represents an XML document as a hierarchy of nodes. The best utilization of DOM classes is when a  request created by HttpRequest or to parse a response accessed by HttpResponse.

If you want to call a external webservice then you have two options in salesforce.

  • You can get the wsdl of the webservice and parse the wsdl in salesforce. It will automatically create the webservice classes and you can use the methods of those classes.
  • You can also create a soap envelope and send the request to endpoint url using HttpRequest class and then parse the HttpResponse using DOM classes.

I am taking an example of how to create a soap envelope and how to parse the response using DOM classes.


public class WebserviceRequest{
public void sendRequest(){
     String endpointUrl = ''; // please provide the endpoint url here
     
     //create a new instance of httprequest
     HttpRequest req = new HttpRequest();
     //set method
     req.setMethod('POST');

     // set endpoint url
     req.setEndpoint(endpointUrl);

     // set header
     req.setHeader('Content-Type', 'text/xml');

     // set soap envelope into request body
     req.setBody(getSoapEnvelope());
     
     // create a new instance of Http class
     Http http = new Http();
     // send request
     HttpResponse res = http.send(req);
     
     // method to parse httpresponse
     parseResponse(res);

}

// method to create envelope
public String getSoapEnvelope(){

// Note this is a sample soap request. 
String envelope = '


  
    IBM
  

' ;

return envelope ;
}

//this method is used to parse the response.
public void parseResponse(HttpResponse res)
{
 dom.document doc = res.getBodyDocument();
 dom.XmlNode [] node = doc.getRootElement().getChildElements();
 // iterate over node will return all the nodes of the xml respose.  
}

}

For more details please refer this link

Please let me know if there is any issue.

Thanks,

Saturday, June 18, 2011

How to send mass emails to users in salesforce


Recently I was working on a requirement where I created multiple portal users in a single process. Now I need to sent them an email with different body. I would like to share the approach which I used.

In the below sample code I am iterating over a list of partner users ("lstPortalUser"). This list is created by me as per my requirement. You can create same list as per your requirement.

List<Messaging.SingleEmailMessage> mails = new List<Messaging.SingleEmailMessage>();
for(User portalUser :lstPortalUser)
{   
   Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
   string body = 'Hi '+ portalUser.LastName;  
   mail.setSubject('Test Subject');
   mail.setTargetObjectId(portalUser.Id);
   mail.setSaveAsActivity(false);
   mail.setHtmlBody(body);
   mails.add(mail);
}
Messaging.sendEmail(mails);

Please let me know if there is any issue.
Thanks,

Friday, June 10, 2011

Gmail Contextual Gadgets (Gmail - Twitter)

A Gmail contextual gadget is a gadget that is triggered by clues in Gmail, such as the contents of Subject lines and email messages. For example, Gmail already provides a YouTube contextual gadget. If the body of an email contains a link to a YouTube video, a clickable thumbnail view of the video appears at the bottom of the email.
A Gmail contextual gadget can be triggered by content in any of the following parts of an email:1. From
2. To
3. CC
4. Subject
5. Body
6. Sent/received timestamps

For more details please click here

I have created my first gmail contextual gadget which is fetching the details from Twitter account. I have currently triggered for the Subject of email.
For e.g. If I send an email with subject @devnatani (My twitter name) , it shows the twitter info related to that user at the bottom of the email.


This information can be helpful for end user to get the information about the user without logging into twitter account.


I am currently working with some other integrations with gmail contextual gadgets and I will update those on the blog. Many more to come related to gmail contextual gadgets...

Thanks,