-
Notifications
You must be signed in to change notification settings - Fork 31
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
[Use Case]: use CDI qualifier annotations to select a data source #476
Comments
Note that a proposed implementation of this idea is in #474. |
So in implementing the spec, I really struggled a bit to know what to do with the In the end what I ended up with was this, which is I believe right for Quarkus, and almost correct for a "regular" Jakarta EE server: @TransactionScoped
@Generated("org.hibernate.processor.HibernateProcessor")
public class Repo_ implements Repo {
private @Nonnull StatelessSession session;
// constructor for testing
public Repo_(@Nonnull StatelessSession session) {
this.session = session;
}
// resource accessor method
@Override
public @Nonnull StatelessSession session() {
return session;
}
// injection of the persistence unit
@Inject
@PersistenceUnit(unitName="myds")
private EntityManagerFactory sessionFactory;
// constructor for CDI
@Inject
Repo_() {
}
// create a session after injection (ugh)
@PostConstruct
private void openSession() {
session = sessionFactory.unwrap(SessionFactory.class).openStatelessSession();
}
// clean up the session
@PreDestroy
private void closeSession() {
session.close();
}
...
} This is OK, but definitely isn't as clean as I would have preferred. The critical bit here is this: @Inject
@PersistenceUnit(unitName="my-persistence-unit")
private EntityManagerFactory sessionFactory; The The actual code is a bit nasty because Now, if the persistence unit were identified by CDI qualifier annotations, I could just replace the |
The data source could be viewed as being injected via a method, which is a concept which does already exist in CDI. On today's call I toyed another possibility similar to this which was to use a |
OK, wait, I just had a new idea that's I guess not terrible and:
I don't know quite what to call this, but something like @RepositoryImplementor
interface DocumentDatabaseClient {
@Inject
void init(@DocumentDatabase DataSource ds);
} It's almost some sort of "facet". Anyway, a repository would not directly implement this interface, but it would indicate that its generated implementation does implement the interface: @Repository(implementor = DocumentDatabaseClient.class)
interface DocumentRepository {
...
} So then the implementation would be conceptually something like Note that I wondered if you could draw the dependence in the opposite direction, and have In future we might find other uses for these hidden "facets", though I can't think of anything off the top of my head. Perhaps a |
Actually the interface DocumentDatabaseClient {
@Inject
void init(@DocumentDatabase DataSource ds);
} @Repository(implementor = DocumentDatabaseClient.class)
interface DocumentRepository {
...
} |
Well, perhaps not. You could do it like this, perhaps: @RepositoryImplementor({DocumentRepository.class, Library.class})
interface DocumentDatabaseClient {
@Inject
void init(@DocumentDatabase DataSource ds);
} @Repository
interface DocumentRepository {
...
} |
As a ...
I need to be able to ...
specify the data source that backs a repository via CDI qualifier annotations.
Which enables me to ...
avoid the use of stringly-typed names.
Additional information
Currently, a datasource, persistence unit, etc, that backs a repository implementation must be specified using
@Repository(dataStore=".....")
which works, but is not properly integrated with the CDI bean manager.It would be nice to be able to disambiguate the data source or persistence unit or whatever via the placement of CDI qualifier annotations on the repository interface. Unfortunately, there's no obvious completely natural place to put them.
static
fields, so we can't put them there either.So, the only options I can really imagine are the following.
Use of method injection
The data source could be viewed as being injected via a method, which is a concept which does already exist in CDI.
The problem with this is that it exposes to clients the possibility of manipulating the state of the repository. (And interface methods are always
public
.)So this is no good. I would say we definitely don't want to do it this way.
Annotate the resource access method
I actually think this option is pretty good and natural. Probably most repositories are going to want to have a resource accessor method, and so that's a place we can put these annotations.
It's true that this is a non-standard place to place qualifier annotations in the sense that it's not contemplated by the CDI spec, but to me that's completely fine. The repository implementation can easily obtain the qualifiers from this method declaration and use them to look up the data source at runtime. Alternatively, an annotation processor can copy them onto an injection point of the repository implementation.
The text was updated successfully, but these errors were encountered: