cancel
Showing results for 
Search instead for 
Did you mean: 

Issue with Clock and multiple engines

tomaszk_
Champ in-the-making
Champ in-the-making
I would like to have to engines running in one Spring application. One engine would have clock set to current time, the other engine would be used to stage the data - so it would have clock that could change to past date. I have created two engines as shown below but for some reason changing clock in one engine changes it also in the other. Any idea why this might be happening? Is there a better way to do this?
Thanks!


<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
   <property name="databaseType" value="mysql" />
   <property name="dataSource" ref="activitiDataSource" />
   <property name="transactionManager" ref="activitiTransactionManager" />
   <property name="databaseSchemaUpdate" value="true" />
   <property name="history" value="full" />
   <property name="jobExecutorActivate" value="false" />
</bean>
   
<bean id="historyProcessEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
   <property name="databaseType" value="mysql" />
   <property name="dataSource" ref="activitiDataSource" />
   <property name="transactionManager" ref="activitiTransactionManager" />
   <property name="databaseSchemaUpdate" value="true" />
   <property name="history" value="full" />
   <property name="jobExecutorActivate" value="false" />
</bean>

<bean id="processEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
   <property name="processEngineConfiguration" ref="processEngineConfiguration" />
</bean>
   
<bean id="histroyProcessEngine" class="org.activiti.spring.ProcessEngineFactoryBean">
   <property name="processEngineConfiguration" ref="historyProcessEngineConfiguration" />
</bean>



@Autowired
@Qualifier("processEngine")
ProcessEngine processEngine;

@Autowired
@Qualifier("histroyProcessEngine")
ProcessEngine histroyProcessEngine;

Calendar cal = Calendar.getInstance();
cal.set(Calendar.MONTH, Calendar.JANUARY);
histroyProcessEngine.getProcessEngineConfiguration().getClock().setCurrentCalendar(cal);
      
System.out.println(histroyProcessEngine.getProcessEngineConfiguration().getClock().getCurrentTime().toGMTString());
System.out.println(processEngine.getProcessEngineConfiguration().getClock().getCurrentTime().toGMTString());
6 REPLIES 6

trademak
Star Contributor
Star Contributor
Hi,

They should be full separate as this is done in the initialisation:

private void initClock() {
    if (clock == null) {
      clock = new DefaultClockImpl();
    }
}

Maybe you could create a bean that defines a clock and inject two different clock beans in the two process engine configurations?

Best regards,

tomaszk_
Champ in-the-making
Champ in-the-making
I have tried creating a clock bean and associating it with the process engine but no luck, still date is set for both engines.
<code>
<bean id="engineClock" class="org.activiti.engine.impl.util.DefaultClockImpl"/>
<bean id="historyEngineClock" class="org.activiti.engine.impl.util.DefaultClockImpl"/>

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="databaseType" value="mysql" />
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionManager" ref="activitiTransactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="history" value="full" />
<property name="jobExecutorActivate" value="false" />
<property name="clock" ref="engineClock"/>
</bean>

<bean id="historyProcessEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="databaseType" value="mysql" />
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionManager" ref="activitiTransactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="history" value="full" />
<property name="jobExecutorActivate" value="false" />
<property name="clock" ref="historyEngineClock"/>
</bean>
</code>

tomaszk_
Champ in-the-making
Champ in-the-making
So i have managed to get it to work. I think that the problem that i am facing is related to the DefaultClockImpl implementation. The CURRENT_TIME field is static hence it is shared across all the instances of the object if it is loaded by the same class loader which in case of my Spring application is the case. I have created a copy of the DefaultClockImpl class and renamed it to MyClock and then injected it to the engine configuration. Now i am able to change clock in one engine and have different time in the other engine. Is there any particular reason why this field is static? Code snippets below for reference.

<java>
public class MyClock implements org.activiti.engine.runtime.Clock {
  
   private static volatile Calendar CURRENT_TIME = null;

   @Override
   public void setCurrentTime(Date currentTime) {
     Calendar time = null;
    
     if (currentTime != null) {
       time = new GregorianCalendar();
       time.setTime(currentTime);
     }
    
     setCurrentCalendar(time);
   }
  
   @Override
   public void setCurrentCalendar(Calendar currentTime) {
     CURRENT_TIME = currentTime;
   }

   @Override
   public void reset() {
     CURRENT_TIME = null;
   }
  
   @Override
   public Date getCurrentTime() {
     return CURRENT_TIME == null ? new Date() : CURRENT_TIME.getTime();
   }

   @Override
   public Calendar getCurrentCalendar() {
     return CURRENT_TIME == null ? new GregorianCalendar() : (Calendar)CURRENT_TIME.clone();
   }

   @Override
   public Calendar getCurrentCalendar(TimeZone timeZone) {
     return TimeZoneUtil.convertToTimeZone(getCurrentCalendar(), timeZone);
   }

   @Override
   public TimeZone getCurrentTimeZone() {
     return getCurrentCalendar().getTimeZone();
   }
}
</java>

<code>
<bean id="engineClock" class="org.activiti.engine.impl.util.DefaultClockImpl"/>
<bean id="historyEngineClock" class="com….MyClock"/>

<bean id="processEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="databaseType" value="mysql" />
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionManager" ref="activitiTransactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="history" value="full" />
<property name="jobExecutorActivate" value="false" />
<property name="clock" ref="engineClock"/>
</bean>

<bean id="historyProcessEngineConfiguration" class="org.activiti.spring.SpringProcessEngineConfiguration">
<property name="databaseType" value="mysql" />
<property name="dataSource" ref="activitiDataSource" />
<property name="transactionManager" ref="activitiTransactionManager" />
<property name="databaseSchemaUpdate" value="true" />
<property name="history" value="full" />
<property name="jobExecutorActivate" value="false" />
<property name="clock" ref="historyEngineClock"/>
</bean>
</code>

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Tomasz,

Can you explain more for what are you going to use histroyProcessEngine?

Regards
Martin

tomaszk_
Champ in-the-making
Champ in-the-making
Application will have a feature that will allow user to load 'demo/test' data. It should start few process in the past and complete couple of the tasks in each of them. Since it is important that those task are completed in the past i need to make sure that the engine clock is set to past date and not current date. I based my assumption that this is the right approach on the class org.activiti.explorer.demo.DemoDataGenerator . If there is an easier way to do it please suggest. I looked into crystalball but there is really not much documentation out there, so thought that having two engines will be a good approach.
So i would like to spin up an engine (possible that multiple users will request it at the same time) when user request demo data, deploy processes and complete tasks - then destroy the engine as i will not need it anymore.

Thanks for any help.

martin_grofcik
Confirmed Champ
Confirmed Champ
Hi Tomasz.

crystalball doc -> It is done by intention 🙂 You have to go through jUnit tests to understand it more. (And I was too lazy to create more than code.)

DefaultClockImpl was done to provide exactly the same behaviour as an obsolete timer implementation. I had to propose virtual time handling several years ago when I started crystalball. 🙂
org.activiti.crystalball.simulator.impl.clock.ThreadLocalClock is used in the simulation runs.

You could consider to reply a process
http://activiti.org/userguide/index.html#crb-playback

Regards
Martin