Thursday, 31 March 2016

Apex: Creating CRON Expression dynamically from VF page

CRON Expression:

A command to an operating system or server for a job that is to be executed at a specified time.

CRONTrigger:

An object that contains schedule information for a schedule job.This object contain all the information related to any schedule job in your organization. Read More Here!

Visualforce Page for Dynamic CRON Creation:

The use case this page covers is when users want to schedule  a class from VF page.User have choice to set schedule date and time according to his convenience from any day of week.

We will be using Multiselect picklist to show days of weeks as user might want to schedule it for more than 1 day.



We will use single select picklist in order to capture preferred time from user.


VF Page Code:

     <apex:pageBlock id="pb4">
            <apex:pageBlockSection title="Frequency" id="pbs10" collapsible="false" 
             columns="1">
            
                <apex:selectList label="Recurs Every Week On" multiselect="true"  
                 size="5" id="FrequencyWeekly" value="{!SelectedFreqValue}">
                    <apex:selectOptions value="{!OppWeekDays}"  />
                       
                </apex:selectList>
               
                <apex:selectList label="Preferred Start Time" multiselect="false"  
                 size="1" id="Time" value="{!SelectedTime}">

                    <apex:selectOptions value="{!FrequencyTime}"/>
                </apex:selectList>
                    
                <apex:outputLabel styleclass="labelCol vfLabelColTextWrap" 
                 value="Exact time will be dependent on Job queue activity" 
                 style="text-align:left !important; font-size: 10px !important;"/>
            </apex:pageBlockSection>
            
        </apex:pageBlock>

Controller Class Code

//Defining Properties for capturing Frequency
    public String SelectedFreqValue {get;set;} 
    public string SelectedTime {get;set;}

//Defining List of selectoption
public List<selectOption> OppWeekDays{get;set;}
 public List<selectoption> FrequencyTime{get;set;}

/****************************************************getFrequencyTime**********************************/
    //get frequency time
    public List<selectOption> getFrequencyTime(){
        
        FrequencyTime = new List<selectoption>();
        
        FrequencyTime.add(new selectOption('0',Constants.CONST_TWELVE_AM));
        FrequencyTime.add(new selectOption('1',Constants.CONST_ONE_AM));
        FrequencyTime.add(new selectOption('2',Constants.CONST_TWO_AM));
        FrequencyTime.add(new selectOption('3',Constants.CONST_THREE_AM));
        FrequencyTime.add(new selectOption('4',Constants.CONST_FOUR_AM));
        FrequencyTime.add(new selectOption('5',Constants.CONST_FIVE_AM));
        FrequencyTime.add(new selectOption('6',Constants.CONST_SIX_AM));
        FrequencyTime.add(new selectOption('7',Constants.CONST_SEVEN_AM));
        FrequencyTime.add(new selectOption('8',Constants.CONST_EIGHT_AM));
        FrequencyTime.add(new selectOption('9',Constants.CONST_NINE_AM));
        FrequencyTime.add(new selectOption('10',Constants.CONST_TEN_AM));
        FrequencyTime.add(new selectOption('11',Constants.CONST_ELEVEN_AM));
        FrequencyTime.add(new selectOption('12',Constants.CONST_TWELVE_PM));
        FrequencyTime.add(new selectOption('13',Constants.CONST_ONE_PM));
        FrequencyTime.add(new selectOption('14',Constants.CONST_TWO_PM));
        FrequencyTime.add(new selectOption('15',Constants.CONST_THREE_PM));
        FrequencyTime.add(new selectOption('16',Constants.CONST_FOUR_PM));
        FrequencyTime.add(new selectOption('17',Constants.CONST_FIVE_PM));
        FrequencyTime.add(new selectOption('18',Constants.CONST_SIX_PM));
        FrequencyTime.add(new selectOption('19',Constants.CONST_SEVEN_PM));
        FrequencyTime.add(new selectOption('20',Constants.CONST_EIGHT_PM));
        FrequencyTime.add(new selectOption('21',Constants.CONST_NINE_PM));
        FrequencyTime.add(new selectOption('22',Constants.CONST_TEN_PM));
        FrequencyTime.add(new selectOption('23',Constants.CONST_ELVEN_PM));
        
        return FrequencyTime;
    }


