Contract-First em REST com Swagger
Em um post tempos atrás falei do Swagger.
Como dito anteriormente, minha experiência estava com o RAML, pensei em usar o Swagger como uma PoC, já que tanta gente falava da documentação de APIs e do Contract-First/ API-First/ Design-First de soluções REST.
O meu código se encontra no meu GitHub.
Quando pensamos em Contract-First, fica evidente que antes de tudo preciso da definição de contrato. A ideia é criar uma camada em que usuário e implementação possam conversar, sendo assim possível alterar mais coisas na implementação sem que impacte o usuário.
Esses inclusive são 2 acoplamentos vistos com bons olhos para SOA: o acoplamento do consumidor com o contrato e o acoplamento da implementação com o contrato.
Sendo o contrato “a máxima do mundo orientado a serviço”, as alterações terão impacto tanto nos consumidores quanto na implementação, mas estes estarão sempre em conformidade com o especificado. Essa, como eu tinha dito em outro post, é para mim uma das grandes sacadas de SOA.
Dado que já conhecia o RAML, fui atrás de uma implementação com Swagger e imaginava um pouco mais da implementação Java.
O RAML possuía uma forma parecida com o que eu trabalhava no CXF quando da construção de serviços SOAP. Através de um plugin Maven primeiramente especifico onde se encontra o WSDL, em seguida em que pacote desejo que as minhas classes sejam geradas. Quando da execução de um comando Maven, era gerado para mim as classes que refletiam aquela especificação de contrato.
Quando fui procurar por algo semelhante no Swagger veio minha primeira decepção, não havia um plugin para gerar as classes do lado servidor.
O que era oferecido era um JAR que poderia ser executado via console para gerar as classes a partir de um arquivo YAML ou JSON onde estaria o contrato da API ou através de uma opção de exportar . Existem uma série de implementações válidas, como SpringBoot, CXF, RestEasy, e outras em várias linguagens, mas era isso, não deixava de ser uma tarefa manual
O problema com essa abordagem é ter que executar sempre que houver alguma alteração no contrato algo para gerar um stub e fazer as devidas alterações.
Não sei se é uma exclusividade da implementação que escolhi, que foi a do SpringBoot, mas não gostei do projeto criado ser gerado em uma classe com anotações, preferia que assim como no caso do CXF fosse gerado a interface, sendo minha responsabilidade implementar a mesma em uma classe concreta, isso geraria um código mais limpo e, caso alguma alteração ocorra depois, não sobrescreve a implementação que eu fiz, sendo o caso de sobrescrever a interface apenas.
Fiz as devidas alterações e o código, como dito acima, pode ser encontrado no meu GitHub.
A grande vantagem do Swagger e a abordagem contract-first é que este gera uma documentação da API também.
Cada aba pode ser expandida, exemplificando detalhes de parâmetros e possíveis saídas e erros
No demais, vou continuar a implementação tentando utilizar SpringData como intermediador da camada de persistência. Quero ver a solução MongoDB do SpringData.