Automatize rotinas de geração automática de clientes SOAP com importação de WSDL para SBT e Scala

Trabalhar com SOAP geralmente fica complicado, e lidar com o WSDL pode ser uma enorme contribuição para a complexidade dessa tarefa. Realmente, poderia ser a coisa menos esperada para enfrentar quando você está em uma linguagem moderna e sofisticada, como por exemplo, Scala, que é bem conhecida por sua reatividade e maneira assíncrona de lidar com solicitações. De fato, muitos dos desenvolvedores de software que entraram no mercado recentemente, podem nem conhecer os protocolos SOAP e WSDL e ficar rapidamente irritados ou até enfurecidos ao tentar se conectar a um serviço herdado. Então, devemos depreciar isso totalmente em favor da pilha de tecnologia moderna, ou talvez exista uma solução menos dolorosa?


SOAP: legado


É difícil argumentar que essa coisa SOAP parece bastante desatualizada atualmente, especialmente em contraste com o estado atual da tecnologia. Escrever um cliente WSDL do zero com Kotlin, Scala ou outra linguagem moderna pode ser uma dor, e a falta de documentação adequada para isso não facilita a vida. Mas tenho boas notícias para você, há um ponto de luz no reino sombrio do SOAP. Bem, na verdade o WSDL é o único. Apesar de ser pesado e um pouco feio, tem uma certa vantagem. O excesso de formato WSDL facilita bastante a geração do código do cliente (e também do servidor), talvez não para humanos, mas definitivamente para sistemas automatizados.


Mesmo em comparação com as especificações modernas da API, ele pode realmente permanecer no mesmo nível dos conceitos OpenAPI ou API Swagger, onde tudo é descrito em uma especificação independente de idioma. Isso permite grandes oportunidades de interoperabilidade entre diferentes plataformas e idiomas, até o nível de implementação. Por exemplo, se um expuser, digamos, um serviço da Web .NET com especificação WSDL, outro poderá gerar automaticamente um cliente baseado em JVM para conectar-se a ele com pouca ou nenhuma dificuldade de conversão ou incompatibilidade de formatos de dados.


Magia de Importação de WSDL


Vamos aprofundar e falar sobre geração automatizada de código. Você pode se surpreender, mas a maioria das plataformas corporativas, principalmente Java e .NET, vem com ferramentas de geração de código WSDL prontas para uso. Por exemplo, existe o wsimport que faz parte de uma distribuição JDK. Essas ferramentas são bastante poderosas e devem abranger uma tarefa de geração automática de ponta a ponta. A única parte restante é conectar sua lógica de negócios ao código do cliente e usá-lo.


Portanto, como estamos atualmente no tema Scala, vamos analisar mais profundamente a ferramenta wsimport do Java:


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

O comando usa um esquema WSDL como um parâmetro necessário e, basicamente, é suficiente para produzir um conjunto inteiro de POJOs e interfaces, marcados com todas as anotações apropriadas. Os últimos realmente fazem o truque: é essencialmente isso que torna todas as coisas possíveis. Quando executada, a JVM conecta seu código de cliente à implementação interna do cliente de serviço da web, que sai da caixa, para que você não precise se preocupar muito com redes de baixo nível e E / S. O restante dos negócios é lidar com entradas e saídas adequadamente e ter cuidado com erros e exceções.


Leve a automação ao próximo nível com o SBT


Tudo bem, é hora de um pouco de prática. Imagine que também temos alguns serviços web SOAP que precisamos conectar e eles expõem o WSDL. Deliberadamente, tomei alguns para testar, apenas em prol da ciência e da educação, é claro. Execute o gerador 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 

Ele produz um número de código Java bruto na pasta de saída. Poderíamos continuar conectando nossa lógica de negócios, conforme sugerido acima. Mas espere um segundo, e se o lado do servidor mudar - nós estaremos cientes disso apenas no momento da execução real do código (ou no momento da falha nos testes de integração, se houver algum). Não é bonito. Rapidamente não fica nada bonito se você pensar em enviar todo esse código Java bean padrão no seu repositório Scala.


Obviamente, seria muito melhor gerar todas essas coisas automaticamente e manter as coisas magras e limpas. Uma primeira etapa para isso seria automatizar a obtenção de todas as classes WSDL com um comando e criar um script Shell com isso. Na verdade, fiz um para você, para que você possa dar uma olhada: wsdl_import.sh .


Em seguida, poderíamos envolvê-lo com uma tarefa de construção: tomemos o SBT como exemplo, já que estamos no Scala, então algo assim deve 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.") } 

Fonte


Agora, precisamos garantir que tenhamos todo esse código antes da parte do Scala ser compilada, por razões óbvias. Fácil, temos o SBT, portanto, precisamos executar o script Shell como uma tarefa do SBT, como acima, e executar as coisas na ordem certa, correto? Bem, é um pouco mais complicado na vida real. Sem entrar em muitos detalhes de como o SBT funciona, as coisas ficam muito mais fáceis se separarmos esta parte WSDL-Java em um subprojeto auto-suficiente e fizermos uma dependência adequada na configuração principal do SBT.


 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) 

Fonte


Quando você compila o projeto mestre, o SBT primeiro garante que o subprojeto já esteja compilado. Mas há um problema: quando você acabou de fazer o check-out do seu repositório, pode não ter executado a compilação. Portanto, quando você abrir pela primeira vez no editor, algumas das dependências estarão ausentes, é claro. Felizmente, a única coisa que você precisa é executar um comando compilador sbt e, talvez, atualizar o projeto no IDE.


Pode haver outra advertência se você estiver executando seu aplicativo Scala como um cliente independente ou em um contêiner da Web enxuto (por exemplo, Netty, se você estiver usando o Play Framework). Nesse caso, é muito provável que o tempo de execução do aplicativo esteja faltando no bit de implementação que ajuda a JVM a fazer a mágica SOAP para você, graças às versões modernas do JRE e ao projeto Java Jigsaw. Não há necessidade de entrar em pânico, basta adicionar algumas bibliotecas à sua lista de dependências ou lançar um único rt.jar da sua distribuição JRE como uma dependência não gerenciada:


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

Como conclusão


Tudo bem, como uma recapitulação: aprendemos um pouco sobre SOAP e WSDL e esperamos perceber que não é um pesadelo trabalhar com isso, graças a todos esses geradores de código e especificações excessivas de WSDL. Também descobrimos como automatizar um trabalho sujo e encontramos uma maneira de manter nossos repositórios intactos e limpos de códigos clichê indesejados. Foi necessário algum conhecimento do SBT para configurar corretamente a ordem e as dependências de compilação, mas, afinal, deve funcionar sem problemas. Para simplificar ainda mais, criei um pequeno modelo de autoinicialização que deve ajudá-lo a iniciar um projeto da próxima vez: https://github.com/sainnr/sbt-scala-wsdl-template . Espero que você tenha gostado dessa pequena jornada de volta ao passado!


Referências



Envie-me uma mensagem se você encontrar algum erro de digitação.


Este artigo foi publicado originalmente no meu blog fullstackme.co.uk com pequenas modificações.

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


All Articles