I would like to use spring data repositories in my Java EE project. I use:
ATTENTION! When you use a Timer with a database there is an important requirement. See https://javaee.github.io/glassfish/doc/5.0/application-development-guide.pdf at the chapter "EJB Timer Service" :
Using the EJB Timer Service is equivalent to interacting with a single JDBC resource manager. If an EJB component or application accesses a database either directly through JDBC or indirectly (for example, through an entity bean's persistence mechanism), and also interacts with the EJB Timer Service, its data source must be configured with an XA JDBC driver.
So for example on GlassFish 5.0 on the admin console you must have for your pool on the "JDBC Connection Pools" the ressource type with "java.sql.XADatasource". If you don't do that you will have error issue when the method annoted with @TimeOut will be called and will try to use an Entity.
The repository initialization breaks the transaction. Initialize the repository beforehand, in a different Thread/transaction by adding @Eager
to your repository instances.
Spring Data repository instances are @ApplicationScoped
and initialized on demand. The Thread (and transaction) that performs the first access to the repository is used for initialization.
Spring Data JPA repository initialization does a couple of things, one of them is trying to figure out, whether you have provided named queries for repository query methods. Unfortunately, JPA does not provide an API to check whether a named query exists, so we rely on EntityManager.createNamedQuery(…)
. If there's no named query, EntityManager
throws an exception and aborts the transaction.
In a later stage, your EJB method uses the EntityManager
within the same Thread (and transaction). It checks for an active transaction. Because the transaction is marked for rollback-only, you see the exception.
Add @Eager
to your repository declaration. The Spring Data CDI extension will initialize the repository on startup:
@Eager
public interface TestRepository extends CrudRepository<TestEntity, Long> {
// …
}
You don't require @Repository
on TestRepository
. Spring Data picks up the repository by picking up beans that are descendants from org.springframework.data.repository.Repository
or plain interfaces annotated with @RepositoryDefinition
.
The transaction manager properties in your persistence.xml
are not required, WildFly already configures the persistence context with the required settings.