External Objects – What Lightning Connect offers to us

On my previous post, I talked about Lightning Connect and tried to explain with the Checa Hotel example how it worked.

This post is going to explain what you can do with one of the most important elements of Lightning Connect: External Objects.

What is an External Object?

This is a new type of object that will help us to visualize the information that we have in a external repository after creating a connection between Salesforce and this repo.

As a quick reminder from the previous post. We will be able to create an External Data Source linked to the External place and we will be able to create one or many External objects from there.

Captura de pantalla 2015-10-03 a las 19.00.55

How can we define it?

Captura de pantalla 2015-10-17 a las 11.35.08

These external objects will be created:

  • Automatically: via the Validate and Sync button that we can find in the External Data Source.
  • Manually: via its entry on the menu.

But in any case my advice is to take advantage of the automatic creation and use the manual one just in case you need to modify something.

How does an External Object look like?

We are going to continue with the same example as the previous post, the Checa Hotel reservations. And this is the external object.

Captura de pantalla 2015-10-19 a las 15.04.17

At a first sight it is similar to a custom one.

External Object vs Custom Object – Differences:

  1. API Name: It ends with __x instead of __c
  2. External Data Source: This field is populated with the External Data Source from where we have created the object. This field is required if you create the object manually.
  3. Table Name: This name is automatically created when you click on Validate and Sync button and is the name of the table found in the external repository once we have created the connection. This field is required if you create the object manually.
  4. Name Field: Here we will specify the field that will help us to open every single record when we create a tab related to this object. At least I couldn’t find a way to modify the value of this field, and the default value is the External ID standard field. However I can also say that if you create the connection via a Custom Connector instead of using Heroku, for instance, this value could be a different one. But this is something we will talk about in a future blog entry.
  5. All checkboxes that you can find on below image and belongs to a Custom object, here are missed. So we can now know that Reports are not provided. That could sound disappointing to some of you, but remember that this can change in the future, and also, you can always move this external object data to a custom object and create these reports and dashboards that you need.

Captura de pantalla 2015-10-17 a las 12.04.48

External Objects Sections:

Standard Fields

Captura de pantalla 2015-10-19 a las 15.08.41

I know what you are thinking. Where are the other fields like Created By, Last Modify By etc. ? Remember that these records till Summer’15 are not writable, so we don’t really need this information. We are just showing what we have in the external repository.

Here we will only find 2 fields:

  1. External ID: This field will help us to keep the uniqueness across the whole organization. This does not mean that the ID concept that Custom Object has are not applicable here. These records will also have an ID and we will see it later, but at the same time this External Id is required.
  2. Display URL: This is a link and if you click on it, in my case where I have read the information from the Google Spreadsheet, I will have the data in XML format of the record where I clicked this field.

Captura de pantalla 2015-10-17 a las 12.31.18

So, if we click on the Display URL field, we would get this information:

<?xml version='1.0' encoding='utf-8'?>
    <entry xmlns="http://www.w3.org/2005/Atom" 
      <title type="text"/>
      <link rel="edit" title="HotelReservation" href="HotelReservation(1)"/>
      <category term="InMemoryProducerExample.HotelReservation" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
      <content type="application/xml">
               <d:StartDate m:type="Edm.DateTime">2015-09-01T00:00</d:StartDate>
               <d:Price m:type="Edm.Double">125.0</d:Price>
               <d:ExternalId m:type="Edm.Int32">1</d:ExternalId>
               <d:Paid m:type="Edm.Boolean">true</d:Paid>
               <d:EndDate m:type="Edm.DateTime">2015-09-03T00:00</d:EndDate>
               <d:GuestName>Anne Kalen</d:GuestName>
               <d:RoomNumber m:type="Edm.Int32">1</d:RoomNumber>
               <d:SpecialRequirement>Balcony please</d:SpecialRequirement>

Custom Fields & Relationships

This is the section that looks like more similar to a custom object. Here we can find all the fields that the object will have. We will be able to define different types and different features. And if my Heroku application didn’t allow me to specify all that I really needed, I can make any change manually just clicking the Edit link beside the field.

