过期的activiti作业在服务器启动时抛出异常 - Grails

时间:2012-10-17 06:00:57

标签: grails jobs activiti

这是关于grails应用程序中的activiti工作流计时器作业。

在启动带有过期作业的grails应用程序时,会抛出正常grails功能(例如日志和域类方法)的异常。

例如:

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

这发生在从Spring STS运行应用程序的开发环境中。我们正在使用activiti插件5.8.2 for grails(1.3.6)

完全启动Web应用程序后,作业(计划到启动后的某个时间)正常运行,并且不会抛出任何丢失的属性异常。

即使我们可以使用private static final log = LogFactory.getLog(this)来修复日志的缺失属性问题,但是对域类的任何引用都会引发错误,例如使用get或find方法。

例如:

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配置

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 = ""

这会导致我的应用程序被终止,因为停机时间使得工作流无法用于计时器任务。

2 个答案:

答案 0 :(得分:1)

我或多或少有同样的问题,在我们的例子中是由Activiti在Spring注入完成之前开始执行作业引起的。这就是为什么它只在启动时发生:作业正在访问尚未存在的属性。

您可以通过在应用程序完成引导后增加ACT_RU_JOB表中的RETRIES_来确认您处于相同的情况,并查看作业是否成功执行。

如果是这种情况,我认为唯一的选择是升级插件,如果仍然失败,请创建一个错误。

答案 1 :(得分:0)

这个问题已经解决了。
1)编辑Config.groovy并在启动期间禁用activiti

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

2)在User BootStrap的init方法中添加Activiti Objects的初始化

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();
}

请注意,使用的DB Id Generator是自定义的,可以用默认值替换。