Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to setup jBPM in a desktop application?

What I want:

I'm creating a prototype that is supposed to read a bpmn2 file and list all its tasks.

What I'm using:

Currently I have a simple Maven application using jBPM 6. I don't need any application server, workbench etc., because it's just a simple desktop application.

The issue:

If I initialize the engine like this (as suggested by the official documentation):

RuntimeEnvironment environment = 
                RuntimeEnvironmentBuilder.Factory.get()
                .newDefaultInMemoryBuilder()
                .persistence(false)
                .addAsset(ResourceFactory.newClassPathResource("poc4.bpmn2"), ResourceType.BPMN2)
                .get();

I get this error:

Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named org.jbpm.persistence.jpa
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:69)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at org.jbpm.runtime.manager.impl.DefaultRuntimeEnvironment.init(DefaultRuntimeEnvironment.java:72)
    at org.jbpm.runtime.manager.impl.RuntimeEnvironmentBuilder.get(RuntimeEnvironmentBuilder.java:314)
    at org.jbpm.runtime.manager.impl.RuntimeEnvironmentBuilder.get(RuntimeEnvironmentBuilder.java:56)
    at com.test.jbpmpoc.main(App.java:11)

Note that I'm trying to start the engine with the persistence explicitly disabled, but I believe that's not needed because the documentation says that the engine does NOT use persistence by default.

What I know:

Accordingly to my researches, there are at least two ways of initializing the engine.

  1. Using a builder that provides the runtime environment - which I'm already doing. This seems the most recommended way of doing it, because all services would be initialized by default. However, as said here and here, this method requires a persistence to be set up if you want to use Tasks (which is something that I do);

  2. Initialize everything manually. I don't like much this one because it sounds too much effort to have a simple application running.

  3. Using other runtime environment builders.

What I have tried:

At first, I tried to use the persistence.xml suggested by the documentation, but I get a different error when I create the EntityManagerFactory:

Exception in thread "main" javax.persistence.PersistenceException: Unable to build entity manager factory
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:83)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
    at com.test.jbpmpoc.App.main(App.java:30)
Caused by: org.hibernate.engine.jndi.JndiException: Error parsing JNDI name [jdbc/jbpm-ds]
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:141)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.locate(JndiServiceImpl.java:112)
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.configure(DatasourceConnectionProviderImpl.java:115)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.buildJdbcConnectionAccess(JdbcServicesImpl.java:260)
    at org.hibernate.engine.jdbc.internal.JdbcServicesImpl.configure(JdbcServicesImpl.java:94)
    at org.hibernate.boot.registry.internal.StandardServiceRegistryImpl.configureService(StandardServiceRegistryImpl.java:111)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:234)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:206)
    at org.hibernate.cfg.Configuration.buildTypeRegistrations(Configuration.java:1887)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1845)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
    ... 3 more
Caused by: javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file:  java.naming.factory.initial
    at javax.naming.spi.NamingManager.getInitialContext(Unknown Source)
    at javax.naming.InitialContext.getDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(Unknown Source)
    at javax.naming.InitialContext.getNameParser(Unknown Source)
    at org.hibernate.engine.jndi.internal.JndiServiceImpl.parseName(JndiServiceImpl.java:135)
    ... 20 more

I'm not using an application server and don't have the JTA Datasource and ORM files, so I commented the lines that point to these files in order to fix this JNDI error, then I get this other exception:

Exception in thread "main" java.lang.NoSuchMethodError: javax.persistence.NamedQuery.lockMode()Ljavax/persistence/LockModeType;
    at org.hibernate.cfg.annotations.QueryHintDefinition.determineLockOptions(QueryHintDefinition.java:138)
    at org.hibernate.cfg.annotations.QueryBinder.bindQuery(QueryBinder.java:72)
    at org.hibernate.cfg.annotations.QueryBinder.bindQueries(QueryBinder.java:219)
    at org.hibernate.cfg.AnnotationBinder.bindQueries(AnnotationBinder.java:374)
    at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:618)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processAnnotatedClassesQueue(Configuration.java:3845)
    at org.hibernate.cfg.Configuration$MetadataSourceQueue.processMetadata(Configuration.java:3799)
    at org.hibernate.cfg.Configuration.secondPassCompile(Configuration.java:1412)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1846)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:857)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:850)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:425)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:849)
    at org.hibernate.jpa.HibernatePersistenceProvider.createEntityManagerFactory(HibernatePersistenceProvider.java:75)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
    at com.test.jbpmpoc.App.main(App.java:30)

I'm pretty sure I'm getting closer here. Do I really need the JTA datasource and ORM files if I'm running outside an application server? The jBPM installer doesn't come with these, where can I find them?

I also tried to use an empty builder instead of one of the default builders, so I would need to initialize everything manually, including the TaskService, which I believe I need to start if I want to manage the tasks (list, execute, etc). However, it requires the persistence.xml too, because I keep getting the No Persistence provider message.

Edit

I should have guessed earlier that the NoSuchMethodError exception was being caused by a Maven artifact in the wrong version. I also had JTA as my transaction strategy in my persistence definition but wasn't providing any jta datasource. However, now that I've changed my pom.xml and persistence.xml, I'm getting this error:

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: org.jbpm.persistence.jpa] Unable to build EntityManagerFactory
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:900)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at com.test.jbpmpoc.App.main(App.java:30)
Caused by: org.hibernate.HibernateException: Errors in named queries: GetProcessInstanceIdByCorrelation
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:435)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1385)
    at org.hibernate.cfg.AnnotationConfiguration.buildSessionFactory(AnnotationConfiguration.java:954)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:891)
    ... 4 more

It seems that one of the named queries form the JBPMorm.xml file is wrong. I copied this file from JBPM source code.

More info about my Java project:

  • My JBPMorm.xml
  • My persistence.xml
  • My pom.xml
  • My project structure

All the examples and tutorials I've found are focused on creating web apps running on application servers, but in my case the absence of an application server requires a workaround that I'm still yet to find. Has anyone managed to run a simple desktop application using jBPM 6?

like image 854
Fappaz Avatar asked Oct 19 '22 06:10

Fappaz


1 Answers

I may not be directly answering your question, but the below answer, I feel can guide you to a solution.

My inference from the question is that basically here we want to programmatically (with out external dependencies like databases) create the jBPM runtime and operate on it.

I would suggest you to go through the user guide - Section 6.8. Testing, which helps you to for testing your process, you test whether the process behaves as expected in specific use cases,

http://docs.jboss.org/jbpm/v6.2/userguide/jBPMBPMN2.html#d0e4026

The documentation suggests you to extend JbpmJUnitBaseTestCase and create junit test case. JbpmJUnitBaseTestCase class abstracts the logic to createRuntimeManager, assertProcessInstanceCompleted etc... You can refer or reuse this class to build your application.

See https://github.com/droolsjbpm/jbpm/blob/master/jbpm-test/src/main/java/org/jbpm/test/JbpmJUnitBaseTestCase.java

like image 80
arunvg Avatar answered Nov 01 '22 13:11

arunvg