Captura de pantalla 2015-10-17 a las 12.15.04

What could we miss?

We don’t see any relationship on above image, but we can really create Lookups for instance. What we would not allow to do is to create a Master-Detail relationship. But Salesforce give us a couple of workarounds to solve this situation.

  • External Lookup: This field type will help me to link 2 external objects, so if for any reason I have 2 different objects in my google spreadsheet and now I can see both in my Salesforce organization, I can link them via this field type that must be created manually because this is a Salesforce type that Java is not aware of it.
  • Indirect Lookup: This field type will help me to link an external object to a custom or standard one. Let’s talk more about this type with an example.

Captura de pantalla 2015-10-03 a las 20.12.08

Based on this image, I want to have somehow more information about my guests, in this case, Kim Rosenber. So that, I can save her information in order to send information about the hotel when we have special offers, or give her special discounts based on the number of reservations she has made with us. Because of that, I will create an Account per guest.

Captura de pantalla 2015-10-17 a las 13.03.29

Now, I would like to be able to click on my Guest Name in the HotelReservation record and go directly to the Account. Also I would like to be able to get all reservations related to each Account, so that, I can decide if this person deserves a special discount.

How can I get it? First of all we will need to create a field on Account object. The only requirement is that it should be External Id and it must be unique.

Captura de pantalla 2015-10-17 a las 13.26.29

Captura de pantalla 2015-10-17 a las 13.12.47

Secondly, we need to populate it with the information of my guest. This data should be the same as I have in the external object, so this time would be the name.

Finally on the External Object we need to modify the Guest Name field type from Text to Indirect Lookup and link it to Account object. As a tip, if for any reason, you don’t create the field on Account properly, it will not appear in the drop down list and you would not have the option to link your Hotel Reservation to Account.

Captura de pantalla 2015-10-19 a las 15.25.39And how does it look like?

Guest name has a link instead of being a simple Text field

Captura de pantalla 2015-10-17 a las 15.43.58

And if we add the related list in the Account object, we can also check all reservations that this person has made

Captura de pantalla 2015-10-17 a las 15.48.35

We could think that this is similar to usual Lookup fields. The main difference is that in this case I can click on the real Guest Name and navigate to the account. However, with a Lookup, we will need to have an Id value in the External Object in order to make the navigation possible.

Page Layout

Like custom objects, this section helps us to modify the look and feel of my record, changing the way that fields are sorted, if I want to add a new section, or blank space.

Captura de pantalla 2015-10-17 a las 12.15.54

Compact Layout and Search Layout

Simple, we have the option to create new Compact Layouts and determine if I require to add any custom button in the List View.

Captura de pantalla 2015-10-17 a las 12.16.23

Buttons, Links, and Actions

We can also perform another actions with these external objects. How? For instance, creating a button with some Apex Code in the background. At the end we could work with them as they were custom or standard objects.

Now, the use case is that every time a guest leaves the hotel, we need to print the invoice in pdf format.

Let’s think that we are doing this job for a custom object. So what should we do first?

  • Create a Custom Controller
public with sharing class HotelReservationController
   public ApexPages.StandardController controller;
   public Decimal amount {get; private set;}
   public Decimal totalAmount {get; private set;}
   public HotelReservation__x reservationInfo {get; private set;}
   public HotelReservationController(ApexPages.StandardController stdController)
     controller = stdController;
     Id reservationId = controller.getRecord().Id;
     amount = calculateAmount(reservationInfo.Price__c);
     totalAmount = calculateTotalAmount(reservationInfo.Price__c);
   public void calculateReservation(Id reservationId)
     HotelReservation__x reservation = [Select EndDate__c, 
                                         From HotelReservation__x
                                         Where Id = :reservationId
                                         Limit 1];
     reservationInfo = reservation;
   public Decimal calculateAmount(Decimal amount)
     return amount.setScale(2, RoundingMode.HALF_UP);
   public Decimal calculateTotalAmount(Decimal amount)
     Decimal tax = (amount * 21) / 100;
     Decimal totalAmt = amount + tax;
     return totalAmt.setScale(2, RoundingMode.HALF_UP);

