martes, 28 de mayo de 2013

ABAP + Transacción SM69 o SM49 + TELNET + Script + Java


Hola que tal a todos lo lectores de este blogg, como bien saben la finalidad de este espacio es para contar mis historias, ayudas, memorias, notas, etc y compartir la solución a diversas situaciones.

Conocimientos previos:

-Unix ( especialmente en Bash )
-Comunicaciones TCP/IP
-Sockets
-Java
-ABAP

La problemática:
Surgió la "necesidad" de comunicar en un sistema SAP R/3, que por medio de un programa "ABAP", se conectara a un Socket (IP / PORT)  y es aquí donde surgió la polémica discusión   

:::: no!! se puede,
:::::si!! se puede,
::::::que no!! se puede...


y salieron las palabras "TE RETO A QUE LO HAGAS..." ( chan chan chan chaaan )

Mi respuesta fue:




(en realidad sin saber en que lió me estaba metiendo).

Después de unos minutos buscando por Internet donde alguna personas preguntaban los mismo y no tenían una respuesta concreta a como solucionarlo empecé a dudar, pues todos decían que lo mandaras por FTP, pero en este caso no se requiere un FTP solo conectar a un SOCKET.

PEROOO!! en este enlace encontré unas palabras mágicas.

"you can use external OS commands (transactions SM69 and SM49). For example on Unix you can use netcat to transfer file. Your FM needs to dump data into folder and then call netcat to transfer file."

Eso me regreso a mis pocos conocimientos en Java, cuando se necesita ejecutar un programa fuera del mismo lenguaje con la clase:
"Process p = Runtime.getRuntime().exec...." (esto podría ser después otra historia....)

Pues manos a la obra, encontramos las transacción SM49 y SM69, que sirven para crear comando externos
del sistema operativo y poder usarlos con funciones en ABAP.

Primero que nada se me ocurrió realizar la conexión vía TELNET o NETCAT como comentaban en el enlace anterior, pero para comprobar esto en el S.O, pregunte cual era el Socket donde se conectaría... y esta pregunta no tuvo efecto, pues no me dijeron que IP / Puerto a conectar, así que esto no me detuvo y utilice un  programa que ya tenia hecho, que funcionaba como servidor "Socket en Java" con el puerto de escucha en el 3333:


/**
 *
 * @author ahmateu
 */
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class TestServerSocket {

    public static void main(String args[]) throws IOException {
        final int portNumber = 3333;
        System.out.println("Escuchando socket java en puerto: " + portNumber);
        ServerSocket serverSocket = new ServerSocket(portNumber);
        while (true) {
            Socket socket = serverSocket.accept();
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os, true);
            pw.println("Conexion ");
            pw.println(socket.getRemoteSocketAddress().toString());

            BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            String dato = br.readLine();

            pw.println("Esto se mando al Servidor, " + dato);
            pw.close();

            System.out.println("IP :" + socket.getRemoteSocketAddress().toString());
            System.out.println("Saludar a :" + dato);
            socket.close();
        }
    }
}


Entonces ya tenemos nuestro Socket abierto para probar la conexiones entrantes con el puerto 3333.


Hacemos una prueba rápidamente para ver su funcionalidad utilizando TELNET:


El Socket espera que mandemos algo y escribo mi nombre:


El Resultado en el servidor Socket es el Siguiente:



Listo!!!!! tenemos nuestro Socket en Java funcionando correctamente para nuestras pruebas.

SAP

Ahora vamos del lado de SAP a la transacción SM69, pero para no entrar en mas detalles y extender mucho esta publicación les dejo este manual :


No vamos usar el comando ls como lo dice el manual usaremos el comando sh para ejecutar algún Script que vamos a crear y probar la conexión con la llamada a la función  ABAP :

 SXPG_COMMAND_EXECUTE.

