-
-
Notifications
You must be signed in to change notification settings - Fork 569
Open
Description
Summary
With JPA @EmbeddedId/@MapsId join entities and Spring Data REST, springdoc generates recursively nested examples instead of compact, reference-like shapes. This misleads client generators and bloats the OpenAPI.
Environment
- Spring Boot + Spring Data JPA + Spring Data REST (HAL)
- springdoc: 2.8.14
Minimal model (flattened for clarity)
@Embeddable
class GoalInitiativeImpactId { Long goalId; Long initiativeId; }
@Entity
class Goal {
@Id @GeneratedValue Long id;
String name;
// other fields
@OneToMany(mappedBy = "goal", cascade = CascadeType.ALL, orphanRemoval = true)
Set<InitiativeImpactOnGoal> impactsByInitiatives = new HashSet<>();
}
@Entity
class Initiative {
@Id @GeneratedValue Long id;
String name;
// other fields
}
@Entity
class InitiativeImpactOnGoal {
@EmbeddedId GoalInitiativeImpactId id;
@ManyToOne @MapsId("goalId") Goal goal;
@ManyToOne @MapsId("initiativeId") Initiative initiative;
@Enumerated(EnumType.STRING) ImpactLevel impactLevel;
}Repositories are exposed via Spring Data REST.
Actual (runtime showcase) — request & response
Request
GET /goals/1
Response (trimmed)
{
"id": 1,
"name": { "en-US": "string" },
"impactsByInitiatives": [
{
"impactLevel": "TRIVIAL",
"_links": {
"goal": { "href": "/goals/1" },
"initiative": { "href": "/initiatives/42" }
}
}
],
"_links": {
"self": { "href": "/goals/1" },
"indicators": { "href": "/goals/1/indicators" },
"parent": { "href": "/goals/1/parent" }
}
}The join entity appears as an item with impactLevel + HAL links.
Generated by springdoc (Swagger UI example) — problematic (trimmed)
{
"id": 1,
"name": { "en-US": "string" },
"description": { "en-US": "string" },
"workflowStatus": "DRAFT",
"impactsByInitiatives": [
{
"id": { "goalId": 1, "initiativeId": 42 },
"goal": {
"id": 1,
"name": { "en-US": "string" },
"parent": {
"id": 7,
"parent": { /* … nests again … */ }
},
"initiatives": [
{
"id": 42,
"name": "string",
"payments": [ { /* … */ } ],
"progressLog": [ { /* … */ } ]
}
],
"children": [ { /* … */ } ]
},
"initiative": {
"id": 42,
"name": "string",
"payments": [ { /* … */ } ],
"progressLog": [ { /* … */ } ]
},
"impactLevel": "TRIVIAL"
}
],
"_links": {
"self": { "href": "/goals/1" }
}
}Issue: deep recursion and full entity expansion inside the join entity, unlike the HAL representation actually returned at runtime.
Expected
Reflect the actual shape for read operations. For write ops we can just use READ_ONLY ourselves.
Workarounds (short)
- Expose DTOs/projections for REST (flatten associations).
- Consider a surrogate
@Idon the join entity if OpenAPI consumers choke on composite keys.
Metadata
Metadata
Assignees
Labels
No labels