As you can see on above code, the controller is really simple. It starts getting the Id of the record so YES!! we can also use getRecord() method with External Object.

And continue doing some calculations. The most important thing is the method where we run a SOQL query. HOW?? Yes, even we don’t have any data stored in our organization, Lightning Connect will allow us to perform such actions as well as SOSL. Also I would like to highlight that even we filter by the Id that we retrieved from the Controller, we would be able to use the External ID field as this is also have a unique field value.

  • Create a Visualforce page

My Visualforce page will be a pdf with the invoice for the guest. First of all the Standard Controller will be the External Object. And secondly we will extend the functionality with the Controller that we created above. The rest, simple, just call Controller methods and fields in order to show data that we need.

Captura de pantalla 2015-10-20 a las 8.30.28

So, is it not allowed to use visualforce tags like <apex:outputField> ? Of course you can use them. Imagine you want to create a Visualforce page with some Reservation data, go for it!! it will show the name of the field as well as the type that belongs to the data. However as this is a pdf, my option was to use directly divs with all data.

  • Create a button linked to the Visualforce page that we have just created and add it to the External Object Page Layout.

Captura de pantalla 2015-10-17 a las 16.02.53

At the end, this is the result. After clicking on the Invoice Print Invoice button

Captura de pantalla 2015-10-17 a las 16.54.35

We get this pdf ready to print and share with the customer

Captura de pantalla 2015-10-17 a las 16.53.14

Field Sets

We can also create a field set related to our External Object and show it in a Visualforce page, for instance.

My field set will not provide different information from the current page layout, but this is a good example to show how Field Sets also works.

First of all we will create the Field Set

Captura de pantalla 2015-10-17 a las 17.15.50

Secondly we are going to create a Visualforce page that we will use to override View mode on this External Object.

<apex:page standardController="HotelReservation__x" extensions="HotelReservationController">
  <apex:form >
    <apex:pageBlock title="Hotel Reservation">
      <apex:pageBlockSection title="Information">
        <apex:repeat value="{!fields}" var="f">
          <apex:outputField value="{!HotelReservationFieldSet[f.fieldPath]}"/>

Similar as before we will use the HotelReservation__x as standard controller and the extension will be the same as before. This time we are going to show dynamically all fields that we have included in the FieldSet. As right now we can find all of them, this is a good page to override the view mode of any Hotel Reservation record. If in the future we need to include more fields or make some modifications, code will be exactly the same, because, as I said before, we get data dynamically.

In the controller we have just added these 2 methods and their calls in the constructor:

public List<Schema.FieldSetMember> getFields()
  return SObjectType.HotelReservation__x.FieldSets.ReservationInformation.getFields();
public HotelReservation__x calculateReservationFieldSets(Id reservationId)
  String qry = 'Select ';
  for(Schema.FieldSetMember f : getFields())
    qry += f.getFieldPath() + ', ';
  qry += 'Id, ExternalId From HotelReservation__x Where Id = :reservationId limit 1';
  return Database.query(qry);

And this is the result

Captura de pantalla 2015-10-18 a las 8.41.03

What else can I do?

If you are one of these persons that usually works with portable devices like tablets and smartphones, you don’t need to worry about this new type of objects because Salesforce1 app and Lightning Connect also allow you to see this data.




Finally I would like to highlight some limitations (based on Summer ’15 release)

  • We can only have 100 External Objects per org
  • It doesn’t allow Master-Detail relationship, but as we show above, Lightning Connect offers 2 workarounds, External Lookups and Indirect Lookups
  • We cannot create reports and dashboards with their information. If this is really required for us we can always move the data to a custom object using some apex code, and then create the report from this object.
  • Triggers are not allow. I think that the reason is that actually we are not able to control what can happens outside of Salesforce.
  • Although we can perform SOSL and SOQL, we still have some limitations, like For Update is not allow today.
  • These objects are read only. It means, we cannot edit it and see the change in my google drive, for instance. I have already realized that Winter ’16 give us this functionality, but this is something that I will talk about in a future entry after doing some more researches.

I hope this post was useful for you and understand better what you can do with these new object types and how.

