[JBoss JIRA] Updated: (JBPM-165) process instance versioning
by Thomas Diesler (JIRA)
[ http://jira.jboss.com/jira/browse/JBPM-165?page=all ]
Thomas Diesler updated JBPM-165:
--------------------------------
Fix Version/s: (was: jBPM jPDL 3.2.4)
> process instance versioning
> ---------------------------
>
> Key: JBPM-165
> URL: http://jira.jboss.com/jira/browse/JBPM-165
> Project: JBoss jBPM
> Issue Type: Feature Request
> Components: Core Engine
> Reporter: Tom Baeyens
> Assigned To: Tom Baeyens
>
> i think jbpm could offer some degree of assistence in process instance versioning.
> when a new version of a process is deployed, jbpm could do the following conversion for a process instance :
> * input required: mapping of the nodes from the old to the new definition.
> * cancel the old process instance
> * create a new process instance and copy the runtime (exe) information such as tokens and process variables from the old process instance.
> * then establish a special link between the 2 process instances to indicate that the new process instance is the continuation of the old process instance.
> this way we can avoid the problematic conversion of logs, while still keeping them in the system.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 7 months
[JBoss JIRA] Updated: (JBPM-1008) ejb deployment : avoid ClassNotFoundException on client side after unmarshalling
by Thomas Diesler (JIRA)
[ http://jira.jboss.com/jira/browse/JBPM-1008?page=all ]
Thomas Diesler updated JBPM-1008:
---------------------------------
Fix Version/s: (was: jBPM jPDL 3.2.4)
> ejb deployment : avoid ClassNotFoundException on client side after unmarshalling
> ---------------------------------------------------------------------------------
>
> Key: JBPM-1008
> URL: http://jira.jboss.com/jira/browse/JBPM-1008
> Project: JBoss jBPM
> Issue Type: Bug
> Affects Versions: jBPM jPDL 3.2.1
> Environment: enterprise jBPM
> Reporter: Adrian Dimulescu
> Assigned To: Tom Baeyens
>
> Two aspects in this jira : 1: hide hibernate-specific exceptions; 2: hide hibernate-specific datatypes.
> 1. The EJB client only depends on the jBPM jar (for the various Command implementations) and on the JBoss client jar. If a Hibernate exception occurs, it is wrapped by a JBPMException and rethrown. When deserialiezed on the client side (which does not have a Hibernate dependency), a ClassNotFoundException occurs.
> I think the CommandServiceBean should not wrap internal implementation-specific exceptions; it should instead simply copy the stack trace and throw a new implementation-independent exception which contains the exception trace without containing the causes themselves. That typically avoids ClassNotFoundExceptions without losing exception history.
> 2. The second problem is that hibernate-specific collections get serialized over the wire, here is the description of the problem :
> I use the GetProcessInstancesCommand in order to experiment with querying the remote ejb. This command returns a list with ProcessInstances. A ProcessInstance is read by Hibernate from the database. As Hibernate uses specific lazy-loading-aware implementations for collections -- the ProcessInstance.instances attribute, which is declared of type java.util.Map, is actually implemented by org.hibernate.collections.PersistentMap.
> Which generates class loading exception while deserializing to hibernate-unaware ejb clients.
> The solution would then be for the Command implementations to return clean JDK collections, by replacing Hibernate collection with JDK standard ones. Note that IIUC only the collections must be replaced, not the collection contents too, so the "cleaning" operation should not be that expensive. Cleaning should be only done in the SLSB remote call use case -- because in-JVM callers may want to benefit lazy-loading.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 7 months
[JBoss JIRA] Updated: (JBPM-627) Cancel timer problem
by Thomas Diesler (JIRA)
[ http://jira.jboss.com/jira/browse/JBPM-627?page=all ]
Thomas Diesler updated JBPM-627:
--------------------------------
Fix Version/s: (was: jBPM jPDL 3.2.4)
> Cancel timer problem
> --------------------
>
> Key: JBPM-627
> URL: http://jira.jboss.com/jira/browse/JBPM-627
> Project: JBoss jBPM
> Issue Type: Bug
> Components: Core Engine
> Affects Versions: jBPM 3.1
> Environment: Windows XP Pro
> Database: DB2/400 v5r3, HSQLDB
> Reporter: Mark Shotton
> Assigned To: Tom Baeyens
> Attachments: JBPM-627-screenshots.doc
>
>
> As reported in issue JBPM-594, timers do not get deleted on the cancel-timer event. This is because in SchedulerSession.cancelTimersByName(String, Token), the timer is deleted by a call to SchedulerSession.deleteTimer:
> public void deleteTimer(Timer timer) {
> if (! deletedTimers.contains(timer)) {
> try {
> session.delete(timer);
> deletedTimers.add(timer);
> } catch (Exception e) {
> log.error(e);
> jbpmSession.handleException();
> throw new JbpmException("couldn't delete timer '"+timer+"' from the database", e);
> }
> }
> }
> but in SchedulerThread, the timer is saved again if timer.getRepeat() is not null:
> public long executeTimers() {
> long millisTillNextTimerIsDue = -1;
> boolean isDueDateInPast = true;
>
> JbpmContext jbpmContext = jbpmConfiguration.createJbpmContext(jbpmContextName);
> try {
> SchedulerSession schedulerSession = jbpmContext.getSchedulerSession();
>
> log.debug("checking for timers");
> Iterator iter = schedulerSession.findTimersByDueDate();
> while( (iter.hasNext())
> && (isDueDateInPast)
> ) {
> Timer timer = (Timer) iter.next();
> log.debug("found timer "+timer);
>
> // if this timer is due
> if (timer.isDue()) {
> log.debug("executing timer '"+timer+"'");
>
> // execute
> timer.execute();
>
> // save the process instance
> jbpmContext.save(timer.getProcessInstance());
>
> // notify the listeners (e.g. the scheduler servlet)
> notifyListeners(timer);
>
> // if there was an exception, just save the timer
> if (timer.getException()!=null) {
> schedulerSession.saveTimer(timer);
>
> // if repeat is specified
> } else if (timer.getRepeat()!=null) {
> // update timer by adding the repeat duration
> Date dueDate = timer.getDueDate();
>
> // suppose that it took the timer runner thread a
> // very long time to execute the timers.
> // then the repeat action dueDate could already have passed.
> while (dueDate.getTime()<=System.currentTimeMillis()) {
> dueDate = businessCalendar
> .add(dueDate,
> new Duration(timer.getRepeat()));
> }
> timer.setDueDate( dueDate );
> // save the updated timer in the database
> log.debug("saving updated timer for repetition '"+timer+"' in '"+(dueDate.getTime()-System.currentTimeMillis())+"' millis");
> schedulerSession.saveTimer(timer);
>
> } else {
> // delete this timer
> log.debug("deleting timer '"+timer+"'");
> schedulerSession.deleteTimer(timer);
> }
> } else { // this is the first timer that is not yet due
> isDueDateInPast = false;
> millisTillNextTimerIsDue = timer.getDueDate().getTime() - System.currentTimeMillis();
> }
> }
>
> } finally {
> jbpmContext.close();
> }
> A work-around was suggested in JBPM-594:
> "As workaround now I do remove timer myself in action just before calling signal():
> if(flag) {
> //need to remove scheduler session as it is not removed during event with
> //cancel-timer element
> SchedulerSession schsession = ctx.getJbpmContext().getSchedulerSession();
> Timer timer=(Timer) schsession.findTimersByName("aaa",ctx.getToken()).get(0);
> log.info("found timer:"+timer.getName());
> timer.setRepeat(null);
> timer.setSuspended(true);
> schsession.saveTimer(timer);
>
> ctx.getToken().signal("tonode1");
> }
> "
> However, this does not seem to be thread-safe as the call to findTimersByName sometimes returns a zero-length array and sometimes an exception if the work-around code to cancel the timer executes before the timer is available from the SchedulerSession (and this does happen even when the code to cancel the timer is within the ActionHandler of the timer) As a different work-around, I set the timer repeat to null in the SchedulerSession.deleteTimer method to ensure that it will not be saved again in the SchedulerThread.executeTimers method:
> public void deleteTimer(Timer timer) {
> if (! deletedTimers.contains(timer)) {
> try {
> session.delete(timer);
> deletedTimers.add(timer);
> //MWS 06/04/06 workaround to ensure that timer is deleted
> timer.setRepeat(null);
> } catch (Exception e) {
> log.error(e);
> jbpmSession.handleException();
> throw new JbpmException("couldn't delete timer '"+timer+"' from the database", e);
> }
> }
> }
> However, this causes an occasional exception to be thrown:
> org.jbpm.persistence.JbpmPersistenceException: couldn't commit hibernate session
> at org.jbpm.persistence.db.DbPersistenceService.close(DbPersistenceService.java:171)
> at org.jbpm.svc.Services.close(Services.java:211)
> at org.jbpm.JbpmContext.close(JbpmContext.java:138)
> at org.jbpm.scheduler.impl.SchedulerThread.executeTimers(SchedulerThread.java:161)
> at org.jbpm.scheduler.impl.SchedulerThread.run(SchedulerThread.java:70)
> Caused by: org.hibernate.StaleStateException: Unexpected row count: 0 expected: 1
> at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:27)
> at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2204)
> at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2118)
> at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2374)
> at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:84)
> at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:243)
> at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:227)
> at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:141)
> at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:296)
> at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
> at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:980)
> at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:353)
> On further investigation, it appears that on some occasions, when deleting a timer on a cancel-timer event, the call to session.getNamedQuery("SchedulerSession.findTimersByName") causes a hibernate flush to occur which attempts to update a timer that has already been deleted:
> public void cancelTimersByName(String timerName, Token token) {
> try {
> Query query = session.getNamedQuery("SchedulerSession.findTimersByName");
> query.setString("timerName", timerName);
> query.setEntity("token", token);
> Iterator iter = query.list().iterator();
> while(iter.hasNext()) {
> deleteTimer((Timer) iter.next());
> }
>
> } catch (Exception e) {
> log.error(e);
> jbpmSession.handleException();
> throw new JbpmException("couldn't delete timer '"+timerName+"' on '"+token+"' from the database", e);
> }
> }
> I have some screenshots below to illustrate this but cannot include them in this form. The attempt to cancel the timer ?processing_error_task_timer? causes the following query to be issued:
> <query name="SchedulerSession.findTimersByName">
> <![CDATA[
> select t
> from org.jbpm.scheduler.exe.Timer t
> where t.name = :timerName
> and t.token = :token
> ]]>
> </query>
> which in turn causes hibernate to flush and attempt to issue the SQL statement:
> update JBPM_TIMER set NAME_=?, DUEDATE_=?, REPEAT_=?, TRANSITIONNAME_=?, EXCEPTION_=?, ISSUSPENDED_=?, ACTION_=?, TOKEN_=?, PROCESSINSTANCE_=?, TASKINSTANCE_=?, GRAPHELEMENTTYPE_=?, GRAPHELEMENT_=? where ID_=?
> where the ID_ of the timer is that of a previous timer that has already been deleted from the database called ?credit_referral_task_timer? (I confirmed this by inspection of the JBPM_TIMER table).
> I am at a loss to explain how the hibernate cache contains a timer that has already been deleted from the database.
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 7 months
[JBoss JIRA] Updated: (JBPM-1032) task-assign-events are sometimes fired when group assignment is performed
by Thomas Diesler (JIRA)
[ http://jira.jboss.com/jira/browse/JBPM-1032?page=all ]
Thomas Diesler updated JBPM-1032:
---------------------------------
Fix Version/s: (was: jBPM jPDL 3.2.4)
> task-assign-events are sometimes fired when group assignment is performed
> -------------------------------------------------------------------------
>
> Key: JBPM-1032
> URL: http://jira.jboss.com/jira/browse/JBPM-1032
> Project: JBoss jBPM
> Issue Type: Bug
> Components: Core Engine
> Affects Versions: jBPM jPDL 3.2.1
> Reporter: Karsten Dello
> Assigned To: Tom Baeyens
>
> A "task-assingn"-event is sometimes fired, if only group assignment (setting pooledActors) is performed. This always happens when a swimlane is in use which specifies pooled-actors (junit test 1).
> On the other hand, when the pooled-actors are expressed via an assignment-element as an child element of a task (junit test 2), the event is not fired.
> From my point of view the engine should either:
> a) not fire an task-assign-event in case of group assignments at all
> b) fire it consequently at all group assignments events
> c) fire a different event
> Ronald suggested in the forum thread (link above) to introduce a seperate event "task-group-assign" in case a task gets assigned to a group. In my opinion this would be the best solution to this problem.
> public void testTaskAssignIsFiredWithSwimlaneGroupAssignment() {
> ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
> "<process-definition name=\"someprocessxyz\">" +
>
> " <event type=\"task-assign\">" +
> " <script>System.out.println(\"task-assign-event fired!\");" +
> " executionContext.setVariable(\"task-assign-event-has-fired\",Boolean.TRUE);</script>"+
> " </event>"+
> " <start-state>" +
> " <transition to='a' />" +
> " </start-state>" +
>
> " <swimlane name='swimlane22'>"+
> " <assignment pooled-actors='jan,nina'/>"+
> " </swimlane>"+
> " <task-node name='a'>" +
> " <task name='sometask' swimlane='swimlane22'/>" +
> " <transition to='end'/>"+
> " </task-node>"+
>
> " <end-state name='end' />" +
>
> "</process-definition>"
> );
> ProcessInstance processInstance = new ProcessInstance(processDefinition);
> Token token = processInstance.getRootToken();
>
> processInstance.signal();
> Object o=processInstance.getContextInstance().getVariable("task-assign-event-has-fired");
> assertEquals(Boolean.TRUE, o);
>
> }
> public void testTaskAssignIsNOTFiredWithSwimlaneGroupAssignment() {
> ProcessDefinition processDefinition = ProcessDefinition.parseXmlString(
> "<process-definition name=\"someprocessxyz\">" +
>
> " <event type=\"task-assign\">" +
> " <script>System.out.println(\"task-assign-event fired!\")"+
> " executionContext.setVariable(\"task-assign-event-has-fired\",Boolean.TRUE);</script>"+
> " </event>"+
> " <start-state>" +
> " <transition to='a' />" +
> " </start-state>" +
>
> " <task-node name='a'>" +
> " <task name='sometask'>" +
> " <assignment pooled-actors='jan,nina'/>"+
> " </task>"+
> " <transition to='end'/>"+
> " </task-node>"+
>
> " <end-state name='end' />" +
>
> "</process-definition>"
> );
> ProcessInstance processInstance = new ProcessInstance(processDefinition);
> Token token = processInstance.getRootToken();
> processInstance.signal();
>
> Object o=processInstance.getContextInstance().getVariable("task-assign-event-has-fired");
> assertEquals(Boolean.TRUE, o);
> }
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://jira.jboss.com/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira
16 years, 7 months