I am trying to develop jBPM spring boot application but getting Unable to lookup JNDI name [jdbc/jbpm-ds] error.
To achieve so, I have used jbpm-7.36.0.Final, Spring-Boot-2.2.6 and jbpm-spring-boot 7.36.0 Final along with spring boot Bitronix api. Below is my pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jta-bitronix</artifactId>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<!-- <version>5.2.6.RELEASE</version> -->
</dependency>
<dependency>
<groupId>com.microsoft.sqlserver</groupId>
<artifactId>mssql-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.kie</groupId>
<artifactId>jbpm-spring-boot-starter-basic</artifactId>
<version>${runtime.version}</version>
</dependency>
</dependencies>
In my application.properties file I have configured below values
#hibernate configuration
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.properties.hibernate.show_sql=true
spring.jpa.properties.hibernate.hbm2ddl.auto=update
#JTA enabled
spring.jta.enabled=true
#bitronix Non-XA transaction manager configuration
spring.datasource.xa.properties.url=jdbc:sqlserver://10.1.5.209:1433;databaseName=MRR3;
spring.datasource.xa.properties.uniqueName=jdbc/jbpm-ds
spring.datasource.xa.properties.username=sa
spring.datasource.xa.properties.password=password_123
spring.datasource.xa.properties.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.xa.data-source-class-name=bitronix.tm.resource.jdbc.lrc.LrcXADataSource
Below is the code snippet
@Bean
public StatefulKnowledgeSession newStatefulKnowledgeSession() throws Exception {
RuntimeEnvironmentBuilder builder = null;
if (usePersistence) {
TransactionManager tm = TransactionManagerServices.getTransactionManager();
entityManagerFactory = Persistence.createEntityManagerFactory("org.jbpm.persistence.jpa");//Line where Exception occurs
System.out.println(entityManagerFactory.getProperties());
Environment env = EnvironmentFactory.newEnvironment();
env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, entityManagerFactory);
env.set(EnvironmentName.TRANSACTION_MANAGER, tm);
builder = RuntimeEnvironmentBuilder.Factory.get().newDefaultBuilder()
.entityManagerFactory(entityManagerFactory)
.addEnvironmentEntry(EnvironmentName.TRANSACTION_MANAGER, tm);
builder.knowledgeBase(readKnowledgeBase);
StatefulKnowledgeSession ksession = JPAKnowledgeService
.newStatefulKnowledgeSession(readKnowledgeBase, null, env);
return ksession;
// builder =
// RuntimeEnvironmentBuilder.Factory.get().newDefaultBuilder()
// .entityManagerFactory(entityManagerFactory);
}
}
Sharing important log info
2020-05-11 23:41:12.122 INFO 18852 --- [main] o.hibernate.jpa.internal.util.LogHelper : HHH000204: Processing PersistenceUnitInfo [
name: org.jbpm.persistence.jpa
...] {} <>
2020-05-11 23:41:12.155 WARN 18852 --- [main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'newStatefulKnowledgeSession' defined in class path resource [com/citiustech/mrr/controller/AbstractionProcessController.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.kie.internal.runtime.StatefulKnowledgeSession]: Factory method 'newStatefulKnowledgeSession' threw exception; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment] {} <>
.
.
.
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.id.factory.internal.DefaultIdentifierGeneratorFactory.injectServices(DefaultIdentifierGeneratorFactory.java:152)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.injectDependencies(AbstractServiceRegistryImpl.java:286)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:243)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.boot.internal.InFlightMetadataCollectorImpl.<init>(InFlightMetadataCollectorImpl.java:179)
at org.hibernate.boot.model.process.spi.MetadataBuildingProcess.complete(MetadataBuildingProcess.java:119)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.metadata(EntityManagerFactoryBuilderImpl.java:904)
at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:935)
at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:56)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:79)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:54)
at com.citiustech.mrr.controller.AbstractionProcessController.newStatefulKnowledgeSession(AbstractionProcessController.java:51)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:154)
... 20 common frames omitted
Caused by: org.hibernate.engine.jndi.JndiException: Unable to lookup JNDI name [jdbc/jbpm-ds]
at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:100)
at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:98)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:100)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:246)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.buildJdbcConnectionAccess(JdbcEnvironmentInitiator.java:145)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:66)
at org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.initiateService(JdbcEnvironmentInitiator.java:35)
at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.initiateService(StandardServiceRegistryImpl.java:94)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
... 39 common frames omitted
Caused by: javax.naming.NameNotFoundException: unable to find a bound object at name 'jdbc/jbpm-ds'
at bitronix.tm.jndi.BitronixContext.lookup(BitronixContext.java:83)
at bitronix.tm.jndi.BitronixContext.lookup(BitronixContext.java:67)
at javax.naming.InitialContext.lookup(InitialContext.java:421)
at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:97)
... 48 common frames omitted
I am also interested to know if below understanding of mine is correct or not
- jBPM only supports JTA type transaction i.e. global transaction. You can't use RESOURCE_LOCAL transaction type while integrating jBPM.
- When I say transaction type RESOURCE_LOCAL, means only one datasource transaction will be shared across the application.
- jBPM RuntimeManager uses 'org.jbpm.domain' persistence unit name (Mandatory type) to handle all it's internal table operations.
- All the application specific transaction can be handled by a default persistence unit name i.e.'org.jbpm.persistence.jpa' . This can be override by a custom persistence context.
- JTA is further divided into two types XADatasource type and Non-XADatasource type. XADatasource should be use when datasource is in application server container. And Non-XADatasource is useful for EJB based application.
XADatasource required below configuration
<provider>org.hibernate.jpa.HibernatePersistenceProvider</provider>and
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.SunOneJtaPlatform" /> <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.WeblogicJtaPlatform" />Non-XADatasource required below configuration
<provider>org.hibernate.ejb.HibernatePersistence</provider>and
<property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform"/>Is point 6 or 7 necessary, if so how to without using persistence.xml.
What is the use of below property and what jar has this class
spring.jpa.properties.hibernate.transaction.manager_lookup_class=org.hibernate.transaction.BTMTransactionManagerLookup
As suggested by @JRichardsz, I made below changes in my code to make it work with Spring Boot
For me xa.properties works along with Bitronix, but if it does not work for you then you can switch to Spring provided datasource.