Snippet about my Dreamforce ’15 sessions

Dreamforce is the most important conference about Salesforce around the world, I’m sure that you already know about it, but if not, look at my first blog entry talking about my experience on such amazing place.

Do you go to Dreamforce’15 this year?

If not, don’t be upset. You can follow it in streaming and start thinking about a good strategy to be there next year. This article is quite useful to convince your manager to send to you 🙂

However, if you answer is yes, then …. I’m looking forward to knowing you in person!!! How can we do it?

Maybe we are lucky and meet in Moscone West center. But this is a big place, so maybe it is difficult to find each other. But I have an idea. What about if you register to attend my sessions?

1. Apex Connector for Lightning Connect – Make anything a Salesforce object

When? Tuesday 15th of September, 4.30pm

I’m sure you already know that in order to read an external repository and show that data in real time in your Salesforce org, you can use Lightning Connect. But how? First of all we need to create a connection, and this could be done by an existing OData provider or create it via OData protocol, Java and Heroku, for instance.

But since Summer ’15 we have a third option, use Apex Connector Framework that would help us to do this job just using Apex and all integrated in Force.com.

What should I do in order to create my connection in Apex? It is really simple. You will only need 2 classes.

Below image shows you a skeleton of the first one, the Connector, and how I need to override 3 methods:

Captura de pantalla 2015-08-10 a las 14.42.39

This second image will help you to understand how is the second class, the Provider where we also have to override 3 methods:

Captura de pantalla 2015-08-10 a las 14.43.20

Do you want to know more about that? Don’t miss my session. Remember, Tuesday 15th of September, Moscone West, at 4.30pm.

Will you not be able to attend? Don’t worry, Salesforce always publish sessions, so I will add a link to mine as soon as it is ready. Also don’t forget to follow my blog as I’m planning a new entry talking about Apex Connector.

2. Data Pipelines – Big Data meets Salesforce

When? Thursday 17th of September, 1.30pm

Actually I will share this session with the MVP Carolina Ruiz (@carolenlanube), and she will post an entry with some explanations about it on her blog soon. So follow Carol Code and Vogue and don’t miss it.

But as a quick summary, Data Pipeline is a feature that is under pilot program and helps to integrate Apache Pig and Salesforce. Having that, we will be able to execute Pig Scripts via the Developer Console, for instance, and process large amount of data asynchronously and in parallel.

Also, another advantage is the performance, that is much better than any other asynchronous feature that Salesforce offers to us right now.

Does it sound really cool? Yes, it is!! So don’t miss the chance to look us in action and show you how to create a Pig Script and get advantage of this pilot.

Remember!! 17th of September, 1.30pm Moscone West center.

See you there!!!

Mi primera Visualforce

This entry will talk about how to start working with Visualforce and Apex. We can find thousand of blogs in English that talk about this topic, however it is more difficult to find information in Spanish. Because of that, this entry will be in my home language so it will try to help Salesforce newbies in my country.

Esta será la primera de una serie de entradas que hablarán sobre Visualforce y Apex. Escribir una única entrada contando todo lo que me gustaría compartir, podría llegar a ser un post difícil de seguir, ó incluso llegar a aburrirte cerrando la ventana antes de terminar, y eso es lo que quiero evitar.

Aunque la entrada está escrita en Español, seguiré usando los términos ingleses por si tu entorno está en ese idioma.

Comencemos por el principio. Una vez que ya tienes tu entorno (org) Salesforce te ofrece ya algunos objetos que llamamos Standard. Dependiendo de la organización que tengas, podrás acceder a unos u otros, pero en principio tendrás acceso por lo menos a Accounts y Opportunities, así que vamos a utilizar esto dos objetos para los casos prácticos.

