Saturday, September 30, 2017

Force.com SOAP API and exposing Apex methods as SOAP Web Services

Before going further, please make sure that the user being used has permission to call API. "API Enabled" must be true for the user's profile.

For SOAP web services API testing, I will be using Postman. This is available as a Chrome extension.

As a first step, you issue a login request where you provide the password and token, as a response to which, you get the session ID and the target URL. To authenticate SOAP API users, you need to acquire session ID.

Enter the below SOAP envelope in your postman's request. Take a note of the POST URL, and the Content-Type that has been set to text/xml. We have also added SOAPAction key in headers whose value is ''.

<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
  <env:Body>
    <n1:login xmlns:n1="urn:enterprise.soap.sforce.com">
      <n1:username>USERNAME</n1:username>
      <n1:password>PASSWORD</n1:password>
    </n1:login>
  </env:Body>
</env:Envelope>

Click on Send button.

We receive a response with status 200 OK. We also get the server URL and the unique session ID.


Now lets query the Account object. Enter the below SOAP envelope in your postman's request. Take a note of the POST URL that we received in our response before.
<?xml version="1.0" encoding="utf-8"?>   
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
   xmlns:urn="urn:enterprise.soap.sforce.com">
  <soapenv:Header>
     <urn:SessionHeader>
        <urn:sessionId>00D1I000001VVPg!ARQAQG3Y4rBp.E79acFggyFeSd8EgnlnhSRB0B4r1UidUhvUr43ulP9MxwX6aKmhQhrnH_fDwEQaB51twKme7tPGn4kFo5Xr</urn:sessionId>
     </urn:SessionHeader>
  </soapenv:Header>
  <soapenv:Body>
     <urn:query>
        <urn:queryString>SELECT Id, Name FROM Account</urn:queryString>
     </urn:query>
  </soapenv:Body>
</soapenv:Envelope>



Lets retrieve server timestamp. Note that I am just changing the SOAP payload.

Lets create an account. Enter the below SOAP envelope in your postman's request.
<?xml version="1.0" encoding="utf-8"?>   
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:urn="urn:enterprise.soap.sforce.com"
  xmlns:urn1="urn:sobject.enterprise.soap.sforce.com"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <soapenv:Header>
     <urn:SessionHeader>
        <urn:sessionId>00D1I000001VVPg!ARQAQG3Y4rBp.E79acFggyFeSd8EgnlnhSRB0B4r1UidUhvUr43ulP9MxwX6aKmhQhrnH_fDwEQaB51twKme7tPGn4kFo5Xr</urn:sessionId>
     </urn:SessionHeader>
  </soapenv:Header>
  <soapenv:Body>
     <urn:create>
        <urn:sObjects xsi:type="urn1:Account"> <!--Zero or more repetitions:-->
           <!--You may enter ANY elements at this point-->
           <Name>Test Account</Name>
        </urn:sObjects>
     </urn:create>
  </soapenv:Body>
</soapenv:Envelope>


Exposing Apex Methods as SOAP Web Services

Apex class methods can be exposed as custom SOAP Web service calls. Use the webservice keyword to define these methods.
global class MathOperations {
    webservice static Integer getSum (Integer a, Integer b) {
        return a + b;
    }
}

Enter the below SOAP envelope in your postman's request. Take a note of the POST URL


Share This:    Facebook Twitter

Friday, September 22, 2017

Salesforce Lightning: Google Places Autocomplete Predictions Search



I have created a lookup component which on entering few characters of a location will display location predictions.

There are 3 methods that has been defined in client-side controller:
  • keyPressController: executed when the user enters a search key. I have taken into consideration that the user need to enter at least 3 characters to fetch the location predictions.
  • selectOption: executed when the user selects a value from the list box
  • clear: executed on click of cross icon to remove the selected value from the lookup

To fetch the results, I am calling Place Autocomplete service, a part of the Google Places API Web Service, using the below Apex method, which returns location predictions in response to this HTTP request. For more details about this web service, please check the link in the references section of this post.
@AuraEnabled
public static string getAddressAutoComplete(String input, String types) {
    String url = 'https://maps.googleapis.com/maps/api/place/autocomplete/json?input='
            + EncodingUtil.urlEncode(input, 'UTF-8')
            + '&types=' + types
            + '&key=' + GoogleMapsController.getGoogleMapsAPIKey();
    return GoogleMapsController.getHttp(url);
}

