I am using spring data rest with Mongo to expose a class with multiple subtypes. When I do this, HATEOAS is compartmentalizing the results based on the actual instantiated type, rather than the common base type. This results in the links being incorrect, and renders paging useless since it is a mixed type list.
I have tried explicitly adding the @Relation tag to all of the classes involved, and it seems to have no affect at all. I get the same results with or without it.
I am using spring boot dependencies 2.1.8.RELEASE with spring-boot-starter-data-rest and spring-cloud-dependencies Greenwich.SR1
The base class:
@Relation(collectionRelation = "notifications", value="notifications")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "notificationType")
@JsonSubTypes({
@JsonSubTypes.Type(value = ModelNotification.class, name = Notification.MODEL_NOTIFICATION),
@JsonSubTypes.Type(value = BasicNotification.class, name = Notification.BASIC_NOTIFICATION)
})
public class Notification extends UUIDEntity implements Serializable {
private static final long serialVersionUID = 8199210081144334378L;
public static final String MODEL_NOTIFICATION = "MODEL_NOTIFICATION";
public static final String BASIC_NOTIFICATION = "BASIC_NOTIFICATION";
public enum Severity {
TRACE,
DEBUG,
INFO,
WARN,
ERROR,
FATAL
}
public Notification() {
this.notificationType = BASIC_NOTIFICATION;
}
@JsonProperty("notificationType")
private String notificationType;
@JsonProperty("createdDate")
@CreatedDate
private Instant createdDate;
@JsonProperty("lastModifiedDate")
@LastModifiedDate
private Instant lastModifiedDate;
@JsonProperty("createdBy")
@CreatedBy
private String createdBy;
@JsonProperty("lastModifiedBy")
@LastModifiedBy
private String lastModifiedBy;
@JsonProperty("severity")
private Severity severity;
@JsonProperty("message")
private String message;
The no additional member version:
@Relation(collectionRelation = "notifications", value="notifications")
public class BasicNotification extends Notification implements Serializable {
private static final long serialVersionUID = 8063077545983014320L;
}
And the extension version:
@Relation(collectionRelation = "notifications", value="notifications")
public class ModelNotification extends Notification implements Serializable {
private static final long serialVersionUID = 3700576594274374440L;
@JsonProperty("storedModel")
private StoredModel storedModel;
public ModelNotification() {
super();
this.setNotificationType(Notification.MODEL_NOTIFICATION);
}
I would expect, given adding the @Relation tag, that all of the results would appear under notifications, which is the correct url for the spring data rest endpoint. Note that all of the endpoints are working correctly, but just the HATEOAS stuff is incorrect, and the bundling creates problems. When accessing at: /api/notifications
I get back:
{
"_embedded" : {
"modelNotifications" : [ {
"notificationType" : "MODEL_NOTIFICATION",
"createdDate" : "2019-10-02T15:53:42.127Z",
"lastModifiedDate" : "2019-10-02T15:53:42.127Z",
...
[SNIP FOR BREVITY]
...
} ]
},
"_links" : {
"self" : {
"href" : "http://fastscore:8088/api/modelNotification/ef81c342-29d3-48fb-bab3-d416e80bc5f6"
},
"modelNotification" : {
"href" : "http://fastscore:8088/api/modelNotification/ef81c342-29d3-48fb-bab3-d416e80bc5f6"
}
}
} ],
"notifications" : [ {
"notificationType" : "BASIC_NOTIFICATION",
"createdDate" : "2019-10-02T15:52:10.261Z",
"lastModifiedDate" : "2019-10-02T15:52:10.261Z",
"createdBy" : "anonymousUser",
"lastModifiedBy" : "anonymousUser",
"severity" : "INFO",
"message" : "Interval Process Completed Successfully",
"_links" : {
"self" : {
"href" : "http://fastscore:8088/api/notifications/93fa5d6b-1457-4fa6-976c-cfdddc422976"
},
"notification" : {
"href" : "http://fastscore:8088/api/notifications/93fa5d6b-1457-4fa6-976c-cfdddc422976"
}
}
...
[SNIP]
...
},
},
"_links" : {
"self" : {
"href" : "http://fastscore:8088/api/notifications{?page,size,sort}",
"templated" : true
},
"profile" : {
"href" : "http://fastscore:8088/api/profile/notifications"
},
"search" : {
"href" : "http://fastscore:8088/api/notifications/search"
}
},
"page" : {
"size" : 20,
"totalElements" : 4,
"totalPages" : 1,
"number" : 0
}
}
This obviously seems incorrect, as modelNotifications is not a spring data rest endpoint. Also, this would make paging useless, as if I have a ton of notifications, the paging works only for those, and I receive modelNotifications every time even if I have only one... So on page two, I would receive the second page of notifications, but still have the modelNotifications on the second page even if I had only a single entry.
This kind of renders the HATEOAS support unusable with spring data rest.