Salesforce Communities – Gestión automática de licencias Customer Community


Publicado en Force.com | Deja un comentario

Salesforce III Developer Day en Madrid el Miércoles 22 de Octubre de 2014


Publicado en Force.com | Deja un comentario

Batch Jobs: Concurrencia y Experiencia de usuario (part 1)


Mira que dan guerra los dichosos trabajos Batch… pero Carolina nos ayuda con este estupendo post.

Carol Code and Vogue

Trabajando con mi Business Analyst  ( cuando digo mi, no es que me haya comprado un Analista de Negocio para mí sola, es que  trabajaba conmigo en el mismo equipo )  me encontré con una serie de casos en los cuales necesitábamos procesar grandes cantidades de datos… ya sabéis que el mundo contable es una fiesta!! Tuvimos una serie de problemillas intentando no tener datos procesados a la vez por diferentes usuarios, por el mismo usuario incluso, no tener resultados dobles… y obviamente queríamos mantener al usuario informado del estado en que el proceso Batch que estaba procesando sus datos se encontraba. Me imagino lo que estáis pensando… bueno quizás lo que pensaba yo… Sabemos que a veces es un poco “doloroso” trabajar con procesos batch, por una serie de razones: tiempo de procesamiento,  solapamiento de procesos que pueden usar los mismos registros,  mantener al usuario informado cuando los resultados…

Ver la entrada original 1.083 palabras más

Publicado en Force.com | 2 comentarios

Salesforce Essentials Madrid y DeveloperZone el Jueves 06 de Marzo de 2014


Publicado en Force.com | Deja un comentario

JavaScript Remoting de Salesforce más allá de Visualforce y Apex. Proyectos Web en Force.com totalmente dinámicos.

Esta galería contiene 6 fotos


Más galerías | Deja un comentario

Entendiendo Salesforce communities


Publicado en Force.com | Deja un comentario

Primer Platform Day para técnicos en Salesforce España


Más galerías | 1 Comentario

Cómo crear Apex SOAP Web Services y Apex REST Web Services en Sites públicos en Force.com


Site.com

Cuando necesitamos realizar integraciones de nuestras aplicaciones con nuestra plataforma de Force.com, y de esta forma poder acceder a los datos de Salesforce.com de la manera más sencilla posible, o necesitamos exponer nuestros métodos APEX de Force.com para poder desarrollar, por ejemplo, aplicaciones móviles, Force.com nos da la posibilidad de poder crear Servicios Web basados tanto en SOAP como en REST.

El acceso a estos Servicios Web desde nuestras aplicaciones externas se realiza mediante autenticación. La forma de autenticarnos con Salesforce es usando OAuth 2.0. Pero, ¿qué ocurre si nuestros Servicios Web los incluimos dentro de un Site público de Force.com? Pues que en este caso no es necesaria la autenticación. Por lo tanto centraré este post en explicar cómo podemos acceder a nuestros Servicios Web de Force.com de forma anónima, sin necesidad de autenticarnos.

Debemos tener muy presentes los permisos que concedemos al perfil del usuario invitado del Site en el que publicamos nuestros Servicios Web, ya que los datos serán accesibles de forma pública.

Antes de nada, daremos un pequeño repaso a la creación de Servicios Web basados en REST y en otro post posterior lo haré sobre los Servicios Web basados en SOAP. La forma de crear estos servicios en Force.com es mediante código APEX.

Servicios Web basados en REST

La API REST de Force.com permite integrar aplicaciones externas con Force.com utilizando métodos sencillos de HTTP, ya sea con formato XML o JSON, haciéndolo ideal para desarrollar aplicaciones móviles o clientes externos.

Gestionar datos usando Force.com REST API

Gestionar datos usando Force.com REST API

