@PersistenceUnit annotated field is not injected by CDI

Hi,

I’m using Hibernate with Jakarta Data 1.0 and trying to make it work with CDI. I configure the maven compiler to use hibernate-jpamodelgen for generating various classes. Among classes generated, there are repository classes corresponding to mine, with underscore appended. These include a sessionFactory field of type EntityManagerFactory annotated with @PersistenceUnit. I believe this field is supposed to be automatically injected, but it is not. CDI (Weld) does seem to be triggered e.g. a @PostConstruct method is called, but the sessionFactory field remains null. If I manually add @Inject to the field injection does work, but this means I have to copy the generated source, otherwise my modification is overwritten.

Am I doing something wrong, anything I’m missing, or is the missing @Inject annotation a bug?

Hallvard

Sounds like a bug in Weld potentially. The EntityManagerFactory is supposed to be injectable by annotating @PersistenceUnit and EntityManager by annotation @PersistenceContext with the appropriate unit name.
Do you use a Jakarta EE container? If so, what is the name of your persistence unit in the persistence.xml? Your @jakarta.data.repository.Repository(dataStore = "...") value must match the name of the persistence unit name, unless your persistence unit is somehow the “default” persistence unit for a CDI/EJB container to pickup.

So you’re saying the the @PersistenceUnit annotation should be enough to trigger injection, without an explicit @Inject?

So far, I’m doing this in a JUnit test, and I create the CDI container (Weld) programmatically. That may imply there is no EE Container, could that be the reason @PersistenceUnit doesn’t trigger injection?

I quote from the specification: “An application usually obtains a reference to an implementation of a repository via dependency injection. Therefore, the provider must make its repository implementations available to the bean container responsible for dependency injection.”. Perhaps I need something to allow the “provider” to make the EntityManagerFactory available for injection?

In the section of Configuration.adoc titled “Obtaining a StatelessSession” it described how this happens for some cases, but it is unclear to me how to do this in a JUnit test where I create the CDI (WelContainer) programmatically. BTW, it works to use new MyRepository_(statelessSession) where statelessSession is created manually, but this isn’t really how it ideally should be done, IMO.

I didn’t provide a dataStore-argument to @Repository, perhaps that’s why the @PersistenceUnit annotation didn’t have an argument, either? I have a persistence.xml file that I used in a manual call to Persistence.createEntityManagerFactory. I now tried to use the same name for alle these three, but it didn’t trigger any injection of the EntityManagerFactory.

Yes, that’s most likely the reason.

In theory, a feature of JPA 3.2 could be leveraged to do this, but I don’t think any provider has already implemented this.

I think that you will have to use some Weld APIs to get this to work in Java SE, also see weld-testing/junit5/src/test/java/org/jboss/weld/junit5/resources/InjectResourcesTest.java at master · weld/weld-testing · GitHub

Would it be wrong to also generate an @Inject annotation to the @PersistenceUnit annotated field? That would make Weld happy (I doubt it would hurt anyone)!

Unfortunately, adding @Inject would not be correct, because neither @PersistenceUnit nor @PersistenceContext are CDI qualifier annotations, so you wouldn’t be able to control what bean is injected into a repository.
AFAICS, it would be easiest if you just use the weld-testing module.