Spring-cloud-contract: Integration with Swagger 2 / Open API

Created on 7 Nov 2016  路  20Comments  路  Source: spring-cloud/spring-cloud-contract

We are considering using Swagger to generate API documentation and spring-cloud-contract for contract driven development.

There is an obvious similarity / overlap between spring-cloud-contract and Swagger 2 in that they both use a DSL to describe some element of an API. spring-cloud-contract focuses on scenarios that an API must fulfill while Swagger generates a technical description of the data model + response codes (as described by @marcingrzejszczak in https://github.com/spring-cloud/spring-cloud-contract/pull/68#issuecomment-243740046)

The current flow to use spring-cloud-contract and Swagger is at a high level:

  1. Define the API for swagger with the Open API DSL
  2. Generate the API technical documentation with swagger
  3. Define the API scenarios for spring-cloud-contract with the spring-cloud-contract DSL
  4. Generate the tests / stubs with spring-cloud-contract

The 2 main problems are:

  1. No validation of spring-cloud-contract definitions versus the Swagger API definitions. The spring-cloud-contract and Swagger API definitions are independent. It is possible to create spring-cloud-contract based contracts which inadvertently break a definition that was generated for Swagger.
  2. Duplication of API definitions. A given API needs to be manually specified with two different DSLs, which overlap. This is tedious (and error prone as stated above)

It seems that spring-cloud-contract (or another spring project) is bound to extend its capability to encompass the full technical description and documentation of APIs through its DSL, this feeling is reinforced by enhancement request https://github.com/spring-cloud/spring-cloud-contract/issues/21 which requires spring-cloud-contract to generate the controller based on the DSL. If this were the case then spring-cloud-contract would need to more fully define the API (e.g. fields, verbs, possibly return codes etc)

We'd love to hear about the short / long term strategy of spring-cloud-contract (or other upcoming spring projects) with respect to full API technical definition and documentation as currently implemented by Swagger 2:

  • Validation of the spring-cloud-contract / OpenAPI DSLs. Is there a plan to somehow integrate spring-cloud-contract with Swagger 2 or the OpenAPI DSL that Swagger 2 uses to perform validation of the DSLs ?
  • Is there a plan for spring-cloud-contract to extend its functionality and fully describe an API and its documentation (https://github.com/spring-cloud/spring-cloud-contract/issues/21 ) seems to be a step towards this)

Thanks ...

help wanted question

Most helpful comment

There are community extensions to Spring Cloud Contract that support Swagger like https://github.com/SvenBayer/spring-cloud-contract-swagger and from what I know more are to come :)

All 20 comments

Hello! Thanks for the introduction :)

let me focus on two last questions:

Validation of the spring-cloud-contract / OpenAPI DSLs. Is there a plan to somehow integrate spring-cloud-contract with Swagger 2 or the OpenAPI DSL that Swagger 2 uses to perform validation of the DSLs ?

We will be treating Swagger and its OpenAPI DSL in the same way as we will treat RAML and Pact. You'll be able to use their DSL to define scenarios. We will then convert their DSL into our DSL and then continue with test generation etc.

Is there a plan for spring-cloud-contract to extend its functionality and fully describe an API and its documentation (#21 ) seems to be a step towards this)

21 would be done only to create a stub of a controller. Contracts are not schemas and never will be. We do not want to describe all possible fields inside a controller. In other words we don't want to replicate what Swagger does. We want to go with Postel's law and we completely don't care how the full model looks like (i.e. what fields it contains).

Thanks for the response @marcingrzejszczak, it makes sense :-)

I guess that OpenAPI will let us use vendor specific DSL which Swagger will ignore but which will be used by spring-cloud-contract to generate the various contract artifacts ?

Yes - instead of using the Groovy DSL you'll be able to use OpenAPI DSL. We will then convert it into our Groovy DSL and then convert those into tests and stubs.

Obviously we're counting on help with implementing this feature cause currently we have bigger priorities. Of course I can help with some guidance. So @BenDave - interested in filing a PR ? :D

That is very tempting :-)

We may have some folks interested in spending a bit of time on this, I will have to get back to you on that ..

Ok! Feel free to ask!

Hi!

Is there any update on this?
I came across this thread, as we are currently into the same situation, planning to use OpenAPI and Spring Contract Verifier together.

May be we would be willing to contribute some time to this feature, though I confess, that after a glance in the github repositry I could not really understand how the code-generation stuff works.

This leads me to another question:

I stumbled across https://bitbucket.org/atlassian/swagger-request-validator, which has a submodule for RestAssured in the form of a filter. But unfortunately it looks like filters are not supported by RestAssuredMockMVC? I thought it might be a cheaper angle of attack to maybe extend the way the testcases are generated in order to offer an optional OpenAPI validation in the generated testst. Sure, this would only remove one "redundancy", the one of writing separate tests for the OpenAPI and the Contract but leaves the "redundancy" of writing two kinds of "specifications" the OpenAPI one and the Contract Verifier DSL specs.