Force.com nos facilita seis anotaciones que nos permiten exponer una clase de Apex como un servicio REST:

  • @RestResource(urlMapping=’/TuUrl‘).  Se usa a nivel de clase y te permite exponer tu clase APEX como un recurso REST. El mapeo de la URL es case-sensitive, es decir, distingue mayúsculas y minúsculas. Para utilizar esta anotación tu clase APEX debe ser definida como global.
  • @HttpDelete. Se usa a nivel de método. Este método es invocado cuando se envía una petición HTTP DELETE. Para utilizar esta anotación tu método APEX deber ser definido como global.
  • @HttpGet. Se usa a nivel de método. Este método es invocado cuando se envía una petición HTTP GET. Para utilizar esta anotación tu método APEX deber ser definido como global.
  • @HttpPatch. Se usa a nivel de método. Este método es invocado cuando se envía una petición HTTP PATCH. Para utilizar esta anotación tu método APEX deber ser definido como global.
  • @HttpPost. Se usa a nivel de método. Este método es invocado cuando se envía una petición HTTP POST. Para utilizar esta anotación tu método APEX deber ser definido como global.
  • @HttpPut. Se usa a nivel de método. Este método es invocado cuando se envía una petición HTTP PUT. Para utilizar esta anotación tu método APEX deber ser definido como global.

Sólo puede existir una anotación de cada tipo en la clase APEX. Es decir, sólo podremos tener una anotación del tipo @HttPost, por ejemplo.

APEX REST soporta dos formatos: JSON y XML, y se debe indicar el tipo utilizado en la propiedad Content-Type de la cabecera HTTP. El formato JSON es el que se utiliza por defecto en el cuerpo de una petición (HttpRequest) o respuesta (HttpResponse). A modo de resumen debemos tener en cuenta las siguientes consideraciones:

  • Los objetos RestRequest (HttpRequest) y RestResponse (HttpResponse) están disponibles por defecto en los métodos APEX a través del objeto estático RestContext. Este ejemplo muestra cómo podemos acceder a estos objetos:
    RestRequest req = RestContext.request;
    RestResponse res = RestContext.response;
  • Si el método APEX utilizado no tiene parámetros,  APEX REST copia el cuerpo de la petición HTTP en la propiedad RestRequest.requestBody, de tipo Blob.
  • Si se han definido parámetros en el método APEX utilizado,  APEX REST intenta deserializar los datos y convertirlos en los parámetros.
  • APEX REST usa una lógica similar de serialización para las respuestas. Si el método APEX está definido para devolver un tipo determinado, APEX REST serializa el valor correspondiente y lo devuelve dentro de la propiedad RestResponse.responseBody.
  • Los métodos con anotaciones @HttpGet o @HttpDelete no deberían tener parámetros. Esto es debido a que las peticiones HTTP GET y DELETE carecen de cuerpo, por lo que no habría nada que deserializar.
  • APEX REST actualmente no soporta peticiones con el Content-Type del tipo multipart/form-data.

A continuación puedes ver un ejemplo de una clase APEX expuesta como servicio REST obtenido de aquí:

@RestResource(urlMapping='/Account/*')
global with sharing class MyRestResource {

    @HttpDelete
    global static void doDelete() {
        RestRequest req = RestContext.request;
        String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        Account account = [SELECT Id FROM Account WHERE Id = :accountId];
        delete account;
    }

    @HttpGet
    global static Account doGet() {
        RestRequest req = RestContext.request;
        String accountId = req.requestURI.substring(req.requestURI.lastIndexOf('/')+1);
        Account result = [SELECT Id, Name, Phone, Website FROM Account WHERE Id = :accountId];
        return result;
    }

    @HttpPost
    global static String doPost(String name, String phone, String website) {
        Account account = new Account();
        account.Name = name;
        account.phone = phone;
        account.website = website;
        insert account;
        return account.Id;
    }
}

La url de acceso a nuestra clase APEX expuesta como servicio REST, utilizando autenticación OAuth 2.0, sería de la siguiente forma:

https://instance.salesforce.com/services/apexrest/urlMapping

Donde:

  • instance. Es el nombre de la instancia de nuestra organización.
  • urlMapping. Es la URL relativa de mapeo de nuestro servicio APEX REST.

Siguiendo este mismo ejemplo, si quisiéramos crear una cuenta nueva utilizando nuestro servicio REST, tendríamos que realizar una petición HTTP POST, con el Content-Type: application/json, a la url:

https://instance.salesforce.com/services/apexrest/Account

