La nueva función de XML en la integración de datos en nube

Usando XML para integrar los datos del Salesforce con aplicaciones empresariales

Aprenda a apalancar servicios web de XML para integrar datos de nube con aplicaciones empresariales, y construir una muestra de aplicación usando el API de servicios web del Salesforce con el Java API for XML Web Services (JAX-WS).

Ryan Knight, Senior Technical Evangelist

Ryan Knight es Senior Technical Consultant con más de 12 años de experiencia en ayudar empresas a apalancar las más recientes tecnologías. Ha trabajado con grandes y pequeñas empresas, como Oracle, IBM y Williams Pipeline y tecnologías apalancadas desde computación en nube hasta arquitectura empresarial. Usted puede leer más sobre su amplia experiencia con la tecnología Java y Adobe Flex en su blog en anvilflex.com.



04-08-2011

Computación en nube: redefiniendo TI

En el último año, hubo una explosión de la computación en nube para incluir las más diversas aplicaciones — tales como Salesforce CRM y Google Apps — y servicios —como IBM® DB2® hospedada en Amazon Elastic Compute Cloud (Amazon EC2), Google App Engine, y la plataforma Force.com de Salesforce. Esos servicios suelen ser denominados Platform-as-a-Service (PaaS), porque los servicios ofrecen una plataforma completa en la cual las empresas pueden construir y hospedar sus aplicaciones de TI.

Siglas más comunes

  • API: Application programming interface
  • HTTPS: Hypertext Transfer Protocol over Secure Sockets Layer
  • IT: Information technology
  • SOAP: Simple Object Access Protocol
  • UI: User Interface
  • URL: Universal Resource Locator
  • XML: Extensible Markup Language

Las ofertas de PaaS son hospedadas en un ambiente para varios usuarios, en el cual se comparte la infraestructura de hardware y software. Esos ambientes son configurados para asegurar que los datos de cada organización sean aislados de un modo seguro de las otras organizaciones — como si se rentara en vez de comprar espacio de oficina para que no necesite preocuparse con mantenimiento y actualizaciones. Con PaaS, las organizaciones tienen no sólo importantes ahorros de costos sino también ventajas como actualizaciones automáticas y cero mantenimiento. El modelo también ofrece una ventaja única para reducir los riesgos comunes a los nuevos proyectos de TI que suelen extrapolar el presupuesto y perder plazos.

Salesforce es un ejemplo de un proveedor de PaaS. La empresa empezó ofreciendo una solución hospedada de customer relationship management (CRM), y esa oferta generó una solución integral para aplicaciones empresariales comunes como ventas, gestión de la relación con socios, y marketing. Salesforce amplió esa plataforma hasta lanzar el Force.com. un PaaS completo para construir aplicaciones empresariales personalizadas, sea en un navegador o usando el integrated development environment (IDE) de Force.com. basado en Eclipse. Las aplicaciones también pueden ser personalizadas usando un lenguaje tipo Java™ de programación denominado Apex.

Salesforce le permite interactuar con el servidor usando un SOAP, que tiene la ventaja de ser independiente en términos de lenguaje y plataforma. Se usa Web Services Description Language (WSDL) para describir qué operaciones estarán disponibles en el servidor. Un documento de WSDL describe una serie de puntos finales de redes denominados puertas, que define el formato XML de los mensajes y datos que son intercambiados con el servidor.

Las muestras en este artículo usan Java API for XML Web Services (JAX-WS). JAX-WS ofrece diversas herramientas para simplificar el trabajo con XML y SOAP, incluso generando automáticamente los objetos necesarios de dominio de un documento WSDL y enlazando automáticamente los objetos XML a los Java.


Integrando el Salesforce con aplicaciones empresariales

Se puede proyectar aplicaciones que se integren al Salesforce de diversas formas. El primer método es configurar un flujo de trabajo en Salesforce para enviar un mensaje usando servicios web siempre que se cree o actualice un registro. Ese proceso usa un WSDL de mensaje de salida — un proceso similar a configurar un desencadenante en una base de datos. El flujo de trabajo configura el Salesforce para enviar un mensaje SOAP a un destino URL preconfigurado siempre que se crean, actualizan o eliminan datos. Por ejemplo, en el caso de Mileage en este artículo, se puede enviar un informe de kilometraje (mileage) a un sistema interno siempre que se agregue un nuevo informe.

