« Back

How to add workflow capabilities on Knowledge Base articles or any custom assets in plugins

General Blogs September 7, 2010 By Jonas Yuan

In previous blogs post, we had discussed applying workflow on Liferay portal core assets. It is true that Liferay 6 integrates workflow system like jBPM or Kaleo on any assets, either core assets or custom assets. Out-of-the-box liferay 6 supports workflow working on following core assets: Blogs Entry, Comments, Document Library Document, Message Boards Message, Web Content and Wiki Page.

Furthermore, we also discussed applying workflow on any custom assets like Knowledge Base articles in Liferay 6 through plugins. We did answer the question what it was in that blogs post, but the question how to make it programmatically was pending.

This article will introduce how to add workflow capabilities on any custom assets in plugins. Knowledge Base articles will be used as an example, one of custom assets. And moreover, we will use Liferay portal 6.0.5 GA 3 as testing environment. Of course, you could use Liferay portal 6.0.5 or latest version, for instance, Liferay 6 EE.

Abstracted from the book: Liferay User Interface Developement.

Prepare plugin

First of all, let’s prepare a plugin with workflow capabilities, called Knowledge Base. Note that the plugin Knowledge Base here is used as an example only. You can have your own plugin as well.

Structure
The plugin Knowledge Base has following folder structure under the folder $PLUGIN_SDK_HOME/knowledge-base-portlet.

  • admin: view JSP files for portlet Admin;
  • aggregator: view JSP files for portlet Aggregator;
  • display: view JSP files for portlet Display;
  • icons: icon images files,
  • js: JavaScript files,
  • META-INF:  context.xml;
  • search: view JSP files for portlet Search;
  • WEB-INF: web info specification; includes sub-folders classes, client, lib, service, sql, src, and tld.

As you can see, JSP files like init.jsp and css_init.jsp are resided in the folder $PLUGIN_SDK_HOME/knowledge-base-portlet

Services and Models

As you have been noticed, the plugin Knowledge Base has specified services and models with the package named com.liferay.knowledgebase. You would be able to find details at $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/service.xml. Service-Builder in plugins SDK will automatically generate services and models against service.xml, plus XML files like portlet-hbm.xml, portlet-model-hints.xml, portlet-orm.xml,  portlet-spring.xml, base-spring.xml, cluster-spring.xml,dynamic-data-source-spring.xml, hibernate-spring.xml, infrastructure-spring.xml, messaging-spring.xml and shard-data-source-spring.xml under the folder $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/src/META-INF.

The service.xml specified knowledge base info as entries: Article and Template. The entry Article included columns: article Id as primary key, resource Prim Key, group Id, company Id, user Id, user Name, create Date, modified Date, parent resource Prim Key, version, title, content, description and priority; the entry Template included columns: template Id as primary key, group Id, company Id, user Id, user Name, create Date, modified Date, title, content and description.

By the way, the custom SQL scripts were provided at $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/src/custom-sql/default.xml. In addition, resource actions – that is, permission actions specification - were provided at $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/src/resource-actions/default.xml.

Of course, you can use Ant target build-wsdd to generate WSDD server configuration file $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/server-config.wsdd and to use Ant target build-client plus namespace-mapping.properties to generate web service client JAR file $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/client/known-base-portlet-client.jar. In brief, based on your own custom models and services specified in service.xml, you can easily build service, WSDD and web service client in plugins of Liferay 6 or above

Add Workflow Instance Link

 First, you have to add workflow instance link and its related columns and finder in service.xml as follows.

<column name="status" type="int" />
<column name="statusByUserId" type="long" />
<column name="statusByUserName" type="String" />
<column name="statusDate" type="Date" />
<!-- ignore details -->
<finder name="R_S" return-type="Collection">
  <finder-column name="resourcePrimKey" />
  <finder-column name="status" />
</finder>
<!-- ignore details -->
<reference package-path="com.liferay.portal" entity="WorkflowInstanceLink" />

As shown in above code, the column element represents a column in the database, here four columns like status, statusByUserId, statusByUserName and statusDate are required for Knowledge Base workflow; the finder element represents a generated finder method, here the method finder R_S is defined as Collection for return-type with two columns, e.g., resourcePrimkey and status; where the reference element allows you to inject services from another service.xml within the same class loader. For example, if you inject the Resource entity, then you'll be able to reference the Resource services from your service implementation via the methods getResourceLocalService and getResourceService.  You'll also be able to reference the Resource services via the variables resourceLocalService and resourceService.

