cancel
Showing results for 
Search instead for 
Did you mean: 

Job retry defaults

mmaker1234
Champ in-the-making
Champ in-the-making
Hello Activiti developers,

As some other users here I do not agree to the default Job Executor behavior to retry a failed job three times. As I remember the plans for an earlier Activti version included (a task) to provide an engine setting for the number of job retries but this not happened until the current version (5.10).

Now I would like to rebuild the Activiti engine with value of DEFAULT_RETRIES in org.activiti.engine.impl.persistence.entity.JobEntity set to 1. Unfortunately, when I try to set the value to 2 or 1, I meet the following error during the sure-fire tests:

testJobCommandsWith2Exceptions(org.activiti.engine.test.jobexecutor.JobExecutorCmdExceptionTest)  Time elapsed: 0.109 sec  <<< FAILURE!
java.lang.AssertionError: DB NOT CLEAN:
  ACT_RU_JOB: 1 record(s)   ACT_GE_BYTEARRAY: 1 record(s)
Fortunately this is the only failing test (in contrast to 5.9 where many other tests failed after the change).

Please fix the JobExecutorCmdExceptionTest to allow setting of DEFAULT_RETRIES to values lower than 3.
7 REPLIES 7

frederikherema1
Star Contributor
Star Contributor
See https://jira.codehaus.org/browse/ACT-1046

Does the described fix work for you?

mmaker1234
Champ in-the-making
Champ in-the-making
Hello Frederik,

As far as I understand, the purpose of the FailedJobListener is to define an exclusion from the default jobs behavior ("in case of a failure, attempt to do the job at most three times sequentially"). Our intention is to define another engine-wide jobs behavior - "try only once" - and this to be the default behavior for all jobs that run in the engine.

We prefer to keep our application not aware about third-party libraries. In the case of the workflow engine we prefer to configure it via a "properties" file (activiti-cfg.xml in case of Activiti). Another approach is to modify the (defaults in the) source code. Manipulating the workflow engine configuration from our applications' code (defining one or more FailedJobListener(s)) is still possible but only as a last resource.

By the way, is there any explanation or examples for FailedJobListener? Activiti 5.10 documentation and forum search returns no results about it.

frederikherema1
Star Contributor
Star Contributor
In discussion with Daniel we found another way to handle the configuration of a delay between retries and the amount of retries.
For that we provide a listener "FailedJobListener" and an interface "FailedJobCommandFactory". The "FailedJobListener" replaces the "DecrementJobRetriesListener" which previously was used in the class "ExecuteJobsCmd". The new listener uses the factory to create an instance of a command to handle a failed job. Activiti uses by default the "DefaultJobCommandFactory" which implements the new interface to create an instance of the command "DecrementJobRetriesCmd" to provide the logic as previously.
Now you can implement your own strategy to handle failed jobs. For example you can implement a strategy to distinguish between the type of the failed job and handle them differently (e.g. set another delay or the the amount of retries).
See revision: 3372

So just create a FailedJobCommandFactory that does NOT retry the job, as the DefaultFailedJobCommandFactory does. No 3rd party libs needed, just some of your code plugged in.

You could return a Command that sets the retries to zero, for example…

mmaker1234
Champ in-the-making
Champ in-the-making
Hello again.

Sorry for the late reply but more urgent tasks delayed the work on this one.

I would like to inform all interested readers about my solution to the problem:
1. (As advised by Frederik Heremans) Create org.activiti.engine.impl.cmd.NoJobRetriesCmd as a copy of DecrementJobRetriesCmd and changed row
   job.setRetries(job.getRetries() - 1);
to read
   job.setRetries(0);

2. (As advised by Frederik Heremans) Create org.activiti.engine.impl.jobexecutor.NoRetryFailedJobCommandFactory that returns org.activiti.engine.impl.cmd.NoJobRetriesCmd as a result;

3. (Last, but I think most important change) Add two methods to org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl:
 
  public String getFailedJobCommandFactoryByClassName() {
    return failedJobCommandFactory.getClass().getName();
  }
 
  public ProcessEngineConfigurationImpl setFailedJobCommandFactoryByClassName(String failedJobCommandFactoryClassName) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
    this.failedJobCommandFactory = (FailedJobCommandFactory) Class.forName( failedJobCommandFactoryClassName ).newInstance();
    return this;
  }
which allow to

4. Configure the failed jobs command factory via activiti.cfg.xml:
  <bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    …
    <property name="failedJobCommandFactoryByClassName" value="org.activiti.engine.impl.jobexecutor.NoRetryFailedJobCommandFactory" />
    …
  </bean>

Notes:
  • The changes in org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl do not impose setting of the failedJobCommandFactoryByClassName property. If the property is missing in the configuration file then the default failed jobs command factory (org.activiti.engine.impl.jobexecutor.DefaultFailedJobCommandFactory) will be used;

  • If an incorrect class name was provided in the failedJobCommandFactoryByClassName property, during the start of the workflow engine will be reported an error similar to
  • Exception while initializing process engine :Error creating bean with name 'processEngineConfiguration' defined in resource loaded through InputStream: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
    PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'failedJobCommandFactoryByClassName' threw exception; nested exception is java.lang.ClassNotFoundException: org.activiti.engine.impl.jobexecutor.InexistingFailedJobCommandFactory
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'processEngineConfiguration' defined in resource loaded through InputStream: Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
    PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'failedJobCommandFactoryByClassName' threw exception; nested exception is java.lang.ClassNotFoundException: org.activiti.engine.impl.jobexecutor.InexistingFailedJobCommandFactor
I hope this information will help other integrators of Activiti engine in their products.

@Activiti developers: please correct this approach if I made something wrong.

Best Regards,
Monique

frederikherema1
Star Contributor
Star Contributor
Why the "byClassName"? Why not just do this:


<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
    …
    <property name="failedJobCommandFactory">
         <bean class="org.activiti.engine.impl.jobexecutor.NoRetryFailedJobCommandFactory" />
    </property>
    …
  </bean>

mmaker1234
Champ in-the-making
Champ in-the-making
Thank you for your quick reply, Frederik!

I have no any experience with Spring and its configurations, that's why I run the known road.

mamtag
Champ in-the-making
Champ in-the-making
Hi,

I am trying to follow a similar approach to set retry count = 0. Have tried the same steps mentioned above.
However, even though the failedJobCommandFactory property is set with the created bean definition, when a job is stored in act_ru_job table, value of RETRIES_  column equals 3.
I am using activiti 5.15.1, is there any change in this version?