swagger-api / swagger-api/swagger-codegen
Java Client Generation Issues with @ApiModel with declared subTypes and discriminator values.
Nobody has claimed this yet.
- Dominant language
- Mustache
- Stars
- 17.8k
- Forks
- 6k
- PR merge metrics
- No merged PRs in 30d
Description
I am trying to use Swagger to describe my JAX-RS Web Services and have decorated my classes with the relevant Swagger annotations (@ApiModel @JsonSubTypes etc). Unfortunately, when I generate the swagger.json (http://localhost:8080/test-application/rest/swagger.json) and use this to create a client jar (Using the swagger editor - http://editor.swagger.io/#/), the generated code doesn't set the discriminator field "type" with the appropriate value. This is unexpected.
For inspiration I used the following:
- https://github.com/javatestcase/RestEasy/blob/RestEasyVersion2/src/main/java/com/sample/rest/Animal.java
- http://stackoverflow.com/questions/27616061/can-swagger-jaxrs-do-apimodel-inheritance-with-discriminator
Is there any good documentation on this feature that goes into more depth than the following?
Swagger Test Client
public class ApiIntegrationTest
{
@Test
public void testClient() throws ApiException {
ApiClient apiclient = new ApiClient();
// apiclient.setUsername("myUsername");
// apiclient.setPassword("myPassword");
EventsApi eventsApi = new EventsApi(apiclient);
{
NetworkEventDataDTO eventDataDTO = new NetworkEventDataDTO ();
NetworkDto network = new NetworkDto();
eventDataDTO.setNetwork( network );
// ISSUE: This should be hard-coded in the pojo.
// private final String type = "NetworkEventDataDTO";
eventDataDTO.setType( "NetworkEventDataDTO" ); //$NON-NLS-1$
eventsApi.processEvent( eventDataDTO );
}
}
}
swagger.json
JAX-RS Web Service
@Path( "/events" )
@Api(value = "/events")
@Stateless
public class EventsLoggerService
{
private static final Logger LOGGER = LoggerFactory.getLogger( EventsLoggerService.class );
@POST
@Path( "/single" )
@Consumes( MediaType.APPLICATION_JSON )
@Produces(MediaType.APPLICATION_JSON)
@ApiOperation(value = "Post a Notification Event", response = String.class)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "OK"),
@ApiResponse(code = 400, message = "Failed to consume Notification Event.")
})
public Response processEvent( @ApiParam(required = true, value = "Notification Event to post.") NotificationEventDTO event )
{
LOGGER.trace( "Processing NotificationEventDTO: {}", event ); //$NON-NLS-1$
try
{
// System.out.println( event );
return Response.ok().entity( "OK" ).build(); //$NON-NLS-1$
}
catch ( Exception e )
{
LOGGER.error( "Unexpected error processing NotificationEventDTO: {}", e.getMessage() ); //$NON-NLS-1$
return Response.serverError().build();
}
}
}
Parent DTO
@JsonAutoDetect
@JsonTypeInfo( use = Id.NAME, include = As.PROPERTY, property = "type", visible = true )
@JsonSubTypes( { @Type( value = SubscriptionEventDataDTO.class, name = "SubscriptionEventDataDTO" ),
@Type( value = ServiceEventDataDTO.class, name = "ServiceEventDataDTO" ),
@Type( value = NetworkEventDataDTO.class, name = "NetworkEventDataDTO" ),
@Type( value = NetworkIdEventDataDTO.class, name = "NetworkIdEventDataDTO" ) } )
@JsonPropertyOrder( { "version" } )
@ApiModel(value = "NotificationEventDTO",
subTypes = { SubscriptionEventDataDTO.class, ServiceEventDataDTO.class, NetworkEventDataDTO.class, NetworkIdEventDataDTO.class},
discriminator = "type")
public class NotificationEventDTO implements EventDataDTO
{
@ApiModelProperty(required=true, value = "the discriminator field.")
private String type;
private long version = 1;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@Override
@JsonProperty( required = true, value = "version" )
public long getVersion() {
return version;
}
public void setVersion(long version) {
this.version = version;
}
}
Example Child DTO
@ApiModel(value = "NetworkEventDataDTO", parent = NotificationEventDTO.class)
public class NetworkEventDataDTO extends NotificationEventDTO
{
private NetworkDto network;
public NetworkEventDataDTO()
{
}
public NetworkEventDataDTO( NetworkDto network )
{
this.network = network;
}
public NetworkDto getNetwork()
{
return network;
}
public void setNetwork( NetworkDto network )
{
this.network = network;
}
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the attached swagger.json.txt and the Java DTO examples, especially NotificationEventDTO, NetworkEventDataDTO, and their discriminator annotations. Compare the generated Java client model with the Swagger Editor output and trace how the type discriminator is represented. Done means the generated client sets the appropriate subtype discriminator without manual assignment, with a regression test covering the example.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, tooling
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100