cancel
Showing results for 
Search instead for 
Did you mean: 

Support for Camel tasks in Alfresco 4.x

arnoldschrijve1
Champ on-the-rise
Champ on-the-rise
I am trying to define a workflow with some Camel Tasks in Alfresco (EE 4.1.1.3) and I am running into trouble.
For the Camel integration I followed the instructions in the 'Activiti in Action' book, added activiti-camel Maven reference, added a camelContext to the bean definitions of my AMP module, and a basic workflow with a Camel serviceTask.

The package scan defined by the camelContext occurs occurs during startup, and it finds my routes, but sometime later a NPE is thrown (see details below).

If I remove the camelContext definition from the context, then Alfresco starts without problem, and the workflow is working (up to the Camel task).

Maybe the camel context should be created differently. I tried changing load sequence (before / after workflow context files) with no result.
Tried debugging the exception, but I don't find much in the code that is related to camel.
Anyone has any experience using Camel tasks in Alfresco? Is this at all supported?

camelContext definition:

    <camelContext id="camelProcess" xmlns="http://camel.apache.org/schema/spring">
        <packageScan>
            <package>com.mycompany.workflow.camel</package>
        </packageScan>
    </camelContext>

Stack trace:

<blockquote>

2013-03-28 17:06:20,780  INFO  [management.subsystems.ChildApplicationContextFactory] [main] Startup of 'Search' subsystem, ID: [Search, managed, lucene] complete
2013-03-28 17:06:21,194  DEBUG [alfresco.repo.workflow] [main] Detached (commit) JBPM Context from transaction 4dddb2d8-dd45-4c66-9659-b8cff70308a0
2013-03-28 17:06:21,227  ERROR [repo.descriptor.RepositoryDescriptorDAOImpl] [main] getDescriptor:
java.lang.NullPointerException
   at org.alfresco.repo.node.MLPropertyInterceptor.getPivotNodeRef(MLPropertyInterceptor.java:323)
   at org.alfresco.repo.node.MLPropertyInterceptor.invoke(MLPropertyInterceptor.java:173)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.enterprise.repo.sync.SyncPropertyInterceptor.invoke(SyncPropertyInterceptor.java:157)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:212)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.enterprise.repo.sync.SyncPropertyInterceptor.invoke(SyncPropertyInterceptor.java:157)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:212)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.enterprise.repo.sync.SyncPropertyInterceptor.invoke(SyncPropertyInterceptor.java:157)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:212)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
   at $Proxy31.getProperties(Unknown Source)
   at org.alfresco.repo.descriptor.RepositoryDescriptorDAOImpl.getDescriptor(RepositoryDescriptorDAOImpl.java:158)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl.bootstrap(DescriptorServiceImpl.java:224)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl.access$100(DescriptorServiceImpl.java:52)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl$3.doWork(DescriptorServiceImpl.java:206)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl$3.doWork(DescriptorServiceImpl.java:202)
   at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:516)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl.onBootstrap(DescriptorServiceImpl.java:210)
   at org.springframework.extensions.surf.util.AbstractLifecycleBean.onApplicationEvent(AbstractLifecycleBean.java:56)
   at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEventInternal(SafeApplicationEventMulticaster.java:209)
   at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEvent(SafeApplicationEventMulticaster.java:180)
   at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:303)
   at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:911)
   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:428)
   at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
   at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
   at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
   at org.alfresco.web.app.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:63)
   at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4135)
   at org.apache.catalina.core.StandardContext.start(StandardContext.java:4630)
   at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
   at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
   at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:546)
   at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:637)
   at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:563)
   at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:498)
   at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277)
   at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321)
   at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
   at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
   at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
   at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
   at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
   at org.apache.catalina.core.StandardService.start(StandardService.java:519)
   at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
   at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:601)
   at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
   at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
2013-03-28 17:06:21,229  ERROR [web.context.ContextLoader] [main] Context initialization failed
java.lang.NullPointerException
   at org.alfresco.repo.node.MLPropertyInterceptor.getPivotNodeRef(MLPropertyInterceptor.java:323)
   at org.alfresco.repo.node.MLPropertyInterceptor.invoke(MLPropertyInterceptor.java:173)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.enterprise.repo.sync.SyncPropertyInterceptor.invoke(SyncPropertyInterceptor.java:157)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:212)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.enterprise.repo.sync.SyncPropertyInterceptor.invoke(SyncPropertyInterceptor.java:157)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:212)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.enterprise.repo.sync.SyncPropertyInterceptor.invoke(SyncPropertyInterceptor.java:157)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.alfresco.repo.node.NodeRefPropertyMethodInterceptor.invoke(NodeRefPropertyMethodInterceptor.java:212)
   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
   at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
   at $Proxy31.getProperties(Unknown Source)
   at org.alfresco.repo.descriptor.RepositoryDescriptorDAOImpl.getDescriptor(RepositoryDescriptorDAOImpl.java:158)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl.bootstrap(DescriptorServiceImpl.java:224)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl.access$100(DescriptorServiceImpl.java:52)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl$3.doWork(DescriptorServiceImpl.java:206)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl$3.doWork(DescriptorServiceImpl.java:202)
   at org.alfresco.repo.security.authentication.AuthenticationUtil.runAs(AuthenticationUtil.java:516)
   at org.alfresco.repo.descriptor.DescriptorServiceImpl.onBootstrap(DescriptorServiceImpl.java:210)
   at org.springframework.extensions.surf.util.AbstractLifecycleBean.onApplicationEvent(AbstractLifecycleBean.java:56)
   at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEventInternal(SafeApplicationEventMulticaster.java:209)
   at org.alfresco.repo.management.SafeApplicationEventMulticaster.multicastEvent(SafeApplicationEventMulticaster.java:180)
   at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:303)
   at org.springframework.context.support.AbstractApplicationContext.finishRefresh(AbstractApplicationContext.java:911)
   at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:428)
   at org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276)
   at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197)
   at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47)
   at org.alfresco.web.app.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:63)
   at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4135)
   at org.apache.catalina.core.StandardContext.start(StandardContext.java:4630)
   at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:791)
   at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:771)
   at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:546)
   at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:637)
   at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:563)
   at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:498)
   at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1277)
   at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:321)
   at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:119)
   at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
   at org.apache.catalina.core.StandardHost.start(StandardHost.java:785)
   at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1045)
   at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:445)
   at org.apache.catalina.core.StandardService.start(StandardService.java:519)
   at org.apache.catalina.core.StandardServer.start(StandardServer.java:710)
   at org.apache.catalina.startup.Catalina.start(Catalina.java:581)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
   at java.lang.reflect.Method.invoke(Method.java:601)
   at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
   at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)
