When Salesforce is life!

Category: Post Page 22 of 27

[Salesforce / Trailhead] Presenting the “Navigate the Salesforce Advantage” trail aka What is Salesforce?

This is a technical blog (“Nerd @ work” say it all) and I usually post exclusively technical stuff.

But in the recent trailhead additions there is a special set of modules that basically answer the question “What is Salesforce and what’s the reason of its Success?”

This is the Navigate the Salesforce Advantage trail and it is meant for those who don’t know anything about the platform and for those who want to better understand the reason of the success.

I may say that if I could have read these modules when I first started making the first steps in the Salesforce platform, I would have understood in few minutes why Salesforce is that awesome…but you know, I discovered it by coding and coding and coding…

What I say before presenting the trail,

Here is a walkthrough of the key concepts of the trail.

Salesforce Success Model

Are you new to Salesforce? Not sure exactly what it is or how to use it? Don’t understand what makes Salesforce special? If you’ve answered “yes” to any of these questions, then you’re in the right place. No matter what brought you, we’re glad you’re here.

Salesforce is a platform of connected features that helps you to make your customers love you (I mean not actually you, but your company!)

How do Salesforce do it? It’s success is handled by the following 4 rules:

  • Customer success: “why can’t buying enterprise software be as easy as buying a book on Amazon.com? How can we make it easier for customers everywhere to achieve their goals?
  • Leadership: “Cloud is still the medium for everything we do. This means all our focus is on innovating the best apps and platform technologies for our customers. This is what we do, all day, everyday.
  • Innovation: “Our customers drive us to be more innovative. … Because what they can do with Salesforce is truly amazing.
  • Giving Back: Our 1-1-1 Model: “To us, the business of business is not business. The business of business is to improve the state of the world.

Salesforce Cloud Benefits

To answer to what Salesforce is and what it does truly depends on each customers’ definition of success. … So it’s up to us to be their Swiss Army knife and provide them with a neatly packaged range of tools to choose from. … The aim is for our customers to have the right mix of tools at the right time.

All the platform features help your customers to solve several issues in their business thus increasing their business with super powers:

There’s a Salesforce App Cloud for That“.

And yes, it is all in cloud, Software As A Service (SAAS)!

It means that we maintain the infrastructure and do all the heavy lifting so you can focus on what matters most to your business.

Salesforce Technology Basics

Understand the basics of the Force.com platform.

Security: “At Salesforce, trust is our #1 priority. Data is one of the most valuable assets that each one of our customers possesses.

Multitenancy: “every customer shares the same infrastructure and runs on the same platform. It’s that simple

Metadata driven architecture: “When we talk about metadata at Salesforce, we’re talking about our metadata-driven architecture that allows each customer to customize their own instance of Salesforce. … Salesforce separates our customers’ customizations into a special metadata layer, so we can update and improve our platform in the background without touching any of their data or customizations

Fast app development: “Building an app with Salesforce is different. There is no installation of hardware and software, and there are standard options for defining security and user access, creating reports, and making the app social and mobile. Metadata allows us to have all of this pre-built in a separate layer for our customers, so all they have to do is add any customizations they may want as icing on the cake. … Point-and-Click Configuration for all, Custom Code for developers

Salesfoce Ecosystem

“Our ecosystem was created to help customers get access to whatever they need, whenever they need it.”

It’s the power of the Community that makes the platform so powerfull.

How to keep in touch with all of us?

  • Dreamforce: this is a HUGE event where you’ll meet people from all over the world
  • Attend a local event: join a local User Group or Developer Group
  • Explore the AppExchange
  • Consult with an Implementation Partner

How huge the Community is?

We developed the online Salesforce Success Community as a place where business users, admins, partners, and employees can go to find answers, get synced up with their local user groups, help new customers get started, and get active in a community of enthusiastic and innovative people.

Meet Our MVPs
I’m one of them now, you can catch me and ask wathever you want, we are here to help!

The most incredible thing about our MVPs? Not a single one is an employee. They put in all this time and effort for the good of the Salesforce community, and we recognize them for their leadership, knowledge, and ongoing contributions. These individuals represent the spirit of the community and what it is all about!

[Salesforce / MVP] Yes guys, I’m a Salesforce MVP! And Thank you all!

Today I woke up and… BAAAMM!

I’ve been nominated a Salesforce MVP: read the announcement from the Salesforce MVP blog.

This is an honor and a motivation of pride for my carreer, and I know I have to thank the whole Force.com Community for this awesome achievement!

This post is just to say thank you all!

In the next days I’ll publish a new post to describe my trailhead to the MVP!

The next question is: am I the first Italian Salesforce MVP?

Update 2016-02-29

Yes I am!!

See you in the next posts!

[Salesforce / Visualforce] Handling Viewstate with Dynamic Visualforce components

I’ve written this post thanks to the help of my colleague Ivano Guerini who has found the solution to the problem I’m going to expose and written down the code you’ll see in this post.

This post is about correctly handling the viewstate when dealing with Dynamic Visualforce Components.

For those of you that have never worked with dynamic components, they are a way to create visualforce components using Apex.

For example the following piece of code returns a Page Block Section with 2 input fields on the Account record:

public Account record{get;set;}

public ApexPages.Component getDynamicComponent() {
    Component.Apex.PageBlockSection result = new Component.Apex.PageBlockSection();
    result.columns = 1;
    List sectionItems = new List();

    Component.Apex.InputField input = new Component.Apex.InputField();
    input.expressions.value = '{!record.Name}';
    result.childComponents.add(input);

    input = new Component.Apex.InputField();
    input.expressions.value = '{!record.Website}';
    result.childComponents.add(input);
}

The visualforce should be called as follows:

<apex:pageBlock>
    <apex:dynamicComponent componentValue="{!dynamicComponent}" />
</apex:pageBlock>

The page prints out a page block with a page block section with 2 input fields for the Name and Website Account’s fields.

