I am building a profile service with the typical REST endpoints for creating, reading, updating and deleting profiles. For this I am using the Spring Framework together with a MongoDB. On top I would like to use QueryDSL to create some custom queries.
A full minimal working example of the current implementation can be found here: https://github.com/mirrom/profile-modules
I would like to have sub profile models that extend the base profile model, and sub sub models that extend the sub models. By this I have hierarchical profiles that inherit the fields of its parent profile. The idea is to store all profiles in the same collection and distinguish them via the automatically created _class field.
A simple example (with Lombok annotations):
@Data
@Document(collection = "profiles")
@Entity
public class Profile {
@Id
private ObjectId id;
@Indexed
private String title;
@Indexed
private String description;
private LocalDateTime createdAt;
private LocalDateTime modifiedAt;
}
@Data
@Entity
@EqualsAndHashCode(callSuper = true)
public class Sub1Profile extends Profile {
private String sub1String;
private int sub1Integer;
}
While (all) profiles can get accessed via the endpoint /api/v1/profiles, the sub1Profiles can be accessed via /api/v1/profiles/sub-1-profiles. Currently the sub1Profiles endpoint delivers all profiles, but it should just deliver the sub1Profiles and its children. For this I would like to use QueryDSL, but I can't add QuerydslPredicateExecutor<Profile> and QuerydslBinderCustomizer<QProfile> to more than one repository interface. This is how my profile repository looks like:
@Repository
public interface ProfileRepository extends MongoRepository<Profile, ObjectId>, QuerydslPredicateExecutor<Profile>,
QuerydslBinderCustomizer<QProfile> {
@Override
default void customize(QuerydslBindings bindings, QProfile root) {
bindings.bind(String.class)
.first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
}
}
If I now try to do the same with Sub1ProfileRepository:
@Repository
public interface Sub1ProfileRepository
extends MongoRepository<Sub1Profile, ObjectId>, QuerydslPredicateExecutor<Sub1Profile>,
QuerydslBinderCustomizer<QSub1Profile> {
default void customize(QuerydslBindings bindings, QProfile root) {
bindings.bind(String.class)
.first((SingleValueBinding<StringPath, String>) StringExpression::containsIgnoreCase);
}
}
I get this error message:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sub1ProfileRepository' defined in com.example.profile.repository.sub1profile.Sub1ProfileRepository defined in @EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property customize found for type Sub1Profile!
What am I missing?