The response which is in JSON format is parsed in Javascript in the helper method of the component as below:
displayOptionsLocation: function (component, searchKey) {
    var action = component.get("c.getAddressAutoComplete");
    action.setParams({
        "input": searchKey,
        "types": '(regions)'
    });

    action.setCallback(this, function (response) {
        var state = response.getState();
        if (state === "SUCCESS") {
            var options = JSON.parse(response.getReturnValue());
            var predictions = options.predictions;
            var addresses = [];
            if (predictions.length > 0) {
                for (var i = 0; i < predictions.length; i++) {
                    addresses.push(
                        {
                            value: predictions[i].types[0],
                            label: predictions[i].description
                        });
                }
                component.set("v.filteredOptions", addresses);
            }
        }
    });
    $A.enqueueAction(action);
}

The look and feel of this component is controlled by $A.util.addClass and $A.util.removeClass methods.

Please check the github link for the component code below:
https://github.com/iamsonal/GoogleMapsAutocomplete

References:
https://developers.google.com/places/web-service/autocomplete
Share This:    Facebook Twitter

Friday, September 8, 2017

Salesforce Lightning: Lookup Component


I created a simple lookup component in Lightning. Its fully based on Lightning Design Systems. You can check the Github link in the reference section. During initialization, the component query for the list of strings (using apex code) to be displayed and store in an attribute. So when the user enters a search keyword, the request won't go to Salesforce again and will query the Javascript string array for the filtered results.

How to use?

From your Lightning component, add a lookup component using the following markup:
<c:DemoLookup placeholder="Enter partner Name" actionMethod="c.getAccountOptions"/>

You need to pass a list of strings which will get displayed in the lookup options when the user enters an input. A sample method is as below:
@AuraEnabled
public static List<String> getAccountOptions() {
    List<String> options = new List<String>();
    for (Account a : [
            SELECT Name
            FROM Account
            LIMIT 100
    ]) {
        options.add(a.Name);
    }
    return options;
}

Reference:
https://github.com/iamsonal/DemoLookup
Share This:    Facebook Twitter

Saturday, September 2, 2017

Lightning: Fetch current location details using Google Maps API

Using Google Maps, I was trying to fetch the current city and other details in a Lightning component using Javascript, but I was getting some error in browser console. I believe that is because of Locker service as described in the reference link. So I had to take a different approach.

But first, we need the latitude and longitude of the user who is accessing the Lightning page. The HTML Geolocation API is used to get the geographical position of a user. Since this can compromise privacy, the position is not available unless the user approves it. The getCurrentPosition() method is used to return the user's position. The example below returns the latitude and longitude of the user's position.

checkGeoLocation : function(component, event, helper) {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(function(position) {
            var lat = position.coords.latitude;
            var lon = position.coords.longitude;
            var action = component.get("c.getCityName");
            action.setParams({
                "latitude": lat,
                "longitude": lon
            });
            action.setCallback(this, function(response) {
                var state = response.getState();
                if (state === "SUCCESS") {
                    var location = response.getReturnValue();
                }
            });
            $A.enqueueAction(action);
        });
    } else {
        console.log('Your browser does not support GeoLocation');
    }
}

To fetch the city details, we need to invoke the Google maps API. We need to send the location details as parameters. The results element in the response needs to be parsed in Apex to extract the desired values. In my case, JsonReader class did the work for me.

Please go through the documentation of Google maps, the link of which has been provided in the reference section. The following fields of the results element are of significance:
1. address_components[]
2. types[]

@AuraEnabled
public static String getCityName (Decimal latitude, Decimal longitude) {
    String url = 'http://maps.googleapis.com/maps/api/geocode/json?latlng=' + latitude + ',' + longitude + '&sensor=true';
    JsonReader jsonobj = new JsonReader(getHttp(url));
    String status = jsonObj.getString('status');
    System.debug(status);
    
    JsonReader addressComponentObj = null;
    String locality= null;
    String adminAreaLevel2= null;
    List<Object> types = null;
    
    for(Object obj : jsonObj.getList('results[0].address_components')) {
        addressComponentObj = new JsonReader(obj);
        types = addressComponentObj.getList('types');
        for(Object typeObj : types) {
            String type = (String) typeObj;
            if (type.equalsIgnoreCase('locality')) {
                locality = addressComponentObj.getString('long_name');
            }
            if (type.equalsIgnoreCase('administrative_area_level_2')) {
                adminAreaLevel2 = addressComponentObj.getString('short_name');
            }
        }
    }
    return (locality + ', ' + adminAreaLevel2);
}

