Automatice las rutinas de generación automática de clientes SOAP con importación WSDL para SBT y Scala

Trabajar con SOAP a menudo se vuelve complicado, y lidiar con WSDL podría ser una gran contribución a la complejidad de esta tarea. Realmente, podría ser lo menos esperado cuando te encuentras en un lenguaje moderno y sofisticado como, por ejemplo, Scala, que es bien conocido por su reactividad y su forma asincrónica de manejar las solicitudes. De hecho, muchos de los desarrolladores de software que se han abierto camino en la industria recientemente, tal vez ni siquiera conozcan los protocolos SOAP y WSDL, y se molesten o enfurezcan rápidamente cuando intentan conectarse a un servicio tan antiguo. Entonces, ¿deberíamos desaprobar esto completamente a favor de la pila de tecnología moderna, o tal vez haya una solución menos dolorosa?


JABÓN: Legado


Es difícil argumentar que esta cosa de SOAP suena bastante desactualizada en estos días, especialmente en contraste con el estado actual de la tecnología. Escribir un cliente WSDL desde cero con Kotlin, Scala u otro lenguaje moderno podría ser una molestia, y la falta de documentación adecuada para ello no hace la vida más fácil. Pero tengo buenas noticias para ti, hay un punto de luz en el oscuro reino SOAP. Bueno, en realidad WSDL es el indicado. A pesar de ser pesado y algo feo, tiene una cierta ventaja. Lo excesivo del formato WSDL hace que sea bastante fácil generar el código del cliente (y también del servidor), tal vez no para humanos pero definitivamente para sistemas automatizados.


Incluso en comparación con las especificaciones modernas de la API, en realidad podría estar a la par con OpenAPI o los sofisticados conceptos de API Swagger donde todo se describe en una especificación independiente del lenguaje. Esto permite enormes oportunidades de interoperabilidad entre diferentes plataformas e idiomas, hasta el nivel de implementación. Por ejemplo, si uno expone, digamos, un servicio web .NET con especificación WSDL, otro podría generar automáticamente un cliente basado en JVM para conectarse con poco o ningún inconveniente en la conversión o incompatibilidad de formatos de datos.


WSDL Import Magic


Vamos a darle más vueltas y hablemos sobre la generación automática de código. Puede que se sorprenda, pero la mayoría de las plataformas empresariales, principalmente Java y .NET, vienen con herramientas de generación de código WSDL listas para usar. Por ejemplo, hay wsimport que viene como parte de una distribución JDK. Dichas herramientas son bastante potentes y deben cubrir una tarea de generación automática de extremo a extremo. La única parte restante es conectar su lógica empresarial al código del cliente y hacer uso de ella.


Entonces, dado que actualmente estamos en el tema Scala, echemos un vistazo más profundo a la herramienta wsimport de Java:


 wsimport -p stockquote http://stockquote.example.com/quote?wsdl 

El comando toma un esquema WSDL como parámetro requerido, y básicamente es suficiente para producir un conjunto completo de POJO e interfaces, que están marcados con todas las anotaciones adecuadas. Los últimos realmente hacen el truco: esto es esencialmente lo que hace que todo sea posible. Cuando se ejecuta, JVM conecta su código de cliente junto con la implementación interna del cliente del servicio web, que viene de fábrica, por lo que no necesita preocuparse mucho por las redes de bajo nivel y las E / S. El resto del negocio consiste en manejar adecuadamente las entradas y salidas, y tener cuidado con los errores y excepciones.


Lleve la automatización al siguiente nivel con SBT


Muy bien, es hora de algo práctico. Imagine que tenemos algunos servicios web SOAP que también necesitamos conectar, y exponen WSDL. Deliberadamente, tomé algunos para probar, solo por el bien de la ciencia y la educación, por supuesto. Ejecute el generador de código:


 wsimport -s ../src/main/java -extension -p your.package.wsdl.nl \ -XadditionalHeaders -Xnocompile \ http://webservices.oorsprong.org/websamples.countryinfo/CountryInfoService.wso?WSDL 

Produce una cantidad de código Java sin procesar en la carpeta de salida. Podríamos proceder a conectar nuestra lógica de negocios, como se sugirió anteriormente. Pero espere un segundo, ¿qué pasa si el lado del servidor cambia? Lo notaremos solo en el momento de la ejecución real del código (o en el momento de falla de las pruebas de integración, si tenemos algo). No bonito Rápidamente no es nada agradable si piensas en comprometer todo este código de Java Beanplate en tu repositorio prístino de Scala.