Y como cuerpo de la petición tendríamos que pasar el siguiente JSON:

{
  "name" : "José Luis ALmazán",
  "phone" : "690968879",
  "website" : "http://www.ticMind.es"
}

Como estamos realizando una petición POST, se ejecutaría el método APEX doPost() y Salesforce devolvería una cadena de texto con el Id de la cuenta que se acaba de crear:

"accountId"

Y básicamente ésta sería una pequeña introducción a los servicios APEX REST.

Todo esto está muy bien, pero como ya he dicho antes, resulta que en este ejemplo debemos utilizar autenticación OAuth 2.0 para poder acceder al servicio REST. Ahora pasaré a explicar qué debemos hacer para poder utilizar este mismo servicio REST de forma pública, sin necesidad de autenticación. Para ello, lo primero que debemos hacer es crearnos un Site o utilizar un Site que ya tengamos. Es muy importante indicar que Force.com Sites sólo está disponible para las ediciones: Developer, Enterprise y Unlimited.

Para crear un Site, siga los siguientes paso:

  1. Haga clic en Su nombre | Configuración | Desarrollos | Sitios -> Botón Nuevo.
  2. Cumplimente los campos necesarios y haga clic en el botón Guardar.
Crear Site

Crear Site

Ya tendríamos el Site creado. Para poder hacer público nuestro servicio REST en este Site, lo primero que necesitamos es conceder acceso al perfil del Site a la clase APEX de nuestro servicio REST, en el ejemplo anterior MyRestResource. Además, debemos conceder los permisos necesarios de lectura y/o escritura sobre los objetos implicados en nuestros métodos APEX REST. Para ello:

  1. Haga clic en Su nombre | Configuración | Desarrollos | Sitios.
  2. Haga clic en el nombre del sitio que desea controlar.
  3. Haga clic en Configuración de acceso público para abrir la página del perfil del sitio.
  4. Vaya hasta Acceso a clase de Apex activado y pulse sobre el botón Modificar para poder Activar la clase APEX correspondiente a nuestro servicio REST. Para aceptar los cambios pulse el botón Guardar.
  5. Si necesita conceder permisos a algún objeto (en el ejemplo anterior necesitaríamos conceder permisos de lectura/escritura sobre el objeto Cuentas), pulse sobre el botón Modificar (seguimos dentro de la Configuración de acceso público), vaya hasta los Permisos de objetos y seleccione los permisos necesarios. Para finalizar pulse sobre el botón Guardar.
Conceder permisos al perfil del Site

Conceder permisos al perfil del Site

Ya tendríamos publicado nuestro servicio APEX REST en nuestro Site, por lo que ya sería accesible de forma pública. En este caso, debemos es muy importante indicar que la url de acceso a nuestro servicio REST es diferente a la que indicábamos anteriormente, cuando el servicio REST requería autenticació. Al estar publicado dentro del Site, la url sería de la siguiente forma:

https://dominioForceCom/site/services/apexrest/urlMapping

Donde:

  • dominioForceCom. Es el nombre de nuestro dominio de Force.com en nuestra organización. En mi entorno de desarrollo, sería jlalmazan-developer-edition.na14.force.com.
  • site. Es el nombre de nuestro Site.
  • urlMapping. Es la URL relativa de mapeo de nuestro servicio APEX REST.

Y ya tendríamos nuestro servicio APEX REST accesible de forma pública.

Espero que os sirva de ayuda este post. Si os ha gustado, podéis seguir mi blog o seguirme en twitter.

Publicado en APEX, APEX REST Web Service, APEX SOAP Web Service, Force.com, Salesforce.com, Sites | Etiquetado , , , , , , , | 8 comentarios

Gestionar archivos de recursos de Salesforce desde el IDE de Force.com con el plugin ZipEditor


ForceZipEditorAntes de mi siguiente post, que centraré en la creación de un proyecto desde el IDE de Force.com, creo que es muy importante saber cómo podemos ver y poder editar los archivos de recursos que utilicemos dentro de nuestros desarrollos.

