Creating an Alfresco Task History; The Java style
I have been working with Alfresco for a while now. It is a very comprehensive tool, but I was missing a nice feature in it. A task history in the document details screen. Now i know you can do alot of coding with the scripting engine in Alfresco, but what I wanted was not possible in my opinion and I wanted it to fully integrate in the java code base instead of scripted into pages. Time for me to go to work. In this article I will briefly explain what I have done to make this feature work.
Intended public
This article is written with the Alfresco developer in mind. If you are not atleast a moderate Alfresco developer you might not be able to fully comprehend what is explained. Also I will omit information in this article that I deem basic Alfresco knowledge.
The creation process
Very early on in my effort to build the task history panel I cam eto the conclusion that I not only needed extra coding effort, but also a solid way of integrating my code into the codebase of alfresco. Now Alfresco has provided me and you with a method of doing this. You can find details about this integration process on the Alfresco wiki. I will in this article give you a brief overview on how to integrate your code into the Alfresco codebase, but I will not go into detail on this. What I will describe is the Task history functionality.
Functionality overview
What am I creating is a panel in the document-details page that displays the tasks for me specific for the document in question. Furthermore I want to see active and completed tasks here. ALL tasks that is. To give you a impression of my wish; a picture to illustrate it.
![]()
My other wish was that it would be coded in Java and integrate in the Alfresco way with the Alfresco codebase. Given these wishes I started this small project.
What do you need to do?
1.Create a extension project
2.Create a new workflowbean class with the added functionality.
3.Modify the faces-config-custom.xml, supplying a enhanced workflowbean
4.Modify the document-details.jsp, to show the task history
5.Create a faces-config.xml, supplying the new navigation rules for your new jsp.
6.Create a custom webclient.properties file for your new labels.
The extension project
The first thing I did was to create a new extension project. I followed the example SDK custom JSP project structure for my own project. You can read on the wiki or in the source on how to do this. I asume you have the nessesary skill.
The new workflowbean
For my function I have to code some extra lines. It is bad practise to start hacking the alfresco source (unless you have no other option), so I created my own java class extending the existing WorkflowBean class. Here is the added code:
package nl.wowww.alfresco.web.bean.workflow;
import java.util.ArrayList;
import java.util.List;
import org.alfresco.service.cmr.workflow.WorkflowInstance;
import org.alfresco.service.cmr.workflow.WorkflowTask;
import org.alfresco.service.cmr.workflow.WorkflowTaskQuery;
import org.alfresco.web.bean.DocumentDetailsBean;
import org.alfresco.web.bean.repository.Node;
import org.alfresco.web.bean.workflow.WorkflowBean;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* Extended workflowbean.
* This extension adds extra task functionality.
*
* @author Marc de Kwant, www.wowww.nl
*/
public class WowwwWorkflowBean extends WorkflowBean {
protected DocumentDetailsBean documentDetailsBean;
protected List
private static final Log logger = LogFactory.getLog(WowwwWorkflowBean.class);
public static final String BEAN_NAME = "WowwwWorkflowBean";
// ------------------------------------------------------------------------------
// Bean Getters and Setters
public List
this.allTasks = new ArrayList
List
workflows = workflowService.getWorkflowsForContent(
documentDetailsBean.getDocument().getNodeRef(), false);
workflows.addAll(workflowService.getWorkflowsForContent(
documentDetailsBean.getDocument().getNodeRef(), true));
if (workflows != null && workflows.size() > 0) {
for (WorkflowInstance wi : workflows) {
WorkflowTaskQuery query = new WorkflowTaskQuery();
query.setActive(wi.active);
query.setTaskState(null);
query.setProcessId(wi.id);
List
// create a list of transient nodes to represents
for (WorkflowTask task : tasks)
{
Node node = createTask(task);
this.allTasks.add(node);
if (logger.isDebugEnabled())
logger.debug("Added task: " + node);
}
}
}
return this.allTasks;
}
/**
* @param documentDetailsBean the documentDetailsBean to set
*/
public void setDocumentDetailsBean(DocumentDetailsBean documentDetailsBean) {
this.documentDetailsBean = documentDetailsBean;
}
}
The code above is what you need to retrieve all tasks, weather complete/active/non-active, and make them available to the front-end.
Faces-config-custom.xml
To make the above bean available to the jsf framework, you need to provide a managed bean configuration. The faces framework provides for this in the form of a faces-config-custom.xml file. I have put the below code into this file:
<managed-bean>
<managed-bean-name>WowwwWorkflowBean</managed-bean-name>
<managed-bean-class>nl.wowww.alfresco.web.bean.workflow.WowwwWorkflowBean</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>navigationBean</property-name>
<value>#{NavigationBean}</value>
</managed-property>
<managed-property>
<property-name>documentDetailsBean</property-name>
<value>#{DocumentDetailsBean}</value>
</managed-property>
<managed-property>
<property-name>nodeService</property-name>
<value>#{NodeService}</value>
</managed-property>
<managed-property>
<property-name>workflowService</property-name>
<value>#{WorkflowService}</value>
</managed-property>
</managed-bean>
This file represents the only manual manipulation of files in the alfresco codebase since the faces framework gives me no alternate option in this. The file must be put into the WEB-INF folder in the alfresco webclient project and nowhere else.
Document-details.jsp
To display my net Task history panel I created a duplicate of the original document-details jsp and added the following panel/richlist to display the tasks provided by my allTasks method in my new WowwwWorkflowBean class.
<f:loadBundle basename="alfresco.extension.webclient" var="customMsg"/>
<a:panel label="#{customMsg.task_history}" id="task-panel" facetsId="workflow-panel-facets" progressive="true"
border="white" bgcolor="white" titleBorder="lbgrey" expandedTitleBorder="dotted" titleBgcolor="white"
expanded='#{DocumentDetailsBean.panels["task-panel"]}' expandedActionListener="#{DocumentDetailsBean.expandPanel}">
<!-- tasksCompleted -->
<a:richList id="taskHistoryList" viewMode="details" value="#{WowwwWorkflowBean.allTasks}"
var="t" styleClass="recordSet" headerStyleClass="recordSetHeader"
rowStyleClass="recordSetRow" altRowStyleClass="recordSetRowAlt" width="100%"
pageSize="10" initialSortColumn="taskId" initialSortDescending="false">
<!-- task id column -->
<a:column id="col1" width="10" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskId}" value="taskId" styleClass="header"/>
</f:facet>
<h:outputText id="tid" value="#{t['bpm:taskId']}" />
</a:column>
<!-- task create date column -->
<a:column id="col2" width="120" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskCreateDate}" value="taskCreateDate" styleClass="header"/>
</f:facet>
<h:outputText id="tcreatedate" value="#{t['cm:created']}">
<f:convertDateTime pattern="yyyy-MMM-dd H:mm:ss" />
</h:outputText>
</a:column>
<!-- task description column -->
<a:column id="col3" width="170" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskDescription}" value="taskDescription" styleClass="header"/>
</f:facet>
<h:outputText id="tdescription" value="#{t['bpm:description']}" />
</a:column>
<!-- task comment column -->
<a:column id="col5" width="170" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskComment}" value="taskComment" styleClass="header"/>
</f:facet>
<h:outputText id="tcomment" value="#{t['bpm:comment']}" />
</a:column>
<!-- task status column -->
<a:column id="col6" width="80" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskStatus}" value="taskStatus" styleClass="header"/>
</f:facet>
<h:outputText id="tstatus" value="#{t['bpm:status']}" />
</a:column>
<!-- task start date column -->
<a:column id="col7" width="120" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskStartDate}" value="taskStartDate" styleClass="header"/>
</f:facet>
<h:outputText id="tstartdate" value="#{t['bpm:startDate']}">
<f:convertDateTime pattern="yyyy-MMM-dd H:mm:ss" />
</h:outputText>
</a:column>
<!-- task due date column -->
<a:column id="col8" width="120" style="text-align:left">
<f:facet name="header">
<a:sortLink label="#{customMsg.taskDueDate}" value="taskDueDate" styleClass="header"/>
</f:facet>
<h:outputText id="tduedate" value="#{t['bpm:dueDate']}">
<f:convertDateTime pattern="yyyy-MMM-dd H:mm:ss" />
</h:outputText>
</a:column>
</a:richList>
</a:panel>
First I load my custom message bundle and secondly I code the task history panel.
Faces-config.xml
To display our newly created document-details.jsp we need to overrule the navigation rules that are present in the alfresco WEB-INF folder. This is not done as the faces-config-custom but in a more sophisticated manner. In the extension project you put a file named faces-config.xml in the META-INF directory. in this file i have declared the following navigation rules to be overruled:
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.1//EN"
"http://java.sun.com/dtd/web-facesconfig_1_1.dtd">
<faces-config>
<navigation-rule>
<from-view-id>/jsp/*</from-view-id>
<navigation-case>
<from-outcome>showDocDetails</from-outcome>
<to-view-id>/jsp/extension/document-details.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/jsp/extension/document-details.jsp</from-view-id>
<navigation-case>
<from-outcome>checkoutFile</from-outcome>
<to-view-id>/jsp/dialog/checkout-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>checkinFile</from-outcome>
<to-view-id>/jsp/dialog/checkin-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>undoCheckoutFile</from-outcome>
<to-view-id>/jsp/dialog/undocheckout-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>updateFile</from-outcome>
<to-view-id>/jsp/dialog/update-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>deleteFile</from-outcome>
<to-view-id>/jsp/dialog/delete-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editFile</from-outcome>
<to-view-id>/jsp/dialog/edit-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editHtmlInline</from-outcome>
<to-view-id>/jsp/dialog/edit-html-inline.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editTextInline</from-outcome>
<to-view-id>/jsp/dialog/edit-text-inline.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editSimpleWorkflow</from-outcome>
<to-view-id>/jsp/dialog/edit-simple-workflow.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>editCategories</from-outcome>
<to-view-id>/jsp/dialog/edit-category.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>createAction</from-outcome>
<to-view-id>/jsp/wizard/create-action/action.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>previewContent</from-outcome>
<to-view-id>/jsp/dialog/preview-file.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>showForum</from-outcome>
<to-view-id>/jsp/forums/forum.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>manageContentUsers</from-outcome>
<to-view-id>/jsp/roles/manage-content-users.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>applyTemplate</from-outcome>
<to-view-id>/jsp/dialog/apply-doc-template.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/jsp/dialog/edit-simple-workflow.jsp</from-view-id>
<navigation-case>
<from-outcome>cancel</from-outcome>
<to-view-id>/jsp/extension/document-details.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>finish</from-outcome>
<to-view-id>/jsp/extension/document-details.jsp</to-view-id>
</navigation-case>
</navigation-rule>
<navigation-rule>
<from-view-id>/jsp/dialog/edit-category.jsp</from-view-id>
<navigation-case>
<from-outcome>cancel</from-outcome>
<to-view-id>/jsp/extension/document-details.jsp</to-view-id>
</navigation-case>
<navigation-case>
<from-outcome>finish</from-outcome>
<to-view-id>/jsp/extension/document-details.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
In this file I overrule all references to document-details with my own reference.
webclient.properties
The final and last thing I did was to create a webclient.properties file and put all my custom labels into it.
task_history=Task History
taskId=Task id
taskDescription=Description
taskCreateDate=Create date
taskStartDate=Start date
taskDueDate=Due date
taskStatus=Status
taskComment=Comment
Final note.
I have omitted all explenation regarding the extension project. This article was intended for a Alfresco developer. And the layout of the article is not that good, but I cannot alter the look and feel of it.
Regards.
wowww.nl
Gepost in categorie: TechTalk
Tweet
This is THE needed feature. Can you do some installation package that users can benefit from your work?
10 september 2008 om 01:24YES! YES! even labs3 is missing this…Please can you do some sort of installation package to download and use.
25 september 2008 om 23:58Hey guys nice blog, love it
26 september 2008 om 00:08This is a great feature Marc. Thanks for posting your work here.
I used this as a starting point and made some changes to the java, properties and jsp so it works in Labs 3.0. If you would like to update this post with the updated code, please send me an email.
The JSP now shows the task title, assignee and workflow ID. I also fixed the sorting and date presentation so it works properly and shows the correct date and times.
Please keep up the good work!
Craig
7 januari 2009 om 08:42Would be nice to have this option also for us that are not that handy with coding….. Craig can you publish your work somewhere?
Thanks!
17 januari 2009 om 10:22Aki,
I placed the modified code here:
http://sites.google.com/site/clbforge/Home
Let me know if you have any problems accessing the files.
Craig
19 januari 2009 om 10:05[...] to drop this requirement, while googling around I came across this genius post, in which Marc de Kwant describes and shares the code of exactly this feature. Ok, I understand [...]
21 januari 2009 om 18:19Hello,
Thank you for this job, it’s great
I have take source from Craig’s site, where it’s write : Notes: I could not get Alfresco to see the new jsp in the extensions directory (alfresco.war\jsp\extension), so I just updated the original jsp (alfresco.war\jsp\content).
Craig, have you found the problem ?
8 juli 2009 om 08:14Hello,
If you have problems to indicate to Alfresco that the jsp is in /jsp/extension/document-details.jsp
(problems with faces-config.xml)
Go here : http://forums.alfresco.com/en/viewtopic.php?f=10&t=20249&p=65779#p66019
9 juli 2009 om 03:18this link was very useful.
can any one please tell me how to create a new task with java style ?, with creating properties,packages resources and transitions ???
tnx
4 augustus 2009 om 05:14vin
Great post! One question — Which “example SDK custom JSP project”? Could you please post a link?
22 juni 2010 om 09:57Or please post a link to where it says *how to deploy/compile Java* in Alfresco.
Thanks!
Okay, this is a great post, but I’m quite eluded.
With the nature of open source, and the fact that this post is not only 3 years old, but also linked from Alfresco’s website……..
Why not include this in their current product? Quite frustrating, and I’m thinking about dropping Alfresco just because of this simple feature. Obviously there is a fix for it…. why not implement it?
24 juli 2010 om 12:46Hi Marc, you can I get this feature?
15 november 2010 om 14:52sorry, I mean, How can I get this feature?
15 november 2010 om 14:53hi,
As was state. This post is over 3 years old. I have read my own post again and can only say that I think the full source is in this post itself… With some understanding of alfresco and the extension of alfresco, you should be able to use the given code in this post and create the widget yourself.
Kind regards,
Marc
15 november 2010 om 16:51Hi, see me on lisachu
http://ipacs-sim.com/phpbb/profile.php?mode=viewprofile&u=204095 drumbeatinsight.com/forums/profile.php?mode=viewprofile&u=71821
7 december 2010 om 21:31Ja, waarschijnlijk dus het is
15 mei 2011 om 05:27644 I just could not depart your site prior to suggesting that I actually enjoyed the standard info an individual provide on your guests? Is going to be again often to inspect new posts.
11 januari 2012 om 13:35