/*************************************************getOppWeekDays****************************************/
    //get renewal opp week days list
    public List<SelectOption> getOppWeekDays(){
        
        OppWeekDays = new List<selectoption>();
        
        OppWeekDays.add(new selectOption('SUN',CONST_SUNDAY));
        OppWeekDays.add(new selectOption('MON',CONST_MONDAY));
        OppWeekDays.add(new selectOption('TUES',CONST_TUESDAY));
        OppWeekDays.add(new selectOption('WED',CONST_WEDNESDAY));
        OppWeekDays.add(new selectOption('THUR',CONST_THURSDAY));
        OppWeekDays.add(new selectOption('FRI',CONST_FRIDAY));
        OppWeekDays.add(new selectOption('SAT',CONST_SATURDAY));
        
        return OppWeekDays;
    }

Create a constant class where you can add all times you want to show on page.Like i create a 
class name "Constant" and add times from "12 AM" till "11 PM" and names of days from Sunday till Saturday.


CRON Creation Method


public string GetCronStringForSchedule(){
        Integer Schdtime = Integer.valueOf(SelectedTime);
         string sch = '';
            string a = '';
            SelectedFreqValue= SelectedFreqValue.replaceAll( '\\s+', '');
            SelectedFreqValue = SelectedFreqValue.remove(')');
            SelectedFreqValue = SelectedFreqValue.remove('(');
            List<String> ListOfValues = SelectedFreqValue.split('\\,');
            if(ListOfValues.size() >0)
                a = ListOfValues.get(0)+ '-' + ListOfValues.get(ListOfValues.size()- 1);
            else
                a = ListOfValues.get(0);
            sch = '0 0 '+ Schdtime +' ? * '+ a;
    }

public string JobSchedular(){
string sch = GetCronStringForSchedule();
      string  jobID = system.schedule(BATCH_JOB_NAME, sch, batchjob);
return jobID;
}

Save this job ID some where so you can re use it in future if you want to abort this job from page.

Hope this helps you. Happy Coding !!

Tuesday, 29 March 2016

Get relationship of an object using dynamic apex or metadata API

Dynamic List of Relations:

In below post i will share some very interesting business scenarios related to getting relations of an object dynamically in Salesforce.

When we normally talk about relations in salesforce. It will be considered in two ways with respect to an object.

  1. The object you are referencing is parent of how many objects in organization
  2. The object you are referencing is child of how many objects in your organization.
E.g: If you want to get relations of "Account" object in your org.Then what actually your requirement is? Get list of all objects which are child of "Account" object or get list of all objects which are parent(Lookup/reference on account object) of "Account".

Get Child Relationship:


In order to access child relationship of an sobject we can use getChildRelationships() method of salesforce.
This is  a built in method of "DescribeSObjectResult" class of Salesforce. You can also access record types, labels and CRUD rights of any sobject using this class methods.

Link to check more!!

Below method will take your object API name as parameter and will provide you list of selectoption of all child relationship in order to show on your VF page.

Apex Method:

public static List<SelectOption> GetObjectChildRelations(String ParentObject){
List<Selectoption> ListOfChildObjects = new List<Selectoption>();
SObjectType objObjectType = Schema.getGlobalDescribe().get('Account');
    //it gives object properties or describe results
    Schema.DescribeSObjectResult   describeresult = objObjectType.getDescribe();
    List<Schema.ChildRelationship>   lstchildrelationships =describeresult.getChildRelationships();
for(Schema.ChildRelationship relname:lstchildrelationships){
        ListOfRelatedObjects.add(new SelectOption(relname.getChildSObject(),relname.getRelationshipName()));
        System.debug('Relationshipname:'+relname.getChildSObject());                      
}
        return ListOfChildObjects ;
}

getGlobalDescrible:

Returns map of all sobject names(keys) to sobject token(values) for standard and custom object define in your organization.

Get Reference Relationship:

In order to access parent/reference relationship of an sobject we can use Reference() method of salesforce.
This is  a built in method of "DisplayType" class of Salesforce. You can check different field types using this class.

Link to check more!!

Below method will take your object API name as parameter and will provide you list of selectoption of all child relationship in order to show on your VF page.

Apex Method:

public static List<SelectOption> GetObjectRelatedRelations(String ParentObject){
    
List<Selectoption> ListOfRelatedObjects = new List<Selectoption>();
    Map<String, Schema.SObjectField> fieldsMap = new Map<String, Schema.SObjectField>();
          
    SObjectType objObjectType = Schema.getGlobalDescribe().get(ParentObject);
            
    //it gives object properties or describe results
    Schema.DescribeSObjectResult   describeresult = objObjectType.getDescribe();
    
    //Adding fields to the fieldsMap
    fieldsMap =  describeresult.fields.getMap();
// This for loop add the field api name as a key and field label as value into field list
    for(Schema.SObjectField fieldName:fieldsMap.Values()){
        
        //Add this if type is Reference then get object name else field API
        if(fieldName.getDescribe().getType() == Schema.DisplayType.Reference){
            ListOfRelatedObjects.add(new SelectOption(fieldname.getDescribe().getName(),fieldName.getDescribe().getLabel()));
            
        }
    }//end of for
    return  ListOfRelatedObjects;
}