El segundo método ofrece la posibilidad de interactuar directamente con Salesforce usando los servicios web SOAP. Ese método usa archivos WSDL generados por Salesforce que son consumidos por los servicios web personalizados. Para este tipo de integración, el Salesforce ofrece dos tipos principales de WSDL:

  • Partner WSDL es más general y puede ser usado en múltiplas organizaciones; es más difícil para trabajar con el Partner WSDL, porque el XML debe ser ordenado en la representación correcta del objeto para la organización.
  • Enterprise WSDL es más rígido y vinculado a una única organización, lo que facilita el trabajo con WSDL, pero sólo funciona dentro de los esquemas de una organización. Además, cualquier cambio en los objetos requiere que el WSDL sea regenerado.

Este artículo muestra la integración con Salesforce explayándose en el ejemplo usado en el Workbook de Force.com: una aplicación para rastrear el kilometraje (vea Resources para enlaces a los tutoriales). Como muestras, se usará el Enterprise Web Services WSDL.

Al trabajar con los servicios web de Salesforce, debe tener un token de seguridad. Para recibir o restablecer el token de seguridad, use la UI de Salesforce. Haga clic en Setup > My Personal Information > Reset your security token. Allí, encontrará una opción para restablecer su token de seguridad y que se lo envíen a su dirección de e-mail. Luego que tenga su token de seguridad, úselo en combinación con su contraseña para iniciar sesión. Por ejemplo, si su contraseña es aaaaaa y el token de seguridad es XXXXXXXXXX, debe insertar aaaaaaXXXXXXXXXX en el lugar de su contraseña.


Integrando con Salesforce a través de servicios web

Para dar un ejemplo de cómo usar XML para integrar con Salesforce, he desarrollado una muestra de aplicación Java que inicia sesión en Salesforce, consulta datos y crea nuevos registros. Todas las comunicaciones con el Salesforce pasan por el canal seguro HTTPS. Siga estos pasos para configurar los servicios web de Java para integrar con Salesforce:

  1. Genere el documento Enterprise WSDL en Salesforce.

    Inicie sesión en la cuenta de Salesforce de su organización y haga clic en Setup > Develop > API. Después, haga clic con el botón derecho en el documento WSDL que quiere generar.

  2. Genere los objetos de dominio y clases de Java del WSDL.

    Para la muestra, usé la herramienta wsimport inclusa en el conjunto de herramientas JAX-WS. Para simplificar el proceso de ejecución de wsimport, la muestra usa la plantilla de construcción que hace parte de las muestras de Salesforce. Los objetos de dominio Java que esa herramienta genera permite que los documentos XML sean automáticamente vinculados a objetos Java para simplificar la comunicación con el servidor.

  3. Inicie la sesión en Salesforce a través de los servicios web.

    Debe primero iniciar sesión para adquirir una URL del servidor e ID de la sesión. El código en la Lista 1 muestra cómo iniciar sesión.

    Una parte importante del inicio de sesión es conseguir el URL del servidor. Salesforce se ejecuta el múltiples instancias, tales como na1.salesforce.com o na2.salesforce.com, para mejorar la confiabilidad y desempeño. Después que inicie sesión en un servidor, necesita usar el mismo URL para todas las llamadas de servicios web subsiguientes, para mantener los datos de la sesión.

