Question

This is with regard to activiti workflow timer jobs in grails application.

While starting the grails app with expired jobs, exception is thrown for normal grails features such as log and methods of domain classes.

For eg:

Caused by: groovy.lang.MissingPropertyException: No such property: log for class: com.service.common.UtilityService
    at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:49)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassGetPropertySite.getProperty(PogoMetaClassGetPropertySite.java:50)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGroovyObjectGetProperty(AbstractCallSite.java:239)
    at com.service.common.UtilityService.insertToQueue(UtilityService.groovy:370)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.activiti.engine.impl.javax.el.BeanELResolver.invoke(BeanELResolver.java:479)
    ... 71 more

This happens in dev environment running the app from Spring STS. We are using activiti plugin 5.8.2 for grails (1.3.6)

After the web-app is started up completely, the jobs (schedule to a time after startup) run properly and no missing property exception is thrown.

Even though we can fix the of missing property issue for log by using private static final log = LogFactory.getLog(this) instead, then any reference to domain classes throw an error, like using get or find method.

eg:

Caused by: groovy.lang.MissingMethodException: No signature of method: static com.domain.wr.WorkRequest.read() is applicable for argument types: (java.lang.String) values: [44700]
Possible solutions: getId(), getAt(java.lang.String), setId(java.lang.Long), grep(java.lang.Object), each(groovy.lang.Closure), find(groovy.lang.Closure)
    at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1357)
    at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1343)
    at groovy.lang.ExpandoMetaClass.invokeStaticMethod(ExpandoMetaClass.java:1082)
    at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:50)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
    at com.service.common.UtilityService.insertToQueue(UtilityService.groovy:373)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.activiti.engine.impl.javax.el.BeanELResolver.invoke(BeanELResolver.java:479)
    ... 71 more

Activiti Configuration

Config.groovy

// Added by the Grails Activiti plugin:
activiti {
      processEngineName = "activiti-engine-default"
      databaseType = "oracle"
      deploymentName = appName
      history = "audit" // "none", "activity", "audit" or "full"
      sessionUsernameKey = "username"
      useFormKey = true
      deploymentResources = ["classpath:activiti/escalation/WorkRequest.bpmn20.xml"]

}

Config.properties

activiti.processEngineName =activiti-engine-default
activiti.databaseSchemaUpdate =true 
activiti.jobExecutorActivate =true
activiti.mailServerHost = "mail1.net"
activiti.mailServerPort = 25
activiti.mailServerUsername = ""
activiti.mailServerPassword = ""
activiti.mailServerDefaultFrom = ""

This is killing my application as a downtime makes the workflow unusable with timer tasks.

Was it helpful?

Solution 2

This issue got solved.
1) Edit Config.groovy and disable activiti during startup

 activiti {
          processEngineName = "activiti-engine-default"
          databaseType = "oracle"
          disabled = true
          deploymentName = appName
          sessionUsernameKey = "username"
          useFormKey = true
          deploymentResources = []
    }

2) add the initialization of Activiti Objects in the init method of User BootStrap

def init = { servletContext ->

    org.springframework.context.ApplicationContext ctx = ServletContextHolder.getServletContext().getAttribute(GrailsApplicationAttributes.APPLICATION_CONTEXT)
    def bb = new grails.spring.BeanBuilder(ctx)
    bb.beans {
        //println "Activiti Process Engine Initialization..."
        customDbIdGenerator(com.mycompany.activiti.customDbIdGenerator){
            idBlockSize=CH.config.activiti.idBlockSize?:100
        }
        processEngineConfiguration(org.activiti.spring.SpringProcessEngineConfiguration) {
            processEngineName = CH.config.activiti.processEngineName?:ActivitiConstants.DEFAULT_PROCESS_ENGINE_NAME
            databaseType = CH.config.activiti.databaseType?:ActivitiConstants.DEFAULT_DATABASE_TYPE
            databaseSchemaUpdate = CH.config.activiti.databaseSchemaUpdate ? CH.config.activiti.databaseSchemaUpdate.toString() : ActivitiConstants.DEFAULT_DATABASE_SCHEMA_UPDATE
            deploymentName = CH.config.activiti.deploymentName?:ActivitiConstants.DEFAULT_DEPLOYMENT_NAME
            deploymentResources = CH.config.activiti.deploymentResources?:ActivitiConstants.DEFAULT_DEPLOYMENT_RESOURCES
            jobExecutorActivate = CH.config.activiti.jobExecutorActivate?:ActivitiConstants.DEFAULT_JOB_EXECUTOR_ACTIVATE
                  history = CH.config.activiti.history?:ActivitiConstants.DEFAULT_HISTORY
            mailServerHost = CH.config.activiti.mailServerHost?:ActivitiConstants.DEFAULT_MAIL_SERVER_HOST
            mailServerPort = CH.config.activiti.mailServerPort?:ActivitiConstants.DEFAULT_MAIL_SERVER_PORT
            mailServerUsername = CH.config.activiti.mailServerUsername
            mailServerPassword = CH.config.activiti.mailServerPassword
            mailServerDefaultFrom = CH.config.activiti.mailServerDefaultFrom?:ActivitiConstants.DEFAULT_MAIL_SERVER_FROM
            dataSource = ref("dataSource")
            transactionManager = ref("transactionManager")
            idGenerator= ref("customDbIdGenerator")
        }

          processEngine(org.activiti.spring.ProcessEngineFactoryBean) {
              processEngineConfiguration = ref("processEngineConfiguration")
          }

        runtimeService(processEngine:"getRuntimeService")
        repositoryService(processEngine:"getRepositoryService")
        taskService(processEngine:"getTaskService")
        managementService(processEngine:"getManagementService")
        identityService(processEngine:"getIdentityService")
        historyService(processEngine:"getHistoryService")
        formService(processEngine:"getFormService")

        activitiService(org.grails.activiti.ActivitiService) {
            runtimeService = ref("runtimeService")
            taskService = ref("taskService")
            identityService = ref("identityService")
            formService = ref("formService")
        }
    }
    println "## Registering Beans ##";
    bb.registerBeans(ctx);
    ctx.getBean("processEngine");

    println "Bean Count2 "+ctx.getBeanDefinitionCount();
}

Please note that DB Id Generator used is custom and can be replaced by the default one.

OTHER TIPS

I had more or less the same problem, and in our case was caused by Activiti starting jobs execution before Spring injection being finished. That's why it only happens at startup: the job is accessing properties that are not there yet.

You can confirm that you are in the same situation by increasing the RETRIES_ in the ACT_RU_JOB table after the app has finished bootstraping and see if the jobs execute successfully.

If this is your case, I think the only option is to upgrade the plugin and if still fails, create a bug.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top