Mar 28, 2013 5:06:21 PM org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.alfresco.web.app.ContextLoaderListener

</blockquote>
1 REPLY 1

arnoldschrijve1
Champ on-the-rise
Champ on-the-rise
For those of you who bounce against the same problem: I solved the issue by not using Spring to create the CamelContext. Instead I created a CamelContextFactory class that instantiates the context and wire that up as a bean. Below is a simplified example that demonstrates this. You'll probably want a more flexible means of loading the routes.

[java]

package com.yourcompany.activiti.camel;

import org.activiti.camel.ActivitiComponent;
import org.apache.camel.CamelContext;
import org.apache.camel.LoggingLevel;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;

public class CamelContextFactory {

    private CamelContext camelContext;
   
    public CamelContext getCamelContext() throws Exception {
        if (camelContext == null) {
            camelContext = new DefaultCamelContext();
           
            try {
                camelContext.addComponent("activiti", new ActivitiComponent(camelContext));
               
                // Add the camel routes
                camelContext.addRoutes(new RouteBuilder(camelContext) {
                   
                    @Override
                    public void configure() throws Exception {
                       
                        from("activiti://CamelTest:camelTask1")
                            .setBody().properties()
                            .to("mock:result");  
                    }
                });

                camelContext.start();
            } catch (Exception e) {
                // TODO: Do something with the exception.
                throw e;
            }
        }
               
        return camelContext;
    }
}

[/java]

In the context-file in your AMP (or in extensions directory if you use that):



<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:camel="http://camel.apache.org/schema/spring"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://camel.apache.org/schema/spring
                               http://camel.apache.org/schema/spring/camel-spring-2.5.0.xsd">

    <!– Creating a Camel context like this results in an error in Alfresco (in EE 4.1.1.3 at least).  
    <camelContext id="camelProcess" xmlns="http://camel.apache.org/schema/spring">
        <packageScan>
            <package>com.yourcompany.activiti.camel</package>
        </packageScan>
    </camelContext –>
   
    <bean id="camelContextFactory" class="com.yourcompany.activiti.camel.CamelContextFactory" />
   
    <bean id="camelContext" factory-bean="camelContextFactory" factory-method="getCamelContext" />

    <!– Extend CamelBehavior. Need to pass the Activiti bean registry. –>
    <bean id="camel" class="com.yourcompany.activiti.camel.CamelActivityBehaviour">
        <constructor-arg index="0">
            <value>camelTaskHandler</value>
        </constructor-arg>
        <constructor-arg index="1">
            <list>
                <bean class="org.activiti.camel.SimpleContextProvider">
                    <constructor-arg index="0" value="CamelTest" />
                    <constructor-arg index="1" ref="camelContext" />
                </bean>
            </list>
        </constructor-arg>
        <property name="beanRegistry" ref="activitiBeanRegistry" />
    </bean>
</beans>


As you can see we also need an extension of the CamelBehaviour in the activiti-camel jar. The Activiti engine in Alfresco uses a separate bean registry to which the camel bean must be added in order to make it available to the delegateExpresion in the camel serviceTask. The name to use in the expression is passed as well ('camelTaskHandler').

[java]

package com.yourcompany.activiti.camel;

import java.util.Collection;
import java.util.Map;

import org.activiti.camel.CamelBehaviour;
import org.activiti.camel.ContextProvider;

public class CamelActivityBehaviour extends CamelBehaviour {

    private String delegateExpressionBeanName;
   
    public CamelActivityBehaviour(String delegateExpressionName, Collection<ContextProvider> camelContext) {
        super(camelContext);
        this.delegateExpressionBeanName = delegateExpressionName;
    }

    /**
     * Register the CamelActivityBehaviour instance in the Activiti bean registry.
     */
    public void setBeanRegistry(Map<Object, Object> beanRegistry)
    {
        beanRegistry.put(getDelegateExpressionBeanName(), this);
    }
   
    protected String getDelegateExpressionBeanName()
    {
        return delegateExpressionBeanName;
    }
}

[/java]

Finally the workflow definition to test it all out:



    <process id="CamelTest" name="Camel Test: A Camel task in an Alfresco workflow">

        <startEvent id="start" />

        <sequenceFlow id="startup" sourceRef="start" targetRef="camelTask1"/>

        <serviceTask id="camelTask1" activiti:delegateExpression="${camelTaskHandler}" />

        <sequenceFlow id='flowToEnd' sourceRef='camelTask1' targetRef='end' />

        <endEvent id="end" />

    </process>


Hope this may have been helpful for you!