The following code has been packed up in this Github repository for further testing and improvements.

If you wanna know more about viewstate this article is a good starting point.

Generally speaking, the viewstate is an input hidden field inside your Visualforce forms that contains all page data and that is used to post your form back to the server and forth to the page.

Too many informations, are you still there?

The problem comes when you try to use dynamic components (that can vary between post backs) and the Visualforce block your post back because of (for instance) required fields: in this specific case the dynamic components does not maintain the viewstate because the postback is blocked just before arriving on the server, so the components are created again and their status is lost.

You can test this behavior by calling the /apex/DynamicViewStateExample?id=[ACCOUNT_ID]&skip=1 (the skip parameters calls the page without the fix shown at the end of this post):

To fix this problem we need to replicate the viewstate component to re-apply the values to the different input fields after the postback has been done.

In your page we have added an apex:inputHidden component called viewstate:

<apex:dynamicComponent componentValue="{!DynamicComponent}" invokeAfterAction="true" />
 <apex:inputHidden value="{!viewState}" id="viewState" />

The trick is to use Javascript to serialize/deserialize the view states.

We use the Serialize jQuery plugin to serialize form data but we had to write our own deserialize method (see the jQuery_Deserialize static resource for more details).

This part of the code is called when there is a post back:

var closestForm = jQuery('[id$="{!$Component.viewState}"]').closest("form");
    closestForm.on("submit", function(event) {
        //serialize esch component except the "viewState" component to avoid recursion
        jQuery('[id$="{!$Component.viewState}"]').val(jQuery(this).find(':not([id$=viewState])').serialize());
    });

And this part is the code that actually deserializes the “custom” viewstate and put it in the form fields:

if(closestForm.find('[id$=viewState]').val()) {
        closestForm.deserialize(jQuery('[id$="{!$Component.viewState}"]').val());
    }

This few lines of Javascript actually to the magic!

For more details on the implementation, have a look at the DynamicViewStateExmaple page and the DynamicViewStateCmp component.

[Salesforce / Visualforce] Input Lookup Custom Component

Have you ever needed a VisualForce lookup input field without using a lookup field from another “fake” object?

I did, and now I have an easy to use VisualForce component that does the trick (almost all the trick).

Here is the GitHub repository that contains the component.

The components simply replicates what the standard lookup field does, with 2 important differences:

  • We have to use a custom Apex class to store the ID value (simple data types as String or ID are passed by value rather than reference, so it is impossibile to change the component’s parameter value on the fly, see Bob Buzzard post Updating Attributes in Component Controller)
  • If you change the value of the “name” of the lookup field and this matches more than one record, the form submission is canceled and a picklist with all the values is shown (so the user can choose the correct record)

The first class is the ID value container:

public class IDCarrier {
    public IDCarrier(){}
    public IDCarrier(ID value){
        this.value = value;
    }
    public ID value{get;Set;}
}

In your test controller, TestLookupController:

public class TestLookupController {
    public IDCarrier idValue1{get;set;}
 public IDCarrier idValue2{get;set;}
    public TestLookupController(){
        this.idValue1 = new IDCarrier([Select Id From Account Limit 1].Id);
  this.idValue2 = new IDCarrier();
    }
    public void submit(){
  //...
 }
}

You are creating 2 ID fields, one populated with a valid Account Id, the other without any value.

And now in the test page use the component:

<apex:page controller="TestPageController" >
    <apex:form >
        <apex:pageblock>
            <apex:pageBlockButtons location="bottom">
             <apex:commandButton value="SUBMIT" action="{!submit}" />
            </apex:pageBlockButtons>
         <apex:pageblocksection columns="2">
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Account lookup</apex:outputLabel>
                 <c:inputLookup sobject="Account" value="{!idValue1}"/>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Selected Account ID:</apex:outputLabel>
                 <apex:outputText value="{!idValue1.value}"/>
                </apex:pageBlockSectionItem>
                
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Contact lookup</apex:outputLabel>
                 <c:inputLookup sobject="Contact" value="{!idValue2}"/>
                </apex:pageBlockSectionItem>
                <apex:pageBlockSectionItem>
                    <apex:outputLabel>Selected Contact ID:</apex:outputLabel>
                 <apex:outputText value="{!idValue2.value}"/>
                </apex:pageBlockSectionItem>
            </apex:pageblocksection>
        </apex:pageblock>
    </apex:form>
</apex:page>

The component has only 2 parameters:

  • sobject: this is the Sobject API Name (with full prefix name if needed, mandatory)
  • lookup: this is the value field (of type IDCarrier). This is field is not mandatory (in case it is not set, the submit won’t set any value)

In the test page we have now 2 input lookup custom components, one of type Account and the other of type Contact:

If you click the “search” button the standard lookup search page appears (it is configurable with the standard object’s search layout options).

Once you select a new value for both input lookups and hit the SUBMIT button, the corresponding controller variables idValue1 and idValue2 are correctly updated:

If you type a different name value (without using the lookup window):

Then hit SUBMIT:

The first “%Sale%” Account found is linked to the input lookup component.
If no object is found by the query, the result is simply null (on the IDCarrier.value member).

That’s it!

[Salesforce / Trailhead] Christmas Trailhead Gifts

Have you been a good or a bad boy this year?

It doesn’t matter to TrailheadClaus, so he put new modules under the tree for you!

At first we have a new trail for advanced administrators.

This includes Event Monitoring and Lightning Connect modules and the new Advanced Formulas module.

This module explains advanced features of the formula fields’s synthax, allowing to reach a high level of proficiency on this important feature of the platform, including examples and use cases with a great diversity of scenarios.
Do you wanna the a Formula Expert? This is your chance!

The next module is about callouts in Apex, Apex Integration Services:

What is a Callout? How to make a REST callout? And what about SOAP? How to test them? Follow this module and all your questions will be answered.