Lista 1. Inicio de sesión en Salesforce
    public void doLogin(String userName, String password) {
    if (userName.length() == 0 || password.length() == 0) {
            throw new RuntimeException("user name length and/or password length 
                cannot be 0 length. \n", 
                new IllegalArgumentException("Invalid password or user name\n"));
        } else {
            try {
                URL wsdlLocation = 
                    this.getClass().getClassLoader().
                    getResource("etc/enterprise.wsdl");
                if (wsdlLocation == null) {
                    WebServiceException e = 
                        new WebServiceException("enterprise.wsdl not found!");
                    //exceptionLogger(e.getMessage(), e);
                    throw e;
                }
                port = new SforceService(wsdlLocation, 
                    new QName("urn:enterprise.soap.sforce.com", 
                    "SforceService")).getSoap();
            } catch (WebServiceException wse) {
                //exceptionLogger("Error creating salesface port ", wse);
                throw wse;
            }

            try {
                loginResponse = port.login(userName, password);
            } catch (Exception e) {
                System.out.println("Error logging in to Salesforce.com " + e);
                return;
            }

            System.out.println("Login was successful.");
            System.out.print("The returned session id is: ");
            System.out.println(loginResponse.getSessionId());
            System.out.print("Your logged in user id is: ");
            System.out.println(loginResponse.getUserId() + " \n\n");
            System.out.print("The server url is: ");
            System.out.println(loginResponse.getServerUrl() + " \n\n");
            // on a successful login, you should always set up your session id
            // and the url for subsequent calls
          ....

Después de configurar la sesión del cliente, puede llamar e interactuar con el servidor a través de llamadas de servicios web. Este artículo abarca dos operaciones: lectura de datos del servidor a través de consultas y la adición de nuevos registros al servidor.


Consultando el Salesforce a través de servicios web

Para consultar los datos de Salesforce, debe usar un lenguaje especial llamado Salesforce Object Query Language (SOQL). Puede usar las consultas SOQL para buscar objetos específicos o campos de un objeto, similar a las consultas SELECT campos específicos en una tabla. También puede usar las consultas SOQL para contar el número de registros que cumplen con un criterio de búsqueda y ordenar los resultados de modo específico.

La mejor forma de familiarizarse con el SOQL es usar el Schema Explorer en el IDE de Force.com (vea Figura 1). Para abrir el Schema Explorer en un proyecto, haga doble clic en salesforce.schema en la raíz de su proyecto. En el Schema Explorer, puede navegar en todos los objetos de su organización, adentrándose en varios objetos, puede seleccionar objetos o campos individuales para generar una consulta automáticamente. Puede también incluir objetos relacionados en una consulta adentrándose en la lista de relaciones hijas para un objeto.

Figura 1. Schema Explorer
Schema Explorer

Cuando haya perfeccionado la consulta SOQL que desea ejecutar, incorpórela a su llamada de servicios web. El resultado de esa consulta es una representación XML de sus datos. Ese documento XML está automáticamente vinculado a los objetos de dominio Java que generó anteriormente con JAX-WS.

Para la muestra de aplicación, tiene que obtener todos los registros de kilometraje. Los resultados de la consulta están entonces vinculados a los objetos de dominio generados en la configuración, como en la Lista 2.

Lista 2. Resultados de consultas para la búsqueda de kilometraje
public void getMileageReports(ForceLogin login) throws UnexpectedErrorFault, 
        InvalidSObjectFault, InvalidIdFault, InvalidQueryLocatorFault, 
        MalformedQueryFault, InvalidFieldFault {

        QueryResult queryResult = login.port
                .query("Select Contact__c, Date__c, Miles__c from Mileage__c");
        
        if (queryResult.getSize() > 0) {
            List<SObject> records = queryResult.getRecords();
            for (SObject record : records) {
                MileageC mileageC = (MileageC) record;
                System.out.println(mileageC.getMilesC().getValue() 
                        + " " + mileageC.getContactC().getValue());
            }
        }

    }

Algo importante a tener en cuenta cuando escribe esas consultas es distinguir los objetos y campos personalizados de los objetos y campos estándar.  Los objetos personalizados son tablas personalizadas de base de datos de Salesforce que son específicas a una organización. Para asegurar que los objetos y campos personalizados sean únicos con respecto a los objetos estándares de Salesforce con el mismo nombre, añada __c después del nombre del objeto.  Eso los distingue de los objetos y campos estándares.

La consulta en la Lista 2 obtiene todos los registros del objeto Mileage.   Observe la convención __c que especifica los nombres de los campos personalizados del objeto de kilometraje.  Puede repetir el proceso con los resultados de consulta, vinculándolos al objeto MileageC, un dominio que fue generado a partir del enterprise WSDL.  Los objetos de MileageC serán automáticamente llenados con los datos reales para los registros de kilometraje.

La consulta anterior emitió todos los registros de kilometraje que suelen ser más de lo que uno necesita. Afortunadamente, es posible especificar un criterio de filtro — por ejemplo, una fecha o contacto — para que obtenga sólo determinados subconjuntos de registros. Supongamos que quisiera encontrar todos los informes en donde el kilometraje fuera mayor de 300. Puede alterar su consulta para que sea:

	Select Name, Miles__c From Mileage__c where Miles__c > 300

Otra forma de filtrar los datos es sólo obtener los datos que cambiaron a lo largo de un determinado período de tiempo. Para ello, use el método getUpdated (obtener actualizados) en vez de realizar una consulta, que toma el objeto buscado por actualizaciones durante una fecha de inicio y término. getUpdated emite todos los objetos que fueron cambiados en el período de tiempo especificado. El código en la Lista 3 emite todos los registros de kilometraje alterados en el último mes.

Lista 3: Cómo obtener registros de kilometraje actualizados
                      GregorianCalendar cal = 
                              port.getServerTimestamp().getTimestamp().
                              toGregorianCalendar();
            GregorianCalendar calEnd = (GregorianCalendar) cal.clone();
            cal.add(GregorianCalendar.MONTH, -1);
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
            GetUpdatedResult updatedRecords = port.getUpdated("Mileage", 
                    datatypeFactory.newXMLGregorianCalendar(cal), 
                    datatypeFactory.newXMLGregorianCalendar(calEnd));

Una operación similar a getUpdated es la getDeleted. Este método tiene la misma firma del método y emite todos los registros eliminados a lo lardo de un período de tiempo.

La otra opción para consultar el Salesforce es usar el Salesforce Object Search Language (SOSL). SOSL es similar a las búsquedas basadas en texto, permitiendo que sea con un formulario más libre. Con SOSL, se puede buscar en múltiplos objetos no relacionados, aún cuando no sepa qué objeto u objetos contiene los datos. Las consultas realizadas con SOSL también pueden emitir múltiples objetos no relacionados.

El código en la Lista 4— un ejemplo de una consulta SOSL de la muestra JAX-WS de Salesforce — es un excelente ejemplo de su flexibilidad. Este código consulta contactos, potenciales clientes y cuentas en búsqueda de un número de teléfono, mostrando cómo se puede buscar en múltiplos objetos no relacionados.

Lista 4. Cómo buscar un número de teléfono en múltiplos objetos
        SearchResult searchResult = port
                    .search("find {4159017000} in phone fields returning 
                            contact(id, phone, firstname, lastname), 
                            lead(id, phone, firstname, lastname), 
                            account(id, phone, name)");
            List<SearchRecord> records = searchResult.getSearchRecords();
            List<Contact> contacts = new ArrayList<Contact>();
            List<Lead> leads = new ArrayList<Lead>();
            List<Account> accounts = new ArrayList<Account>();

            if (records != null && !records.isEmpty()) {
                for (SearchRecord recordType : records) {
                    SObject record = recordType.getRecord();
                    if (record instanceof Contact) {
                        contacts.add((Contact) record);
                    } else if (record instanceof Lead) {
                        leads.add((Lead) record);
                    } else if (record instanceof Account) {
                        accounts.add((Account) record);
                    }
                 }
		}

En este ejemplo, el método search es utilizado en vez del query para ejecutar una consulta SOSL. Los resultados son mapeados en un objeto SearchResults y los registros individuales de los resultados de búsqueda son inspeccionados para determinar su tipo.


Adicionando datos al Salesforce a través de servicios web

Para adicionar datos al Salesforce, use los mismos objetos de dominio generados en el enterprise WSDL. Esos objetos son llenados con objetos normales, y luego serializados como XML hacia el servidor para persistencia. El único desafío está en crear relaciones entre diferentes objetos. Por ejemplo, supongamos que desea adicionar nuevo registro de kilometraje para un contacto específico. Primero, necesita buscar el ID de contacto que desea usar. En este ejemplo, busca contactos para una persona cuyo nombre es Edna, como en la Lista 5.

Lista 5. Cómo encontrar un contacto específico en la base de datos
  QueryResult qr = login.port
                .query("Select Id, FirstName, LastName, AccountId " +
                        "from Contact where FirstName = 'Edna'");

        String contactID = null;
        if (qr.getSize() > 0) {
            Contact contact = (Contact) qr.getRecords().get(0);
            contactID = contact.getId().getValue();
        }

Esta consulta provee el ID del primer contacto en una lista. (En una aplicación real, puede ser interesante hacer verificaciones de errores más extensas para asegurarse de que tiene el registro correcto). Cuando tenga el ID del usuario, lo almacena en su nuevo registro de kilometraje en la Lista 6.

Lista 6. Cómo crear un nuevo registro de kilometraje
	  MileageC mileageC = new MileageC();
        GregorianCalendar cal = new GregorianCalendar();
        cal.setTime(new Date());
        XMLGregorianCalendar activityDate = 
                DatatypeFactory.newInstance().newXMLGregorianCalendar(cal);
        mileageC.setDateC(soFactory.createMileageCDateC(activityDate));
        mileageC.setMilesC(soFactory.createMileageCMilesC(new Double(300)));
        mileageC.setContactC(soFactory.createMileageCContactC(contactID));

Ahora que ha configurado el registro de kilometraje, llame el método create en el servicio web para persistir el registro en el Salesforce. Tenga en cuenta que create toma una lista de objetos y le permite adicionar un conjunto de registros de kilometraje. Lista 7 muestra el código para persistir los datos en Salesforce.

Lista 7. Cómo salvar un nuevo registro de kilometraje en la base de datos
        // call the create method passing the array of tasks as Sobjects
        ArrayList list = new ArrayList();
        list.add(mileageC);
        List<SaveResult> saveResults = login.port.create(list);
        for (SaveResult saveResult : saveResults) {
            if (saveResult.isSuccess()) {
                System.out.println("saveResult success, id= " + saveResult.getId());
            } else {
                System.out.println("saveResult error");
                // there were errors during the create call, go through the
                // errors and write them to the screen
                List<Error> errorList = saveResult.getErrors();
                for (Error error : errorList) {
                    System.out.println("Error code is: "
                            + error.getStatusCode().toString());
                    System.out
                            .println("Error message: " + error.getMessage() + "\n\n");
                }

            }
        }

Este código persiste el registro en Salesforce y devuelve una lista de los resultados salvados, que muestra si el salvado tuvo éxito o fallos. Los mensajes de error que el Salesforce devuelve tienden a ser bastante descriptivos, lo que facilita entender qué anduvo mal. No obstante, ese abordaje sencillo no garantiza que los datos estén salvados adecuadamente en Salesforce. Para datos críticos, considere reintentar salvar los datos automáticamente hasta que estén salvados con éxito.

De forma similar, puede actualizar datos en el Salesforce. El modo más fácil es primer consultar el registro que desea cambiar, después cargar el registro en un objeto. Puede actualizar el objeto y luego llamar el método update.

La otra opción para actualizar datos es fusionar registros duplicados. Con una operación de fusión, especifica un registro principal junto con el registro que debe ser fusionado. De esta forma, se actualiza el registro principal con todos los datos del registro de fusión. Se puede fusionar hasta tres registros a la vez.


Conclusión

Al apalancar la fuerza del XML, usted puede integrar fácilmente los datos en nube en los aplicativos empresariales existentes. XML provee un formato de datos común que pueden ser intercambiados entre diversos servicios y lenguajes. La muestra de aplicación en este artículo ha demostrado cómo se puede interactuar con el Salesforce a través de servicios web de XML usando SOAP específicamente.

Esa técnica de utilización de servicios web para integrar aplicaciones en sitio con datos en nuevo también puede ser usada con diversas otras aplicaciones, desde Google Apps a Basecamp. Al realizar la integración con servicios en nube, las organizaciones pueden construir varias nuevas aplicaciones en la nube y también apalancar su inversión existente en software.

Recursos

Aprender

  • Force.com Fundamentals: Obtenga más información acerca de cómo el Force.com funciona con nube.
  • Force.com workbook: Aprenda más sobre cómo usar la plataforma Force.com para construir su propia aplicación on demand con el libro de ejercicios de Force.com.
  • JAX-WS: Aprenda más sobre JAX-WS que define las APIS y convenciones que suportan los protocolos de remote procedure call (RPC) basada en XML en la plataforma Java.
  • JAX-WS User Guide: Aprenda lo que necesita para usar el JAX-WS.
  • IBM XML certification: Descubra cómo ser un Desarrollador Certificado de IBM en XML y tecnologías relacionadas.
  • XML technical library: Vea la Zona XML de developerWorks para encontrar los más variados artículos y ayudas, tutoriales, estándares y Redbooks de IBM.
  • developerWorks technical events and webcasts: Manténgase actualizado con la tecnología en esas sesiones.
  • Technology bookstore: Busque libros acerca de este y otros tópicos técnicos.
  • developerWorks podcasts: Escuche entrevistas y discusiones interesantes para desarrolladores de software.

Obtener los productos y tecnologías

Comentar

Comentarios

developerWorks: Ingrese

Los campos obligatorios están marcados con un asterisco (*).


¿Necesita un IBM ID?
¿Olvidó su IBM ID?


¿Olvidó su Password?
Cambie su Password

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


La primera vez que inicie sesión en developerWorks, se creará un perfil para usted. La información en su propio perfil (nombre, país/región y nombre de la empresa) se muestra al público y acompañará a cualquier contenido que publique, a menos que opte por la opción de ocultar el nombre de su empresa. Puede actualizar su cuenta de IBM en cualquier momento.

Toda la información enviada es segura.

Elija su nombre para mostrar



La primera vez que inicia sesión en developerWorks se crea un perfil para usted, teniendo que elegir un nombre para mostrar en el mismo. Este nombre acompañará el contenido que usted publique en developerWorks.

Por favor elija un nombre de 3 - 31 caracteres. Su nombre de usuario debe ser único en la comunidad developerWorks y debe ser distinto a su dirección de email por motivos de privacidad.

Los campos obligatorios están marcados con un asterisco (*).

(Por favor elija un nombre de 3 - 31 caracteres.)

Al hacer clic en Enviar, usted está de acuerdo con los términos y condiciones de developerWorks.

 


Toda la información enviada es segura.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=90
Zone=Lotus, WebSphere, Cloud computing
ArticleID=427871
ArticleTitle=La nueva función de XML en la integración de datos en nube
publish-date=08042011