Details
-
Bug
-
Resolution: Unresolved
-
Major
-
None
-
None
-
None
-
None
Description
org.drools.persistence.SingleSessionCommandService throws a NullPointerException during the application startup. As described in the environment section the application uses Drools 5.2.0.CR1 and Spring 2.5.6. Drools configuration is created in a Spring xml file:
<drools:kbase id="knowledgeBase"> <drools:resources> <drools:resource type="BPMN2" source="..." /> </drools:resources> </drools:kbase> <drools:ksession id="knowledgeSession" kbase="knowledgeBase" type="stateful"> <drools:configuration> <drools:jpa-persistence> <drools:entity-manager-factory ref="entityManagerFactory" /> <drools:transaction-manager ref="transactionManager" /> </drools:jpa-persistence> </drools:configuration> </drools:ksession>
Releated EntityManagerFactory and TransactionManager declarations are as follows:
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" /> </property> </bean> <tx:jta-transaction-manager />
The related stack trace is as follows:
Caused by: java.lang.IllegalStateException: java.lang.reflect.InvocationTargetException at org.drools.persistence.jpa.KnowledgeStoreServiceImpl.buildCommanService(KnowledgeStoreServiceImpl.java:130) at org.drools.persistence.jpa.KnowledgeStoreServiceImpl.newStatefulKnowledgeSession(KnowledgeStoreServiceImpl.java:54) at org.drools.persistence.jpa.JPAKnowledgeService.newStatefulKnowledgeSession(JPAKnowledgeService.java:109) at org.drools.container.spring.beans.StatefulKnowledgeSessionBeanFactory.internalAfterPropertiesSet(StatefulKnowledgeSessionBeanFactory.java:82) at org.drools.container.spring.beans.AbstractKnowledgeSessionBeanFactory.afterPropertiesSet(AbstractKnowledgeSessionBeanFactory.java:108) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1369) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1335) ... 30 more Caused by: java.lang.reflect.InvocationTargetException at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:44) at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) at java.lang.reflect.Constructor.newInstance(Constructor.java:516) at org.drools.persistence.jpa.KnowledgeStoreServiceImpl.buildCommanService(KnowledgeStoreServiceImpl.java:116) ... 36 more Caused by: java.lang.RuntimeException: Could not commit session at org.drools.persistence.SingleSessionCommandService.<init>(SingleSessionCommandService.java:136) ... 41 more Caused by: java.lang.NullPointerException at org.drools.persistence.SingleSessionCommandService.<init>(SingleSessionCommandService.java:125)
The problem is also discussed in the forum in this thread: http://community.jboss.org/message/595927#595927 The actual problem is caused by the line 232 in org.drools.persistence.SingleSessionCommandService:
if ( tm.getClass().getName().toLowerCase().contains( "jpa" ) ) {
Now, if Spring is configured to use a JpaTransactionManager there is no problem. However, if a JtaTransactionManager is used, which I believe is the usual case, it is ignored and no PersistenceContextManager is created which causes the NPE on line 125:
jpm.getApplicationScopedPersistenceContext().persist( this.sessionInfo );
To fix the problem I, currently, use a modified version of the org.drools.container.spring.beans.StatefulKnowledgeSessionBeanFactory which creates an org.drools.runtime.Environment as follows:
DroolsSpringTransactionManager dstm = new DroolsSpringTransactionManager((AbstractPlatformTransactionManager) jpaConfiguration.getPlatformTransactionManager()); Environment env = KnowledgeBaseFactory.newEnvironment(); env.set(EnvironmentName.ENTITY_MANAGER_FACTORY, jpaConfiguration.getEntityManagerFactory()); env.set(EnvironmentName.TRANSACTION_MANAGER, dstm); env.set(EnvironmentName.OBJECT_MARSHALLING_STRATEGIES, new ObjectMarshallingStrategy[] { new SerializablePlaceholderResolverStrategy(ClassObjectMarshallingStrategyAcceptor.DEFAULT) }); DroolsSpringJpaManager dsjm = new DroolsSpringJpaManager(env); env.set(EnvironmentName.PERSISTENCE_CONTEXT_MANAGER, dsjm);
This creates a PersistenceContextManager which uses the correct JtaTransactionManager. This way I have no problems.