Cómo puedes leer en esta entrada, Salesforce se basa en el patrón MVC – Modelo Vista – Controlador. Cuando un usuario interactúa con una página, cualquier acción se manda al controlador el cual se encarga de ejecutar el proceso que la acción necesita con la ayuda del Modelo, y cuando éste finaliza, devuelve a la página el resultado para que lo pueda mostrar. Esto se puede hacer de dos formas, utilizando la funcionalidad Standard y la Custom. Recuerda estas dos palabras porque vamos a hacer referencia a ellas en muchos sitios.

  • ¿Qué significa Standar? Todo aquello que Salesforce te ofrece y puedes utilizar sin añadir una sola línea de código.
  • ¿Qué significa Custom? Si lo que Salesforce te ofrece no es lo que necesitas, lo puedes modificar. Para ello Salesforce te ofrece la posibilidad de hacerlo con sólo clicks de ratón, ó usando Apex y Visualforce.

Todo objeto en Salesforce, ya sea Standard ó Custom (el que creas tú con clicks de ratón) ofrece una vista que puedes utilizar en tu aplicación. Este es un ejemplo de un registro del objeto Account.

Account Record

Esta vista se puede modificar sin una línea de código. ¿Cómo? Edita el Page Layout del objeto hasta conseguir el look and feel que desees.

  • Si es un objeto Standar, cómo Account, ve a Setup | App Setup | Customize |  | Page Layout
  • Si lo has creado tú, es decir, es un objeto Custom, ve a Setup | App Setup | Create | Objects . En esta página, selecciona tu objeto y busca la sección Page Layout

Pero como hemos dicho anteriormente, puede que necesites algo más que ordenar los campos en el Page Layout del objeto.

Para ello crearemos una página visualforce que llamaremos accountview ya que nos servirá para mostrar los datos de la cuenta en modo lectura.

Esta página la enlazaremos con un controlador, y al igual que antes, todo objeto, Standard y Custom tiene su propio Controlador Standard y para usarlo, sólo tenemos que indicar el API name del object que vamos a usar. Posteriormente añadiremos una cuantas secciones con los tags pageBlock (para definir la cabecera la página) y pageBlockSection (nos ayuda a definir una sección) NOTA: podemos añadir tantos bloques y secciones en nuestra página, aunque lo más normal suele tener un único bloque con múltiples secciones.

<!-- accountview -->
<apex:page standardController="Account">
        <apex:pageBlock title="Vista Cuenta">
            <apex:pageBlockSection title="Campos Cuenta">

¿Cómo lo visualizamos en nuestro entorno? Simplemente tendremos que añadir a la URL /apex/, en nuestro caso: https://c.eu2.visual.force.com/apex/accountview y este es el resultado: Captura de pantalla 2015-02-08 a las 14.06.29 Nuestro siguiente paso será añadir campos a la sección Campos Cuenta utilizando el tag outputField. Vamos a crear una página con una apariencia similar a la que nos ofrece Salesforce, pero este ejemplo te puede ayudar a empezar a buscar cómo conseguir el look and feel que realmente quieres. Revisa los links que ofrezco para saber más de los tags que utilizamos en estos ejemplos. Todos ofrecen distintos atributos para personalizar la vista de la página.

<!-- accountview -->
<apex:page standardController="Account">
        <apex:pageBlock title="Vista Cuenta">
            <apex:pageBlockSection title="Campos Cuenta">
                <apex:outputField value="{!account.name}"/>
                <apex:outputField value="{!account.site}"/>
                <apex:outputField value="{!account.type}"/>
                <apex:outputField value="{!account.accountNumber}"/>

Y si volvemos a refrescar la página, vemos como en la sección Campos Cuenta aparece lo que hemos añadido, el Nombre, Tipo, Site y Número de Cuenta.

Captura de pantalla 2015-02-08 a las 14.13.08

Viendo esta imagen nos pueden surgir dos dudas.

  1. ¿Por qué el nombre de los campos viene en inglés? Porque estamos usando el controlador Standard de objeto Account, y la llamada account. traerá la etiqueta que hemos definido para ese campo. Mi entorno está en inglés, de ahí el obtener Account Name en vez de Nombre de Cuenta.
  2. ¿Por qué sólo veo la etiqueta de los campos y no el valor? Para poder mostrar los valores, debemos indicarle qué cuenta quiero mostrar. Salesforce asigna un identificador único (15 ó 18 caracteres) a todos sus registro. Es lo que llamaremos Id. Si añadimos ese id al final de la URL, le estamos diciendo a Salesforce que queremos ver la información relacionada a ese registro.
    1. ¿Cómo obtenemos este Id? Muy fácil, si abrimos el registro que queremos, pero usando su vista Standard, la URL nos lo proporciona.

