Hello.
We use the Play framework in our java application and migrated to version 2.5 recently.
We use Jpa plugin for persistence (hibernate) with next settings:
application.conf:
# Database configuration
# ~~~~~
db.default.driver=oracle.jdbc.driver.OracleDriver
db.default.url="jdbc:oracle:thin:@orahost:1521:crm"
db.default.username=user_default
db.default.password=user_default
db.default.jndiName=FullDS
jpa.default=fullPersistenceUnit
persistence.xml:
<persistence … version="2.1">
<persistence-unit name="fullPersistenceUnit" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>
<non-jta-data-source>FullDS</non-jta-data-source>
…
</persistence>
During migration to the play 2.5 we replaced play.db.jpa.JPA static methods with instance methods calls:
public class SomeService {
@Inject
private JPAApi jpaApi;
…
public CompletionStage<CustomerProfile> registerCustomer {
…
jpaApi.withTransaction(…);
…
}
}
But now, sometimes, application cannot initialize guice modules on startup:
play.api.UnexpectedException: Unexpected exception[CreationException: Unable to create injector, see the following errors:
1) Error injecting constructor, javax.persistence.PersistenceException: Unable to build entity manager factory
at play.db.jpa.DefaultJPAApi$JPAApiProvider.<init>(DefaultJPAApi.java:39)
at play.db.jpa.DefaultJPAApi$JPAApiProvider.class(DefaultJPAApi.java:34)
while locating play.db.jpa.DefaultJPAApi$JPAApiProvider
while locating play.db.jpa.JPAApi
for parameter 0 at core.transaction.TransactionInterceptor.setJpaApi(TransactionInterceptor.java:41)
at core.modules.CoreBindingModule.configure(CoreBindingModule.java:59) (via modules: com.google.inject.util.Modules$OverrideModule -> core.modules.CoreBindingModule)
Caused by: javax.persistence.PersistenceException: Unable to build entity manager factory
….
Caused by: javax.naming.NameNotFoundException: FullDS not found
at tyrex.naming.MemoryContext.internalLookup(Unknown Source)
at tyrex.naming.MemoryContext.lookup(Unknown Source)
at javax.naming.InitialContext.lookup(InitialContext.java:421)
at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:114)
... 70 more
Number of non-initialized guice modules in exception message can vary from 0 (application starts and works correctly) to n (n = number of modules where JPAApi is used). In logs I can see that DB pool is initialized:
[info] application - Creating Pool for datasource 'default'
[info] p.a.d.HikariCPConnectionPool - datasource [default] bound to JNDI as FullDS
As I see the jndi pool name is initialized in the play.api.db.HikariCPModule. And it looks like there is no any order/dependency between this module and modules where the JPAApi is used with injection. So sometimes the JPAApi is initialized before play.api.db.HikariCPModule initialization.
How can I solve this problem?