cancel
Showing results for 
Search instead for 
Did you mean: 

How to store data from each task of a workflow?

joe_182
Champ in-the-making
Champ in-the-making
Hi guys, I'm developing a workflow and I need to store some data of each task node: which user took the task (all task are from the pooled task type), date of that action, what's the next task, and more.

The problem here is that I'm storing that data in an .csv file into the Alfresco repository. Then with that data, I have to make some reports. But that's a terrible solution, because a user can download that file, modify it and make a report with false data.

So the question here is, Is there a way to select data from Alfresco data's base, like workflow data? Or a way to store data into a new data base from each task node of a workflow?

Thank's a lot!

Joel.
9 REPLIES 9

chalford
Champ in-the-making
Champ in-the-making
Each task in Activiti can have variables get and set on it (with getVariable(String) and setVariable()), as well as the whole process flow itself (with the execution variable in JavaScript).

Acitviti, by default, logs changes to form properties, as well as process and activity instance information. There is an aditional level to this history, "full", which also records all updates to process variables and user task form properties. To enable this level of auditing, you can insert <property name="history" value="full" /> into your activiti.cfg.cml file. This data can then be accessed in one of two ways:

    Use the HistoryService of Acitivi to query previous process instances, or
    Go directly into the DB, grabbing the info you need from ACT_HI_PROCINST, ACT_HI_ACTINST and ACT_HI_DETAIL

joe_182
Champ in-the-making
Champ in-the-making
Hi Chalford, thanks for the reply!

The problem here is that my workflows are made with JBPM engine, not with Activiti.

Do you know if JBPM also stores that info? And if that's true, should I access that data in the same way that with Activiti?

Thanks!

chalford
Champ in-the-making
Champ in-the-making
I'm not as familiar with jBPM, but one possible solution would be to use the Alfresco Audit service (http://wiki.alfresco.com/wiki/Auditing_(from_V3.4)) to record changes as you execute through tasks in a JBPM workflow. There are then Audit webscripts that you can call to query that information. However, inserting all these extra calls into the Audit service (or adding a Data Producer) would require a fair amount of extra effort.

On the jBPM side, this forum post might be helpful (https://community.jboss.org/message/394384?_sscc=t), it details turning on process auditing in jBPM.

joe_182
Champ in-the-making
Champ in-the-making
Chalford,

I've been looking at the Alfresco Audit Service wiki but it isn't useful to me because I can't query the log as if it were a data table, and then make a report with that info.

Is there any way to create some database (e.g. MyAlfrescoDataBase) and in each task node, insert info that is important to me on that database?

Thanks, Joel.

chalford
Champ in-the-making
Champ in-the-making
Hi Joel,

If the Alfresco Audit service doesn't do what you'd like it to (there is an Audit web script that has some quering capabilities - http://docs.alfresco.com/4.0/topic/com.alfresco.enterprise.doc/tasks/audit-advanced-query.html), then you could write your own. You could do the following:

Write a Java service that writes data to a DB (using direct JDBC, Hibernate or MyBatis)
Expose the service as a Spring bean
Add the bean as a JavaScript root object
On each task in jBPM, call the service to write data to your DB.

Thanks, Charlie.

joe_182
Champ in-the-making
Champ in-the-making
Hi Charlie,

Thank you very much for that answer, i've been asking me if that is possible to do. The only things that I don't know how to make is to add the bean as a JavaScript root object. And then how to call that service?

If you know some place that is explained, I'd really apreciate it!

Joel.

chalford
Champ in-the-making
Champ in-the-making
I can definitely help you out there.

To add a Java POJO as a JavaScript root object, you need to ensure your class extends the BaseProcessorExtension Alfresco class. Any public methods used here will be accessible from JavaScript. The the last step is to add some Spring wiring to bring the POJO into the JavaScript engine:

<bean id="yourScript" parent="baseJavaScriptExtension" class="org.alfresco.repo.jscript.ScriptLogger">
    <property name="extensionName">
        <value>yourRootObjectName</value>
    </property>
</bean>

The important part here is to ensure the bean's parent is baseJavaScriptExtension,

All of this information was taken from the Custom Script API's section of the JavaScript API wiki page: http://wiki.alfresco.com/wiki/4.0_JavaScript_API#Adding_Custom_Script_APIs

joe_182
Champ in-the-making
Champ in-the-making
Ok, I understand that, but where should I put MyPOJO?

And when it says 'class="org.alfresco.repo.jscript.ScriptLogger"', that ScriptLogger I have to replace with MyPOJO?

Thank you very very much!

joe_182
Champ in-the-making
Champ in-the-making
Thank you very much Charlie, finally I've done it!

Here I post the things I've done:

1- First you have to do a Java class, with public methods. Here is my Java class:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

import org.alfresco.repo.processor.BaseProcessorExtension;

public class MyPOJO extends BaseProcessorExtension
{   
   public Connection conn = null;
   
   private void openConnection() throws SQLException
   {
      if (conn == null)
      {
         try
         {
            Class.forName("com.mysql.jdbc.Driver");
            System.setProperty("sqlfile.charset", "ISO-8859-1");
            conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/DBname","user","password");         
         }
         catch (Exception ex)
         {
            System.err.println("Error at initialization block");
            ex.printStackTrace();            
            if (conn != null)
            {
               try
               {
                  conn.close();
                  conn = null;
               }
               catch (SQLException e)
               {
                  e.printStackTrace();
               }
            }
         }
      }      
   }
   
   public boolean insert(String foo, String bar) throws SQLException
   {
      boolean sqlRet = true;
      this.openConnection();
      if (conn != null)
      {
         String insertString = "INSERT INTO SampleTable(foo,bar) VALUES (?,?);";
         
         PreparedStatement insertStatement = null;
         insertStatement = conn.prepareStatement(insertString);
         insertStatement.setString(1, foo);
         insertStatement.setString(2, bar);
   
         try
         {         
            insertStatement.executeUpdate();
         }
           catch (SQLException ex)
           {
               ex.printStackTrace();
               sqlRet = false;
           }
           finally
           {
              if(insertStatement != null)
              {
                 insertStatement.close();
              }
           }
      }
      return sqlRet;
   }
   
   private void closeConnection() throws SQLException
   {
       if (conn != null)
       {
          if (conn.isValid(1) == true)          
          {
             try             
             {
                conn.close();
                conn = null;
             }
             catch (SQLException e)
             {
                e.printStackTrace();
             }
          }
          else if (conn.isClosed() == false)
          {
             try             
             {
                conn.close();
                conn = null;
             }
             catch (SQLException e)
             {
                e.printStackTrace();
             }
          }
       }       
   }
   
   protected void finalize() throws SQLException
   {
      this.closeConnection();
   }
}

This class creates a connection with a MySQL DB and inserts some stuff into it.

2- Then you have to make a .jar file and put it into /tomcat/webapps/alfresco/WEB-INF/lib.

3- You have to add your POJO to the /tomcat/webapps/alfresco/WEB-INF/classes/alfresco/script-services-context.xml


    <bean id="MyPOJOScript" parent="baseJavaScriptExtension" class="MyPOJO">
        <property name="extensionName">
            <value>myPOJO</value>
        </property>
    </bean>

4- In each task node of your workflow, you have to put a tag that tells that you are going to put some javascript code, and then put "myPOJO.insert(…,…)"



So thats all!

Joel