cancel
Showing results for 
Search instead for 
Did you mean: 

Deploy Activiti as OSGi Bundles

capacia
Champ in-the-making
Champ in-the-making
Hi all,

is there already a possibility to deploy all activiti modules as OSGi bundles?
If not which modules are already available as OSGi bundle and when will the other ones be available ?
6 REPLIES 6

gnodet
Champ in-the-making
Champ in-the-making
I've been working on OSGi support for Activiti.  Currently, you can deploy activiti-engine which is a valid OSGi bundle.  You also need to deploy activiti-osgi which brings blueprint support along with fileinstall deployer based support.
Here's the Karaf feature I'm working with atm…

<feature name="activiti" version="5.0-SNAPSHOT" resolver="(obr)">
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.aries.transaction/org.apache.aries.transaction.manager/0.2-incubating</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.bundles/org.apache.servicemix.bundles.wsdl4j/1.6.2_3</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.bundles/org.apache.servicemix.bundles.mybatis/3.0.2_1</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.specs/org.apache.servicemix.specs.activation-api-1.1/1.4.0</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.specs/org.apache.servicemix.specs.jaxb-api-2.1/1.4.0</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.0/1.4.0</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.bundles/org.apache.servicemix.bundles.jaxb-impl/2.1.13_1</bundle>
  <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.bundles/org.apache.servicemix.bundles.jaxb-xjc/2.1.13_1</bundle>
  <bundle>mvnSmiley Surprisedrg.activiti/activiti-engine/5.0-SNAPSHOT</bundle>
  <bundle>mvnSmiley Surprisedrg.activiti/activiti-osgi/5.0-SNAPSHOT</bundle>
</feature>

You can also deploy the rest api in OSGi using:

<feature name="activiti-rest" version="5.0-SNAPSHOT" resolver="(obr)">
        <feature version="5.0-SNAPSHOT">activiti</feature>
        <feature>war</feature>
        <feature>spring</feature>
        <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.specs/org.apache.servicemix.specs.javamail-api-1.4/1.4.0</bundle>
        <bundle dependency="true">mvn:commons-codec/commons-codec/1.4</bundle>
        <bundle dependency="true">mvnSmiley Surprisedrg.apache.abdera/abdera-i18n/1.1-SNAPSHOT</bundle>
        <bundle dependency="true">mvnSmiley Surprisedrg.apache.abdera/abdera-core/1.1-SNAPSHOT</bundle>
        <bundle dependency="true">mvnSmiley Surprisedrg.apache.abdera/abdera-parser/1.1-SNAPSHOT</bundle>
        <bundle dependency="true">mvnSmiley Surprisedrg.apache.servicemix.bundles/org.apache.servicemix.bundles.dom4j/1.6.1_3</bundle>
        <bundle dependency="true">mvn:eu.medsea.mimeutil/mime-util/2.1.3</bundle>
        <bundle dependency="true">mvnSmiley Surprisedrg.springframework/spring-web/3.0.4.RELEASE</bundle>
        <bundle dependency="true">mvnSmiley Surprisedrg.springframework/spring-webmvc/3.0.4.RELEASE</bundle>
        <bundle>mvnSmiley Surprisedrg.activiti/activiti-cycle/5.0-SNAPSHOT</bundle>
        <bundle>mvnSmiley Surprisedrg.activiti/activiti-osgi-rest/5.0-SNAPSHOT</bundle>
</feature>

Lastly, you'd have to deploy a blueprint configuration so that the process engine is actually created using a blueprint file like:


<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
        xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0">

<extSmiley Tongueroperty-placeholder />

    <bean id="dataSource" class="org.h2.jdbcx.JdbcDataSource">
        <property name="URL" value="jdbc:h2:file:${karaf.data}/activiti/database;DB_CLOSE_DELAY=1000"/>
        <property name="user" value="sa"/>
        <property name="password" value=""/>
    </bean>

    <reference id="transactionManager" interface="javax.transaction.TransactionManager"/>

    <bean id="configuration" class="org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration" ext:field-injection="true">
        <property name="databaseType" value="h2"/>
        <property name="dataSource" ref="dataSource"/>
        <property name="transactionManager" ref="transactionManager"/>
        <property name="databaseSchemaUpdate" value="true"/>
    </bean>

    <bean id="processEngineFactory" class="org.activiti.osgi.blueprint.ProcessEngineFactory" init-method="init" destroy-method="destroy">
  <property name="processEngineConfiguration" ref="configuration"/>
        <property name="bundle" ref="blueprintBundle"/>
    </bean>

    <bean id="processEngine" factory-ref="processEngineFactory" factory-method="getObject"/>

    <service ref="processEngine" interface="org.activiti.engine.ProcessEngine"/>

</blueprint>