Nope - no progress for now. You can check out this example - https://github.com/spring-cloud/spring-cloud-contract/blob/master/spring-cloud-contract-tools/spring-cloud-contract-spec-pact/src/main/groovy/org/springframework/cloud/contract/verifier/spec/pact/PactContractConverter.groovy It's pretty straightforward. You have to provide a conversion to a Collection and from it.

May be we would be willing to contribute some time to this feature, though I confess, that after a glance in the github repositry I could not really understand how the code-generation stuff works.

If you just do the conversion to/from Contract you don't have to touch the code generation. If you want to have your custom code generation then you could base your work on how org.springframework.cloud.contract.verifier.builder.JavaTestGenerator is working. Then you could just provide your own implementation and register it in spring.factories under org.springframework.cloud.contract.verifier.builder.SingleTestGenerator entry

Filters are not handled by MockMVC but you can use the EXPLICIT mode in SC-Contract to start RestAssured and send a real request.

... testcases are generated in order to offer an optional OpenAPI validation in the generated testst ...

What do you mean exactly by this? What is this additional optional OpenAPI validation?

My assumption was that the OpenAPI validation as done by swagger-request-validator via a RestAssured filter would be something, that not all users of Spring Contract Validator would want to use. So I thought one would provide this feature optional. Like "test, what was specified in the DSL" and (optionally) "check the request/response against an OpenAPI specification".
These thoughts were based on the assumption, that the verification would have to be initialized in the generated code part and not the custom baseClass. If it can be done in the baseClass, of course it would be totally up to the user of the framework.

I did not dig into the EXPLICIT mode yet, as maybe I misunderstood its intention. I will check.
Thanks for the support!

Hmm I don't think it's generic enough to consider putting in core :/ Here you have an example of working with context paths that require the EXPLICIT mode - https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_working_with_context_paths

@BenDave @markward-schubert @Fitzoh I was thinking about this issue when working on this one https://github.com/spring-cloud/spring-cloud-contract/pull/227 and I have one gigantic problem with this compatibility. Swagger / Open API are schema based. They define a schema and possible responses for different response codes. Spring Cloud Contract is scenario based. For a single request you've got a single response. It's actually impossible to make those two work (you'd have to start keeping multiple Open API schema files for different status codes which obviously makes no sense).

I'm on the verge of closing that PR and both issues for RAML and Open API due to incompatibilities. What do you think about this?

Yeah, I was always a little bit curious about how those implementations were going to work out, there's a pretty big mismatch in how SCC and swagger/RAML work.

Regarding your comments on #227 about not including it due to the limitations, maybe it makes sense to release it separately as a community-ish project? You've got the plug-in interface for converting stuff now, maybe it makes sense to have some external converters that aren't going to have first class support?

Following the discussion here #227 it turns out that schema based solutions are not really suitable as input for Spring Cloud Contract. @Fitzoh the RAML thing will be moved to Spring Cloud Incubator.

Yes, that decision makes sense - thanks for looking into this ....

@marcingrzejszczak This might be worth checking out if this gets reopened at some point:
https://bitbucket.org/atlassian/swagger-mock-validator

And some info on how it works with Pact:
https://docs.pact.io/faq/convinceme.html#but-i-use-swaggeropenapi
https://github.com/pact-foundation/pact-specification/issues/28

cc @mefellows

Good idea @Fitzoh.

Broadly speaking, the two technologies offer up different things; one is really useful for documenting APIs, in particular providing a strong definition where the consumers are not well known, the other is well suited to integration tests and providing confidence for known consumers.

It seems there is a common but happy middle ground that people are constantly wanting - the ability to do _both_.

As a suggestion, I'd see how the mock validator goes and if it turns out people like it, one option could be to create a spring-cloud-contracts integration that does something similar, or even implement something similar into the core library.

Wanted to include a link to the other half of that project:
https://bitbucket.org/atlassian/swagger-request-validator

They have wiremock and restassured validators as well.

Thanks for the feedback! Looks interesting. However I think that the best place to make that integration would be on the atlassian side. Also it's a validator that the Swagger special tells the truth. This issue was about making the Swagger spec input for sc contract. So it's a little bit different thing. WDYT?

Hi, it might be a silly idea, but could you use the default values of the parameters for the input mock and the response examples for the validation of responses? In this way the swagger template would also serve as a data scenario.

There are community extensions to Spring Cloud Contract that support Swagger like https://github.com/SvenBayer/spring-cloud-contract-swagger and from what I know more are to come :)

There is also project to kind of merge openapi with spring cloud contracts: https://github.com/springframeworkguru/spring-cloud-contract-oa3#spring-cloud-contract-open-api-30-contract-converter

Was this page helpful?
0 / 5 - 0 ratings