Then, you need to run ANT target build-service to rebuild service based on newly added workflow instance link.

Add Workflow Handler

Liferay 6 provides pluggable workflow implementations, where developers can register their own workflow handler implementation for any entity they build. It will appear automatically in the workflow admin portlet so users can associate workflow entities with available permissions. To make it happening, we need to add Workflow Handler in $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/WEB-INF/liferay-portlet.xml of plugin as follows.

<workflow-handler>com.liferay.knowledgebase.admin.workflow.ArticleWorkflowHandler</workflow-handler>

As shown in above code, the workflow-handler value must be a class that implements com.liferay.portal.kernel.workflow.BaseWorkflowHandler and is called when workflow is run.
Of course, you need to specify ArticleWorkflowHandler under the package com.liferay.knowledgebase.admin.workflow. The following is snippet.

public class ArticleWorkflowHandler extends BaseWorkflowHandler {
 public String getClassName(){/* ignore details */};
 public String getType(Locale locale) {/* ignore details */};
 public Article updateStatus( int status, Map<String, Serializable> workflowContext) throws PortalException, SystemException {/* ignore details */};
 protected String getIconPath(ThemeDisplay themeDisplay) {/* ignore details */};
}

As you can see, ArticleWorkflowHandler extends BaseWorkflowHandler and overrode the methods getClassName, getType, updateStatus and getIconPath. That’s it.

Add the method updateStatus

 As mentioned in previous section, you added method updateStatus in ArticleWorkflowHandler. Now you should provide implementation of the method updateStatus in com.liferay.knowledgebase.service.impl.ArticleLocalServiceImpl.java. The following is sample code. 

public Article updateStatus(long userId, long resourcePrimKey, int status, ServiceContext serviceContext) throws PortalException, SystemException {
/* ignore details */
// Article
Article article = getLatestArticle(resourcePrimKey, WorkflowConstants.STATUS_ANY);
articlePersistence.update(article, false);
if (status != WorkflowConstants.STATUS_APPROVED) { return article; }
// Articles
// Asset
// Social
// Indexer
// Attachments
// Subscriptions
}

As shown in above code, it first gets latest article by resourcePrimKey and WorkflowConstants.STATUS_ANY. Then it updates the article based on workflow status. And moreover, it updates articles display order, asset tags and categories, social activities, indexer, attachments, subscriptions, etc.

After adding new method at com.liferay.knowledgebase.service.impl.ArticleLocalServiceImpl.java, you need to run ANT target build-service to rebuild services.

Add workflow-related AUI tags

Now it is time to add workflow related AUI tags at $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/admin/edit_article.jsp. First of all, add AUI input workflow action with value WorkflowConstants.ACTION_SAVE_DRAFT.

<aui:input name="workflowAction" type="hidden" value="<%= WorkflowConstants.ACTION_SAVE_DRAFT %>" />

As shown in above code, the default value of AUI input workflowAction was set as SAVE DRAFT with type hidden. That is, this AUI input is invisible to end users.

Afterwards, it would be better to add workflow messages by UI tag liferay-ui:message, like a-new-version-will-be-created-automatically-if-this-content-is-modified for WorkflowConstants.STATUS_APPROVED, and there-is-a-publication-workflow-in-process for WorkflowConstants.STATUS_PENDING.

<c:choose>
<c:when test="<%= status == WorkflowConstants.STATUS_APPROVED %>"> <div class="portlet-msg-info">
<liferay-ui:message key="a-new-version-will-be-created-automatically-if-this-content-is-modified" />
</div> </c:when>
<c:when test="<%= status == WorkflowConstants.STATUS_PENDING %>">
<div class="portlet-msg-info">
<liferay-ui:message key="there-is-a-publication-workflow-in-process" />
</div></c:when>
</c:choose>
And then add AUI workflow status tag aui:workflow-status at $PLUGIN_SDK_HOME/knowledge-base-portlet/docroot/admin/edit_article.jsp.
<c:if test="<%= article != null %>">
 <aui:workflow-status id="<%= String.valueOf(resourcePrimKey) %>" status="<%= status %>" version="<%= GetterUtil.getDouble(String.valueOf(version)) %>" />
