I am running the keycloak Photoz example. When I deploy to Wildfly, the EntityManager is not injected and I get a NullPointerException (below). I've tried a few different strategies -- tweaking persistence.xml (remove LOCAL_RESOURCE
) and switching to the @PersistenceContext
attribute without luck. Since the examples are canned, one would think I can't be too far off?? I don't really understand Java well enough to debug this. This would seem to have something to do with my Wildfly installation? But the example is designed to run in wildfly (mvn clean package wildfly:deploy
). Any advice?
Note: I am able to manually create the EntityManager as shown below. Also note, that I must call init(), so something seems to be wrong with DI in this app in general...
Resources r = new Resources();
r.init();
EntityManager entityManager = r.createEntityManager();
Stack trace:
Caused by: java.lang.NullPointerException
keycloak_1 | at org.keycloak.example.photoz.album.AlbumService.findAll(AlbumService.java:86)
keycloak_1 | at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
keycloak_1 | at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
keycloak_1 | at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
keycloak_1 | at java.lang.reflect.Method.invoke(Method.java:498)
keycloak_1 | at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:139)
keycloak_1 | at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:295)
keycloak_1 | at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:249)
keycloak_1 | at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:236)
keycloak_1 | at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:395)
Service:
...
@Path("/album")
@Transaction
public class AlbumService {
public static final String SCOPE_ALBUM_VIEW = "urn:photoz.com:scopes:album:view";
public static final String SCOPE_ALBUM_DELETE = "urn:photoz.com:scopes:album:delete";
@Inject
private EntityManager entityManager;
...
@GET
@Produces("application/json")
public Response findAll() {
return Response.ok(this.entityManager.createQuery("from Album where userId = '" + request.getUserPrincipal().getName() + "'").getResultList()).build();
}
...
.../src/main/resources/META-INF/beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<interceptors>
<class>org.keycloak.example.photoz.util.TransactionInterceptor</class>
</interceptors>
</beans>
.../src/main/resources/META-INF/persistence.xml
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="primary" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.keycloak.example.photoz.entity.Album</class>
<class>org.keycloak.example.photoz.entity.Photo</class>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.H2Dialect" />
<property name="hibernate.connection.driver_class" value="org.h2.Driver" />
<property name="hibernate.connection.url" value="jdbc:h2:~/keycloak-photoz-example" />
<property name="hibernate.connection.user" value="sa" />
<property name="hibernate.flushMode" value="FLUSH_AUTO" />
<property name="hibernate.hbm2ddl.auto" value="update" />
<property name="hibernate.show_sql" value="false" />
</properties>
</persistence-unit>
</persistence>
.../src/main/java/org/keycloak/example/photoz/util/TransactionInterceptor.java
@Interceptor
@Transaction
public class TransactionInterceptor {
@Inject
private Instance<EntityManager> entityManager;
@AroundInvoke
public Object aroundInvoke(InvocationContext context) {
EntityManager entityManager = this.entityManager.get();
EntityTransaction transaction = entityManager.getTransaction();
try {
transaction.begin();
Object proceed = context.proceed();
transaction.commit();
return proceed;
} catch (Exception cause) {
if (transaction != null && transaction.isActive()) {
transaction.rollback();
}
throw new RuntimeException(cause);
} finally {
entityManager.close();
}
}
}
.../src/main/java/org/keycloak/example/photoz/util/Resources.java
@ApplicationScoped
public class Resources {
private EntityManagerFactory entityManagerFactory;
@PostConstruct
public void init() {
entityManagerFactory = Persistence.createEntityManagerFactory("primary");
}
@PreDestroy
public void dispose() {
entityManagerFactory.close();
}
@RequestScoped
@Produces
public EntityManager createEntityManager() {
return entityManagerFactory.createEntityManager();
}
}