Por supuesto, sería mucho mejor generar todas esas cosas automáticamente y mantener las cosas esbeltas y limpias. Un primer paso para esto sería automatizar la obtención de todas las clases WSDL con un comando y hacer un script de Shell a partir de esto. Realmente hice uno para ti para que puedas echarle un vistazo: wsdl_import.sh .


Entonces podríamos envolverlo con una tarea de compilación: tomemos SBT como ejemplo, ya que estamos en Scala, por lo que algo como esto debería funcionar:


 lazy val wsdlImport = TaskKey[Unit]("wsdlImport", "Generates Java classes from WSDL") wsdlImport := { val wsdlSources = "./wsdl/src/main/java" val d = file(wsdlSources) if (d.isDirectory) { // don't forget to rename to your fav one in line with WSDL generating sh val gen = file(s"$wsdlSources/github/sainnr/wsdl") if (!gen.exists() || gen.listFiles().isEmpty) { import sys.process._ println("[wsdl_import] Importing Java beans from WSDL...") "./wsdl/bin/wsdl_import.sh" ! } else println("[wsdl_import] Looks like WSDL is already imported, skipping.") } else println(s"[wsdl_import] Make sure the directory ${d.absolutePath} exists.") } 

Fuente


Ahora, debemos asegurarnos de tener todo este código antes de que se compile la pieza Scala, por razones obvias. Fácil, tenemos SBT, así que solo necesitamos ejecutar el script de Shell como una tarea SBT como la anterior y ejecutar las cosas en el orden correcto, ¿correcto? Bueno, es un poco más complicado en la vida real. Sin entrar en muchos de los detalles de cómo funciona SBT, las cosas se vuelven mucho más fáciles si separamos esta parte WSDL-Java en un subproyecto autocontenido, y hacemos una dependencia adecuada en la configuración SBT maestra.


 lazy val wsdl = (project in file("wsdl")) .settings ( publishSettings, sources in (Compile, doc) := Seq.empty ) lazy val root = (project in file(".")) .aggregate(wsdl) .dependsOn(wsdl) 

Fuente


Cuando compila el proyecto maestro, SBT primero se asegura de que el subproyecto ya esté compilado. Pero hay un problema: cuando acaba de revisar su repositorio, es posible que no haya ejecutado la compilación. Entonces, cuando lo abra por primera vez en el editor, faltarán algunas de las dependencias, por supuesto. Con suerte, lo único que necesita es ejecutar un comando de compilación sbt y, tal vez, actualizar el proyecto en IDE.


Puede haber otra advertencia si está ejecutando su aplicación Scala como un cliente independiente o en un contenedor web ligero (por ejemplo, Netty si está utilizando Play Framework). En este caso, es muy probable que al tiempo de ejecución de la aplicación le falte el bit de implementación que ayuda a JVM a hacer la magia SOAP por usted, gracias a las versiones modernas de JRE y el proyecto Java Jigsaw. Sin embargo, no es necesario entrar en pánico, solo agregue algunas bibliotecas a su lista de dependencias, o arroje un único rt.jar desde su distribución JRE como una dependencia no administrada:


  unmanagedJars in Test += Attributed.blank( file(System.getenv("JAVA_HOME") + "/jre/lib") ) 

Como conclusión


Muy bien, como recapitulación: hemos aprendido un poco sobre SOAP y WSDL y esperamos habernos dado cuenta de que no es una pesadilla trabajar con ellos, gracias a todos estos generadores de códigos y especificaciones excesivas de WSDL. También descubrimos cómo automatizar un trabajo sucio y encontramos una manera de mantener nuestros repositorios prístinos y limpios del código repetitivo no deseado. Se necesitó cierto conocimiento de SBT para configurar el orden de compilación y las dependencias correctamente, pero después de todo, debería funcionar sin problemas. Para simplificar aún más las cosas, hice una pequeña plantilla de arranque que debería ayudarlo a poner en marcha un proyecto la próxima vez: https://github.com/sainnr/sbt-scala-wsdl-template . ¡Espero que hayas disfrutado de este pequeño viaje de regreso al pasado!


Referencias



Envíeme un mensaje si ve algún error tipográfico o error.


Este artículo fue publicado originalmente en mi blog fullstackme.co.uk con pequeñas modificaciones.

Source: https://habr.com/ru/post/470349/


All Articles