</c:if>

Finally you should add JavaScript to implement the function publishArticle() as follows.

function <portlet:namespace />publishArticle() {
 document.<portlet:namespace />fm.<portlet:namespace />workflowAction.value = "<%= WorkflowConstants.ACTION_PUBLISH %>";
 <portlet:namespace />updateArticle();
}

As you can see, the workflow action value is set as WorkflowConstants.ACTION_PUBLISH.

You did add workflow capabilities on Knowledge Base articles in plugins. From now on, you would be able to apply workflow on Knowledge Base articles through Control Panel, as shown in the blogs post applying-workflow-on-custom-assets-in-liferay-6-through-plugins.

Where would you find sample code - Knowledage base plugin with workflow capabilities?

You can simply download WAR (with source code) of Knowledge Base plugin with workflow capabilities from

knowledge-base-portlet-6.0.6.1.war

And then deploy it. You would be able to see portlets: Knowledge Base Admin (managing knowledge base articles and templates), Knowledge Base Aggregator (publishing knowledge base articles), Knowledge Base Display (displaying knowledge base articles) and Knowledge Base Search (ability to search knowledge base articles).

You may be interested in the latest version of Knowledge Base plugin with workflow capabilities. Thus you can find latest code at SVN like:

svn://svn.liferay.com/repos/public/plugins/trunk/portlets/knowledge-base-portlet

Summary

As you can see, you would be able to add workflow capabilities on any custom assets generated by Service-Builder in plugins. The asset Knowledge Base articles is one of them (custom assets).Try it now, you would be able to have workflow capabilities on your own custom assets.

Last but not least, I'd like to send thanks to Peter Shin and Brian Chan,  who did a great job to make Knowledge Base plugin a reality in Liferay portal 6.

Threaded Replies Author Date
Thanks for the post Pius Onobhayedo September 7, 2010 8:59 AM
Great article! Thanks, Jonas! Xinsheng Robert Chen September 7, 2010 2:47 PM
Very nice!!!It's very helpful. Sohui Gu September 8, 2010 7:34 PM
Hi Jonas ? Please give some update on how to... Mohd Amjed Ahmed Chand March 17, 2011 5:47 AM
Thanks, Mohd, Let me verify the same and come... Jonas Yuan March 17, 2011 11:03 AM
Hallo Jonas, any news on your verification? Lars Bürkner March 23, 2011 7:46 AM
@Lars and @Mohd, do you test... Jonas Yuan March 24, 2011 7:03 AM
@Lars and @Mohd, just applied the steps... Jonas Yuan March 24, 2011 3:29 PM
@Jonas thanks a lot,, it works. Can you please... Mohd Amjed Ahmed Chand March 24, 2011 11:57 PM
Maybe a tutorial for integrating a workflow... Lars Bürkner March 28, 2011 4:40 AM
@Mohd and @Lars Thanks for your comments. I am... Jonas Yuan March 29, 2011 12:54 PM
Jonas, great article! How can I apply workflow... Andreas Firnau May 5, 2011 9:33 AM
Hi Andreas, this is a new feature - apply... Jonas Yuan May 5, 2011 10:42 AM
Could you pls update ,... Manikandan S June 24, 2011 5:37 AM
The url's for the war don't seem to be working... Peter Bierman July 22, 2011 7:13 AM
Hi Peter, is it working well after you sign... Jonas Yuan July 26, 2011 3:48 PM
Thanks Jonas for sharing this.. I have... Jay Patel December 5, 2011 11:38 AM
[...] Ahí va! Fallo que se nos ha pasado para... Anonymous February 1, 2012 10:55 PM
Great Work....Very helpful article but the... Keyur Ashra February 29, 2012 10:12 PM
[...] Échale un vistazo a esta publicación del... Anonymous March 20, 2012 8:55 AM
Hi, I'm new member. I don't know how to import... Nguyễn Cường April 14, 2012 12:40 AM
I found it in this link :D... Nguyễn Cường April 15, 2012 12:35 AM
[...] Hi everyone, thanks for reading my topic!... Anonymous April 16, 2012 9:57 PM
[...] Hi everyone, thanks for reading my topic!... Anonymous April 17, 2012 1:52 AM
[...] Hi Ajay, Please take a look at This link.... Anonymous June 12, 2012 11:13 PM
When I try to download the war file i get ... Kelis Narun September 14, 2012 3:47 PM
I don't have permission to download the example... Célio Latorraca October 24, 2012 2:02 PM
[...] Hi akram, check these links link1 link2... Anonymous March 1, 2013 8:48 AM
[...] I am new to liferay. I am using Liferay... Anonymous October 26, 2013 9:00 AM
[...] Q1.How to combine Kaleo workflow in... Anonymous November 23, 2014 8:39 PM

