quarkus: @Inject Injection into EntityListener not working
Describe the bug I do have JPA entities annotated with @EntityListeners. I @Inject some CDI bean (@RequestScoped in my case but happens for other scopes, too) into the EntityListener. The bean never gets injected, the reference is allways null.
Things I tried:
- placing some CDI scope annotation onto the entity listener.
- Tried different CDI scopes on the injected bean
- Tried all variants of injection: constructor-, setter- and attribute-injection on the listener
Expected behavior Instance of the CDI bean should get injected
Actual behavior The CDI bean reference is allways null resulting in a NPE when accessing some attribute of the bean.
To Reproduce See attached test case
Configuration
quarkus.datasource.url=jdbc:h2:tcp://localhost/mem:test
quarkus.datasource.driver=org.h2.Driver
quarkus.hibernate-orm.database.generation=drop-and-create
(Also happens with postgresql, drop-and-create is just for testing)
Environment (please complete the following information):
- Output of
java -version
: from 8 to 11 - Quarkus version or git rev: 1.2.0
Additional context Interestingly, when the CDI bean I want injected into the EntityListener ist injected somewhere else (e.g. some @ApplicationScoped bean), injection works. Possible causse: looks like Quarkus bean discovery does not regard EntityListeners as trigger for registering some bean during compile-time-initialization.
Example code:
src/main/java/…
package org.acme;
import java.util.UUID;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.Id;
import javax.persistence.Version;
@Entity
@EntityListeners(FooListener.class)
public class FooEntity {
@Id
private String id = UUID.randomUUID().toString();
@Version
private long version;
private String data;
// getters/setters omitted for brevity
}
package org.acme;
import javax.enterprise.context.Dependent;
import javax.inject.Inject;
import javax.persistence.PrePersist;
// also happens with @Dependent
public class FooListener {
@Inject
private FooBean fooBean;
@PrePersist
public void prePersist(FooEntity entity) {
entity.setData(fooBean.pleaseDoNotCrash());
}
}
package org.acme;
import javax.enterprise.context.RequestScoped;
@RequestScoped
public class FooBean {
public String pleaseDoNotCrash() {
return "Yeah!";
}
}
src/test/java/…
package org.acme;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.transaction.Transactional;
import io.quarkus.test.junit.QuarkusTest;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
@QuarkusTest
public class EntityListenerInjectionTest {
@Inject
private EntityManager em;
@Test
@Transactional
public void shouldNotCrash() {
FooEntity o = new FooEntity();
em.persist(o);
}
@Test
@Transactional
public void shouldInvokeEntityListener() {
FooEntity o = new FooEntity();
em.persist(o);
assertEquals("Yeah!", o.getData());
}
}
package org.acme;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.h2.H2DatabaseTestResource;
@QuarkusTestResource(H2DatabaseTestResource.class)
public class TestResources {
}
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Reactions: 9
- Comments: 34 (21 by maintainers)
Commits related to this issue
- Removed: workaround for entity listeners fix: https://github.com/quarkusio/quarkus/issues/6948 — committed to smclab/openk9 by cbianco 3 years ago
For all those arriving here via google:
A workaround is to create some other bean and @Inject your bean there… just so Quarkus knows it needs to register your bean for CDI injection.
Then retrieve your bean instance in the EntityListener like this:
FooBean fooBean = CDI.current().select(FooBean.class).get();
+1
@eliaharm I think you still need to
@Inject JsonWebToken
somewhere (it doesn’t really matter where or if it is used there, as long as the bean injecting it is used, or marked as@io.quarkus.arc.Unremovable
).I think Quarkus is like “you don’t use the bean? I’ll not pack it then” on buildtime, and
CDI.current()
lookup alone do not classify as “use”.Fixed by #20708
@TheParad0X
CDI.current().select(FooBean.class).get();
still works fine for me in Quarkus 2.1. Just make sure the bean is injected somewhere else, or that it carries@io.quarkus.arc.Unremovable
.OMG, sorry for missing this 😦
sure!