-
-
16. Re: In memory TaskClient without Mina or JMS
suadalshamsi Jun 5, 2011 7:54 AM (in response to salaboy21)Hi Mauricio,
Any update on Module 6? When are expecting to complele?
-
17. Re: In memory TaskClient without Mina or JMS
daniele.ulrich Jun 20, 2011 2:56 AM (in response to dombi)I implemented a InJVMConnector (see attachment) - although it is possible to work directly with the locally instantiated TaskService, see at the end.
This has, however, some drawbacks: all events from the task service can only be recevied by a client that registers locally (in jvm) to the task service. And I'm working on a good solution for a proper JTA integration (injected EntityManager) to support an integration within an appserver.
List<TaskSummary> getOpenTasks() {
nullTaskServiceSession session =
;
try{
knowledgeBaseBeansession =
.getTaskServiceSession();
return session.getTasksAssignedAsPotentialOwner("mary", "en-UK");
finally}
{
if (session != null) {
session.dispose();
}
}
}
-
handler.zip 2.3 KB
-
-
18. Re: In memory TaskClient without Mina or JMS
frankee787 Jul 21, 2011 6:23 AM (in response to dombi)Hi Gergely Dombi,
Have you been able to successfully talk to the server in a transactional scope. Assume you communicated with the TaskServer and claimed a task. However, when you updated your application with the claim status, if an exception occurs...how would you rollback jBPM?
PS: I have been asking this same question all over the forum but in vain!!
Regards,
Franklin
-
19. Re: In memory TaskClient without Mina or JMS
frankee787 Jul 21, 2011 6:46 AM (in response to salaboy21)Hi Maruricio,
Thanks for the insight.
I can now use
taskSession.addTask(task, contentData)
instead of
client.addTask(task, content, responseHandler)
However what do I do instead of
client.complete(taskId, userId, outputData, responseHandler)
client.claim(taskId, userId, responseHandler)
Regards,
Franklin
-
20. Re: In memory TaskClient without Mina or JMS
mariemm Jul 21, 2011 7:13 AM (in response to frankee787)There is taskSession.taskOperation(). Eg.
taskSession.taskOperation(Operation.Claim, taskToComplete.getId(), user.getId(), null, null, null);
-
21. Re: In memory TaskClient without Mina or JMS
frankee787 Jul 21, 2011 8:15 AM (in response to mariemm)Hi Marie,
Excellent. Thanks for the info.
Now I need to try and put the taskSession into my transacitional scope.
Any hints on that ?
Regards,
Franklin
-
22. Re: In memory TaskClient without Mina or JMS
daniele.ulrich Jul 21, 2011 8:44 AM (in response to frankee787)Hi Franklin
To my mind is not possible to have the Tasks in a transactional scope. Neither if you are using the Mina Server nor if your using the TaskSession directly. The libraries are written for J2SE with local (manual) transactions, we could integrate it successfully in an app server by the use of <no-tx-datasources>. And: they are not transactional... please refer to the findings of a collegue of mine. If you are using the Mina Server you will be responsible to do a rollback manually
If you find a solution to that problem, I would be grateful if you could post it here...
Regards
Daniele
-
23. Re: In memory TaskClient without Mina or JMS
salaboy21 Jul 21, 2011 9:32 AM (in response to daniele.ulrich)Hi Everyone, I'm now working on this matter, I'm trying to provide a better access to the services and I will be tackling all these issues and improving the docs about them. About the transaction stuff I would like to understand a little bit more your use cases and which are the main problems that you are finding so I can address that inmediately. Cheers
-
24. Re: In memory TaskClient without Mina or JMS
frankee787 Jul 21, 2011 10:14 AM (in response to salaboy21)Hi Mauricio,
I have tried to put together as much information as possible , but its really hard to express all the possible use cases. Anyways, following are what I am facing right now.
I think one of the major pains everyone is suffering is the Transaction Management aspect.
As mentioned, the HumanTask Service is completely emebedabble and is one of the STRONGEST points of jBPM. However that is also one of the biggest problems now. Let me explain
USE CASE 1
My application uses the the following to create a client and interact with a task. No process is associated with this.
client = new TaskClient(new MinaTaskClientConnector("client", new MinaTaskClientHandler(SystemEventListenerFactory.getSystemEventListener())));
In a situation like the following
1)I insert/update into my database(Flight ticket Task / User Approval Task / Backoffice Data Auditing etc: business specific data)
2)I call client.addTask(task, null, addTaskResponseHandler) (to create a task in jBPM)
3)I update my database saying the task has been created sucessfully in jBPM
NOTE: Reason for step 1 is as follows : Putting all business related data inside the TaskData doesnt seem to be good idea(Getting serialized and persisted, looses the ability to search). Also there is no task history being mainted in the jBPM
QUESTIONS:
How can I ensure steps 1 - 3 are in one transaction?
This should be achieveable outside an appserver since HumanTask Service is completely emebedabble.
USE CASE 2
My application uses a Kession to start of a process(which comprises of mutiple human tasks)
In a situation like the following
1)I insert/update into my database saying process has been started(Flight ticket booking Process/ User Enrollment Process etc: business specific processes)
2)I call ksession.startProcess("com.sample.evaluation", params) (to start the process in jBPM)
3)I update my database saying the process has been started sucessfully in jBPM
QUESTIONS:
How can I ensure steps 1 - 3 are in one transaction?
How can my business application be notified when a Task is being created as part of a process execution?
This should also be achieveable outside an appserver since HumanTask Service is completely emebedabble.
USE CASE 3
Putting all business related data inside the TaskData doesnt seem to be good idea(Getting serialized and persisted, looses the ability to search). It would be better just to keep a reference of your business data inside TaskData and look it up when interacting with a Task.
QUESTIONS:
Which brings us to the last question. How can my business application be notified when a Task is being created as part of a process so that this reference can be made in my application.
I hope my USER CASESes are clear now ?
Thanks a lot Mauricio for hearing out for the community.
Regards,
Franklin
-
25. Re: In memory TaskClient without Mina or JMS
daniele.ulrich Jul 21, 2011 11:02 AM (in response to salaboy21)Hi Mauricio
I don't even try to break it down to single use cases, I'd rather raise some questions:
a) if we are using an appserver, why should we rely on a socked based mini server that does not implement only minimal security?
b) wouldn't it be nice, if the libraries could be integrated in JTA? Even if the hornetq integration would be used, you cannot guarantee transactions.
c) have a look at the user and roles implementation; is this good enough?
d) how could real life situations (timer exceeded for a user task, send a reminder or similar things) be implemented with JBoss as the base?
c) what about task categories? meta data? queries for these criterias?
I think there is really a lot of work left to before I can really recommend to use the human task service in a productive environment.
All the best and thanks a lot for your work.
Cheers
Daniele
-
26. Re: In memory TaskClient without Mina or JMS
frankee787 Jul 21, 2011 1:26 PM (in response to daniele.ulrich)At least one thing is for sure. The major pain point is TRANSACTION Management and defintely having a MinaConnector or HornetQConnector is not helping much.
Regards,
Franklin
-
27. Re: In memory TaskClient without Mina or JMS
daniele.ulrich Jul 21, 2011 7:10 PM (in response to frankee787)Hi Franklin
I had already started to do some changes to the classes that are managing persistence. If you like, you can try if it works this way...
You can start the same way as the original version:
TaskService taskService = new TaskService(emf,
SystemEventListenerFactory.getSystemEventListener());
TaskServiceSession taskSession = taskService.createSession();
If you are in a container managed transaction environment, the persistence should work now within the JTA scope without further effort.
In a non managed environment you will have to use UserTransactions and XA Datasources to ensure transactions over multiple databases.There are a lot of implementations available, maybe you try this one http://docs.codehaus.org/display/BTM/Hibernate13. You will have to manually start transactions
TransactionManagerServices.getConfiguration().setResourceConfigurationFilename("./datasources.properties");
userTransaction = TransactionManagerServices.getTransactionManager();
userTransaction.setTransactionTimeout(60);
userTransaction.begin();
try {
System.out.println("*** DB1 ***");
persistUser(sf1, "user");
listUsers(sf1);
System.out.println("*** DB2 ***");
persistUser(sf2, "user");
listUsers(sf2);
userTransaction.commit();
}
catch (Exception ex) {
ex.printStackTrace();
userTransaction.rollback();
}
this way you can keep multiple databases transactional.... Drawback: it definitely will have impact to all the other code you have already implemented that is not using JTA. Try it first without changing your own code, but I'm quite sure, you'll have to use the userTransactions in every situation where you want to guarantee transactions over more than one database.
I did not have the time to test the patch properly, so please take care!
The implementation uses threadLocalStorage and heavily depends on calling the session.dispose() method to perform clean up of the resources of a thread. Make sure it will be called even if an exception occurs ( catch/finally block ).
Cheers
Daniele
PS: after shutting down my computer I had another idea: you can save some effort changing your existing code by driving the transactions manually... just call taskServiceSession.getEntityManager().getTransaction().begin(); and do a commit or rollback in the same way. I don't like this approach because conceptionally you won't have proper transaction demarcation this way, but maybe it helps to save some time to try it out without the need to use JTA and XA datasources. The method
taskService.executeEscalatedDeadline
cannot be treated that way, but as it is a read only operation it should work anyway.
by the way: getEntityManager() is a public method in the original implementation, but as in the original implementation a commit is performed inside you will not have the necessary control over the transaction. I did not realize this before otherwise I would have set this method to private
-
28. Re: In memory TaskClient without Mina or JMS
frankee787 Jul 23, 2011 10:49 AM (in response to daniele.ulrich)First of all, thanks a lot for all the help especially Daniele Ulrich for the patched files. After 10-12 hours night out slogging, following are my findings.
Only the patched files(jbpm-human-task-jpa-5.0.0-patched.jar) work with JTA and the default (jbpm-human-task-5.0.0.jar) doesnt work saying java.lang.IllegalStateException: A JTA EntityManager cannot use getTransaction()
Hence I would humbly as the authors of jBPM5 to reconsider the option of making the TaskServiceSession support JTA transactions as well.
I have been able to support the following usecase with the Bitronix JTA implementation.
The main serivce class is MainService
import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainService implements IMainService { IBusinessProcessService jbpmService; IBusinessProcessService ourService; public IBusinessProcessService getJbpmService() { return jbpmService; } public void setJbpmService(IBusinessProcessService jbpmService) { this.jbpmService = jbpmService; } public IBusinessProcessService getOurService() { return ourService; } public void setOurService(IBusinessProcessService ourService) { this.ourService = ourService; } public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext(new String[]{"jBPM-layer.xml","dao-layer.xml"}); IMainService mainService = (IMainService)cp.getBean("mainService"); mainService.doThis(); } public void doThis() { getOurService().createTask(null); getJbpmService().createTask(null); getOurService().createTask(null); getJbpmService().createTask(null); if(1==1) { throw new RuntimeException(); } } }
As can be seen the MainService is something like a façade which calls two other service. One creates a record in the application database(getOurService()) and the other (getJbpmService()) creates a task/user inside the jBPM database. I have been trying to transactionalize this for quite sometime but in vain. However now its possible , but again only with the patched files.
This is ourService TXNJBPMServiceImp. Although the class name says JBPM, it has nothing to do with jBPM . Just a copy paste of a class …was so tired to give even a proper name. So, basically this is our application service which inserts a dummy testUser record in our application database.
import java.util.List; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import org.apache.log4j.Logger; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TXNJBPMServiceImp implements IBusinessProcessService{ private static Logger log = Logger.getLogger(TXNJBPMServiceImp.class); private EntityManagerFactory entityManagerFactory; public EntityManagerFactory getEntityManagerFactory() { return entityManagerFactory; } public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { this.entityManagerFactory = entityManagerFactory; } public static void main(String[] args) { } @Override public BPMTaskResponse createTask(Task task) { System.out.println("Creating...Task!!"); EntityManager em = getEntityManagerFactory().createEntityManager(); TestUser testUser = new TestUser(); testUser.setName("TXNJBPMServiceImp"); //em.getTransaction().begin(); em.persist(testUser); //em.getTransaction().commit(); System.out.println("Creating...Task DONE!!"); return null; } }
Next comes the actual jBPM service which now just creates a user in the jBPM database. As can be seen, it does nothing great. It just hacks into jBPM and gets a taskSession and creates a user. You can use the same taskSession and create Tasks, claim them, complete them etc.
import java.util.List; import javax.persistence.EntityManagerFactory; import org.apache.log4j.Logger; import org.drools.SystemEventListenerFactory; import org.jbpm.task.service.TaskService; import org.jbpm.task.service.TaskServiceSession; public class FinalTXNJBPMServiceImp implements IBusinessProcessService{ private static Logger log = Logger.getLogger(FinalTXNJBPMServiceImp.class); public TaskServiceSession getTaskSession() { return getTaskService().createSession(); } public TaskService getTaskService() { return new TaskService(getEntityManagerFactory(), SystemEventListenerFactory.getSystemEventListener()); } private EntityManagerFactory entityManagerFactory; public EntityManagerFactory getEntityManagerFactory() { return entityManagerFactory; } public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) { this.entityManagerFactory = entityManagerFactory; } public static void main(String[] args) { } @Override public BPMTaskResponse createTask(Task task) { TaskService taskService = new TaskService(getEntityManagerFactory(), SystemEventListenerFactory.getSystemEventListener()); TaskServiceSession taskSession = taskService.createSession(); org.jbpm.task.User aUser = new org.jbpm.task.User(); aUser.setId("DELNOW2"); taskSession.addUser(aUser); System.out.println("Creating...Task DONE!!"); return null; } }
Almost there. Now the spring configuration file.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="mainServiceRef" class="ae.emaratech.em.bpm.jbpm.MainService" > <property name="jbpmService" ref="finalbusinessProcessServiceRef"></property> <property name="ourService" ref="businessProcessServiceRef"></property> </bean> <bean id="mainService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="JtaTransactionManager" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED, -Exception</prop> </props> </property> <property name="target" ref="mainServiceRef" /> </bean> <context:annotation-config/> <bean id="JtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" > <property name="transactionManager" ref="BitronixTransactionManager" /> <property name="userTransaction" ref="BitronixTransactionManager" /> </bean> <bean id="btmConfig" factory-method="getConfiguration"class="bitronix.tm.TransactionManagerServices"> <property name="serverId" value="spring-btm" /> </bean> <!-- create BTM transaction manager --> <bean id="BitronixTransactionManager" factory-method="getTransactionManager"class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig" destroy-method="shutdown" /> <bean id="finalbusinessProcessService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="JtaTransactionManager" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED, -Exception</prop> </props> </property> <property name="target" ref="finalbusinessProcessServiceRef" /> </bean> <bean id="finalbusinessProcessServiceRef" class="ae.emaratech.em.bpm.jbpm.FinalTXNJBPMServiceImp" > <property name="entityManagerFactory" ref="entityManagerFactory"/> </bean> <bean id="businessProcessService"class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager" ref="JtaTransactionManager" /> <property name="transactionAttributes"> <props> <prop key="*">PROPAGATION_REQUIRED, -Exception</prop> </props> </property> <property name="target" ref="businessProcessServiceRef" /> </bean> <bean id="businessProcessServiceRef" class="ae.emaratech.em.bpm.jbpm.TXNJBPMServiceImp" > <property name="entityManagerFactory" ref="ourEntityManagerFactory"/> </bean> <bean id="userInfoImp" class="ae.emaratech.em.bpm.jbpm.DBUserInfoImp"> <property name="userDAO" ref="userDAO" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="btmConfig"> <property name="persistenceUnitName" value="org.jbpm.task"></property> <property name="dataSource" ref="jBPMDataSource"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="MYSQL" /> <property name="showSql" value="true" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> </bean> </property> </bean> <bean id="ourEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" depends-on="btmConfig"> <property name="persistenceUnitName" value="ourUnit"></property> <property name="dataSource" ref="ourDataSource"/> <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml" /> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="database" value="MYSQL" /> <property name="showSql" value="true" /> <property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> <property name="generateDdl" value="true"/> </bean> </property> </bean> <!-- Bitronix Transaction Manager embedded configuration --> <bean id="jBPMDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init" destroy-method="close"> <property name="uniqueName" value="java/jbpmdb" /> <property name="maxPoolSize" value="5" /> <property name="minPoolSize" value="0" /> <property name="driverProperties"> <props> <prop key="user">${jdbc.jbpm.username}</prop> <prop key="password">${jdbc.jbpm.password}</prop> <prop key="url">${jdbc.jbpm.url}</prop> </props> </property> <property name="className" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="allowLocalTransactions" value="false" /> <property name="enableJdbc4ConnectionTest" value="true"/> </bean> <!-- Bitronix Transaction Manager embedded configuration --> <bean id="ourDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource" init-method="init"destroy-method="close"> <property name="uniqueName" value="java/emdb" /> <property name="minPoolSize" value="0" /> <property name="maxPoolSize" value="5" /> <property name="driverProperties"> <props> <prop key="user">${jdbc.emdb.username}</prop> <prop key="password">${jdbc.emdb.password}</prop> <prop key="url">${jdbc.emdb.url}</prop> </props> </property> <property name="className" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" /> <property name="allowLocalTransactions" value="false" /> <property name="enableJdbc4ConnectionTest" value="true"/> </bean> </beans>
And finally the persistence.xml file.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <persistence version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistencehttp://java.sun.com/xml/ns/persistence/persistence_1_0.xsd http://java.sun.com/xml/ns/persistence/orm http://java.sun.com/xml/ns/persistence/orm_1_0.xsd" xmlns:orm="http://java.sun.com/xml/ns/persistence/orm" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/persistence"> <persistence-unit name="org.jbpm.task" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <mapping-file>META-INF/orm.xml</mapping-file> <class>org.jbpm.task.Attachment</class> <class>org.jbpm.task.Content</class> <class>org.jbpm.task.BooleanExpression</class> <class>org.jbpm.task.Comment</class> <class>org.jbpm.task.Deadline</class> <class>org.jbpm.task.Comment</class> <class>org.jbpm.task.Deadline</class> <class>org.jbpm.task.Delegation</class> <class>org.jbpm.task.Escalation</class> <class>org.jbpm.task.Group</class> <class>org.jbpm.task.I18NText</class> <class>org.jbpm.task.Notification</class> <class>org.jbpm.task.EmailNotification</class> <class>org.jbpm.task.EmailNotificationHeader</class> <class>org.jbpm.task.PeopleAssignments</class> <class>org.jbpm.task.Reassignment</class> <class>org.jbpm.task.Status</class> <class>org.jbpm.task.Task</class> <class>org.jbpm.task.TaskData</class> <class>org.jbpm.task.SubTasksStrategy</class> <class>org.jbpm.task.OnParentAbortAllSubTasksEndStrategy</class> <class>org.jbpm.task.OnAllSubTasksEndParentEndStrategy</class> <class>org.jbpm.task.User</class> <class>org.drools.persistence.info.SessionInfo</class> <class>org.jbpm.persistence.processinstance.ProcessInstanceInfo</class> <class>org.jbpm.persistence.processinstance.ProcessInstanceEventInfo</class> <class>org.drools.persistence.info.WorkItemInfo</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.connection.autocommit" value="false" /> <property name="hibernate.hbm2ddl.auto" value="validate" /> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.show_sql" value="" /> <property name="hibernate.transaction.manager_lookup_class"value="org.hibernate.transaction.BTMTransactionManagerLookup"/> </properties> </persistence-unit> <persistence-unit name="ourUnit" transaction-type="JTA"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>ae.emaratech.em.bpm.jbpm.TestUser</class> <exclude-unlisted-classes>true</exclude-unlisted-classes> <properties> <property name="hibernate.connection.autocommit" value="false" /> <property name="hibernate.hbm2ddl.auto" value="validate" /> <property name="hibernate.max_fetch_depth" value="3"/> <property name="hibernate.show_sql" value="" /> <property name="hibernate.transaction.manager_lookup_class"value="org.hibernate.transaction.BTMTransactionManagerLookup"/> </properties> </persistence-unit> </persistence>
Few notes . After changing to the patched jBPM files, the orm.xml throws error while trying to be passed. You will have to change references to “Task” in queries to “org.jbpm.task.Task”. Likewise all other objects such as I18NText, OrganizationalEntity etc.
Final note to "Daniele Ulrich " : Could you please tell us what changes you have made in the class so that I can maintain the same in my project.
-
29. Re: In memory TaskClient without Mina or JMS
daniele.ulrich Jul 24, 2011 8:31 AM (in response to frankee787)Hi Franklin
Thanks for posting your (very detailled) findings back to the community. As you were able to use the human task service within JTA transaction boundaries maybe we will try the same within a JEE application (and not with Spring).
- persistence unit: we had to change the file name for the orm.xml file to something like orm-human-task-service.xml; orm.xml is the default file name and it seems that it will be taken from ANY persistence unit that has access to it. So it could save you some headache if you are using
<mapping-file>META-INF/orm-human-task-service.xml</mapping-file> - you can get the source for jbpm here https://github.com/droolsjbpm/jbpm.git (JBoss Tools provides a GIT Client for eclipse, or you can use TortoiseGIT). I started with my patch from Tag 5.0.0, now already 5.1.0-Final is available. I already attached the sources of my patch in my last post. You just have to concentrate at org.jbpm.task.service.TaskService and org.jbpm.task.service.TaskServiceSession where I had to change the handling of the EntityManager (transaction begin, commit, rollback, entityManager.close).
- As in org.jbpm.task.service.TaskServiceSession a rather strange transaction handling was implemented and I had not enough time to inspect all call stacks in detail, I decided to use some kind of a hack to create the EnttityManager with the help of threadLocalStorage. If you can guarantee that your taskServiceSession is always created and disposed within the same thread and exclusively used by this one and only thread you could make the implementation somewhat simpler by using a simple instance variable for the entityManager. As far as I know the taskServiceSession is not thread safe anyway. My hack ensures that every thread will have an entityManager of its own and that it is only one time created even if a call causes multiple actions on the entityManager - but you have to make sure that threadLocalStorage is freed after closing the session.
Please keep us up to date; I will try to get in contact with the responsible developers for this sub project if we really decide to use this library in our project. Currently we are discussing to write it completely from scratch because it has not so many features implemented or is this mature that we could not do the same in a couple of days. I think the whole architecture should be reconsidered, with a pure business core and several providers for the different contexts this service could be running in.
Regards
Daniele
- persistence unit: we had to change the file name for the orm.xml file to something like orm-human-task-service.xml; orm.xml is the default file name and it seems that it will be taken from ANY persistence unit that has access to it. So it could save you some headache if you are using