On the beginner admin trail an awesome Lightning Chatter Basics module, that guides you through the Chatter Lightning experience:

This is a complete and easy guide on how to use and configure Chatter in Lightning mode.

The Lightning Data Management module helps admins and developers to import CSV data in your CRM using the Lightning experience mode

The Application Lifecycle Management modulo has been edited and improved to better explain application lifecycle management (how to deploy in sandbox, production, version control, …):

Last but not least a trailhead comes with a new awesome project, Build a Battle Station App: create the CRM for your Death Star, so you can manage its resources and report all your supplies!

And if you complete it before December 31st you can win awesome prices!

[Salesforce / Amazon Echo] Integrate Alexa with Salesforce

Among the #swag I got from my colleagues from their trip to DreamForce 15, there was a pearl: Amazon Echo, well known as Alexa.

The first (funny) thing I wanted to do was to make it (her) speak italian, and believe me it was as fun as learning how to use the Alexa Skill Kit: the only language you can use is English of course but you can still make her say strange words that “sound like” italian (after practicing building the library, even you would call it “her”).

As usual, if you are a TL;DR person (btw I’m one of you guys), this is the GitHub repository with all the Apex Code.

If you know how to setup a Connected App and expose e public webservice, you are ready to go (some changes on the code are still necessary, refer to the README.md file).

When developing an Alexa Skill you have two choices:

In this post I’m not going to show you how Alexa’s Request/Response paradigm works, but instead I’ll show you how to use the simple Apex library I’ve developed to help you implement your own skills and make the provided example service run on your Org.

Why Salesforce?

First of all because the Force.com platform is awesome and you can easily create REST services in few steps.

Secondly because you can integrate Alexa with Salesforce services (read this awesome post by Jeff Douglas, he has already developed some cool examples in NodeJS playing with Alexa) using your CRM with just voice commands.

So instead of setting up a middleware between Alexa and Salesforce I thought that it would have been amazing to have the service built directly inside Salesforce!

The recipe

This is what we’ll be using:

  • A new Alexa Skill (defined in the developer portal)
  • A Salesforce Alexa Skill Kit implementation (the library)
  • A REST webservice (public, to whom Alexa will be speaking)
  • A Connected App (to enable OAuth, your service will be using an auth. token)
  • A Salesorce Community (custom domain + Branding + Profiles)
  • An Amazon Echo (don’t you say?!?)

Create a new Alexa Skill

The first thing is to define a new skill.

With your amazon account go to the Amazon Developer site.

Choose the Alexa Skill Kit and create a new skill:

The Invocation name is the name that you have to say when calling this skill (e.g. Alexa, ask alexaforce for my user).

The Endpoint is the URL of the service (it will be your custom Salesforce REST service inside the Community): for now add a fake endpoint, you’ll be configuring it later (after configuring the Community and creating the REST service).

Write down your new Application ID.

By clicking the Next button you are setting the skill’s schema:

We’ll be having 3 simple intents:

  • AlexaForceHelp: this helps the user by saying what you can do with this skill
  • AlexaForceStop: this is used when you don’t want to use the skill anymore (e.g. the AlexaFOrceHelp intent ask for a continuation, by saying “stop” the skill ends)
  • SFUserInfo: Alexa reads the full name of the current user (if he is logged)

The next configuration step sets up the SSL certificate option (this is all handled by Salesforce platform):

Click “Next” again and the Test step allow to do some tests with your service (no service is defined for now, so leave this step for now):

The last step is about branding:

And account linking:

This configuration can only be completed when the Connected app has been created so you can link you Salesforce account to the skill: Alexa will be sending to Salesforce REST service the authorization token got when activating the skill on the Alexa site.

For now get the Redirect URL and write it down somewhere but select Account Linking or Creation to No (we’ll be activating this further).

The skill is half configured: to complete the configuration we need some Salesforce configuration.

The skill is now connected to your developer account, so it is shown in the Skill section of your https://alexa.amazon.com site.

Implement your skill in Apex

First thing to create is a new Skill class by creating a new AlexaSkill object:

AlexaSkill skill = new AlexaSkill();
skill.setApplicationId('amzn1.echo-sdk-ams.app.APP_ID');
skill.addIntent(new AlexaUserInfoIntent());
skill.addIntent(new AlexaForceHelpIntent());
skill.addIntent(new AlexaForceStopIntent());
skill.addOnLaunchIntent(new AlexaForceHelpIntent());
return skill;

The setApplicationId sets the application you got from the first page of configuration of the skill on the Amazon site.

The next lines create the new intents.

Each intent is an extension of the AlexaIntent class:

public class AlexaForceHelpIntent extends AlexaIntent{
    public AlexaForceHelpIntent(){
        super('AlexaForceHelp');
        List<AlexaIntent.Slot> slots = new List<AlexaIntent.Slot>();
        List<String> utterances = new List<String>();
        utterances.add('Help'); 
        utterances.add('What to do');
        utterances.add('What can i do');
        utterances.add('What can you do');
        utterances.add('Help me'); 
        this.setSlots(slots);
        this.setUtterances(utterances);
    }
    
    public override ASkillResponse execute(ASkillRequest request){
        String responseText = 'You can use ask for Salesforce info. For example try asking Alexaforce for "my user".';
        return this.say(responseText, null, null, null, false);
    }
}

The intent have to provide:

  • Its describe informations, such as the slots you will use and the utterances (both are not mandatory but suggested to help the configuration phase of the skill)
  • The implementation of the execute() method that handles the code behind the intent

The AlexaSkill class, among various getters and setters (to get/get utterances, slots and the name) provides an helper method to automatically create a response, the say() method.

You can pass the following parameters say(String text, String cardTitle, String cardContent, String reprompt, Boolean shouldEndSession):

  • text: text to be “said” by Alexa
  • cardTitle: title of the card sent to your alexa app (void for no card)
  • cardContent: content of the card
  • reprompt: reprompt sentence
  • shouldEndSession: this response will or will not close the current session