VF Page Controller:

//Property to use on VF page
public List<selectoption> ObjectsShown {get;set;}

//Method to populate objects in select option list
public List<SelectOption> getObjectsRelation(){
ObjectsShown = new List<selectoption>();
ObjectsShown = GetObjectRelatedRelations(‘Opportunity’);
    return ObjectsShown;
}

Hope it helps to get relation objects dynamically.

Friday, 25 March 2016

Configure Salesforce for On demand Integration Using Dell Boomi


In this post I will give you example of invoking Boomi process using Apex class.

Invoke Boomi Atom

You require an End point URL to invoke your Boomi atom. Boomi atom could be a cloud atom or an on premises atom (locally deployed atom). Below example will explain how to connect with on premises atom.

Login your Boomi environment and click on "Atom Management".Navigate to "Shared Web Server Setting" and copy "Base URL" of your on premises atom along with port.


Salesforce Remote Site Setting

When ever you access any external site from Salesforce you need to add that in remote site setting. This is a security layer that force.com platform will check.
Enter base URL in remote site setting in your salesforce organization. 

Apex Class

Below example demonstrate that how we can pass some parameter to Dell Boomi interface in the form of an XML.

In my previous post we created "End point URL". 

Now we will use our end point url in apex class and call our Boomi process simply by writing below code.

Note: This is a generic XML structure.XML structure may differ on the bases of response profile you created in Boomi.

 public static HttpResponse getInfoBoomi()
    {
        // Get the Endpoint URL from custom label      
        String EndPointUrl = Endpoint URL;
        Httprequest request = new Httprequest();
        request.setmethod('POST');
        request.setTimeout(120000);

        request.setEndpoint(EndPointUrl);
        //set the request string for Boomi service connector containing Invoice No which will than pass to SAP to get the Invoice Base64 code
        string strInput = '<?xml version="1.0" encoding="UTF-8"?>' +
            '<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 
            '   <soapenv:Body> <setOutput xmlns="https://secure.logmeinrescue.com/API/API.asmx"> 
            '      <notifications xmlns="http://soap.sforce.com/2005/09/outbound">' +
            '         <Notification> ' +
            '               <InvoceId>' + ApexPages.currentPage().getParameters().get(ID) + '</InvoceId>' +
            '         </Notification>' +
            '      </notifications>' +
            '   </soapenv:Body>' +
            '</soapenv:Envelope>';

        //replace all & with &amp; to avoid xml encoding issue                      

        strInput = strInput.replaceAll('&', '&amp;');
        request.setBody(strInput);
        Http httprequest = new Http();
        string responseMessage;
        HttpResponse res;
        //send http request to boomi process
        res = httprequest.send(request);
        return res;


    }

By calling above mention function "getInfoBoomi" will provide you http response coming from your Boomi process.You can use built in function getbody to extract your data from response file.

HttpResponse res = getInfoBoomi();
 sData = res.getbody();

This way you can invoke your Boomi process from Salesforce. Hope this helps you !




Boomi Integration Best Practice Part 2

Continuing on my previous post Boomi Best Practice. In following post we will talk about SAP Connector of Boomi.

SAP Connector
To implement a connection to your SAP account from Dell Boomi AtomSphere, you need to copy SAP JCo drivers to the folder where atom is installed. Follow this link for the list of drivers to be copied:


  • .       Use Naming Convention
 Always use standard naming convention for integration processes. Naming convention can be like” INT-001 Account Updates from SAP”. While creating  process for Sandbox append “SANDBOX” keyword as prefix with name of process and for production process use “PROD” as prefix.

  •     Main Listner for IDOC Integration     
      Create a common Listner in order to listen all IDOC integrations. Create a single “Listen” action.
1     Use “Route” component and attach all sub processes which are using IDOC to listen data from SAP.

      Note:
     Whenever changes are need to be deployed on atom, always deploy actual process and IDOC main Listner.

  •     Data Filter on the basis of Identifier
      To filter IDOC segment on the basis of identifiers use “identifier instance”.
         1. First you have to add a qualifier in the IDOC XML profile

2. After adding qualifier, add identifier instance. Click on blue triangle sign you will have option to add identifier.

3. After clicking identifier instance you have to choose your previously added qualifier. You can also identify on the basis of occurrence.

Note: You cannot put identifier on both parent and child node.