Thanks for the post
Posted on 9/7/10 8:59 AM.
Great article! Thanks, Jonas!
Posted on 9/7/10 2:47 PM in reply to Pius Onobhayedo.
Very nice!!!It's very helpful.
Posted on 9/8/10 7:34 PM.
Hi Jonas ? Please give some update on how to write custom assets in Liferay 6.0.6.
Example here does not hold valid anymore with the new versions.
<workflowhandler/> doesnt seem to be the way of letting liferay know the workflow handler for the asset.


Thanks
Posted on 3/17/11 5:47 AM.
Thanks, Mohd, Let me verify the same and come back to you shortly.
Posted on 3/17/11 11:03 AM in reply to Mohd Amjed Chand.
Hallo Jonas, any news on your verification?
Posted on 3/23/11 7:46 AM in reply to Jonas Yuan.
@Lars and @Mohd, do you test knowledge-base-portlet in 6.0.6?

svn://svn.liferay.com/repos/public/plugins/branches/6.0.6/portlets/knowled­ge-base-portlet

You can check out above KB and test it.

Hope that it helps,

Thanks
Posted on 3/24/11 7:03 AM in reply to Lars Bürkner.
@Lars and @Mohd, just applied the steps mentioned in the blogs, it is working well.

Steps to build WAR
1) get KB source code (from 6.0.6 branch)
2) fix a default issue
3) following steps mentioned in the blogs
4) deploy WAR

Do you need new WAR file - knowledge-base-portlet-6.0.6.1.war?
Posted on 3/24/11 3:29 PM in reply to Jonas Yuan.
@Jonas thanks a lot,, it works.
Can you please write an article on writing plugins around workflow ? may be on custome assets, I believe that will cover many things.
Posted on 3/24/11 11:57 PM in reply to Jonas Yuan.
Maybe a tutorial for integrating a workflow (single approver)in the "My greeting portlet" from the Liferay Developer Tutorials.

I tried to do it myself, but i get an XML-error "The markup in the document preceding the root element must be well-formed." when i want to add the workflow instant link to the service.xml
Posted on 3/28/11 4:40 AM in reply to Mohd Amjed Chand.
@Mohd and @Lars Thanks for your comments. I am trying to provide more detailed articles for workflow, specially releasing the same in the book: Liferay Cookbook as earlier as possible.
Posted on 3/29/11 12:54 PM in reply to Lars Bürkner.
Jonas, great article! How can I apply workflow to approve new users? "Users" is not displayed in my LR 6 EE SP1. Thanks!
Andreas
Posted on 5/5/11 9:33 AM in reply to Jonas Yuan.
Hi Andreas, this is a new feature - apply workflow on entities users. It should be available in 6.1 or EE 6 SP2, if you can wait.
Posted on 5/5/11 10:42 AM in reply to Andreas Firnau.
Could you pls update , knowledge-base-portlet-6.0.6.1.war it seems not working
Pointing out this URL
http://www.liferay.com/c/document_library/get_file?uuid=0bb28d50-d680-4cd6-a1­5a-3ab4dbcf5437&groupId=31578
Posted on 6/24/11 5:37 AM in reply to Jonas Yuan.
The url's for the war don't seem to be working any more.
And the svn url asks for a username password.
Where can i find this example war?
Posted on 7/22/11 7:13 AM in reply to Mani kandan.
Hi Peter,

is it working well after you sign in? You may need to sign in first.
Posted on 7/26/11 3:48 PM in reply to Peter Bierman.
Thanks Jonas for sharing this..