Captura de pantalla 2015-02-08 a las 15.03.03

Después, podemos usar ese Id en nuestra nueva URL quedando así: https://c.eu2.visual.force.com/apex/accountview?id=001b000000Cw7X8 

Captura de pantalla 2015-02-08 a las 15.06.23

Podría seguir contándoos más cosas sobre las páginas Visualforce, pero creo que por hoy os he dado bastante información. En futuros post partiremos de este ejemplo para complicar la personalización de esta página.

Mi recomendación antes del próximo post:

  1. Lee y asimila cómo funciona el Modelo Vista Controlador de Salesforce.
  2. Familiarízate con los objetos Standard, su campos, sus Page Layout, etc.
  3. Crea algún objeto custom por ti mimo.
  4. Crea tu primera página Visualforce usando el Controlador Standard.
    1. Investiga los tags de hoy:
      1. apex:page
      2. apex:form
      3. apex:pageBlock
      4. apex:pageBlockSection
      5. apex:outputField

Hasta la próxima!!

Spring’15 is here – Some unknown issues

When I arrived at work last Monday, I could realice that most of our Development orgs were upgraded to Spring ’15 version during the weekend. That was a fantastic new, as we could start using new features that the new release offers.

I would like to talk more about some nice enhancements that Spring’15 brings to us, but these posts will be written in the future. Today I would like to mention a couple of changes that I found and made me also need to contact Salesforce.

Running some of our code that was working without issues on Winter’15, suddenly was failing and since the upgrade was the only change that we applied since last week, we started to think that the new behavior could be due to the upgrade.

As usual, my first try was to look for it on google, and it happened something complete new for me. Nothing related to the bellow topics. Next try, talk with some colleagues … they gave me some good advices, but nothing fixed the issues. After that I tried on StackExchange. Unfortunately , answers just confirmed what I was getting, so finally I raised some cases to Salesforce.

1. common.exception.SfdcSqlException: 
Unable to find column 'parent.NAME' in result set metadata

Have you ever seen this? It was my first time, but as one of my unit tests were returning the error, it was quite quick to identify the line that was causing it. I was trying to remove a feeditem record via code. Somehting so simple as:

delete [Select Id From myObject__Feed];

What did I try?

  • I commented the line in order to be sure that the error was not thrown somewhere else. But the test worked without it.
  • I created the feedItem and remove it manually. No issue at all.
  • I created the feedItem and executed the above line of code on Developer Console. It worked and the chatter post also disappeared from my org.
  • At this point I was thinking that the issue could be related with just the code, so the next step was to check with another API version. The latest one, the previous one … but the error appeared again.

Salesforce case status is escalated to Development support so we can say that something wired is happening with Salesforce and Chatter post and although I don’t have the answer yet to help you how to fix it, I will post it on this blog as son as I have. I know this is not an answer, but at least, you can confirm that you are not the only one getting it.

2. Insert failed. First exception on row 0; first error: 
FIELD_INTEGRITY_EXCEPTION, Related To ID: id value of incorrect 
type: a0S24000000HeEQEA0: [WhatId]

It looked quite familiar to me, and I’m sure that most of you know the reason as well. If you disable Allow Activity checkbox on a custom object, and you try to create a Task related to it you get this error. So you can think, which is the issue then? Winter’15 provided this exception:

Insert failed. First exception on row 0; first error: 
id value of incorrect type: a0Sw000000Nt4j9EAB: [WhatId]

However now Salesforce has updated the message and replace Opportunity/Account ID with Related To ID. The reason is quite simple, they have changed the Task WhatID label to Related To ID, and before its label was Opportunity/Account ID. You can find more information on documentation.

I would really appreciate any comment or feedback on this post related to other issues that you have found after the upgrade, or fixes.

In any case I would like to also say that Spring’15 offers amazing features and we should not be disappointed just because we found some issues at the beginning.