Las buenas prácticas aconsejan separar todos los recursos utilizados en un desarrollo, como por ejemplo, imágenes, archivos javascript, hojas de estilo, etc… y empaquetarlos dentro de un archivo de recursos estático. Así pues, un archivo de recursos es un archivo comprimido, en formato zip, guardado dentro de Salesforce y cuyo contenido es accesible desde nuestras páginas Visualforce y componentes Visualforce.

Para poder ver el contenido de los archivos de recursos dentro del IDE de Force.com, necesitamos tener instalado un editor de archivos zip. En mi caso, yo tengo instalado Eclipse Zip Editor y es el que utilizo como mi editor de archivos de recursos, pero podríamos instalar cualquier otro. Se trata de un plugin gratuito para Eclipse. A continuación indico los pasos necesarios para poder instalar este plugin en el IDE de Force.com.

Descargar el plugin

La forma de instalar los plugins en el IDE de Force.com sería de forma automática, indicando una url de descarga del plugin, o de forma manual. Como creo que no existe una url de descarga de este plugin (que me corrija alguien si me equivoco), lo haremos de forma manual, lo cual nos sirve para otros plugins que queramos ir instalando en nuestro IDE.

Lo primero que debemos hacer es descargarnos el plugin de la página oficial de sourceforge.net, Eclipse Zip Editor. Una vez en la página de descarga, pulsamos sobre el link de descarga de la última versión disponible:

Download Eclipse Zip Editor

Download Eclipse Zip Editor

Tras unos instantes, comenzará la descarga y guardaremos el archivo descargado. Por último debemos extraer el contenido del archivo zip descargado en la carpeta que queramos. Es importante indicar que esta carpeta no es temporal, sino que la utilizará el IDE de Eclipse como origen del site que crearemos a continuación, por lo que es conveniente tener bien ubicada la carpeta (por ejemplo dentro de la carpeta de instalación del IDE de Force.com, en una subcarpeta que llamaremos sites).

Instalar el plugin

El primer paso es abrir el IDE de Force.com. Si lo tenemos recién instalado veremos algo parecido a esto:

Inicio IDE Force.com

Inicio IDE Force.com

Pulsaremos sobre la opción Help del menú principal, lo cual nos despliega las opciones disponibles. Dentro de estas opciones, pulsaremos sobre Sorftware and Workspace Center:

IDE Force.com Software

IDE Force.com Software

Desde las nuevas opciones, pulsaremos sobre la pestaña de Software y después sobre el link add site:

Eclipse Zip Editor Installation

Eclipse Zip Editor Installation

Tras lo cual nos aparecerá una pequeña pantalla como la siguiente:

Eclipse Zip Editor Installation add site

Eclipse Zip Editor Installation add site

Pulsaremos sobre el link Add from Local Folder y seleccionaremos la carpeta en la cual tenemos el contenido descomprimido del archivo zip que descargamos en el punto anterior:

Eclipse Zip Editor Installation zip folder

Eclipse Zip Editor Installation zip folder

Aceptaremos y configuraremos un nombre para este site personal, como por ejemplo Eclipse Zip Editor:

Eclipse Zip Editor Installation add site ok

Eclipse Zip Editor Installation add site ok

Pulsaremos el botón OK lo cual nos llevará de nuevo a la pestaña de Software en la que estábamos previamente. En el apartado Personal Sites veremos ahora el nuevo site que acabamos de añadir Eclipse Zip Editor:

Eclipse Zip Editor Installation personal site

Eclipse Zip Editor Installation personal site

Desplegamos el contenido del site hasta llegar al plugin ZipEditor. Pulsaremos sobre el botón derecho del ratón para acceder a las opciones a realizar con este plugin y pulsaremos sobre Add to Profile… para añadir el plugin a nuestro IDE de Force.com.

En el apartado de Pending Changes veremos el cambio pendiente correspondiente a nuestro plugin. Pulsaremos sobre el botón Apply Change para cargar el plugin en nuestro IDE de Force.com:

Eclipse Zip Editor Installation apply change

Eclipse Zip Editor Installation apply change