And that's it.


Reference: http://www.rattanpal.com/2017/03/19/salesforce-implement-google-maps-lightning-components/
https://developers.google.com/maps/documentation/geocoding/intro
Share This:    Facebook Twitter

Saturday, August 26, 2017

Salesforce Lightning Interview Questions I


1. What are the different types of Lightning events?
  • Browser: browser notifications that are triggered by user interaction with an element. Eg. onClick
  • System: fired by LC framework during LC lifecycle. They notify component states. Eg. init, render, afterRender
  • Navigation: force:navigateToURL, force:createRecord, force:editRecord
  • Component: A component event is fired from an instance of a component. A component event can be handled by the component that fired the event or by a component in the containment hierarchy that receives the event.
  • Application: Application events follow a traditional publish-subscribe model. An application event is fired from an instance of a component. All components that provide a handler for the event are notified.


2. How to register, fire and handle a component and application event?
<aura:registerEvent name="componentEventFired" type="c:compEvent"/>
<aura:registerEvent name="appEvent" type="c:appEvent"/>

var compEvents = cmp.getEvent("componentEventFired");
compEvents.setParams({ "context" : parentName });
compEvents.fire();

var appEvent = $A.get("e.c:appEvent");
appEvent.setParams({ "context" : parentName });
appEvent.fire();
...
...
...
...
...
<aura:handler event="c:appEvent" action="{!c.handleApplicationEventFired}"/>
<aura:handler name="componentEventFired" event="c:compEvent" 
 action="{!c.handleComponentEventFired}"/>

{
 handleComponentEventFired : function(cmp, event) {
  var context = event.getParam("context");
 },

 handleApplicationEventFired : function(cmp, event) {
  var context = event.getParam("context");
 }
}
For more details, check the link below:
http://hellosnl.blogspot.in/2017/06/lightning-advanced-events-example.html


3. Let's say that you have an app myApp.app that contains a component myCmp.cmp with a ui:button component. During initialization, the init() event is fired in what order?
Answer: ui:button, ui:myCmp, and myApp.app.


4. Why do we use @AuraEnabled annotation?
  • Use @AuraEnabled on Apex class static methods to make them accessible as remote controller actions in your Lightning components.
  • Use @AuraEnabled on Apex instance methods and properties to make them serializable when an instance of the class is returned as data from a server-side action

5. Why do we use $A.enqueueAction(action)?
It adds the server-side controller action to the queue of actions to be executed. Rather than sending a separate request for each individual action, the framework processes the event chain and batches the actions in the queue into one request. The actions are asynchronous and have callbacks.


6. What is Namespace?
It is used to group related components together.


7. What is LockerService?
It enhances security by isolating Lightning components in their own namespace. A component can only traverse the DOM and access elements created by a component in the same namespace.


8. Examples of how to use some of the out-of-the-box events to enable component interation within your Lightning components?
$A.get("e.force:refreshView").fire(): reloads all data for the view.

createRecord : function (component, event, helper) {
    var createRecordEvent = $A.get("e.force:createRecord");
    createRecordEvent.setParams({
        "entityApiName": "Contact"
    });
    createRecordEvent.fire();
}

editRecord : function(component, event, helper) {
    var editRecordEvent = $A.get("e.force:editRecord");
    editRecordEvent.setParams({
         "recordId": component.get("v.contact.Id")
   });
    editRecordEvent.fire();
}


9. What is Lightning CLI?
It is a Heroku Toolbelt plugin that lets you scan your code for general JavaScript coding issues and lightning-specific issues.


10. Difference between bound and unbound expressions.
Bound expression {!expression}
  • Any change to the value of the childAttr attribute in c:child also affects the parentAttr attribute in c:parent and vice versa.
  • When you use a bound expression, a change in the attribute in the parent or child component triggers the change handler in both components.