I have downloaded very latest tomcat-liferay bundle LR-6.1.0-CE-Beta4, still I don't find proper way to implement Workflow on any OOB asset for example "User" model.

Assume that I want to implement Workflow on "User" asset. Meaning when new user is created, it should be assigned to some Work-flow definition e.g. single-approver definition. Then when it is approved by approver then only status may be changed to "Approved".

What I have learned as of now is, in order to have WF on any asset service.xml & liferay-portlet.xml should be changed..correct me if I am wrong.

And I don't find any proper way to modify/override these service.xml & liferay-portlet.xml.

Still for just POC purpose, I changed the following files in Portal source code directly to have work-flow on User asset:

1. service.xml to add columns & reference package path for Work-flow
2. liferay-portlet.xml to add UserWorkflowHandler

Now the problem is after changing this service.xml, portal does not allow me to build services again saying that "Could not find com.liferay.portal.tools.servicebuilder.ServiceBuilder. Make sure you have it in your classpath", though ServiceBuilder class is available under the same package.

What can be root cause here?

Also can you also suggest some other better way for above kind of requirement when Liferay's OOB asset needs to be customized to apply Workflow on it?

Thanks in advance,
Jay.
Posted on 12/5/11 11:38 AM.
[...] Ahí va! Fallo que se nos ha pasado para esta release. Abro ticket. Para hacértelo a mano tendrás que tirar de ext plugin. Puedes seguir los pasos de este artículo de blog:... [...] Read More
Posted on 2/1/12 10:55 PM.
Great Work....Very helpful article but the Example WAR is not available for Download right now. Please kindly share it once again or provide some fresh link...Thanks
Posted on 2/29/12 10:12 PM.
[...] Échale un vistazo a esta publicación del Blog... http://www.liferay.com/web/jonas.yuan/blog/-/blogs/5786756 Flag Please sign in to flag this as inappropriate. Mark as an Answer [...] Read More
Posted on 3/20/12 8:55 AM.
Hi, I'm new member.
I don't know how to import "knowledge-base-portlet" source code to like a normal portlet project - "sample-portlet" in Eclipse

thank a lot emoticon
Posted on 4/14/12 12:40 AM.
I found it in this link emoticon
http://www.liferay.com/documentation/liferay-portal/6.0/development/-/ai/importi­ng-existing-projects-into-liferay-ide
comment for new members like me :d
Posted on 4/15/12 12:35 AM.
[...] Hi everyone, thanks for reading my topic! I want to create a portlet for recruitment process for a organization. Assume that: In Liferay portal, I created an organization, named as TD. I also created... [...] Read More
Posted on 4/16/12 9:57 PM.
[...] Hi everyone, thanks for reading my topic! I want to create a portlet for recruitment process for a organization. Assume that: In Liferay portal, I created an organization, named as TD. I also created... [...] Read More
Posted on 4/17/12 1:52 AM.
[...] Hi Ajay, Please take a look at This link. Thanks Rahul Flag Please sign in to flag this as inappropriate. Mark as an Answer [...] Read More
Posted on 6/12/12 11:13 PM.
When I try to download the war file i get


Forbidden

You do not have permission to access the requested resource.

http://www.liferay.com/c/document_library/get_file?uuid=0bb28d50-d680-4cd6-a15a-­3ab4dbcf5437&groupId=31578
Posted on 9/14/12 3:47 PM.
I don't have permission to download the example code.

Is there a way to download it?

Thanks!
Posted on 10/24/12 2:02 PM in reply to Adrian Layne.
[...] Hi akram, check these links link1 link2 Sign in to vote. Flag Please sign in to flag this as inappropriate. Mark as an Answer [...] Read More
Posted on 3/1/13 8:48 AM.
[...] I am new to liferay. I am using Liferay 6.1.1 CE. I want to add workflow (Kaleo) to a portlet which contains two textfields and a button. The portlet is created through Plugins-SDK. I’ve already... [...] Read More
Posted on 10/26/13 9:00 AM.
[...] Q1.How to combine Kaleo workflow in tradition Portlet? I have combined one tradition portlet in that i am carrying one Button named INITIATE . What i wish is that on click of this symbol my... [...] Read More
Posted on 11/23/14 8:39 PM.