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

How can subtypes of an abstract return type be included in the output? #1209

Open
cw2501 opened this issue Jul 23, 2024 · 7 comments
Open

How can subtypes of an abstract return type be included in the output? #1209

cw2501 opened this issue Jul 23, 2024 · 7 comments
Labels
Milestone

Comments

@cw2501
Copy link

cw2501 commented Jul 23, 2024

Hello, I have a question concerning the documentation of subtypes, which themselves are not being used in the API directly.

This is our setup:

A Spring RestController defines the endpoint

@GetMapping(path = {"/actor/{actorId}"})
public AbstractActorDto getActor(@PathVariable("actorId") UUID actorId)

The AbstractActorDto defines a discriminator field so the type can be determined.

@JsonDeserialize(using = ActorDeserializer.class)
public abstract class AbstractActorDto
{
     private ActorEnum actorType;
     ... 

Problem is well... there's 69 subclasses, some of them multilayered with additional abstracts inbetween 😬
I know of the @JsonSeeAlso annotation which would link the subtypes and lead to their inclusion in the apidocs, but maybe there's a more elegant way of including them all?

Best regards
Chris

@stoicflame
Copy link
Owner

Have you tried the api-classes configuration element?

@stoicflame stoicflame added this to the 2.18.1 milestone Jul 23, 2024
@cw2501
Copy link
Author

cw2501 commented Jul 24, 2024

I have. What I forgot to mention in the initial post is that the DTOs reside in a different module than our REST endpoints. I tried including the missing DTOs directly:

<api-classes>
    <include pattern="our.domain.backend.impl.**" />

but that didn't make a difference. If I mention subclasses with @JsonSeeAlso they are included, so it's not a visibility problem.

Our module structure looks like this:

  • backend
    • backend-rest-api (this is what enunciate is being pointed at)
    • backend-impl (this is where the DTOs are)

Maybe we already got it wrong with our module configuration?

@stoicflame
Copy link
Owner

What I forgot to mention in the initial post is that the DTOs reside in a different module than our REST endpoints.

Yeah, that's fine.

You may have to annotate your subclasses with some kind of Jackson annotation just so Enunciate knows it's a JSON data type.

You're building with Maven, yes? Try running with mvn -X (verbose) flag and look for messages like:

our.domain.backen.impl.MyClass isn't a potential Jackson type because (reason).

@stoicflame
Copy link
Owner

If there's no "reason" that your types are being excluded, then it's probably just that Enunciate can't tell that they're supposed to be JSON types because there's no reference to them as JSON types from any JSON types or endpoints. So you probably just need to add some Jackson annotation so Enunciate knows to include them as JSON types. I'd suggest something like:

@com.fasterxml.jackson.annotation.JsonClassDescription("description of class here")
public class MyDto {
  //...
}

@cw2501
Copy link
Author

cw2501 commented Jul 25, 2024

I'll give that a try tomorrow. Thank you for your help!

@cw2501
Copy link
Author

cw2501 commented Jul 29, 2024

Hi Ryan, I've given your suggestion a try but I'm afraid there's no change in the behaviour.

I have referenced the file directly
<include pattern="our.domain.backend.impl.planning.actor.dto.ArrowDto" />

and added the annotation @JsonClassDescription to the dto

package our.domain.backend.impl.planning.actor.dto;
...
@Data
@JsonClassDescription("description of class here")
public class ArrowDto extends AbstractActorDto

I've then run the maven build with the -X option but strangely enough the above DTO is not being mentioned anywhere in the log and I'm kind of stuck now. Might this have anything to do with the AbstractActor's custom deserializer? @JsonDeserialize(using = ActorDeserializer.class)? But then... as soon as I use the @JsonSeeAlso, the DTO appears in the apidocs as expected.

@cw2501
Copy link
Author

cw2501 commented Jul 29, 2024

I unleashed the debugger and figured out, that Enunciate.loadApiReflections(...) only returned entries from the sourcePath, but none from the classPath.

It seems that our api-classes exclude pattern was responsible for this. Our strategy was to exclude everything with <exclude pattern="**.*" /> and then add includes pointed at our own packages.

This seemed valid, as the wiki entry 'Excluding Including Classes' states "Note that includes take precedence over excludes". Is this no longer valid or did we misinterpret its meaning?

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