Comenzará entonces la instalación del mismo. Una vez detectadas las dependencias necesarias, si todo está correcto, nos mostrará la pantalla del acuerdo de licencia. Es conveniente leer el contenido del acuerdo de licencia. si estamos de acuerdo con el contenido, pulsaremos sobre el check I acknowledge and accept ALL of the above licenses y sobre el botón Next. Pasamos a la siguiente pantalla en la que pulsaremos sobre el botón Update y así completamos la instalación del plugin en el IDE de Force.com. Por último nos pedirá que reiniciemos el IDE.

Una vez que volvamos a abrir el IDE de Force.com, ya estará disponible el editor de archivos zip.

Espero os sirva de ayuda.

Publicado en Eclipse, Force.com, IDE, Plugins de Eclipse, Salesforce.com | Etiquetado , , , , | Deja un comentario

Post ‘multipart/form-data’ out of Salesforce.com with APEX


¿Es cierto que Salesforce no permite realizar peticiones HTTP (callouts) con datos multipart/form-data desde APEX? Pues la respuesta es que Salesforce sí lo permite, lo único que tenemos que tener en cuenta es qué tipo de datos admite el servidor destino al que enviamos la petición.

Esto es muy importante cuando queremos subir archivos desde Salesforce (vía APEX, por supuesto) a un servidor externo a Salesforce, como Box o WatchDox, por ejemplo. Esto resulta económicamente rentable, cuando el coste de almacenamiento del servidor externo es inferior al coste de almacenaniento de Salesforce.

Lo primero que debemos averiguar es qué tipo de datos admite el servidor externo en las peticiones con datos multipart/form-data. Puede ser que el servidor externo sólo admita contenido binario, o puede ser que admita contenido codificado en base64, o ambos.

En el primero de los casos, en el que el servidor destino sólo admita contenido binario, Enrico Murro, miembro de Cloudspokes al igual que yo, ha desarrollado hace escasos días una magnífica solución, que puedes ver aquí. Se trata de una solución que muchos desarrolladores de Salesforce estaban esperando, y que gracias a este reto de Cloudspokes en el que ambos hemos participado, pudimos investigar a fondo sobre este tema.

Si el servidor destino admite también contenido codificado en base64, en este caso la solución es mucho más sencilla. Esta fue la opción que yo opté para este reto, ya que el servidor destino admitía ambos tipos de contenido.

A continuación muestro un código de ejemplo para este tipo de servidores:

public static HTTPResponse uploadFile(String fileName, Blob fileBody, String contentType){

		// Body
		String boundary = String.valueOf(DateTime.now().getTime());
		String body = '------------' + boundary + '\r\n';
        body+='Content-Disposition: form-data; name="data"; filename="' + fileName + '"\r\n';
        body+='Content-Transfer-Encoding: base64\r\n';
        if ((contentType == null) || (contentType == '')){contentType = 'application/octet-stream';}
        body+='Content-Type: ' + contentType + '\r\n\r\n';
        body+=EncodingUtil.base64Encode(fileBody);
       	body+='\r\n------------' + boundary + '--';

		// Instantiate a new HTTP request, specify the method (POST) as well as the endpoint
		HttpRequest req = new HttpRequest();

		// Set headers
		req.setHeader('Content-Type', 'multipart/form-data; boundary=----------' + boundary);
		req.setHeader('Content-Length',String.valueof(body.length()));

		// Set body
		req.setBody(body);

        // Set method and endpoint
		req.setMethod('POST');
		req.setEndpoint('http://www.TuServidorExterno.com');

		// Send HTTP request and get HTTP response
		Http http = new Http();
 		return(http.send(req));
    }

Puedes ver el vídeo de esta funcionalidad en acción correspondiente a mi solución creada para el reto de Cloudspokes, la cual permite subir todo tipo de archivos de hasta 3Mb a WatchDox desde Salesforce. Si el explorador web soporta HTML5, se pueden seleccionar varios archivos para subirlos en el mismo proceso, soporta drag&drop, y además se muestra una barra de progreso por cada archivo que se quiere subir.

Espero que este post os sirva de ayuda.

Publicado en APEX, Force.com, HTTP POST, HttpRequest, Salesforce.com | Etiquetado , , , , , , | 10 comentarios