Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swagger inheritance is broken #1050

Closed
mnisius opened this issue Jul 21, 2020 · 4 comments
Closed

Swagger inheritance is broken #1050

mnisius opened this issue Jul 21, 2020 · 4 comments
Labels
Milestone

Comments

@mnisius
Copy link

mnisius commented Jul 21, 2020

It seems like the generated swagger file does not know about inheritance wich makes my generated client unusable.

My example rest api looks like this:
We use immuables to generate pojos so please ignore that these are all interfaces

//Main Input object for my rest service
public interface TestInput {
  LocalDateTime getCallTime();
  String getMessage();
  CommunicationLink getCommunicationLink();
}
public interface CommunicationLink {
  String commonField();
}
public interface Email extends CommunicationLink {
  String getEmailAddress();
}
public interface Telephone extends CommunicationLink {
  String getTelephonenumber();
}

I used the swagger.json to generate a java client. I tried to call my service like that:

TestInput input = new TestInput();
input.setCallTime(LocalDateTime.now());
input.setMessage("Hello World");
final Email email = new Email();
email.setCommonField("test");
email.setEmailAddress("[email protected]");
input.setCommunicationLink(email); //does not compile: Email does not extends CommunicationLink :-(

It seems like the inheritance is not translated into the generated swagger.json.

This is what enunciate generated (only the relevant parts of the section "definitions")

  "CommunicationLink": {
    "type": "object",
    "title": "CommunicationLink",
    "example": {},
    "description": ""
  },
  "Email": {
    "type": "object",
    "title": "Email",
    "properties": {
      "commonField": {
        "readOnly": false,
        "description": "The value of the commonField attribute",
        "type": "string"
      },
      "emailAddress": {
        "readOnly": false,
        "description": "The value of the emailAddress attribute",
        "type": "string"
      }
    }
  },
  "Telephone": {
    "type": "object",
    "title": "Telephone",
    "properties": {
      "commonField": {
        "readOnly": false,
        "description": "The value of the commonField attribute",
        "type": "string"
      },
      "telephonenumber": {
        "readOnly": false,
        "description": "The value of the telephonenumber attribute",
        "type": "string"
      }
    }
  }
}
@mnisius
Copy link
Author

mnisius commented Jul 21, 2020

I did another test. I replaced the interfaces with actual classes. Now enunciate generates a different swagger.json
It has an allOf section and references the supertype. But in the generated swagger client the inheritance is still missing so I get the same error as before.

here is how the swagger.json looks if i replace the interfaces with classes.

  "CommunicationLink": {
    "type": "object",
    "title": "CommunicationLink",
    "properties": {
      "commonField": {
        "readOnly": false,
        "description": "",
        "type": "string"
      }
    }
  },
  "Email": {
    "type": "object",
    "title": "Email2",
    "allOf": [
      {
        "$ref": "#/definitions/CommunicationLink"
      },
      {
        "properties": {
          "emailAddress": {
            "readOnly": false,
            "description": "",
            "type": "string"
          }
        }
      }
    ]
  },
  "Telephone": {
    "type": "object",
    "title": "Telephone",
    "allOf": [
      {
        "$ref": "#/definitions/CommunicationLink"
      },
      {
        "properties": {
          "telephonenumber": {
            "readOnly": false,
            "description": "",
            "type": "string"
          }
        }
      }
    ]
  }

@mnisius
Copy link
Author

mnisius commented Jul 21, 2020

I think I found the solution.

  1. Make Interfaces behave like classes (with allOf Sections)
  2. Add this line to the super type: "discriminator": "type",

If I add this line manually the generated client uses inheritance as well and my code is working.

I'm not sure why you tread interface inheritance diffrent than class inheritance. Is this because of this: #374

So finally here is how the swagger.json definitions section should look like:

  "CommunicationLink": {
    "discriminator": "type",
    "type": "object",
    "title": "CommunicationLink",
    "properties": {
      "commonField": {
        "readOnly": false,
        "description": "",
        "type": "string"
      }
    },

  },
  "Email": {
    "type": "object",
    "title": "Email2",
    "allOf": [
      {
        "$ref": "#/definitions/CommunicationLink"
      },
      {
        "properties": {
          "emailAddress": {
            "readOnly": false,
            "description": "",
            "type": "string"
          }
        }
      }
    ]
  },
  "Telephone": {
    "type": "object",
    "title": "Telephone",
    "allOf": [
      {
        "$ref": "#/definitions/CommunicationLink"
      },
      {
        "properties": {
          "telephonenumber": {
            "readOnly": false,
            "description": "",
            "type": "string"
          }
        }
      }
    ]
  }

@stoicflame stoicflame added the bug label Jul 21, 2020
@stoicflame stoicflame added this to the 2.14.0 milestone Jul 21, 2020
@stoicflame
Copy link
Owner

stoicflame commented Aug 27, 2020

Fixed at 5184d70.

Note that the interface "superclass" (in this case CommunicationLink) will need to be annotated with @JsonTypeInfo in order for the discriminator to be determined and applied.

@stoicflame
Copy link
Owner

Fixed in 2.13.2.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants