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.

Acerca de José Luis Almazán

Senior Salesforce Developer y cofundador de ticMind Consulting (Consultoría Salesforce y Force.com y parter de Salesforce en Madrid). Poseo una amplia experiencia con más de 10 años en desarrollos en C# .NET, y más de 4 años en desarrollos en Salesforce. En la actualidad trabajo como Freelance en proyectos de Salesforce. Realizo trabajos de desarrollo, integración y administración de Salesforce CRM. Mi principal dedicación con Salesforce la he centrado en realizar desarrollos avanzados en Force.com. Poseo amplia experiencia en Visualforce, APEX, Remoting, Web Services, Future, SOAP API, REST API, Bulk API, Streaming API, Metadata API, Chatter REST API, Database.com, Sites, AJAX Toolkit, Triggers, Workflows... He realizado integraciones en Force.com con otros servicios, como Pusher, Tokbox, Box, WatchDox, Google Cloud Storage (XML API y JSON API), Google Maps API... Y en la parte cliente, amplia experiencia con HTML, HTML5, Javascript, jQuery, CSS... He trabajado en varios proyectos muy importantes de Salesforce, desarrollando entre otras funcionalidades, Chat, Videoconferencia, Mensajería interna, Gestión de eventos, Formularios WebToLead dinámicos, Generación de encuestas, etc... Además, fui un miembro activo de CloudSpokes, una importante comunidad crowdsourcing de más de 70.000 desarrolladores de todo el mundo, en cuyo ranking estuve entre los 35 primeros. Cofundador de ticMind Consulting, empresa especializada en Consultoría Salesforce.com y Force.com, y formada por un equipo estable de profesionales altamente cualificados y con gran experiencia en entornos cloud.
Esta entrada fue publicada en APEX, APEX REST Web Service, APEX SOAP Web Service, Force.com, Salesforce.com, Sites y etiquetada , , , , , , , . Guarda el enlace permanente.

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

  1. arjun dijo:

    Very informative Post.
    Could you please explain with example how to call the REST API from an outside application which is built on javascript.

  2. Piyush Kalra dijo:

    Very Helpful Sir. Really Appreciated

  3. Saludos, gracias por hacer publicaciones de este tipo en español.

    Ahora por favor necesito de tu apoyo para aclarar un punto que no se mencionan en este «how to».

    Cuando creas un Site uno de los campos obligatorios es contar con una visualforce que vaya ligada al site.

    ¿Hay que tener alguna visualforce?
    ¿o simplemente puedo seleccionar cualquiera de las opciones que muestra el campo?

    Gracias por el apoyo!

    • Hola Alejandro.

      Lo primero, gracias a ti por interesarte por mi blog, y lo segundo, pedirte disculpas por el retraso en mi respuesta.

      Cuando creas un site que sólo lo vas a usar para alojar tu Web Service, realmente no será un sitio visitable desde la web, es decir, es un sitio que carece de interfaz de usuario. Lo único obligatorio al crear un site, a nivel de páginas Visualforce, es el campo «Página de inicio de sitio Web activa». Como no va a ser un sitio visitable, yo seleccionaría la página Visualforce «UnderConstruction» por defecto, pero puede ser cualquiera de las que viene por defecto.

      Espero haberte ayudado.

      Un saludo.

  4. Muchisimas gracias por esta publicacion, a sido de gran ventaja. Quiero preguntarte, ahi alguna forma de pasar todo el JSON por el metodo, en lugar de parametro por parametro, mejor dicho algo asi?
    global static String doPost(String myWebInfo) {
    en lugar de
    global static String doPost( String name, String phone, String website) {

    pregunto esto por 2 razones, la primera si estoy recolectando mucha informacion se vuelve un poco tedioso poner muchas variable. Y la segunda aun no me queda claro como asi el metodo para saber la relacion con los parametros, asumo que es algo que salesforce tiene uno no se tiene q preocupar, pero me llama bastante la atencion que el orden de los parametros y es lo mismo poner
    global static String doPost( String name, String phone, String website) {
    que algo asi
    global static String doPost( String phone, String website, String name) {

    Gracias

Deja un comentario