Para ello vamos a crear un archivo Script ( sh ) en el servidor con los comando para enviar por medio de tuberías, esto lo explicare mas adelante, aquí topamos con otro problema mas, no tengo acceso para conectarme por SSH al servidor, "claro esta que no pregunte si me podrían dar un usuario con esos privilegios, pues si no me dijeron el Socket y puerto donde se conectaría, no esperaba mucho resultado de un usuario",  ademas en caso que fuera aprobada mi solicitud de usuario, tendría que realizar un reporte, describiendo para que se utilizaría, condiciones y horarios de conexión, bla bla bla, todo un tramite burocrático que podría durar horas, días o semanas y esto mejor nos lo ahorraremos y  utilicemos el lado "Hacker!! y pensemos ..." estamos dentro de un servidor y podemos programar  ... por ejemplo es como si estuviéramos en un servidor con un "IDE" de frente que es lo "único" que vemos .... "BINGO"... pues no nos detiene nuestra conexión SSH o si? , sabemos crear archivos y solo necesito una carpeta donde crear y leer archivos...  y no precisamente TXT (muajajajaja ,  en la transacción AL11 puedes navegar entre las carpetas del servidor SAP siempre y cuando el usuario tenga permisos en la transacción. ), ok ya tengo la carpeta donde voy a experimentar.

De tener SSH conectaríamos directo al servidor y enviaríamos un archivo de nuestra maquina local al servidor Remoto, pero como no lo tenemos, vamos a realizar un programa en ABAP que genere un archivo script, mas adelante explicare que hace.



Y la magia nace de este hermoso Script, ¿y que es lo que hace?:
-Abap creara un archivo .sh en la carpeta /tmp/ llamado TEST.sh  y que contiene la las variables host y port  el comando Open, espera un segundo, escribo mi nombre (SAPArmando H. Mateu) ,espera otro segundo termino el comando quit, esto con la tubería lo mando al comando Telnet que es quien usara lo antes escrito y el resultado lo mando a otro archivo que se llama TESTout.txt (esto para saber el resultado de la conexión  ) y después ejecuto el comando CAT para desplegar el contiene dicho archivo. ( Interesante o no ?  =) !!! ) .


Esto seria una ejecución simple desde una terminal ( root#sh /tmp/TEST.sh ), pero no tenemos un terminal, ¿como lo ejecutamos? ....pues con la transacción SM69 ya dimos de alta nuestra "Terminal" con el comando de sh  ahora vamos a utilizar la call funtion como lo muestra la siguiente imagen:



¿y Que es lo que hace? ...en el manual que deje como enlace esta bien explicado, solo como comentario en la linea 116 de mi código esta /tmp/TEST.sh por lo tanto como ya tenemos dado de alta nuestro comando es como si usáramos en un terminal la ejecución  root#sh /ruta/Script.sh 

Guardamos nuestro programa, lo activamos y lo ejecutarlo (F8).



Vamos a interpretar el resultado que nos arrojo en SAP, lo que muestra al final es lo que se despliega con el comando CAT escrito en el archivo /tmp/TESTout.txt  y vemos que se conecto por telnet a la IP y Socket de la variables especificadas en el Script anterior y que mando mi nombre SAPArmando H. Mateu y termino la conexión, nos manda como resultado por parte del servidor nos contesta: "Esto se mando al Servidor, SAPArmando H. Mateu.

Veremos el resultado del Socket en Java, donde comprueba que se realizo la conexión y que mando la cadena SAPArmando H. Mateu :




Como conclusión  podemos crear archivos Script para usarlos posteriormente como comunicadores por Socket desde ABAP, pues en ocasiones los lenguajes de programación no cuentan con todo el poderío y necesitan bajar de nivel o apoyarse de otros programas externos que faciliten finalidad.

Esto fue como demostración para utilizar SOCKETS en ABAP  y comandos del S.O, pues ABAP cuenta con funciones para comunicar por FTP que se pueden desarrollar desde su propio lenguaje sin la necesidad de usar Scripts, pero no con una función propia para conectar a un Socket abierto o por lo menos no encontré algo en código puro de ABAP para solventar esta necesidad.


Ahora esto ya fue Solucionado... !!!

¿Que pasaría si en lugar de crear un archivo .sh creamos uno .Java? ( chan chan chan chan !!! )
"agregar en la SM69 javac para compilar y java para correr nuestro archivo .class" y LISTOOO!!




Saludos !!,
Armando Hernandez Mateu


No hay comentarios:

Publicar un comentario en la entrada