Unbound expression {#expression}
  • Any change to the value of the childAttr attribute in c:child doesn’t affect the parentAttr attribute in c:parent and vice versa.
  • When you use an unbound expression, the change is not propagated between components so the change handler is only triggered in the component that contains the changed attribute.
For more details, check this link: http://hellosnl.blogspot.in/2017/05/data-binding-between-components.html


11. Use of THIS CSS class?
This adds namespacing to CSS and helps prevent one component's CSS from blowing away another component's styling.


12. How to set the value of an inherited attribute?
Use the <aura:set> tag.


13. What are the different ways to conditionally display markup, and what is the preferred approach?
Using the <aura:if> tag
Use CSS to toggle visibility of markup by calling $A.util.toggleClass(cmp, 'class') in JavaScript code.


14. What is $Resource global value provider? Is it possible to obtain a reference to a static resource in Javascript code?
It lets you reference images, style sheets, and JavaScript code you’ve uploaded in static resources.
To obtain a reference to a static resource in JavaScript code, use $A.get('$Resource.resourceName').
For more details, check this link http://hellosnl.blogspot.in/2017/04/lightning-using-static-resources.html


15. Let’s say you have several buttons that reuse the same onclick handler. How will you retrieve the name of the button that fired the event?
http://hellosnl.blogspot.in/2017/05/which-button-was-pressed.html


16. What are the names of interfaces that are added to a Lightning component to allow it to be used as custom tabs, and to be used in Lightning and Community builder?
http://hellosnl.blogspot.in/2017/05/configuring-lightning-components.html


17. What is the use of force:hasRecordId interface?
Add the force:hasRecordId interface to a Lightning component to enable the component to be assigned the ID of the current record.
The recordId attribute is set only when you place or invoke the component in a context of a record. For example, when you place the component on a record page, or invoke it as an action from a record page or object home. In all other cases, such as when you create this component programmatically inside another component, recordId isn’t set, and your component shouldn’t depend on it.


18. How to delete a design attribute for a component that implements the flexipage:availableForAllPageTypes or forceCommunity:availableForAllPageTypes interface?
First remove the interface from the component before deleting the design attribute. Then reimplement the interface. If the component is referenced in a Lightning page, you must remove the component from the page before you can change it.


19. How to add Lightning components to your Visualforce pages?
https://developer.salesforce.com/docs/atlas.en-us.lightning.meta/lightning/components_visualforce.htm


Share This:    Facebook Twitter

Total Pageviews

My Social Profiles

View Sonal's profile on LinkedIn

Tags

__proto__ $Browser Access Grants Accessor properties Admin Ajax AllowsCallouts Apex Apex Map Apex Sharing AssignmentRuleHeader AsyncApexJob Asynchronous Auth Provider AWS Callbacks Connected app constructor Cookie CPU Time CSP Trusted Sites CSS Custom settings CustomLabels Data properties Database.Batchable Database.BatchableContext Database.query Describe Result Destructuring Dynamic Apex Dynamic SOQL Einstein Analytics enqueueJob Enterprise Territory Management Enumeration escapeSingleQuotes featured Flows geolocation getGlobalDescribe getOrgDefaults() getPicklistValues getRecordTypeId() getRecordTypeInfosByName() getURLParameters Google Maps Governor Limits hasOwnProperty() Heap Heap Size IIFE Immediately Invoked Function Expression Interview questions isCustom() Javascript Javascript Array jsForce Lightning Lightning Components Lightning Events lightning-record-edit-form lightning:combobox lightning:icon lightning:input lightning:select LockerService Lookup LWC Manual Sharing Map Modal Module Pattern Named Credentials NodeJS OAuth Object.freeze() Object.keys() Object.preventExtensions() Object.seal() Organization Wide Defaults Override PDF Reader Performance performance.now() Permission Sets Picklist Platform events Popup Postman Primitive Types Profiles Promise propertyIsEnumerable() prototype Query Selectivity Queueable Record types Reference Types Regex Regular Expressions Relationships Rest API Rest Operator Revealing Module Pattern Role Hierarchy Salesforce Salesforce Security Schema.DescribeFieldResult Schema.DescribeSObjectResult Schema.PicklistEntry Schema.SObjectField Schema.SObjectType Security Service Components Shadow DOM Sharing Sharing Rules Singleton Slots SOAP API SOAP Web Services SOQL SOQL injection Spread Operator Star Rating stripInaccessible svg svgIcon Synchronous this Token Triggers uiObjectInfoApi Upload Files VSCode Web Services XHR
Scroll To Top