I know it's not really an easy process for now, but I'm planning to make all those files part of activiti so that it becomes easy to deploy in Karaf at least (if you use a different environment, you'll still have to do the deployment of all bundles).

capacia
Champ in-the-making
Champ in-the-making
Thanks for the detailed reply.

I use Glassfish and a Postgres database. I have deployed the activiti-engine OSGi bundle successfully and a simple test webapp (another OSGi bundle) which shall use the engine.

Now I have a question related to the engine's configuration file. I want that the Glassfish manages the database data source. Is it possible to reference the data source by its JNDI name (in the engine's configuration file)?

I have already tried something like this:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
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">
<bean id="serverDataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName"  value="jdbc/activiti"/>
</bean>
<bean id="processEngineConfiguration"
  class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
  <property name="dataSource" ref="serverDataSource" />
  <property name="databaseSchemaUpdate" value="true" />
  <property name="history" value="audit" /> 
</bean>
</beans>

But this causes the following error:

Exception while initializing process engine :Error creating bean with name 'processEngineConfiguration' defined in resource loaded through InputStream: Initialization of bean failed; nested exception is org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'org.springframework.jndi.JndiObjectFactoryBean' to required type 'javax.sql.DataSource' for property 'dataSource'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.springframework.jndi.JndiObjectFactoryBean] to required type [javax.sql.DataSource] for property 'dataSource': no matching editors or conversion strategy found

Do you have any idea? What am I doing wrong?

Thanks for your help.

tombaeyens
Champ in-the-making
Champ in-the-making
<bean id="processEngineConfiguration" class="org.activiti.engine.impl.cfg.StandaloneProcessEngineConfiguration">
!=

<bean id="configuration" class="org.activiti.engine.impl.cfg.JtaProcessEngineConfiguration" ext:field-injection="true">

could that be the problem?

ancoron
Champ in-the-making
Champ in-the-making
I'm currently giving the OSGi blueprint solution a try run but I had to completely reimplement big parts of the ProcessEngineConfiguration stuff as almost any setter method is not POJO-style, resulting in the following behavior when trying to start such a blueprint bundle:

org.osgi.service.blueprint.container.ComponentDefinitionException: No setter for databaseType property
        at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:830)
        at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:793)
        at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:774)
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:740)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
        at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:60)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
        at org.apache.aries.blueprint.container.BeanRecipe.setProperty(BeanRecipe.java:819)
        at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:793)
        at org.apache.aries.blueprint.container.BeanRecipe.setProperties(BeanRecipe.java:774)
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:740)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
        at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:60)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
        at org.apache.aries.blueprint.container.BeanRecipe.getInstance(BeanRecipe.java:215)
        at org.apache.aries.blueprint.container.BeanRecipe.internalCreate(BeanRecipe.java:726)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
        at org.apache.aries.blueprint.di.RefRecipe.internalCreate(RefRecipe.java:60)
        at org.apache.aries.blueprint.di.AbstractRecipe.create(AbstractRecipe.java:64)
        at org.apache.aries.blueprint.container.BlueprintRepository.createInstances(BlueprintRepository.java:219)
        at org.apache.aries.blueprint.container.BlueprintRepository.createInstance(BlueprintRepository.java:198)
        at org.apache.aries.blueprint.container.BlueprintRepository.create(BlueprintRepository.java:137)
        at org.apache.aries.blueprint.container.ServiceRecipe.createRecipe(ServiceRecipe.java:352)

This is because Aries only considers setters as valid when they are of return type "void", as all POJO's should be:

org.apache.aries.blueprint.utils.ReflectionUtils::getPropertyDescriptors


                String name = method.getName();
                Class<?> argTypes[] = method.getParameterTypes();
                Class<?> resultType = method.getReturnType();
               
                if (name.length() > 3 && name.startsWith("set") && resultType == Void.TYPE && argTypes.length == 1) {
                    name = decapitalize(name.substring(3));
                    if (!!!setters.containsKey(name)) setters.put(name, new ArrayList<Method>());
                    setters.get(name).add(method);
                    propertyNames.add(name);

ancoron
Champ in-the-making
Champ in-the-making
…and be careful when upgrading MyBatis version because I just tested with 3.0.4, which already comes as an OSGi bundle. With that micro-version update you'll have to chose different namespaces inside the …/*.mapping.xml files for MyBatis as MyBatis overwrites them, which results in the behavior that only the statements from the last mapping file are available at runtime.

Version 3.0.1 works differently and doesn't have that issue but is not available as an OSGi bundle directly from upstream.

suresh1
Champ in-the-making
Champ in-the-making
Plz help for this

mvnSmiley Surprisedrg.activiti.karaf/activiti-karaf-feature/1.0.0-SNAPSHOT/xml/features

when i am adding this url to my servicemix it showing white screen..
plz anyone can help..
Thank you.