The AlexaSkill class provides the following methods:

  • getIntentSchema(): provides a JSON rapresentation of the intent’s schema. This will be exposed by the REST service we are going to implement
  • getUtterances(): provides a JSON rapresentation of the intent’s utterances. Exposes by the REST service
  • addOnLauchIntent(): (and remove method) allow to set an intent called when you call your skill without saying any of the utterances (e.g. Alexa ask alexaforce. This may be used to guide the user
  • addIntent(): (and remove method) adds an intent to the skill
  • addDefaultIntent(): (and remove method) this is an intent that is called when Alexa asks for an intent but this has not (yet) been implemented (not mandatory)
  • execute(): this method has 2 implementation, we’ll be using the one returning a String and getting a String as the only parameters: this method simply accepts a request JSON string and output the JSON response (this is the core method of the skill)

This classes use the ASkillRequest and ASkillResponse classes that rapresent the JSON request and response object.

Implement the Apex REST service

Once we have implemented our skills, we can create our new Skill REST service:

@RestResource(urlMapping='/AlexaRestTest/*')
global class AlexaRestTest {
    @HttpGet
    global static void get(){
        AlexaSkillRESTApp.handleGet(createAlexaSkill());
    }
    @HttpPost
    global static void post(){
        AlexaSkillRESTApp.handlePost(createAlexaSkill());
    }
    
    //Creates a new Skill
    private static AlexaSkill createAlexaSkill(){
        AlexaSkill skill = new AlexaSkill();
        skill.setApplicationId('amzn1.echo-sdk-ams.app.APP_ID');
        skill.addIntent(new AlexaUserInfoIntent());
        skill.addIntent(new AlexaForceHelpIntent());
        skill.addIntent(new AlexaForceStopIntent());
        skill.addOnLaunchIntent(new AlexaForceHelpIntent());
        return skill;
    }

}

This REST service uses the AlexaSkillRESTApp helper class that handles the GET and POST methods: this class implements a simple Debug process by registering every request/response couple in the RestLog__c Sobject:

You can disable this behavior changing the following member on the AlexaSkillRESTApp class to return false:

public class AlexaSkillRESTApp {
    
    //Enable debug
    public static BOOLEAN ENABLE_DEBUG{
        get{
            //to be replace with a CS / Custom Metadata
            return true;
        }
    }
    //. . .
}

The GET method supports the parameter schema to which you can pass the values utterances to get the JSON rappresentation to be copied in the skill configufation on the Amazon Developer site or leave it blank to get all the intant definitions.

E.g. https://alexaforce-00-developer-edition.eu5.force.com/alexaforce/services/apexrest/AlexaRestTest?schema=utterances
Outputs:

SFUserInfo get my user info
SFUserInfo get my user
SFUserInfo my user
SFUserInfo user info
AlexaForceHelp Help
AlexaForceHelp What to do
AlexaForceHelp What can i do
AlexaForceHelp What can you do
AlexaForceHelp Help me
AlexForceStop Stop
AlexForceStop Bye
AlexForceStop Bye bye
AlexForceStop Shut up
AlexForceStop Shut the fuck up
AlexForceStop Go to sleep
AlexForceStop sleep

E.g. https://alexaforce-00-developer-edition.eu5.force.com/alexaforce/services/apexrest/AlexaRestTest?schema
Outputs:

{
  "intents" : [ {
    "slots" : [ ],
    "intent" : "SFUserInfo"
  }, {
    "slots" : [ ],
    "intent" : "AlexaForceHelp"
  }, {
    "slots" : [ ],
    "intent" : "AlexForceStop"
  } ]
}

The next step is to configure a public endpoint (es. the one provided in the example) to make this REST service available.

Configure the Community

The Salesforce community will be used to give public access to the REST service we’ll be implementing, to get a custom domain and to allow different profiles to get logged in into the community.

Go to Setup > Communities > Settings and enable Communities and create a custom domain (e.g. alexaforce-00-developer-edition.eu5.force.com).

Now create a new community and activate it:

Add the profiles you want to log into the community:

The community allow branding so you can change default styling (color and logo) with few clicks.

This is not the only valid solution (you could have used a simple Site with custom Visualforce pages).

Make the REST service public

Go to Setup > Developer > Sites and search for the Community site just created:

Click on its name:

And then on Public Access Settings. Search for the Enable Apex Class Access Settings and add the AlexaRestTest class:

This way your service will be accessible outside with the endpoint https://[community_base_url]/[community_endpoint_folder]/services/apexrest/AlexaRestTest: note that the [community_endpoint_folder] is not mandatory when configuring the Community access url.

You have to set this endpoint on the skill’s configuration:

Last step is to configure the account linking.

Implement a connected intent

In the code provided you have an intent that does a simple request that requires a valid session ID:

public class AlexaUserInfoIntent extends AlexaIntent{
    
    public AlexaUserInfoIntent(){
        super('SFUserInfo');
        List<String> utterances = new List<String>();
        utterances.add('get my user info');
        utterances.add('get my user');
        utterances.add('my user');
        utterances.add('user info');
        this.setUtterances(utterances);
    }
    
    public override ASkillResponse execute(ASkillRequest request){
        Http h = new Http();
        HttpRequest req = new HttpRequest();
        //change this with your current community folder name (or leave blank string)
        String communityFolder = '/alexaforce';
        String endpoint = URL.getSalesforceBaseUrl().toExternalForm()+communityFolder+'/services/Soap/c/34.0';
        req.setMethod('POST');
        req.setEndpoint(endpoint);
        req.setHeader('Content-Type', 'text/xml; charset=utf-8');
        req.setHeader('SOAPAction','getUserInfo');
        
        String authToken = request.session.user.accessToken;
        
        String soapBody = '<?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>'
                    +authToken+'</urn:sessionId></urn:SessionHeader></soapenv:Header><soapenv:Body><urn:getUserInfo /></soapenv:Body></soapenv:Envelope>';
        
        req.setBody(soapBody);
        HttpResponse resp = h.send(req);
        Dom.Document doc = resp.getBodyDocument();
        //Retrieve the root element for this document.
        Dom.XMLNode soapenvEnvelope  = doc.getRootElement();
        String SOAPENV_NS = 'http://schemas.xmlsoap.org/soap/envelope/';
        String NS = 'urn:enterprise.soap.sforce.com';
        Dom.XMLNode bodyNode = soapenvEnvelope.getChildElement('Body', SOAPENV_NS);
        Dom.XMLNode userinfoRespNode = bodyNode.getChildElement('getUserInfoResponse', NS);
        Dom.XMLNode resultNode = userinfoRespNode.getChildElement('result', NS);
        Dom.XMLNode fullnameNode = resultNode.getChildElement('userFullName',NS);
        String fullName = fullnameNode.getText();
        String responseText = 'Your user's full name is '+fullName;
        return this.say(responseText, 'Salesforce User Info', responseText, null, true);
    }  
}

The intent’s execute() method makes a call getting the (SOAP) UserInfo info about the current users associated to the authorization token provided with the request received (request.session.user.accessToken value): the response will be Alexa telling “You user’s full name is …”.

Remember to add a Remote Site Setting configuration to your community domain, otherwise the callouts won’t work.

The code is not optimized at all (you have to change the communityFolder variable to fit to your Community configuration).

Create a Connected App

Let’s enable OAuth within the Salesforce Org:

The Callback URL is set with the Redirect URL of the Skill configuration in the Amazon developer site (the one got at the beginning of the article).

The Consumer Key will be filled the Client Id field on the Skill configuration in the Amazon developer site (see the first part of this article)

The last piece of configuration of the Account Linking is the Authorization URL that should be the the Community’s login page like https://alexaforce-00-developer-edition.eu5.force.com/alexaforce/login: unfortunately when linking accounts Amazon’s Alexa Skills page doesn’t sends to the login page the redirect_uri parameter that is mandatory for successfull Salesforce OAuth process completion.

That’s why we need a custom login page that will be a proxy to the real login page: this is the AlexaOAuthStarter Visualforce page.

Open its controller class named AlexaOAuthStarterController:

public class AlexaOAuthStarterController {

    //Load action executed by the visualforce page called by Alexa's linked account attempt
    //ATTENTION: change the "communityName" and "alexaOauthCallbackURL" variables with the 
    //correct values
    public PageReference onLoad(){
        //change this with your current community folder name (or leave blank string)
        String communityFolder = '/alexaforce';
        //redirect uri configured in the Alexa Skill configuration
        String alexaOauthCallbackURL = 'https://pitangui.amazon.com/spa/skill/account-linking-status.html?vendorId=XXXXXXXXX';
        String communityURL = URL.getSalesforceBaseUrl().toExternalForm()+communityFolder;
        PageReference page = new PageReference(communityURL+'/services/oauth2/authorize');
        for(String k : ApexPages.currentPage().getParameters().keyset()){
            page.getParameters().put(k, ApexPages.currentPage().getParameters().get(k));
        }
        //appends the "redirect_uri" that amazon's configuration does not send
        //this class should be configured to change depending on the context (1 visualorce page per skill?)
        page.getParameters().put('redirect_uri',alexaOauthCallbackURL);
        return page;
    }
}

Replace the following variables:

  • communityFolder: replace with your community endpoint folder, if any
  • alexaOauthCallbackURL: the redirect URL got from Alexa’s skill configuration

This page will be your entry point for the authorization process.

Remember to enable this page to all the Community’s profiles.

Let’s finalize the configuration

Go again on the Alexa’s skill configuration page and let’s add the remainig configurations:

Where:

  1. https://[community_base_url]/[community_endpoint_folder]/AlexaOAuthStarter
  2. Consumer Key of the Connected App
  3. The domain of the community ([community_base_url])
  4. The redirect URL you have set up in the Connected App
  5. Add a fake URL for the privacy policy

Connect your skill

Your skill is ready to be used.

Go to the Skill section of your https://alexa.amazon.com site:

And click Enable (Chrome blocks the popup, so pay attention to the warning massages):

After you login allow the Connected App:

And you’ll be redirected to the following page (that you can close):

Now Alexa has your access token to make requests to your Community’s API interface (whether it is via SOAP or REST).

Remember: Salesforce sessions don’t last forever and the Amazon Skill documentation states that you are forced to disable and re-enable the skill if you have to refresh the access token.

Now try to say Alexa ask alexaforce for my user and she’ll magically cry out your name!

You have no excuse to develop some awesome app integrating Alexa with Salesforce.

Enjoy!

[Salesforce / Custom Settings] How and Why

This is a beginner’s guide to Custom Settings, that shows a practical way of using all the features they convey.

For TL;DR people, this is the GitHub repository of the example.

One of the greatest pros of the Force.com platform is the extraordinary quick development phase: even when you are under continous software development, you can change your processes implementation within minutes.

With great features come great responsibilities, that’s why you should give administrators, who may not be developers, the same power to configure the code flow.

Before the introduction of custom settings, the only options were:

  • Hard coding constants on your classes
    • Pros: Simple to handle for developers
    • Cons: You need a deploy every time you need to change a value

  • Creating custom objects where storing your configuration (even if only 1 set of data)
    • Pros: High flessibility
    • Cons: You need to do a query every time you need a configuration value (this could be painfull in large and complex implementations)

The introduction of Custom settings made developer lifes easier.

A Custom Setting is an SObject that is available in every execution context (i.e. within apex classes, triggers, visualforce pages, formulas, workflows, …) without the need of query, so basically you always have an instance of an object with all its fields ready to be used.

Let’s do it

Let’s start with a simple Visual Force page that shows, calling a public API, a random quote, *QuoteOfTheDay.page*:

<apex:page controller="QuoteOfTheDayController" action="{!onLoad}" tabStyle="Idea">
    
    <b><apex:outputText value="{!qod}" escape="false" /></b>
     
    <i>{!author}</i>
    
    <hr />
    
    <i>Quote of the day - <b>{!dt}</b></i>
    
    <br/> 
    
    <apex:pageBlock rendered="{!DEBUG_MODE}">
        <apex:pageBlockSection  title="Callout details" columns="1">
        
            <apex:pageBlockSectionItem>
                <apex:outputLabel value="Endpoint" />
                <apex:outputPanel>{!CALLOUT_ENDPOINT}</apex:outputPanel>
            </apex:pageBlockSectionItem>
            
            <apex:pageBlockSectionItem>
                <apex:outputLabel value="Timeout" />
                <apex:outputPanel>{!CALLOUT_TIMEOUT}</apex:outputPanel>
            </apex:pageBlockSectionItem>
            
            <apex:pageBlockSectionItem>
                <apex:outputLabel value="Error Message" />
                <apex:outputPanel>{!errorMessage}</apex:outputPanel>
            </apex:pageBlockSectionItem>
            
        </apex:pageBlockSection>
        
    </apex:pageBlock>
    
</apex:page>

public with sharing class QuoteOfTheDayController {
    
    public String CALLOUT_ENDPOINT{
        get{
            return ConfigurationManager.CALLOUT_ENDPOINT;
        }
    }
    
    public Integer CALLOUT_TIMEOUT{
        get{
            return ConfigurationManager.CALLOUT_TIMEOUT;
        }
    }
    
    public Boolean DEBUG_MODE{
        get{
            return ConfigurationManager.DEBUG_MODE;
        }
    }
    
    public String DATE_FORMAT{
        get{
            return ConfigurationManager.getDateFormat(UserInfo.getLocale());
        }
    }
    
    //quote of the day
    public String qod{get;Set;}
    //quote of the day author
    public String author{get;Set;}
    //date of request
    public String dt{get;set;}
    //debug message
    public String errorMessage{get;Set;}
    
    //loads the Quote of the Day on load
    public void onLoad(){
        
        //date of callout
        DateTime dateOfCall = System.now();
        
        try{
            Http h = new Http();
            HttpRequest request = new HttpRequest();
            request.setEndpoint(CALLOUT_ENDPOINT);
            request.setTimeout(CALLOUT_TIMEOUT);
            request.setMethod('GET');
            HttpResponse response = h.send(request);
            List<String> result = getQuoteFromResponse(response);
            this.qod = result[0];
            this.author = result[1];
        }catch(Exception e){
            this.qod = 'Something bad happened. Please reload';
            this.errorMessage = e.getMessage();
        }
        this.dt = dateOfCall.format(DATE_FORMAT);
    }
    
    /*
    Parse the "Quote Of The Day" API response (details @ http://quotesondesign.com/api-v4-0/)
    @return - List<String> contains 0 => quote, 1 => author 
    */
    public static List<String> getQuoteFromResponse(HttpResponse response){
        String resp = response.getBody();
        List<Object> jsonResponse = (List<Object>)JSON.deserializeUntyped(resp);
        Map<String,Object> quote = (Map<String,Object>)jsonResponse[0];
        String quoteString = (String)quote.get('content');
        String authorString = (String)quote.get('title');
        return new List<String>{quoteString, authorString};
    }
    
    public class CustomException extends Exception{}
}

On page load, the controller:

  1. Stores date/time of request
  2. Creates an HttpRequest setting its endpoint, timeout, method (GET)
  3. Sends the request and parses the response (getting the quote and the author)
  4. Formats the callout’s date depending of current User’s locale

The DEBUG_MODE allow to see some info about the current callout (for debug porpouses).

On the page controller we have no configuration, because they are written on the following utility class:

public class ConfigurationManager{
    
    //global endpoint
    public static String CALLOUT_ENDPOINT{
        get{
            return 'http://quotesondesign.com/wp-json/posts?filter[orderby]=rand';
        }
    }

    //global timeout in ms
    public static Integer CALLOUT_TIMEOUT{
        get{
            return 60000;
        }
    }

    //user/profile centric debug mode
    public static Boolean DEBUG_MODE{
        get{
            return false;
        }
    }

    //returns a specific date format given the locale code
    public static String getDateFormat(String localeCode){
        if(localeCode == 'it_IT'){
            return 'dd/MM/yyyy';
        }
        return 'MM/dd/yyyy';
    }

}

The result is:

Before running the page remember to add the http://quotesondesign.com endpoint among the trusted endpoints for the ORG, by selecting Setup > Security Controls > Remote Siste Settings.

Now let’s open the page:

You can change the hardcoded configurations on the ConfigurationManager class: let’s set the DEBUG_MODE variable to true:

This example clearly shows that it is hard, for non developers, to alter the configurations.

Here come the Custom Settings: they are Custom Objects that can be used without making any SOQL and are fitted to current User’s context.

Let’s create a new Custom Setting with Setup > Custom Settings > New:

The Hierarchic custom setting is a setting that has a global value for its fields which can be overridden on a per User / User’s Profile basis.

This will be more clear later.

A Custom Setting is just like a Custom SObject, so you can add all fields you want (with some exceptions on the types):

To set a value for the fields, click on the Manage button and then on the **Edit** button:

These are global values for the fields and they will be the only values we will be needing for this custom setting.

Set the same values we have on the ConfigurationManager class.

Let’s create another Custom Setting for the DEBUG_MODE flag:

Let’s set a global value with Manage > Edit:

Then click the New button on the lower section of the “Manage” page and add new values for the “System Administrator” profile:

This means that the Debugging custom setting will have a global value and a value fitted for System Administrator users: every administrator that will execute the page will see the debug section.

Finally let’s add the last custom setting for the date formats, by choosing a List type:

With the following fields:

This time, when creating a new value, we will have a set of values (remember the List type) instead of global/user/profile values, each one identified by a Name field:

For each locale code you can set a specific date format plus a Default value (to be handled manually).

Now that we have create all the settings, we need to link them to the code, so let’s change the *ConfigurationManager* class accordingly:

public class ConfigurationManager{
    
    //global endpoint
    public static String CALLOUT_ENDPOINT{
        get{
            return Endpoints__c.getOrgDefaults().Callout_Endpoint__c;
        }
    }

    //global timeout in ms
    public static Integer CALLOUT_TIMEOUT{
        get{
            return Endpoints__c.getOrgDefaults().Callout_Timeout__c.intValue();
        }
    }

    //user/profile centric debug mode
    public static Boolean DEBUG_MODE{
        get{
            return Debugging__c.getInstance().Callout_Debug_Mode__c;
        }
    }

    //returns a specific date format given the locale code
    public static String getDateFormat(String localeCode){
        Date_Formats__c defaultFormat = Date_Formats__c.getInstance('Default');
        Date_Formats__c localeFormat = Date_Formats__c.getInstance(localeCode);
        if(localeFormat != null) return localeFormat.Format__c;
        return defaultFormat.Format__c;
    }

}

From now on if you need to change the endpoint of the service, debug a specific user or change data format according to user locale, you will not need to change the code but you can train an administrator to do it by him self.

There is only some limitation:

In this brief article you have:

  • Created 2 different Hierarchic Custom Settings
  • Created a List Custom Setting
  • Managed all kind of values (global, profile, list)
  • Recalled their values from Apex controller
  • Been an **awesome** developer

Here are some useful resources:

  • GitHub repository of the article
  • Salesforce Docs: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_customsettings.htm?search_text=custom%20settings
  • Custom settings methods: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_custom_settings.htm?search_text=custom%20settings
  • Custom settings limits: https://help.salesforce.com/apex/HTViewHelpDoc?id=cs_limits.htm&language=en_US
  • Live example: https://blog-enreeco-community-developer-edition.eu5.force.com/examples/QuoteOfTheDay

[Salesforce / Lightning] Create your own Lightning Progress Bar

This is a repost from the article I wrote for the Salesforce Developer Blog.

Have you ever wanted a progress bar in your linghtning app?
I have and so I came up with a simple bootstrap library wrap up.

Following the successful Lightning series, I’m going to show you how I’ve made a simple Lightning Component out of the awesome Bootstrap library Bootstrap Progressbar (see details in the project’s home page).

For those who are in a TL;DR mode, here is the Github repository with the full code of the component and the demo app.

Let’s start with the component signature:

<c:ProgressBar 
 name="pb1" 
 valueMin="0"
 valueMax="1000"
 value="500"
 displayText="center"
 usePercentage="true"
 barContainerClass="progress-striped active" 
 barClass="progress-bar-info" 
 transitionDelay="10"
 displayText="center"/>

These are the attributes we can set:

  • name: name of the progress bar. This is used to ease events management
  • valueMin: bar minimum value, defaulted to 0
  • valueMax: bar maximum value, defaulted to 100
  • value: starting progress bar value
  • displayText: position of current value’s text (center or fill), blank for no text
  • usePercentage: shows the a % value text or value/max
  • barContainerClass: class of the container of the progress bar: this gives a style (leave blank for no additional effect, “progress-striped” for a “stripped” decoration and “active” to get a move)
  • barClass: this is to be applied to the bar, following the Bootstrap style (progress-bar-info, progress-bar-danger, progress-bar-warning, progress-bar-success, progress-bar-primary)
  • transitionDelay: delay in ms for the animation

This is an example of what you’ll see (simply use the provided app at https://YOUR_INSTANCE.lightning.force.com/c/ProgressBarApp.app):

The component uses 2 kind of events:

  • ProgressBarActionEvt: this is an event used to command the progress bar
  • ProgressBarMessageEvt: this is an event that is used by the progress bar to alert that the MIN/MAX values has been reached

ProgressBarActionEvt

<aura:event type="APPLICATION" description="Inbound event to guide the progress bar" >
    <aura:attribute name="value" type="Integer" default="" 
                    description="Value of the event"/>
    <aura:attribute name="name" required="true" type="String" 
                    description="Progress bar name"/>
 <aura:attribute name="action" required="true" type="String" 
                    description="Progress bar action"/>
</aura:event>

ProgressBarMessageEvt

<aura:event type="APPLICATION" description="Outboud event to guide the progress bar" >
    <aura:attribute name="value" type="Integer" default="" 
                    description="Value of the event"/>
    <aura:attribute name="name" required="true" type="String" 
                    description="Progress bar name"/>
 <aura:attribute name="message" required="true" type="String" 
                    description="Progress bar message"/>
</aura:event>

Both messages are really similar. Both have a name attribute to understand which progress bar should trap / fire the event, and a value attribute that has the value of the event.
The ProgressBarActionEvt has an action parameter that could have the following values:

  • Increment: increment by the value passed
  • Decrement: decrement by the value passed
  • FullFill: fullfills the progress bar
  • Reset: resets progress bar’s value
  • SetValue: sets a specific value

The app calls these actions in its controller’s button functions:

//...
increment10_p1 : function(component, event, helper) {
 helper.sendMessage("Increment","pb1",10);
},
//...

And in its helper:

({
 sendMessage : function(message,name,value) {
  var incrementEvt = $A.get("e.c:ProgressBarActionEvt");
        incrementEvt.setParams({
            name: name,
            value: value,
            action: message
        });
        incrementEvt.fire();
 }
})

On the other side, when we want to handle a message from the progress bar to the container app, we attach a handler to the event:

<aura:application>
    <aura:handler event="c:ProgressBarMessageEvt" 
                  action="{!c.handleProgressBarEvent}" />
 <!-- ... -->
 <div id="{!globalId+'_msg'}" />
//...
handleProgressBarEvent  : function(component, event, helper){
 var originName = event.getParam("name");
 var message =  event.getParam("message");
 document.getElementById(component.getGlobalId()+'_msg')
   .innerHTML = message+" event for progress bar named '"+originName+"' at "+(new Date()).toLocaleString();
},
//...

So every time a ProgressBarMessageEvt event is fired, the apps catches it and write down some of its info into the given DIV HTML component.

Finally let’s see how the component is constructed.
First we need to load jQuery and Bootstrap libraries and the required stylesheets:

<aura:component >
 <ltng:require scripts="/resource/BootstrapSF1/js/jquery-2.1.1.min.js,
             /resource/BootstrapSF1/bootstrap320/js/bootstrap.min.js,
             /resource/BootstrapProgressbar/bootstrap-progressbar.min.js"
        styles="/resource/BootstrapSF1/bootstrap320/css/bootstrap.min.css,
                /resource/BootstrapProgressbar/bootstrap-progressbar.min.css"
     afterScriptsLoaded="{!c.onInit}"/>
 
 <aura:handler event="c:ProgressBarActionEvt" action="{!c.handleEvent}" />
 <aura:registerEvent name="progressBarMsgEvt" type="c:ProgressBarMessageEvt"/>
 
 <!-- ... -->

And then define the place where the Bootstrap Progressbar will be drawn:

<!-- ... -->

<div class="{!'progress '+v.barContainerClass}">
 <div id="{!globalId+'_progbar'}" class="{!'progress-bar '+v.barClass}" 
   role="progressbar" 
   data-transitiongoal="{!v.value}"
   aria-valuemin="{!v.valueMin}"
   aria-valuemax="{!v.valueMax}"></div>
</div>

<!-- ... -->

This component will be fully configured by the “onInit” function of the component’s controller (that is called once all JS/CSS files are loaded):

//...
onInit : function(component, event, helper) {
        $("[id='"+component.getGlobalId()+"_progbar']")
        .progressbar({
            display_text: 'center',
            transition_delay: component.get('v.transitionDelay'),
            refresh_speed: component.get('v.refreshSpeed'),
            display_text: component.get('v.displayText'),
            use_percentage: component.get('v.usePercentage'),
            done : function(cmp){
                $A.run(function(){
                    if(component.get("v.value") >= component.get("v.valueMax")){
                        var evt = $A.get("e.c:ProgressBarMessageEvt");
                        evt.setParams({
                            name: component.get("v.name"),
                            message: "MaximumReached",
                            value: component.get("v.value")
                        });
                        evt.fire();
                    }
                    if(component.get("v.value") <= component.get("v.valueMin")){
                        var evt = $A.get("e.c:ProgressBarMessageEvt");
                        evt.setParams({
                            name: component.get("v.name"),
                            message: "MinimumReached",
                            value: component.get("v.value")
                        });
                        evt.fire();
                    }
                });
            }
        });
    },
//...

The done handler of the progress bar is used to fire the ProgressBarMessageEvt when the bar reaches min o max values.

handleEvent is the controller’s function that handles an incoming action event:

//...
 handleEvent : function(component, event, helper){
        var targetName = event.getParam("name");
        if(targetName !== component.get("v.name")) return;
        var targetIncrement = event.getParam("value");
        var action = event.getParam("action");
        var value = component.get("v.value");
        if(action === 'Decrement') value -= targetIncrement;
        else if(action === 'Increment') value += targetIncrement;
        else if(action === 'FullFill') value = component.get("v.valueMax");
        else if(action === 'Reset') value = component.get("v.valueMin");
        else if(action === 'SetValue') value = targetIncrement;

        var pb = $("[id='"+component.getGlobalId()+"_progbar']");

        if(value = component.get("v.valueMax")){
            value = component.get("v.valueMax");
        }
        component.set("v.value",value);
        pb.attr("data-transitiongoal",value).progressbar();
        
    },
//...

It simply checks progress bar name’s, action, value and executes the corresponding action.

The last command “redraws” the progress var with the new value, and executed the animation.

This is an example of fully javascript components you can make wrapping up existing javascript plugins.

Enjoy this component and may the Force.com be with you!

[Salesforce / Trailhead / Winter16] The Lightning fever: follow the trailhead!

Excited about the latest Lightning Experience announcement?

Me too but unfortunately it was published when I was on vacations without any internet connection, that’s why I read it days after its release, but I just thought “WOW!”.

with great power comes great responsibility, and the guys at Salesforce.com knows it, so they created some cool Trailhead modules to get you started, whether you are a developer, admin or a user.

Learn about why and how you can migrate to the new Lightning Experience, which are the differences and enhancements that has been made.

Watch the new Setup menu in action, saless tools, reporta and dashboards, customize the User interface and plan your rollout strategy: you can even decide which user will be using the new Lightning experience!

These set of modules are useful to understand user management, reports and dashboard creation, app customization (layouts, objects, fields) all with the new Lightning Experience interface.

If you are an experienced Salesforce.com admin you may find some of these modules way too easy, but I bet you’ll still find some new feature you didn’t know/expect!

Developers! That’s what we (most of us?) are!

These modules help you dig into the Lightning Experience as a developer: how can you use the Lightning Components? Is Visual Force dead (don’t worry, the answer is NO)?
The best feature IMHO? The Lightning Design System, finally a unique set of styles and HTML components to build custom applications with a look and feel that is consistent with Salesforce core features — without reverse engineering Salesforce styles!

…Without reverse engineering Salesforce styles!!!!

Finally some cool hints for users and how to use the new Lightning Experience interface (standard objects, list views appearance, dashboards, reports and feeds).

Next step (as usual)?

Page 22 of 27

Powered by WordPress & Theme by Anders Norén