Servicio para obtener datos de SAP
Servicio para enviar datos a SAP
Obtener template del XML de entrada
Acceso al servicio sin seguridad
Acceso al servicio restingido por Usuario/Password
Acceso a servicios que reciben XML de entrada y retornan XML de salida
Copyright Ó ARTech Consultores 1988-2002.
Todos los derechos reservados. El presente documento no puede ser duplicado de ninguna forma sin el expreso consentimiento de ARTech Consultores SRL. La información contenida en este documento es para uso personal del lector.
TRADEMARKS
ARTech, GeneXus, GeneXus Query y GXplorer son marcas o marcas registradas de ARTech Consultores S.R.L.
ARTech reconoce que el resto de las marcas registradas contenidas adjunto son propiedad de sus respectivos dueños.
En las empresas que usan SAP, se presenta la necesidad de cubrir funcionalidades no resueltas por SAP o cuya forma de resolverla no se adapta exactamente a los requerimientos del usuario.
En la mayoría de los casos dichas aplicaciones deben interactuar con los datos de SAP (leer y/o grabar datos).
Si bien siempre fue posible la comunicación entre sistemas generados con GeneXus y SAP, ésta ha evolucionado en muchos aspectos hasta llegar a una comunicación estándar basada en XML.
Partiendo de esa base y considerando que GeneXus implementa funciones para el manejo de XML, la comunicación con SAP se torna muy sencilla y natural.
El software utilizado para la integración puede ser SAP Business Connector o BizTalk de Microsoft (http://www.microsoft.com/biztalk/default.asp), ya que este cuenta con componentes de software adicionales que le permiten a BizTalk Server conectarse con aplicaciones de terceros tales como SAP, J.D. Edwards y PeopleSoft. En particular el adaptador para SAP fue producido directamente por Microsoft.
SAP R/3 es un software de origen alemán, el mismo es un sistema ERP (Enterprise Resource Planning) el cual esta básicamente dividido en módulos (SD – Ventas, FI – Financiero, etc.), esta desarrollado en un lenguaje propietario (ABAP4).
Para acceder a los objetos de negocios SAP (Clientes, Materiales, etc., en definitiva ‘cajas negras’ que encapsulan los datos R/3 y los procesos de negocio) debido a que tiene una arquitectura basada en componentes la cual permite interactuar e integrar SAP con terceras partes, se utiliza la tecnología de BAPIs (Business Application Programming Interfaces).
Si bien estos objetos de negocios no cubren un 100% de las funcionalidades SAP, lo hacen en una gran parte.
Esta visión orientada a objetos y su acceso a través de BAPIs está creciendo, por lo tanto se continúan agregando nuevas.
Los objetos de negocio SAP revelan solamente su interfase, la cual consiste de un conjunto de métodos bien definidos. Las aplicaciones no SAP, pueden acceder a los datos de los Business Objects solamente a través de los métodos de los objetos.
Por ejemplo, un método que se puede usar con el Business Object ‘Empleado’ es ‘chequee la existencia del empleado’.
Los métodos pueden consultar datos de los Business Objects o modificar datos de éstos.
Todos los tipos de Business Objects y sus métodos están identificados y descriptos en el Repositorio de Business Objects de R/3 (BOR) o en internet en http://ifr.sap.com/catalog/query.asp.
Para usar un método de una BAPI, una aplicación solamente debe saber como llamar al método, o sea debe conocer la definición de la interfase del método.
Se pretende lograr integración transparente entre aplicaciones generadas con GeneXus e instalaciones SAP utilizando la tecnología de BAPIs.
Para implementar la comunicación entre GeneXus y SAP se utiliza la tecnología de BAPI’s (Business Application Programming Interfaces) o funciones RFC (remote function call) y el software Business Conector de SAP o BizTalk Server de Microsoft, que recibe los requerimientos del sistema desarrollado en GeneXus (ya sea una petición de datos a SAP o un envío de datos hacia SAP) y dispara la función remota que obtendrá los datos de SAP o procesará los datos recibidos.
A continuación se detalla una de las soluciones posibles, en este caso la solución mostrada utiliza:
SAP Business Connector permite la integración de diferentes aplicaciones y tecnologías con sistemas SAP a través de estándares abiertos y no propietarios.
Utiliza Internet como plataforma de comunicación y permite comunicación bi-direccional desde y hacia sistemas SAP.
Business Connector consiste en el Business Connector Server y el Business Connector Integrator (Develop).
Debe instalar BC en un servidor y para acceder a la pantalla de administración simplemente digite en un web browser la dirección de BC (por defecto: http://xxx.xx.xx.xx:5555 donde xxx.xx.xx.xx es la IP del servidor y 5555 es el puerto por el cual se comunica, si lo esta ejecutando directamente en el servidor puede digitar http://localhost:5555)
Las tareas de administración más comunes son:
Arrancar y finalizar el servidor
Configurar el servidor
Configurar usuarios y seguridad
Manejar paquetes y servicios
Al conectarse solicita usuario/password, por defecto es Administrator/manage.
El servidor BC alberga los paquetes quienes contendrán los servicios y sus archivos relacionados.
Se debe definir la conexión al servidor SAP con el cual interactuaran los servicios a definir.
Esto se realiza en el área Adapters, opción SAP.
Dentro de ésta se selecciona Add SAP Server.
Los datos básicos que se deben completar son:
Nombre al sistema.
Usuario y password con el cual se conectara al sistema R/3 y mandante.
Se debe indicar la dirección IP del servidor de aplicación y el numero de sistema.
Una vez definida se puede probar la conexión oprimiendo el botón Test Connection.
Para ejecutar BC Integrator, quien permitirá crear y trabajar con los distintos servicios que definiremos, se debe instalar en el equipo Cliente y requerirá una conexión a SAP BC Server.
Se ejecuta desde InicioàProgramasàSAP BCàSAP Business Connector Integrator 4.0
Para definir los servicios (los cuales obtendrán y/o introducirán datos a SAP) utilizaremos el lenguaje de flujo webMethods.
Un
paquete contiene un conjunto de servicios y sus archivos relacionados tales
como especificaciones, registros y templates de salida.
La idea sería crear un paquete por proyecto o por sistema, o sea, crear uno y colocar dentro todos los servicios que estén relacionados de alguna manera.
Todos los servicios y archivos colocados en un paquete podrán ser fácilmente manejados como una unidad.
Todos los servicios en el servidor deben pertenecer a un paquete. Antes que se pueda dejar un servicio disponible para ser usado se debe cargar el paquete al cual pertenece.
Los paquetes se definen en BCIntegrator desde FileàNew, hay que indicar que lo que se esta creando es un paquete y colocarle un nombre.
Una
vez definido el paquete se debe crear, también desde FileàNew, una carpeta dentro del paquete
creado.
El servidor almacena los paquetes físicamente en sapbc40\serverpackages, el nombre del subdirectorio que creará dentro de éste es el nombre del paquete.
Si lo que se desea es solamente obtener datos de SAP, si bien se puede utilizar una BAPI ya existente, también se puede utilizar una función RFC escrita por nosotros.
Si este es el caso, para crear un servicio que nos retorne los valores de la misma se procede como sigue:
Seleccionar desde BCServer AdaptersàSAP, a continuación seleccionar Lookup.
En este punto lo que se hará es crear el servicio indicándole cual será la función RFC en SAP R/3 que ejecutará indicando en el área RFC lookup, el nombre del servidor R/3 (ver Definición servidor SAP).
Se digita el nombre de la misma en la ventana de Functión By Name y se oprime el botón Lookup.
Para definir el mapeo, se oprime el link Define New Map de SAP BCàSAP.
Finalmente se indica el nombre de la carpeta donde residirá el servicio, el nombre de éste, con el cual luego se invocará, el paquete y se graba.
Lo que resta por hacer es definirle al servicio el template del XML que devolverá, el cual depende de los parámetros de salida de la función que estemos invocando.
Esto lo hacemos
desde BCIntegrator, donde veremos el nuevo servicio recién definido (si ya nos
encontrábamos conectados a BCIntegrator en el momento que realizamos el mapeo,
para poder ver el servicio recién creado oprimir el botón Refresh ).
Seleccionamos el servicio y en la solapa de Settings se le asigna el nombre al template de salida del servicio y se indica que será de tipo xml.
Oprimiendo el botón Edit, se especifica el template del XML de salida que devolverá éste.
Los pasos de que constará, en la solapa Flow ya fueron definidos automáticamente, en este caso solamente se utilizará el servicio INVOKE, como se muestra a continuación:
En este momento ya estamos listos para poder invocarlo.
Para invocarlo http://xxx.xx.xx.xx:5555/invoke/FOLDER/NombreServicio
Para invocar con parámetros
http://xxx.xx.xx.xx:5555/invoke/FOLDER/Precios?IN_FECHA=2000-01-01
Para definir servicios que envían datos a SAP, tenemos dos alternativas, si bien siempre es recomendable que el alta de los datos lo ejecutemos a través de una Bapi, podemos llamar directamente a ésta o hacerlo a través de una función RFC la cual haga el call a la Bapi.
Explicaremos a continuación la definición de un servicio que invoca una función RFC la cual hace un call a una Bapi, esta función recibirá los parámetros de entrada en formato XML y devuelve los resultados en igual formato.
La definición del servicio se efectúa de la misma manera que se explicó en la sección anterior (Servicios para obtener datos de SAP).
La diferencia se da en el flujo de Servicios que debemos definir dentro de nuestro servicio en BCIntegrator.
Este es el siguiente:
service: pub.web:queryDocument
service: pub.web:documentToRecord
label: INVOKE sap:OutboundRFC service: sap:OutboundRFC
service: pub.report:runTemplateOnPipe
service: pub.flow:setResponse
A continuación se muestra como quedaría el flujo de servicios utilizados, para una creación de pedido de ventas.
Pipeline para pub.web:documentToRecord
Pipeline para INVOKE sap:OutboundRFC: OutboundRFC
Pipeline para pub.report:runTemplateOnPipe
Pipeline para pub.flow:setResponse
La Segunda alternativa es crear un servicio que invoque directamente a una Bapi.
Para hacer esto seleccionar desde BCServer AdaptersàRouting...
En esta pantalla podremos agregar una Routing Rule, estas reglas de ruteo son las que mira BC cada vez que llega un call (ya sea desde SAP con el protocolo RFC o desde un sistema externo con el protocolo http), y de acuerdo a la información que extrae acerca del Sender, Receiver y MsgType busca una regla que matchee con esto.
Para definir dicha regla seleccionamos Routing Rules, lo cual nos muestra las existentes y permite modificarlas o agregar una nueva.
En el caso que estemos agregando una nueva, ingresamos el nombre lógico del Sender, del Receiver y en el MsgType el nombre de la Bapi (pe.: Customer.GetDetail).
Al oprimir el botón Add Rule, debemos agregar los demás datos de la regla.
Al oprimir Save se crea la regla pero deshabilitada, para habilitarla se debe clickear en la columna Enabled? sobre el indicador (No), lo cual lo transforma en habilitada (Si).
Nuestro nuevo servicio creado de esta manera, lo podremos ver desde BC Integrator, Dentro del paquete indicado y de una carpeta con el nombre del Sender y una subcarpeta con el nombre del Receiver las cuales crea automáticamente.
En aquellos casos que la función (ya sea RFC o Bapi) requiera un XML de entrada de datos, para obtener el template del mismo se accede en BCServer a SAPàLookup
En caso de ser una función RFC, se ingresa su nombre en Function By Name y en caso de ser una Bapi, se escribe el nombre en BAPI By Name y luego se oprime el botón bXML. BC mostrará el template del XML de entrada.
Aquí se tienen dos alternativas:
Si se tiene configurado el acceso a BC o el acceso al servicio sin password, en este caso basta con definir una variable de tipo xmlReader y utilizar sus métodos y propiedades para obtener el archivo XML y procesarlo. Simplemente se invoca el servicio a través del método Open y si no hubo error se puede comenzar a consumir el XML devuelto.
Ejemplo
&url = ‘http://xxx.xx.xx.xx:5555/invoke/FOLDER/Productos’
&xmlReader.Open(&url)
if &xmlReader.ErrCode <= 0
do while &xmlReader.EOF <> 1
…a partir de aquí se pueden comenzar a consumir los nodos del XML…
enddo
else
...aquí se trata el error....
endif
&xmlReader.Close()
En caso de tener el acceso restringido por usuario/password, se debe utilizar el protocolo HTTP mediante una variable de tipo httpClient, lo cual permite construir un request, autentificarse con usuario/password, enviar el request a una URL y leer los resultados.
El código GX debe ser como sigue:
Ejemplo
&httpClient.Host = "xxx.yy.ww.zz" // dirección IP del servidor BC
&httpClient.Port = 5555 // puerto
&httpClient.BaseUrl = "/invoke/FOLDER/"
&httpClient.AddAuthentication(&httpClient.Basic, "RealmX", "UsuarioBC", "PasswordBC")
&httpClient.Execute("GET", "Productos")
&xmlReader.OpenResponse(&httpClient)
if &xmlReader.ErrCode <= 0
do while &xmlReader.EOF <> 1
…a partir de aquí se pueden comenzar a consumir los nodos del XML…
enddo
else
...aquí se trata el error....
endif
Si los parámetros a pasar a la función son pocos, una posibilidad es colocándolo directamente en la URL del servicio que se invocará.
&url = 'http://xxx.yy.ww.zz:5555/invoke/SPV/Precios?IN_FECHA='
&url = concat( &url, &fechaTxt)
Hay casos en que el servicio que se va a invocar, recibe un archivo XML como entrada y devuelve otro archivo XML de salida.
Esto puede ser por que la función que invocará en SAP espera parámetros, por ejemplo, para filtrar la información que devolverá o porque será una función que grabe datos en SAP, por ejemplo, BAPI de creación de pedidos.
En este caso se debe también utilizar el protocolo HTTP mediante una variable de tipo httpClient, y definir variables de tipo xmlWriter para los parámetros de entrada al servicio y xmlReader para obtener los parámetros de salida y procesar el resultado.
Se debe enviar un XML con el formato del template de entrada (de acuerdo al que propone BC, éste será proporcionado por el responsable del sistema SAP con el que interactuará nuestra aplicación GeneXus, ver Obtener template del XML de entrada), se setea la propiedad Content-type del header del XML en: "application/x-sap.rfc" y se hace un “POST” al servicio.
Ejemplo
&httpClient.Host = "xxx.yy.ww.zz" // dirección IP del servidor BC
&httpClient.Port = 5555 // puerto
&httpClient.BaseUrl = "/invoke/FOLDER/"
&httpClient.AddAuthentication(&httpClient.Basic, "RealmX", "UsuarioBC", "PasswordBC")
// Agrego el XML al request
&xmlWriter.OpenRequest(&httpClient)
//Armo XML que contendrá los parámetros de entrada al servicio
&xmlwriter.WriteStartDocument()
// Prestar atención que este formato debe ser acorde al propuesto por // BC
&xmlwriter.WriteRawText('<sap:Envelope xmlns:sap="urn:sap-com:document:sap"version="1.0">')
&xmlwriter.WriteRawText('<sap:Header xmlns:rfcprop="urn:sap-com:document:sap:rfc:properties">')
&xmlwriter.WriteRawText('<saptr:From xmlns:saptr="urn:sap-com:document:sap:transport">BC1</saptr:From>')
&xmlwriter.WriteRawText('<saptr:To xmlns:saptr="urn:sap-com:document:sap:transport">BC2</saptr:To>')
&xmlwriter.WriteRawText('</sap:Header>')
&xmlwriter.WriteRawText('<sap:Body>')
&xmlwriter.WriteRawText('<rfc:Z_ECO_CREAPEDIDO
xmlns:rfc="urn:sap-com:document:sap:rfc:functions">')
&xmlwriter.WriteStartElement("XHEADERIN")
.................. Se continúa armando el XML ..................
&xmlwriter.WriteRawText('</rfc:Z_ECO_CREAPEDIDO>')
&xmlwriter.WriteRawText('</sap:Body>')
&xmlwriter.WriteRawText('</sap:Envelope>')
&xmlwriter.Close()
&httpclient.AddHeader("Content-type", "application/x-sap.rfc")
&httpclient.Execute("POST", "SDCreaPedido" )
//A continuación se obtiene la respuesta y se procesa
&xmlreader.OpenResponse(&httpclient)
................. Procesar XML con respuesta ...................
A continuación se muestra un ejemplo de una aplicación GeneXus que accede a los datos de SAP para realizar una lectura de precios de venta de productos en una determinada fecha pasada por parámetro.
&ano = year(&fecha)
&anoTxt = trim(str(&ano))
&mes = month(&fecha)
&mesTxt = trim(str(&mes))
&dia = day(&fecha)
&diaTxt = trim(str(&dia))
&fechaTxt = concat(&anoTxt, '-')
&fechaTxt = concat(&fechaTxt, &mesTxt)
&fechaTxt = concat(&fechaTxt, '-')
&fechaTxt = concat(&fechaTxt, &diaTxt)
&url = 'http://xxx.xx.xx.xx:5555/invoke/SPV/Precios?IN_FECHA='
&url = concat( &url, &fechaTxt)
&xmlReader.Open(&url)
if &xmlReader.ErrCode <= 0
do while &xmlReader.EOF <> 1
if &xmlReader.ReadType(1, 'mercado') <> 0
&mercado = &xmlReader.Value
endif
if &xmlReader.ReadType(1, 'codpro') <> 0
&codpro = &xmlReader.Value
endif
if &xmlReader.ReadType(1, 'moneda') <> 0
&moneda = &xmlReader.Value
endif
if &xmlReader.ReadType(1, 'importe') <> 0
&importe = &xmlReader.Value
endif
if &xmlReader.EOF <> 1
&codigoMer = val(&mercado)
&codigoPro = val(&codpro)
&precio = val(&importe)
for each
if PROCod = &codigoPro
Call(PPV3097, &fecha, &codigoMer, &codigoPro, &moneda, &precio)
endif
endfor
endif
enddo
&exito = 'S'
else
&exito = 'N'
endif
&xmlReader.Close()
El ejemplo 2 muestra un procedure de una aplicación GeneXus que crea un pedido de ventas directamente en SAP y devuelve el resultado, ya sea el número de pedido creado o el error ocurrido al intentar crearlo.
El servicio BC que se utiliza invoca una función RFC que recibe como parámetro los datos necesarios para crear el pedido, invoca a la Bapi SalesOrder.CreateFromDat1 y devuelve el número de pedido o el error ocurrido.
// Determina el host y el puerto a donde hacer el request
&httpClient.Host = "xxx.xx.xx.xx"
&httpClient.Port = 5555
&httpClient.BaseUrl = "/invoke/SDeCommerce/"
&httpClient.AddAuthentication(&httpclient.Basic, "RealmX", "UsuarioBC", "PasswordBC")
// Agrega el XML al request
&xmlWriter.OpenRequest(&httpClient)
//Arma XML del pedido
&xmlWriter.WriteStartDocument()
&xmlWriter.WriteRawText('<sap:Envelope xmlns:sap="urn:sap-com:document:sap"version="1.0">')
&xmlWriter.WriteRawText('<sap:Header xmlns:rfcprop="urn:sap-com:document:sap:rfc:properties">')
&xmlWriter.WriteRawText('<saptr:From xmlns:saptr="urn:sap-com:document:sap:transport">BC1</saptr:From>')
&xmlWriter.WriteRawText('<saptr:To xmlns:saptr="urn:sap-com:document:sap:transport">BC2</saptr:To>')
&xmlWriter.WriteRawText('</sap:Header>')
&xmlWriter.WriteRawText('<sap:Body>')
&xmlWriter.WriteRawText('<rfc:Z_ECO_CREAPEDIDO xmlns:rfc="urn:sap-com:document:sap:rfc:functions">')
// Arma cabezal del pedido
&xmlWriter.WriteStartElement("XHEADERIN")
&xmlWriter.WriteElement("DOC_TYPE", &DocTypPar)
&xmlWriter.WriteElement("SALES_ORG", &SalOrgPar)
&xmlWriter.WriteElement("DISTR_CHAN", &DisChaPar)
&xmlWriter.WriteElement("DIVISION", &DivPar)
&xmlWriter.WriteEndElement()
// Arma posiciones del pedido
&int = 1
&xmlWriter.WriteStartElement("XITEMIN")
do while &int <= 100
if &CodMat(&int) <> nullvalue(&CodMat(&int))
&xmlWriter.WriteStartElement("item")
&xmlWriter.WriteElement("MATERIAL",
&CodMat(&int))
&xmlWriter.WriteElement("REQ_QTY", &Cant(&int))
&xmlWriter.WriteElement("SALES_UNIT",
&UniMat(&int))
&xmlWriter.WriteEndElement()
endif
&int = &int + 1
enddo
&xmlWriter.WriteEndElement()
// Arma estructura con datos del Cliente que solicita el pedido
&int = 1
&xmlWriter.WriteStartElement("XPARTNER")
do while &int <= 3
if &PartCod(&int) <> nullvalue(&PartCod(&int))
&xmlWriter.WriteStartElement("item")
&xmlWriter.WriteElement("PARTN_ROLE",
&PartCod(&int))
&xmlWriter.WriteElement("PARTN_NUMB",
&PartNum(&int))
&xmlWriter.WriteEndElement()
endif
&int = &int + 1
enddo
&xmlWriter.WriteEndElement()
&xmlWriter.WriteRawText('</rfc:Z_ECO_CREAPEDIDO>')
&xmlWriter.WriteRawText('</sap:Body>')
&xmlWriter.WriteRawText('</sap:Envelope>')
&xmlWriter.Close()
&httpclient.AddHeader("Content-type", "application/x-sap.rfc")
&httpclient.Execute("POST", "SDCreaPedido" )
//Obtiene respuesta
&xmlReader.OpenResponse(&httpClient)
do while &xmlReader.EOF <> 1
if &xmlReader.ReadType(1, "NROPED_OUT") <> 0
&nroped = &xmlReader.Value
//Muestra el nro. de pedido creado
msg(&nroped)
else
//Tratar el error
if &xmlReader.ReadType(1, "NUMBER") <> 0
&errmsgnum = &xmlReader.Value
endif
if &xmlReader.ReadType(1, "MESSAGE") <> 0
&errmsgtxt = &xmlReader.Value
endif
.....................................................
endif
enddo
Información detallada sobre Business Connector:
SAPBCAdministrationGuide40.pdf
SAP XML Comunication.pdf
Para clientes/partners SAP: http://service.sap.com/connectors.
Set up de BCServer: BCServer40.exe.
Información detallada sobre Integrator:
SAPBCDEVELOPERSGUIDE.pdf
Set up de BCIntegrator: BCIntegrator40.exe.
GeneXus Developer Library de ARTech:
http://www.artech.com.uy/gxdlsp/pub/iehelp.htm?Gxhome.htm