As I am gradually trying to remove Dependencies on Spring in the domain part of my library without minimal extra effort, I now turn to Spring Data and the Repositories
Originally we annotated our domain entities to look like this:
@Document
public void MyEntity {
@Id
@Getter private final EntityIdentifier identifier;
@PersistenceConstructor
public MyEntity( ... ) {}
...
}
and so on.
where @Document, @PersistenceConstructor and @Id originate from the Spring Project and some are for a specific database backend (MongoDB).
I would like to cut this dependency and use my own annotations, that make sense in my domain - @Document is definitly nothing my domain experts would understand when appearing on e.g an clas Chair or a Desk.
For de/serialization with Jackson, I can create mixins to add specific annotations to classes without modifying them in their origin.
Maybe there is a similar technique for Spring or some other way to achive this that is more elegant than creating a wrapping class?
Apparently I need some clarification:
Lets suppose we try to write a clean architecture application which consists out of the following modules: domain, adapters, application. In the domain module, I have my domain logic and domain entities and everything domainy. I do not have anything springy - no dependency on spring whatsoever, not even by having a dependency that somehow depends on spring.
In the adapters and application module, I do have dependencies on spring. I might use spring-data to implement the Repository-Adapters. I will use Spring to configure and glue together the application.
Now, in my domain module I have the following classes:
@AllArgsConstructor
@HashAndEquals(of="identifier")
@DomainEntity // <-- This is an Annotation that has no dependency on Spring!
public class DomainEntity {
@DomainId // <-- This is an Annotation that has no dependency on Spring!
@Getter private final DomainEntityIdentifier identifier;
@Getter @Setter private String someValue;
...
}
@HashAndEquals
@AllArgsConstructor
public class DomainEntityIdentifiers {
@Getter private final String name;
}
public void interface DomainEntityRepository {
DomainEntity findById(DomainEntityIdentifier identifier);
void save(DomainEntity domainEntity)
void deleteById(DomainEntityIdentifier identifier);
}
Now the task is, to provide the implementation of that interface in the adapters module, using Spring Data - e.g. spring-data-mongo and inject this adapter to the domain in the application module.
Now, surly I can create an class, lets say DomainEntityMongo which is basically the same as the DomainEntity just with the spring-data-mongo-annotations, then a public interface MyEntityRepository extends CrudRepository<EntityIdentifier, MyEntityMongo> and implement the interface DomainRepository by using MyEntityRepository and converting there and back again between DomainEntityMongo <=> DomainEntity.
What I am looking for is a more magical/generical solution. E.g.
- Having jackson-style mixin-classes, which provide Spring with the necessary/missing meta-data to do the work
- Configuring Spring to use non-spring-annotations to do the work (just as it is possible with the ComponentScan for non-component-inheriting Annotations)
- Or - if the data guys have crafted another innovative solution - this innovative solution.